I am trying to create a custom method in Google Spreadsheet. I have the following method to replace the missing WEEKNUM method. (I leave to second parameter in order to allow upload of excel files.)
function WEEKNUM(inDate, dummy){
return Utilities.formatDate(inDate, "GMT", "w");
}
I call in method in approximately 400 rows twice (800 times) in one spreadsheet. Some of the formulas complete however for other I get this error message.
error: There are too many scripts running simultaneously for this Google user account.
Is there anything I can do to fix this? I understand 800 executions it a lot but not anymore than would be expected of built in functions. I know there are alternative ways to calculate the week number (such as =LEFT(TEXT(A2; "w d"); 2)) however I want to know if it is even possible to create custom formula functions that wont be subjected to this invisible ceiling.
Thank you in advanced for your replies.
Have you custom function receive a range and output an array. No need to use an arrayformula, which also wont work on a custom function
Have you tried an ArrayFormula? In your spreadsheet, instead of having 800 calls to:
=WEEKNUM(-cell-, -dummy-)
in cells A1 to B400, try:
=ARRAYFORMULA(WEEKNUM(A1:B400, -dummy-))
in cell A1.
Related
A few days ago I got help from Stack Overflow to modify my then Apps Script code used to make calendar events from info on Google sheet, so as to tick a checkbox whenever an entry from the corresponding row is made and subsequently make new events only when the checkbox is unticked.
function addEvent() {
let webinarCalendar = CalendarApp.getCalendarById("blablablablablabla#gmail.com");
let calendarSheet = SpreadsheetApp.getActiveSheet();
let schedule = calendarSheet.getDataRange().getValues();
schedule.splice(0, 1);
const k = 16; // colIndex of checkbok col
const created = schedule.map(e => [e[k]]);
schedule.forEach(function(entry, i) {
if (entry[k] == true) { return; }
webinarCalendar.createEvent(entry[3], entry[14], entry[15], {description: entry[13]});
created[i][0] = true;
});
calendarSheet.getRange(2, k + 1, created.length, 1).setValues(created);
}
This current code worked just fine until 2 days ago when I updated 3 of the 4 cells with the required inputs to work on an array formula so that they get populated automatically whenever a new row entry is made.
The error on the app script console says :
Exception: The parameters (String,String,String,(class)) don't match the method signature for CalendarApp.Calendar.createEvent.
The parameters required for this createEvent() as per documentation are title(string), start time(string), finish time(string) and description(which is inside a javascript object I think and is also a string). To ensure that the datatype did not somehow get changed in the process of creating array formula, I cross checked the cells with an ISTEXT() and all of the inputs returned TRUE.
Second trial that I made was to change the splice() from (0,1) to (0,2) so that it ignores the first row which has the array formula written into the cells, which also did not fix the issue.
I would greatly appreciate if someone could show me what is causing this issue and help me fix it.
I don't know why it worked previously, but startTime and endTime should be Date.
I have checked that you columns are String.
Reference:
createEvent(title, startTime, endTime, options)
The error on the app script console says : Exception: The parameters (String,String,String,(class)) don't match the method signature for CalendarApp.Calendar.createEvent.
This is simply saying it's reading from data that is not in the proper data type. In this case, perhaps, try encasing the entries with 'new Date(entry[x])' for the respective start and end date/time entries.
For people trying to run the scripts, one underlying cause might be the fact that you may be using US locale when the date have been formatted as UK.
(e.g. Date that App Script is looking for is mm/dd/yyyy tt:tt:tt, but if you click in the formula cell it shows as dd/mm/yyyy tt:tt:tt)
What you would do is to go to Files > General > Locale > (Country of Choice) > Save settings.
You would then reload the page and try if the script is working now without that "Cannot find method createEvent(string,string,string)" error.
The line of code to use in your script would be:
SpreadsheetApp.getActive().setSpreadsheetLocale('en_UK');
You could include it in your onOpen trigger function.
I'm using a custom function to pull price data for EVE Online and I would only like the function to update upon a specific cell change. Instead it's updating every ~10-20 minutes which is using up a ton of my daily quota for URL Fetches.
Looking below you can see the main function is in a page labeled "Warehouse Stock". It pulls all price data for items in the "Item" column. The cell refreshes with a custom function that changes cell B4 in the utility sheet. When that cell changes it updates the values in the custom function because of the IF/THEN statement. Lastly the prices are loaded into the main sheet and sorted by the "product" column.
Also I have recalculation "On Change" and Iterative Calculation turned off.
Thank you for reading and any help you can provide.
The custom function is:
/**
* Query's Fuzz market API for the given types
* #param {range} A vertical range of type_ids.
* #return maxBuy and minSell for each type_id
* #customfunction
*/
function fuzzApiPriceData(type_ids) {
if (!type_ids) throw 'type_ids is required';
const ids = Array.isArray(type_ids) ? type_ids.map(id => id[0]) : [type_ids];
const fuzz_price_data = JSON.parse(UrlFetchApp.fetch(`https://market.fuzzwork.co.uk/aggregates/?station=60008494&types=${ids.join(',')}`));
return [['minSell', 'maxBuy']].concat(type_ids.map(type_id => [parseFloat(fuzz_price_data[type_id]['sell']['min']), parseFloat(fuzz_price_data[type_id]['buy']['max'])]));
}
i think there's a fairly basic misunderstanding here.
"Custom functions" are designed to be written in cells on a sheet. they are by there nature designed to run ALL the time, constantly updating.
If you are attempting to run a custom script, you do that from the script editor itself, you don't even write the function in a cell at ALL.
I'm assuming you didn't write the "custom function" you're using(?) So it will be a bit difficult (but not impossible!) to convert it to a script that writes to a certain place on the sheet at a certain time. But you might research a bit more about the difference between custom functions designed to be executed in cells, and scripts designed to be run on a time trigger.
Regarding you answer:
I would like the function to refresh everyday, aswell as having the option to manually refresh the function by the contents of the cell Utility!B4
I propose you to use Installable Triggers:
Time-driven trigger: It can execute a function each day at specific time.
Installable edit trigger: It can execute a function when a certain value in a specific cell changes.
However, if you want to execute a function manually, I recommend you to insert a drawing and assign a function to it.
Reference
Installable Triggers
Clickable images and drawings in Google Sheets
What I usually do for that is : put a checkbox in a cell. Then, when calling your custom function, add an extra reference to that cell, even if the parameter is not included in your custom function. Each time you will switch true/false, your custom function will be reactivated. Then you can also define another function with a trigger that just change the value of true/false. Here is an example in sheet 'Data' cell A3 : the function is getDataJSON(C1,A2:U2,A1) with A1 even if the custom function take into account only the first and second parameter. https://docs.google.com/spreadsheets/d/1DN0Gfim0LC098zVgrUpt2crPWUn4pWfZnCpuuL1ZiMs/edit?usp=sharing
I'm trying to convert order form data submitted from a Squarespace website from the following format to a table with 4 columns:
Store,Item,Quantity,Details;Store2,Item2,Quantity2,Details2; (etc...)
Commas separate columns while semi-colons separate rows.
All the methods I've tried so far have been successful in splitting the data into the desired form, but the problem occurs when new data is added. When the form is submitted, it creates a new row in the next available empty row. I can't seem to find a way to automate the process without receiving cyclical dependency errors, since each order can have any amount of item entries.
Example spreadsheet:
https://docs.google.com/spreadsheets/d/1ZEWtmMiWO0Us76Z7o7GB7Salw1Rl_-1PhK6GzeOD0GM/edit?usp=sharing
The above example splits the data as desired. I cannot figure out how to make it work with the data added as a new row. I would also like to continue using sheets for its cloud functionality.
Any advice is appreciated, including entirely new ways of processing the data, whether with a script, a different remotely accessible order processing app compatible with Squarespace forms, or natively within Sheets.
You want to achieve the following conversion.
Sample formula:
=ARRAYFORMULA(SPLIT(TRANSPOSE(split(A4,";")),","))
In this formula, the cell "A4" has the input value.
You have already used the formula of =TRANSPOSE(split(A10,";")). In this answer, I used this.
For TRANSPOSE(split(A10,";")), the value is splitted with , using SPLIT and ARRAYFORMULA.
Result:
Sample script:
When you want to use Google Apps Script, you can also use the following script.
function myFunction(value) {
const values = value.split(";");
return values.splice(0, values.length - 1).map(e => e.split(",").map(f => isNaN(f) ? f : Number(f)));
}
In this case, please copy and paste the script to the script editor, and put the custom function of =myFunction(A4) to a cell.
The same result with above formula can be obtained.
References:
SPLIT
ARRAYFORMULA
split()
map()
Im putting together a pretty lengthy spreadsheet in google spreadsheets. This spreadsheet contains information about products ie name, brand, part number, ect... I was helped previously and given some nice solutions but I am still running into limitations.
What I am trying to do is generate, automatically, a description field based on information in other cells.
The formula I am using in the descriptions column is ="Brand Name"&" "&A3&" "&B3&" "&(joinVals(E3:G3," x "))&" "&K3
joinVals(E3:G3," x ") is joining together separate columns containing Length(E) Width(F) Height(G) and adding 'x' between the values. That results in E x F x G
This Script does work for the above formula
function joinVals( rangeValues, separator ) {
function notBlank(element) {return element != '';}
return rangeValues[0].filter(notBlank).join(separator);
}
However I keep getting this error
Script invoked too many times per second for this Google user account.
I am wondering If I can do this as an array to avoid the error as this doc contains 1000+ ROWS.
When all is said and done my result I would like to achieve should be something like this
"Brand Name" Part Number(A) Product Name(B) Dimensions(E x F x G) Size(K)
Should I be running an ARRAY Script?
Thank you all so much, this forum has been such a help!
It is possible to use an Array solution, but you'd have to change a lot how you use formulas in your spreadsheet. The easiest solution is to use built-in spreadsheet formulas directly. There's no need for a custom Apps Script formula for this.
="Brand Name"&" "&A3&" "&B3&" "&(join(" x ";filter(E3:G3;E3:G3<>"")))&" "&K3
As shown by AdamL in the comments, here's an ArrayFormula solution that uses only built-in formulas.
=ArrayFormula(IF(LEN(A3:A),REGEXREPLACE("Brand Name "&A3:A&" "&B3:B&" "&REPT(E3:E&" x ",E3:E<>"")&REPT(F3:F&" x ",F3:F<>"")&REPT(G3:G&" x ",G3:G<>"")&CHAR(9)&" "&K3:K,"( x \t)|\t",""),))
As I said, such ArrayFormula style of solution can be used when writing custom Apps Script as well. I just don't think that's worth it when there's (arguably) simpler built-in solutions (but surely faster and way larger quotas).
I have a spreadsheet contains thousands of rows.
sometimes i wanna check the newest data by my smart phone ,
(the newest data always on the bottom)
if i open the sheet it spent me vary long time to scroll it to the bottom to see the latest data.
So,is there anyway to copy the last 10 or 30 data to another sheet automatically , so i can save mytime ?
many thanks for helping my problem, thank you!
Hi i can tell you how to reverse the data we fetch. To reverse the order of the data we receive from the spreadsheet can be done using the following procedure.
What you need to do,, find following function, inside your functions file. like in my case in am using GoogleSheet.php
private function findRows($search=FALSE)
It should look like this:
private function findRows($search=FALSE)
{
$query = new Zend_Gdata_Spreadsheets_ListQuery();
$query->setSpreadsheetKey($this->getSpreadsheetId());
$query->setWorksheetId($this->getWorksheetId());
and add
$query->setReverse('true');
line after
$query->setWorksheetId($this->getWorksheetId());
This will reverse the order of data you will fetch.
i hope this will help you for reversing the data you receive.
thank you.