I have to fetch data from an API to google sheets which is supposed to plot nearly 1600 entries. However, the execution stops at 6 mins plotting only about 1000 entries. My initial code in the Apps Script was:
function myFunction() {
var spreadsheet=SpreadsheetApp.getActive();
var sheet=spreadsheet.getActiveSheet();
var nextPage=1;
sheet.clear();
var headerRow=["ID","NAME","SOURCE","STATUS","PRICING_MIN_PRICE","PRICING_MAX_PRICE","LOACTION_COUNTRY","LOACTION_LOCALITY","IMAGES_COUNT","VIDEOS_COUNT","FEATURES_COUNT"];
sheet.appendRow(headerRow);
sheet.getRange(
spreadsheet.getCurrentCell().getRow(),
1, 1, sheet.getMaxColumns()).activate();
spreadsheet.getActiveRangeList().setFontWeight('bold');
var curr;
while(nextPage){
curr=nextPage;
var apiURL=`https://base.amberstudent.com/api/v0/inventories?p=${curr}&limit=10&sort_key=relevance&sort_order=desc&statuses=active`;
var response=UrlFetchApp.fetch(apiURL);
var json=response.getContentText();
var dataPoints=JSON.parse(json);
var resArray=dataPoints.data.result;
for(var i=0;i<resArray.length;i++){
var id=resArray[i].id!=null?resArray[i].id:"";
var name=resArray[i].name!=null?resArray[i].name:"";
var source=resArray[i].source!=null?resArray[i].source:"";
var status=resArray[i].status!=null?resArray[i].status:"";
var pricing_min_price=resArray[i].pricing?resArray[i].pricing.min_price:"";
var pricing_max_price=resArray[i].pricing?resArray[i].pricing.max_price:"";
var location_country=(resArray[i].location&&resArray[i].location.country)?resArray[i].location.country.long_name:"";
var location_locality=(resArray[i].location&&resArray[i].location.locality)?resArray[i].location.locality.long_name:"";
var images_count=resArray[i].images.length;
var vid_count=resArray[i].videos.length;
var feature_count=resArray[i].features.length;
var row=[id,name,source,status,pricing_min_price,pricing_max_price,location_country,location_locality,images_count,vid_count,feature_count];
sheet.appendRow(row);
}
nextPage=dataPoints.data.meta.next; //for every page the nextPage stores the value of the next page, and for the last page (159 approx), nextPage=null
}
}
This did not work as I already mentioned. After some searching in the internet, I found some ways to bypass the execution time and I modified my code as shown below:
var spreadsheet=SpreadsheetApp.getActive();
var sheet=spreadsheet.getActiveSheet();
var nextPage=1; //set nextPage as a global variable so that it can be accessed by all functions
function isTimeUp(today) {
var now = new Date();
return now.getTime() - today.getTime() > 300000; //setting up a limit of 5 minutes
}
function myFunction() {
sheet.clear();
var today=new Date();
var headerRow=["ID","NAME","SOURCE","STATUS","PRICING_MIN_PRICE","PRICING_MAX_PRICE","LOACTION_COUNTRY","LOACTION_LOCALITY","IMAGES_COUNT","VIDEOS_COUNT","FEATURES_COUNT"];
sheet.appendRow(headerRow);
sheet.getRange(
spreadsheet.getCurrentCell().getRow(),
1, 1, sheet.getMaxColumns()).activate();
spreadsheet.getActiveRangeList().setFontWeight('bold');
var curr;
while(nextPage){
if (isTimeUp(today)) {
// schedule a trigger for a different function
ScriptApp.newTrigger("repeatFunction")
.timeBased()
.everyMinutes(5)
.create();
break;
}
curr=nextPage;
var apiURL=`https://base.amberstudent.com/api/v0/inventories?p=${curr}&limit=10&sort_key=relevance&sort_order=desc&statuses=active`;
var response=UrlFetchApp.fetch(apiURL);
var json=response.getContentText();
var dataPoints=JSON.parse(json);
var resArray=dataPoints.data.result;
for(var i=0;i<resArray.length;i++){
var id=resArray[i].id!=null?resArray[i].id:"";
var name=resArray[i].name!=null?resArray[i].name:"";
var source=resArray[i].source!=null?resArray[i].source:"";
var status=resArray[i].status!=null?resArray[i].status:"";
var pricing_min_price=resArray[i].pricing?resArray[i].pricing.min_price:"";
var pricing_max_price=resArray[i].pricing?resArray[i].pricing.max_price:"";
var location_country=(resArray[i].location&&resArray[i].location.country)?resArray[i].location.country.long_name:"";
var location_locality=(resArray[i].location&&resArray[i].location.locality)?resArray[i].location.locality.long_name:"";
var images_count=resArray[i].images.length;
var vid_count=resArray[i].videos.length;
var feature_count=resArray[i].features.length;
var row=[id,name,source,status,pricing_min_price,pricing_max_price,location_country,location_locality,images_count,vid_count,feature_count];
sheet.appendRow(row);
}
nextPage=dataPoints.data.meta.next; //for every page the nextPage stores the value of the next page, and for the last page (159 approx), nextPage=null
}
}
function repeatFunction(){
while(nextPage){
var curr=nextPage;
var apiURL=`https://base.amberstudent.com/api/v0/inventories?p=${curr}&limit=10&sort_key=relevance&sort_order=desc&statuses=active`;
var response=UrlFetchApp.fetch(apiURL);
var json=response.getContentText();
var dataPoints=JSON.parse(json);
var resArray=dataPoints.data.result;
for(var i=0;i<resArray.length;i++){
var id=resArray[i].id!=null?resArray[i].id:"";
var name=resArray[i].name!=null?resArray[i].name:"";
var source=resArray[i].source!=null?resArray[i].source:"";
var status=resArray[i].status!=null?resArray[i].status:"";
var pricing_min_price=resArray[i].pricing?resArray[i].pricing.min_price:"";
var pricing_max_price=resArray[i].pricing?resArray[i].pricing.max_price:"";
var location_country=(resArray[i].location&&resArray[i].location.country)?resArray[i].location.country.long_name:"";
var location_locality=(resArray[i].location&&resArray[i].location.locality)?resArray[i].location.locality.long_name:"";
var images_count=resArray[i].images.length;
var vid_count=resArray[i].videos.length;
var feature_count=resArray[i].features.length;
var row=[id,name,source,status,pricing_min_price,pricing_max_price,location_country,location_locality,images_count,vid_count,feature_count];
sheet.appendRow(row);
}
nextPage=dataPoints.data.meta.next; //for every page the nextPage stores the value of the next page, and for the last page (159 approx), nextPage=null
if (nextPage==null) {
var triggers = ScriptApp.getProjectTriggers();
for (var i = 0; i < triggers.length; i++) {
// delete all triggers
ScriptApp.deleteTrigger(triggers[i]);
}
break;
}
}
}
I tried to set nextPage as a global variable and set up a trigger which called the repeatFunction method every 5 minutes. This however, creates something like an infinite loop. Data keeps gettind added into the spreadsheet. I cannot figure out how to overcome this problem as I am new to the concept of Google App Scripts and its usage. Please help me out with a solution for this. Please ask for more details if necessary. Thank you!
I believe your goal as follows.
myFunction()
works. But, you want to reduce the process cost of your script.appendRow
is used in the loop. I thought that this might be one of the reason of your issue.
limit=10
is used. And, from I have to fetch data from an API to google sheets which is supposed to plot nearly 1600 entries.
, if limit=10
is the number of values for one API call, 160 requests are required to be done. I thought that this will be another reason of your issue. In this case, I would like to propose to modify the value of limit
.
limit=2000
is used. In my test, no error occurs. But if an error occurs, please modify this value and test it again.When above points are reflected to your script, it becomes as follows.
In this modification, please modify your myFunction()
as follows.
function myFunction2() {
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getActiveSheet();
var nextPage = 1;
sheet.clear();
var headerRow = ["ID", "NAME", "SOURCE", "STATUS", "PRICING_MIN_PRICE", "PRICING_MAX_PRICE", "LOACTION_COUNTRY", "LOACTION_LOCALITY", "IMAGES_COUNT", "VIDEOS_COUNT", "FEATURES_COUNT"];
sheet.appendRow(headerRow);
sheet.getRange(spreadsheet.getCurrentCell().getRow(),1, 1, sheet.getMaxColumns()).activate();
spreadsheet.getActiveRangeList().setFontWeight('bold');
var ar = [];
var curr;
while (nextPage) {
curr = nextPage;
var apiURL = `https://base.amberstudent.com/api/v0/inventories?p=${curr}&limit=2000&sort_key=relevance&sort_order=desc&statuses=active`;
var response = UrlFetchApp.fetch(apiURL);
var json = response.getContentText();
var dataPoints = JSON.parse(json);
var resArray = dataPoints.data.result;
for (var i = 0; i < resArray.length; i++) {
var id = resArray[i].id != null ? resArray[i].id : "";
var name = resArray[i].name != null ? resArray[i].name : "";
var source = resArray[i].source != null ? resArray[i].source : "";
var status = resArray[i].status != null ? resArray[i].status : "";
var pricing_min_price = resArray[i].pricing ? resArray[i].pricing.min_price : "";
var pricing_max_price = resArray[i].pricing ? resArray[i].pricing.max_price : "";
var location_country = (resArray[i].location && resArray[i].location.country) ? resArray[i].location.country.long_name : "";
var location_locality = (resArray[i].location && resArray[i].location.locality) ? resArray[i].location.locality.long_name : "";
var images_count = resArray[i].images.length;
var vid_count = resArray[i].videos.length;
var feature_count = resArray[i].features.length;
var row = [id, name, source, status, pricing_min_price, pricing_max_price, location_country, location_locality, images_count, vid_count, feature_count];
ar.push(row);
}
nextPage = dataPoints.data.meta.next; //for every page the nextPage stores the value of the next page, and for the last page (159 approx), nextPage=null
}
sheet.getRange(sheet.getLastRow() + 1, 1, ar.length, ar[0].length).setValues(ar);
}
setValues
is used in stead of appendRow
, and limit=2000
is used. In this case, the 1,585 values are retrieved by one API call. And in my environment, the process time of above modified script was about 20 seconds.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.