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.
Related
I have a Google Sheet that uses an IMPORTRANGE query to combine data from multiple other sheets. This combined import sheet is read by Google AppSheet. We have realized that the data AppSheet is reading is always outdated. It only reads the data as of the last time the sheet was manually opened.
I followed the steps in this post to try to fix this issue by creating this function: function refresh() {SpreadsheetApp.flush()}. I then set up a timed trigger to activate it once an hour. Logs show the function is running, but the data is still not updating until I manually open the sheet.
This is my first time using Apps Script. Any tips/ideas? Is there a different or better way to have the formulas update without opening the file?
Thank you for reading.
SpreadsheetApp.flush() only works for the script execution that calls it. If you need to refresh the data results from a formula it's uncertain how exactly the spreadsheet will respond as most of the formula calculations are done on the client side. You could verify this by yourself by using your web browser developer tools.
Anyway, spreadsheet formulas have several caveats so it will not be extrange that at some point you will have to rethink your solution. Assuming that you want to keep using AppSheet:
Use AppSheet for your front end and some no-code / low-code automation. Keep your app small, if you need many forms / views consider to distribute them among several apps.
Use Google Sheets only for data storage for your AppSheet app. Please bear in mind that it has 10 million cells limit for the whole spreadsheet, so you might want to delete the unused sheets and delete the unused columns and rows on each sheet.
You might use Google Apps Script to do the data import and transformation tasks. If you need that something be updated based on actions done on the AppSheet app, you might use an installable change trigger or use webhook from the AppSheet side to and a "simple" web application using Google Apps Script (you could use GET / POST http requests to trigger some Google Apps Script functions).
Also you might use other programming platforms for the data import / transformation tasks and keep using Google Sheets as your AppSheet database by using the Google Sheets API or other automation tools like Zappier, IFTTT, Integromat among many others.
solution #1
You can try this solution :
define a checkbox (for instance in A1 in tab Sheet1)
set this script
function myFunction() {
var chk = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1').getRange('A1')
chk.setValue(false);
SpreadsheetApp.flush();
Utilities.sleep(500);
chk.setValue(true);
}
define a trigger on it
define the formula as follows
=if(A1,importrange("1n-rjSYb63Z2jySS3-M0BQ78vu8DTPOjG-SZM4i8IxXI","A:Z"),"")
when A1 is unchecked, the result will be empty, then check A1 to fill once again the result as expected
solution #2
by script, try for instance
function myFunction() {
var sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet9')
var data = SpreadsheetApp.openById('1n-rjSYb63Z2jySS3-M0BQ78vu8DTPOjG-SZM4i8IxXI').getSheets()[0].getDataRange().getValues()
sh.getRange(1,1,data.length,data[0].length).setValues(data)
}
put a daily triger as needed
I have a scheduled addon, which writes data periodically into a Google Sheet, without to open file. I have a formula, which should make some calculations on written data and write calculated values into the sheet, so then Data Studio with this sheet as data source updates the visualization.
What is the way to periodically run a formula calculation and write calculated values without manual steps like opening file?
I'm pretty new to this topic: my search approaches to find something like convert formula to app script or schedule formula execution brought me not to any fruitful idea.
PS_ the formula, which should do the calculation is:
=IFERROR(((VLOOKUP(A2,'[1]SV'!$A:$B,2.0))/B2)+(IF(B2=1,"33,9",IF(B2=2,"16,28",IF(B2=3,"10,36",IF(B2=4,"7",IF(B2=5,"5,64")))))+IF(B2=6,"4,13",IF(B2=7,"3,27",IF(B2=8,"2,61",IF(B2=9,"2,18",IF(B2=10,"1,82")))))+IF(B2=11,"1,77",IF(B2=12,"1,81",IF(B2=13,"1,85",IF(B2=14,"1,9",IF(B2=15,"2,04")))))+IF(B2=16,"1,68",IF(B2=17,"1,61",IF(B2=18,"1,65",IF(B2=19,"1,62",IF(B2=20,"1,59","0")))))),0)
If i would know, how to convert the formula to app script, i would manage the rest - i'm familiar with running scripts with time based trigger. Or, maybe, there is a method to run formula on the same scheduled way, like scripts...?
*Disclaimer: I have not tried this and it might not work, if it doesn't, comment and I will try to provide another solution
OK here's what i would try:
In google scripts there is a trigger function, manly used for testing. what it does is it runs your script and sends you an email if there is a error, and hypothetically, you could use this to run you script periodically.
A couple of other things I may try if this doesn't work, leave a comment if you would like me to go in depth about these:
depending on how you want this to work, you could set up a web app to do this, and instead of opining google sheets open the web app with a timer built into the script, that would trigger as long as you had the web page opened.
It might also be possible to run the script automatically with a JavaScript function, requires more research.
If Google Data Studio is not showing you the correct value then you could use a time-driven trigger to save the formula results in another cell. Example:
function respondToTimeDrivenTrigger(e){
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
/** The range holding the formula */
var range = spreadsheet.getRange('Sheet1!A1');
/** The value returned by the formula */
var value = range.getValue();
/** Write the value to the cell to the right or the source cell */
range.offset(0,1).setValue(value);
}
Resources
https://developers.google.com/apps-script/guides/sheets
https://developers.google.com/apps-script/guides/triggers/installable
I need to save my Google Form in two different sheets.
The first sheet will be the one for history and the other one will be exploited by the logistic services (who may delete some rows when the clients receive the shipped stuff).
I really need to keep all the responses on the first sheet whatever the logistic services do on the second.
The fact is; I was using formRat, but is not working anymore and I don't see any complementary module that does exactly the same thing. I'm not good enough in programming to write the script by myself.
I tried to write this in the second sheet:
=ArrayFormula('first_sheet_name'!A:W)
But when I try to delete a row on the second sheet, it reappears a few seconds later because Google Sheets recalculates it.
A form submission trigger script attached to the Form Response spreadsheet can easily copy responses to the second sheet, as they arrive. Any modifications made later on the second sheet will survive.
Here is a very simple example of such an Installable Trigger Function. You need to declare ss2ID with the Sheet ID of spreadsheet 2. The script assumes that the responses are to be copied to the first sheet in spreadsheet 2, and that all form answers are populated.
function copyResponse( event ) {
fixFormEvent( event ); // From https://stackoverflow.com/a/26975968/1677912
var ss2Id = "---sheet-id---";
var sheet2 = SpreadsheetApp.openById( secondSheetId ).getSheets()[0];
sheet2.appendRow( [event.values] );
}
This function uses fixFormEvent( event ) from e.values in google forms skips empty answers, is there a workaround? to ensure the columns in the new sheet align with the original questions.
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)
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);