Google Spreadsheet run script slow - google-apps-script

Let's say I have a spreadsheet called A. When i run a script on spreadsheet A it will load very slowly and may cause timeout sometime. (I thought something was wrong with the function I created so i improved it - but still causing same result). However, once I make a copy of spreadsheet A (name it B). With the exact same code and functions spreadsheet B runs script rather fast. How is that possible when spreadsheet B is the exact same as spreadsheet A?

I found out what was the problem. It is actually because of getScriptProperties in my google spreadsheet. So, in my old spreadsheet the getScriptProperties will take old data (whereby, when i create a new one, i does not exist). On the other hand, when I duplicate a new spreadsheet, it is running for the first time so it will take everything. What i did was deleteProperty of the old spreadsheet so that it can create a new Script Property (which will take new additions).
The code is as below:
var scriptProperties = PropertiesService.getScriptProperties();
scriptProperties.deleteProperty('test');

Related

Problem with trigger 'On change' running continuously while source of data spreadsheet is updating

I have a spreadsheet (Data_Collect_API) that collects data from an API and it's quite an extensive function.
I then have another spreadsheet (Data_Stats) that =IMPORTRANGE from (Data_Collect_API).
The spreadsheet (Data_Stats) copies some data around etc. (function is triggered by On change) after =IMPORTRANGE have changed (thus there was new data on source spreadsheet).
The problem I'm facing is that source spreadsheet (Data_Collect_API) is updating with data from API, and then the destination spreadsheet (Data_Stats) IMPORTRANGE updates a sheet, triggering the On change and then running a function. This is all good... but, the Data_Stats spreadsheets On change gets triggered multiple times while Data_Collect_API is still busy running it's function.
So question is how can I make sure that Data_Stats sheet function triggered by On change only happens once after the Data_Collect_API has been updated?
Hope my question makes sense...

How to copy triggers/projects from one spreadsheet to another?

I'm attempting to create a spreadsheet that needs to be copied a bunch of times from within one spreadsheet but each copy is also meant to have triggers within it and it appears that this is harder than I initially thought.
The actual project involves an editable database that takes from single sheet spreadsheets each one a copy of a single sheet from the main spreadsheet and the whole thing then needs to be duplicated.
I first just tried to create a copy of the first spreadsheet but it seems that the project that the triggers are contained within doesn't copy over. I have tried using installable triggers but it seems that you cant do this easily from within another spreadsheet as explained here (I don't really understand the answer to this question). I have also looked at the possibility of copying the project from one spreadsheet to another but this also just seems like a dead end.
I can appreciate that this is quite vague but I really have no idea what to do about this and any suggestions would be appreciated.
Hmm I am not sure about copying triggers over. (I normally just use onOpen triggers for menu items.) However I can confirm the following bit of code copies the spreadsheet and all of it's embedded scripts.
function copyTemplate() {
//A file needs a name
var fileName = "Your File Name Here"
//Get the ID of the Master Spreadsheet (This script is embedded, you can change to get by id.)
var id = SpreadsheetApp.getActiveSpreadsheet().getId();
//Get the Destination folder by ID
var destFolder = DriveApp.getFolderById("YOUR_ID_HERE")
//Get the master template, make a copy in the destination folder.
DriveApp.getFileById(id).makeCopy(fileName, destFolder)
}//END OF FUNCTION

IMPORTRANGE function not refreshing new entries in linked Google sheet

My IMPORTRANGE function is not refreshing with new data once the linked spreadsheet is added to. Instead, I am having to cut and paste all of the formulae again whenever I want to view the new information.
I'm using the new version of Google Sheets and I know there were some issues around the release of this with the IMPORTRANGE function.
I currently have 24 columns of data that I'm importing and the original spreadsheet will just keep growing as it is linked to a form. This is the main reason I'm using IMPORTRANGE, as it will help to keep the original spreadsheet working at maximum speed.
What I'd like to know is, has anyone else had a problem such as this, and if so is there any work around (in apps script/another function)? In worst case scenario, is there an apps script about which would clear the spreadsheet and re-enter all of the formulae on open/on a menu click as it really is a pain updating every column every time a new entry is made.
EDIT - Almost all of the cells I'm trying to import are formulated within the original spreadsheet if that changes anything - EDIT
In the spreadsheet settings under "File", go into the Calculations tab and change the Calculation Setting to "On Change and every minute". I had to do this on another importrange sheet and it did the trick for me.
What solves the problem? Setting the same owner for both spreadsheets: the one that you import data from and the one where you use importrange formula. I had the same problem. I updated the source and no response on final spreadsheet. After setting same owner for both spreadsheets refreshing takes few seconds
I've worked out an ultimate (and very simple) solution to any importrange problems. Let's say you have your data in Sheet1 and it's being collected from a google form. You'd like to importange it somewhere else but newly received rows don't trigger importrange refresh. The solution is to move the data using QUERY to Sheet2 (in the same file) and then importrange the data from Sheet2 to another file; it's easy to force refresh of the QUERY function using simple macro, below I pasted simplified version of my function:
function myFunction() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.setActiveSheet(spreadsheet.getSheetByName('Sheet2'), true);
spreadsheet.getRange('A1').activate();
spreadsheet.getActiveRangeList().clear({contentsOnly: true, skipFilteredRows: true});
spreadsheet.getCurrentCell().setFormula('=QUERY(\'Sheet2\'!A:Z;"SELECT *";1)');
};
So basically I clear the A1 cell that contains the QUERY formula and then I fill it with the same QUERY formula. I set this macro to trigger every 1 minute. Works like a charm.
A trick that seems to work
Instead of
=importrange("Relevant_Sheet_ID","Archive!a1:p259")
Use the below just adding => &"?"&now()
=importrange("Relevant_Sheet_ID"&"?"&now(),"Archive!a1:p259")
Basically, it fools GoogleSheets to think the data set referred is ever changing by adding a timestamp through a now() function.
Feedback welcomed, seems to work for me, but might not be consistent.
Click File > Spreadsheet Setting... and check both sheets are in the same Locale and if responces are comming from Jotforms, set the same Locale there too.
Make a copy of your master sheet and change url of your importrange function. it's work for me..
=importrange(new_master_sheet_copy_url,string_range)

script to force republish of google spreadsheet

I have created a form that pushes data to a Google Spreadsheet. The data is latitude, longitude, location, and other identifying data. The spreadsheet is then published as a .CSV file and imported into ARC GIS to be displayed on an interactive map. It works exactly as I wanted and I set it to republish after each change.
The problem is that when the spreadsheet has rows appended by the script, it is not seeing it as a change and republishing. In order to get the updated data imported to the map, I need to go in and manually republish. Is there anyway through the Google Apps Script that I could make a few lines of code to force a republish? I could then add that to the "on form submit" script I have or another time based one that already runs at 3 am everyday.
I have looked through the Google Apps Script documents and not found anything. When searching for help on the web, the overwhelming majority of responses are for how to publish your script as a template for other.
My testing sheet was republished after the following function was executed by either a menu entry or a time-based trigger.
function ChangeIt() {
var sheet = SpreadsheetApp.getActiveSpreadsheet()
var t = new Date()
var x = 'upd: ' + t
var range = sheet.getRange('a3')
range.setValue(x)
}
If I were in your shoes, I'd add an extra column to the end of the sheet with some benign constant data that a script can change without affecting the systems consuming the data. If an extra column isn't an option, try modifying my sample to read in a current value, change it, and immediately change it back.
Also, I'd see if the spreadsheet onEdit() trigger fires when the form submit adds a new row. If so, tie your GAS function to it to force the republish. If not, setup a timed trigger to execute the GAS function.
A quick workaround for this issue that doesn't require scripting is to simply make an array copy of the data.
For example, I made a new tab and in A1 put this: =ArrayFormula('Form Responses 1'!A1:Z1000)
While the main Form responses tab will insert rows and not play nice with formulas this new tab stay nice and constant and updates automatically when new data is added.

Some spreadsheet cells not updated before trigger function sends email

I have a spreadsheet which extracts and accumulates all the required data from other 6 spreadsheets using Vmerge and Query formulas and all the consolidated data will be converted to pdf and emaild to mail ids using trigger event.
Here begins the problem every time the attachment mail posted consist all the headers and other format, but the data which is extracted does not appear. It seems to appear like - to open the same spreadsheet, after a while all the - (hyphens) are replaced by the data / Hope all the data updates after a while of opening the spreadsheet.
link for sheet
Can anyone direct me to make this issue sorted out.
For this solution should be -> all the data should be updated and then the email script should work; or either it should update before emailing script starts.
Or any other better ideas are appreciated.
Some spreadsheet formulas, like ImportRange and ImportXml (and also Apps Script custom formulas) are only evaluated when there's someone logged in the spreadsheet. It's like these functions need an account to be evaluated from, for example, in importRange the account logged in must have access to the range being imported, if you share this spreadsheet with someone but not the importRange source, when this person is viewing this spreadsheet, the importRange function will not work (well, unless you're also in the spreadsheet and the formulas have already been evaluated).
Bottom line is, you can't have this formulas and use a script triggered on time-driven (or other trigger that does not require someone logged in) and expect the script to be able to read this data.
The workaround though is quite simple. Do what the importRange function does inside your script! e.g.
var source = SpreadsheetApp.openById('source-spreadsheet-key');
var data = source.getSheetByName('List').getRange('I6:AT500').getValues();
//then save it somewhere
var s = Spreadsheet.getActive().getSheetByName('hidden-import');
s.getRange('I6:AT500').setValues(data);
SpreadsheetApp.flush(); //force the data to be written
//so all the other formulas on your spreadsheet get updated with the new data
All your "logic" formulas, like query and vmerge, which are difficult for the script to mimic, can be left on the spreadsheet, but reference this "hidden-import" sheet I just invented instead of nesting importRange directly.
[edit]
To copy only non-empty rows do like this:
var data = SpreadsheetApp.openById('source-spreadsheet-key').
getSheetByName('List').getDataRange().getValues();
Spreadsheet.getActive().getSheetByName('hidden-import').
getRange(1,1,data.length,data[0].length).setValues(data);