I have a spreadsheet Target that uses ImportRange to get some data from another spreadsheet Source, as in
A6 = query(ImportRange("mykey", "Weekly!B:BI"), CONCATENATE("select * WHERE Col1='",B3,"'"), 0)
The select clause is to sub-select the data that matches on a value in B3 - if this cell value is changed then the import is updated "immediately".
I want to be able to force an update if someone changes something in the Source spreadsheet so that we see it reflected in the Target "immediately". Currently this only happens "after some unspecified time" which is up to a minute or so, and too slow for my purposes.
Update:
As per the answer and comments below, I added a function UpdateTarget in the Source that is called from a on edit trigger*:
function UpdateTarget() {
try {
var ss = SpreadsheetApp.openById("targetID");
}
catch(err)
{
Browser.msgBox(err);
}
var sheet = ss.getSheetByName("Weekly");
sheet.getRange("A4").setValue("=query(ImportRange("sourceID", "Weekly!B:BI"), CONCATENATE("select * WHERE Col1='",B3,"'"), 0) ");
SpreadsheetApp.flush();
}
This seems to work more effectively but I may as well have a script to write the updated values directly into the target if I'm going down this route.
I really wanted the Target to be a template which other users could duplicate and which would extract specific "live" data from a master Source, I am reluctant to implement scripts in the Source that would need maintaining as new Targets are added.
I think what I really need is a way of re-stating the formula such that it depends on a cell which can be edited and will trigger a re-calc - but the has no effect on the result?
(*An aside: I found that the openByID function returned "Action not allowed" exception unless its called via an explicit trigger - onEdit is forbidden from editing other spreadsheets -see https://developers.google.com/apps-script/understanding_triggers).
Formulas are recalculated when the spreadsheet is opened by a user or when a cell (within the same spreadsheet) is changed that affects the formula.
Since you are working with two different spreadsheets, the latter case is not applicable.
From which spreadsheet are you calling the flush() function. I assume it is in the target spreadsheet. This will be of no use.
One solution would be to write a script in the source spreadsheet that will modify the target spreadsheet each time the source is edited
Force recalculation of importrange by reinstating the cell formula
Required:
Imported Data - Your target where everything will be copied to.
Imported Data Config - Has the following fields:
+---------------------------------------------+--------------------------------+ | A | B | +---------------------------------------------+--------------------------------+ | Import Data from Spreadsheet with the key: | key | | Import Data from Spreadsheet between range: | A:AA | | Imported Data select columns: | SELECT * | | Imported Data criteria: | WHERE Col15 contains 'Offered' | | Imported Data should by ordered by column: | ORDER BY Col1 | +---------------------------------------------+--------------------------------+
Script:
function onOpen() {
try {
var ss = SpreadsheetApp.getActiveSpreadsheet();
}
catch(err)
{
Browser.msgBox(err);
}
var configsheet = ss.getSheetByName("Imported Data Config");
var configkey = configsheet.getRange("B1").getValue();
var configrange = configsheet.getRange("B2").getValue();
var configselect = configsheet.getRange("B3").getValue();
var configwhere = configsheet.getRange("B4").getValue();
var configorderby = configsheet.getRange("B5").getValue();
var importedsheet = ss.getSheetByName("Imported Data");
importedsheet.getRange("A1").setValue('=QUERY(IMPORTRANGE("' + configkey + '","' + configrange + '"),"' + configselect + ' ' + configwhere + ' ' + configorderby + '")');
SpreadsheetApp.flush();
// Solution of sourcecode is: http://stackoverflow.com/questions/13631584/how-can-i-force-a-recalculation-of-cell-using-importrange-function-in-a-google-s
// OnOpen Trigger: https://developers.google.com/apps-script/understanding_triggers
// Active Spreadsheet solution: https://productforums.google.com/forum/#!topic/docs/XIY0WNX0uL8
Browser.msgBox("Sync Complete!");
}
This allows you to change your formula without editing the script, and make it easier to transfer the script across various sheets.
I also had this issue. I only need to import one cell that is at a constant location.
What I did to solve this issue for myself was use the following function triggered onEdit on the target sheet.
function Refresh() {
var ss = SpreadsheetApp.openById('*yourtargetsheetID*');
var sheet = ss.getSheetByName('*yourtargetsheetname*');
sheet.getRange('*locationofyourimportrangeformula*').setFormula('*yourimportrangeformula*');
}
来源:https://stackoverflow.com/questions/13631584/how-can-i-force-a-recalculation-of-cell-using-importrange-function-in-a-google-s