Google Script - Take on array several cell values at same time - google-apps-script

I've developed a script, but it is TOOOOO slow (>1min). I've read that less calls to take values reduces that time, so I'd ask how to do that. The idea is to take the cell values on just one single line, and then for each "let", take one part of that array.
Do you know how to do that? The code is this:
function createPDF() {
const currentSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("CRM");
let profe_nombre = currentSheet.getRange(14,40).getValues();
let profe_direccion = currentSheet.getRange(16,40).getValues();
let profe_dni = currentSheet.getRange(15,40).getValues();
let profe_iban = currentSheet.getRange(17,40).getValues();
let profe_paypal = currentSheet.getRange(18,40).getValues();
let profe_email = currentSheet.getRange(19,40).getValues();
let factura_nombre = currentSheet.getRange(26,39).getValues();
let factura_fecha = currentSheet.getRange(23,40).getDisplayValues();
let factura_importe = currentSheet.getRange(22,40).getValues();
let factura_notas = currentSheet.getRange(26,38).getValues();
const docFile = DriveApp.getFileById("sheetID");
const tempFolder = DriveApp.getFolderById("folderID");
const pdfFolder = DriveApp.getFolderById("folderID");
const tempFile = docFile.makeCopy(tempFolder);
const tempDocFile = DocumentApp.openById(tempFile.getId());
const body = tempDocFile.getBody()
body.replaceText("{profe_nombre}", profe_nombre);
body.replaceText("{profe_direccion}", profe_direccion);
body.replaceText("{profe_dni}", profe_dni);
body.replaceText("{profe_iban}", profe_iban);
body.replaceText("{profe_paypal}", profe_paypal);
body.replaceText("{profe_email}", profe_email);
body.replaceText("{factura_nombre}", factura_nombre);
body.replaceText("{factura_fecha}", factura_fecha);
body.replaceText("{factura_importe}", factura_importe);
body.replaceText("{factura_notas}", factura_notas);
tempDocFile.saveAndClose();
const pdfContentBlob = tempFile.getAs(MimeType.PDF);
pdfFolder.createFile(pdfContentBlob).setName(factura_nombre + ".pdf");
tempFolder.removeFile(tempFile);
SpreadsheetApp.getUi().alert("Factura creada");
}
function apendiceRemesa() {
const SheetCRM = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("CRM");
const SheetRemesas = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Remesas");
let remesa_cuenta = SheetCRM.getRange(17,40).getValue();
let remesa_importe = SheetCRM.getRange(22,40).getValue();
let remesa_nombre = SheetCRM.getRange(14,40).getValue();
let remesa_concepto = SheetCRM.getRange(26,39).getValue();
const remesa_estado_pago = SheetCRM.getRange(24,40).getValue();
let remesa_estado_pago_fila = SheetCRM.getRange(23,43).getValue();
let remesa_estado_pago_columna = SheetCRM.getRange(24,43).getValue();
if (remesa_estado_pago == 'P') {
SheetRemesas.appendRow([remesa_cuenta,remesa_importe,remesa_nombre,remesa_concepto]);
SpreadsheetApp.getActiveSheet().getRange(remesa_estado_pago_fila, remesa_estado_pago_columna).setValue('RM');
} else {
SpreadsheetApp.getUi().alert('ERROR. Esta factura ya fue pagada')
}
}
I've separated both functions because I have two different buttons for each, so it is not mandatory to first execute createPDF and then apendiceRemesa (I will develop a new function too for both functions, removing some redundant variables then).
Thank you!
%%% UPDATE %%%
Yuri and Iamblichus sokution have reduced about 20% of the execution time. Now, I wonder if there is any other way to identify the worksheet name:
From
const currentSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("CRM");
const data = currentSheet.getRange('al8:ar26').getDisplayValues();
To something like this:
const data = getRange("CRM!AL8:AR26").getDisplayValues();

Solution:
First, retrieve a range containing all your desired values. A simple option would be to use getDataRange(), which will simply get a range corresponding to all sheet values.
Then, retrieve the different desired values from the resulting 2D array, using the corresponding indexes (first row index, then column index). It's important to note that arrays are 0-indexed, contrasting with the 1-indexed parameters from getRange, so you'll have to subtract 1 to each index.
Sample:
To show you how it's done, here's a sample that retrieves the first variables:
const values = currentSheet.getDataRange().getDisplayValues();
const profe_nombre = values[13][39];
const profe_direccion = values[15][39];
const profe_dni = values[14][39];
// ...and so on...
Note: If the cells were more contiguous with each other, I would recommend array destructuring to accomplish this with fewer lines of code.

The trick is to get all data from the sheet as a 2d array and then get 'cells' from the array, not directly from the sheet.
Instead of this:
let profe_nombre = currentSheet.getRange(14,40).getValues();
let profe_direccion = currentSheet.getRange(16,40).getValues();
let profe_dni = currentSheet.getRange(15,40).getValues();
let profe_iban = currentSheet.getRange(17,40).getValues();
let profe_paypal = currentSheet.getRange(18,40).getValues();
let profe_email = currentSheet.getRange(19,40).getValues();
let factura_nombre = currentSheet.getRange(26,39).getValues();
let factura_fecha = currentSheet.getRange(23,40).getDisplayValues();
let factura_importe = currentSheet.getRange(22,40).getValues();
let factura_notas = currentSheet.getRange(26,38).getValues();
Try this:
const data = currentSheet.getDataRange().getDisplayValues(); // the 2d array
// take values from the array
let profe_nombre = data[13][39];
let profe_direccion = data[15][39];
let profe_dni = data[14][39];
let profe_iban = data[16][39];
let profe_paypal = data[17][39];
let profe_email = data[18][39];
let factura_nombre = data[25][38];
let factura_fecha = data[22][39];
let factura_importe = data[21][39];
let factura_notas = data[23][37];
Etc.
For your second function apendiceRemesa():
const data = SheetCRM.getDataRange().getValues();
let remesa_cuenta = data[16][39];
let remesa_importe = data[21][39];
let remesa_nombre = data[13][39];
let remesa_concepto = data[25][38];
const remesa_estado_pago = data[23][39];
let remesa_estado_pago_fila = data[22][42];
let remesa_estado_pago_columna = data[23][42];

Related

With Goosle Apps Script, how to write 2D-array on SpreadSheet with aspect length-to-width ratio of 12 to 2

I would to have ideas with GAS codes from you.
I could not get my ideal output like below
(My Ideal)
Both Headlines and URLs go tandemly (I mean Column A and B have them respectively)
However, my current output goes below:
Both go horizontally. (I mean Row 1 and 2 have them respectively)
| Headline1 | Headline2 | Headline3 |
|-----------|-------|-----------|
|URL_1|URL_2|URL_3|
function jijiPress() {
let response = UrlFetchApp.fetch("https://jen.jiji.com/jc/eng?g=ind");
let text = response.getContentText("utf-8");
let biz_article = Parser.data(text).from('class="textL">').to('</ul>').build();
topics = Parser.data(biz_article).from('<a').to('</a>').iterate();
let dt = new Date();
let now = new Date();
let y = dt.getFullYear();
let m = ("00" + (dt.getMonth()+1)).slice(-2);
let d = ("00" + (dt.getDate())).slice(-2);
let h = now.getHours();
let mm = now.getMinutes();
let filename = y+m+d+h+mm + "_jiji_articles";
let Title = new Array();
let URL = new Array();
for(news of topics){
//Get URLs
let newsUrl = news.replace(/.*href="/,"").replace(/".*/,"");
newsUrl = "https://jen.jiji.com/jc/eng?g=ind"+newsUrl
URL.push(newsUrl);
//Get Headlines
let newsTitle = news.replace(/href[^>]*>/,"")
Title.push(newsTitle);
}
let dTitle =[Title];
dTitle.push(URL);
let ss = SpreadsheetApp.create(filename);
// The code below works, but is not my ideal.(please see myIdeal.xlsx)
let sheet = ss.getActiveSheet().getRange(1,1,dTitle.length,dTitle[0].length).setValues(dTitle);
dTitle.push(URL);
Logger.log(dTitle);
Logger.log("did it!");
}
Any comments are welcome. Thank you in advance.
I would suggest you change as I have shown.
1st, don't use new Array() use the array literal [] its faster.
2nd, I create an array URL. Then push each item newUrl and newTitle into it. I then push URL into results which makes it a 2D array.
let results = [];
for(news of topics){
let URL = [];
//Get URLs
let newsUrl = news.replace(/.*href="/,"").replace(/".*/,"");
newsUrl = "https://jen.jiji.com/jc/eng?g=ind"+newsUrl
URL.push(newsUrl);
//Get Headlines
let newsTitle = news.replace(/href[^>]*>/,"")
URL.push(newsTitle);
results.push(URL)
}
let ss = SpreadsheetApp.create(filename);
let sheet = ss.getActiveSheet().getRange(1,1,results.length,2).setValues(results);
Logger.log(results);

Generating a table from google sheet ranges to google docs only if there is data in the first cell of each row

This is my google scrip that pulls information from a google sheet and generates an invoice from a template.
function Invoice2() {
let ss = SpreadsheetApp.getActiveSpreadsheet();
let overview = ss.getSheetByName("Overview");
let ssn = ss.getSheetByName(ss.getRange("F13").getDisplayValue());
// Template and folder details
let templateID = overview.getRange("H20").getDisplayValue();
let folderidID = overview.getRange("H19").getDisplayValue();
let folder = DriveApp.getFolderById(folderidID);
// File name
let namedata = overview.getRange("C19").getDisplayValue();
let monthdata = ssn.getRange("F13").getDisplayValue();
let yeardata = overview.getRange("F14").getDisplayValue();
let fileName = namedata + ' ' + monthdata + ' ' + "Invoice" + ' ' + yeardata;
// Rates and hours
let sessionHourlyRate = ssn.getRange("G2").getDisplayValue();
let opwHourlyRate = ssn.getRange("G6").getDisplayValue();
let sessionhours = ssn.getRange("G3").getDisplayValue();
let otherPaidWorkHours = ssn.getRange("G7").getDisplayValue();
// Totals
let stotaldata = ssn.getRange("G4").getDisplayValue();
let opwtotal = ssn.getRange("G8").getDisplayValue();
let allTotal = ssn.getRange("G11").getDisplayValue();
// Bank details
let bankName = overview.getRange("D19").getDisplayValue();
let sortCode = overview.getRange("E19").getDisplayValue();
let accountNumber = overview.getRange("F19").getDisplayValue();
// Copy the template and open it as a document
let file = DriveApp.getFileById(templateID);
let copy = file.makeCopy(fileName, folder);
let doc = DocumentApp.openById(copy.getId());
let body = doc.getBody();
// Replace text placeholders with values from the spreadsheet
body.replaceText('<NAME>', namedata);
body.replaceText('<MONTH>', monthdata);
body.replaceText('<YEAR>', yeardata);
body.replaceText('<HR>', sessionHourlyRate);
body.replaceText('<OPWHR>', opwHourlyRate);
body.replaceText('<SHOUR>', sessionhours);
body.replaceText('<OPWHOUR>', otherPaidWorkHours);
body.replaceText('<STOTAL>', stotaldata);
body.replaceText('<OPWTOTAL>', opwtotal);
body.replaceText('<ALLTOTAL>', allTotal);
body.replaceText('<BANKNAME>', bankName);
body.replaceText('<AN>', accountNumber);
body.replaceText('<SC>', sortCode);
var srcData = ssn.getRange("A1:E50").getDisplayValues();
body.insertParagraph(0, 'Invoice').setHeading(DocumentApp.ParagraphHeading.HEADING1).setAlignment(DocumentApp.HorizontalAlignment.CENTER);
table = body.appendTable(srcData);
table.getRow(0).editAsText().setBold(true);
}
The script works but I have a few issues all related to this section of the code
var srcData = ssn.getRange("A1:E50").getDisplayValues();
body.insertParagraph(0, 'Invoice').setHeading(DocumentApp.ParagraphHeading.HEADING1).setAlignment(DocumentApp.HorizontalAlignment.CENTER);
table = body.appendTable(srcData);
table.getRow(0).editAsText().setBold(true);
}
Firstly, Cell A1 should be "Name" but for some reason it is generating a numerical value. Also, not all the values in the range "A1:E50" are populated, is there a way of adding in 5 standardise headings then pull data from A2:E? As row A1:E are just headings I would like it so the script will only pull in each row A:E if there is a value in cell A of each row. Finally, I would like it to generate an empty column to the right of the table in the doc. I would select the range to be "A1:F50" but F has cells that contain data that isn't relevant to the generated table.
I have tried using this instead
var srcData = ssn.getRange("A1:E50,S1:S").getDisplayValues();
body.insertParagraph(0, 'Invoice').setHeading(DocumentApp.ParagraphHeading.HEADING1).setAlignment(DocumentApp.HorizontalAlignment.CENTER);
table = body.appendTable(srcData);
table.getRow(0).editAsText().setBold(true);
> }
As Column S is empty but the script breaks.
I can't help you with why the name is a number. getDisplayValues() should return a string if the name is a string. But for the rest try this.
// start with row 2
var srcData = ssn.getRange("A2:E50").getDisplayValues();
srcData = srcData.filter( row => row[0] !== "" );
srcData.forEach( row => row.push("") );
Reference
Array.filter()
Array.forEach()
Arrow function

Function Keeps Looping After Last Row

I am using the following code to fill a Google Docs template with data pulled from a spreadsheet.
function createBulkMembershipCards() {
const template = DriveApp.getFileById("--------");
const docFolder = DriveApp.getFolderById("----------");
const pdfFolder = DriveApp.getFolderById("----------------");
const libroSoci = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("LibroSoci");
const data = libroSoci.getRange(352, 1, libroSoci.getLastRow()-1,19).getDisplayValues();
data.forEach(row => {
createMembershipCard (row[3],row[4],row[0],row[1], row[6],template,docFolder,pdfFolder);
});
}
function createMembershipCard (name,surname,msnumber,timestamp, email,template,docFolder,pdfFolder) {
const file = template.makeCopy(docFolder);
const docFile = DocumentApp.openById(file.getId());
const body = docFile.getBody();
body.replaceText("{name}", name);
body.replaceText("{surname}", surname);
body.replaceText("{msnumber}", msnumber);
body.replaceText("{timestamp}", timestamp);
body.replaceText("{email}", "<<"+email+">>");
docFile.saveAndClose();
docFile.setName(msnumber+" "+name+" "+surname);
const pdfBlob = docFile.getAs(MimeType.PDF);
pdfFolder.createFile(pdfBlob).setName(msnumber+" "+name+" "+surname);
}
I do not understand why, even though I used "getLastRow", the function keeps going on indefinitely after the last populated row.
Please not that I put 352 as the starting row because I want to extract data from that row on.
Is anyone able to help?
Thank you!
Let's say getLastRow() returns 1000. Then you are getting 999 rows. What you want is 1000-351 rows.
Change
const data = libroSoci.getRange(352, 1, libroSoci.getLastRow()-1,19).getDisplayValues();
To
const data = libroSoci.getRange(352, 1, libroSoci.getLastRow()-351,19).getDisplayValues();

Randomize rows when google doc is opened

I am trying to create a petition with a google form and doc. I've found an app script that will take the responses from the form and input them into a table on the doc. To help reduce the bias early respondents may face, I am trying to develop a script that will randomize the rows of the table every time the document is opened. Trying to scramble the signatures so that the same signatures aren't always at the top (can't be targeted).
Can anyone help me with this?
Below is the code I am using to populate the table from the form
//Since there could be a bunch of people submitting, we lock the script with each execution
//with a 30 second timeout so nothing gets overwritten
const lock = LockService.getScriptLock();
lock.waitLock(30000);
//Here we read the variables from the form submission event
const date = new Date(e.values[0]).toLocaleDateString();
//of you can use toLocaleString method if you want the time in the doc
const name = e.values[1];
const employeeNumber = e.values[2];
var form = FormApp.openById('');
const num = form.getResponses().length;
var num1 = num.toString()
//Next format those values as an array that corresponds to the table row layout
//in your Google Doc
const tableCells = [num1,name,employeeNumber]
//Next we open the letter and get its body
const letter = DocumentApp.openById('')
const body = letter.getBody();
//Next we get the first table in the doc and append an empty table row
const table = body.getTables()[0]
const tableRow = table.appendTableRow()
//Here we loop through our table cells from above and add
// a table cell to the table row for each piece of data
tableCells.forEach(function(cell, index){
let appendedCell = tableRow.appendTableCell(cell)
})
//here we save and close our letter and then release a lock
letter.saveAndClose();
lock.releaseLock();
}
Got this from a helpful vimeo tutorial by Abhishek Narula and Rebekah Modrak.
Randomize row in a google document table
First function Creates a table in a google document from a table in a spreadsheet
function creatTable() {
const style1 = {};
style1[DocumentApp.Attribute.HORIZONTAL_ALIGNMENT]=DocumentApp.HorizontalAlignment.RIGHT;
const ss = SpreadsheetApp.openById("ssid");
const sh = ss.getSheetByName('Sheet0');
const tA = sh.getDataRange().getValues();
const doc = DocumentApp.getActiveDocument();
let body = doc.getBody();
body.clear();
let n = body.getNumChildren();
for(let i =0;i<n-1;i++) {
if(i==0) {
body.getChild(i).asText().setText('');
} else {
body.getChild(i).removeFromParent()
}
}
let table=body.appendTable(tA).setAttributes(style1);
}
Second function reads the table from the document and randomizes the rows it and reloads the table. This function actually searches through all of the children to find a table. If there is more than one table it will randomize all of them so it will need to be modified to integrate with your specific document.
This now removes the first line and then randomizes the array and then adds the first line back
function readandrandomizetable() {
const style1 = {};
style1[DocumentApp.Attribute.HORIZONTAL_ALIGNMENT] = DocumentApp.HorizontalAlignment.RIGHT;
const doc = DocumentApp.getActiveDocument();
let body = doc.getBody();
let vs = [];
let fl = '';
[...Array.from(new Array(body.getNumChildren()).keys())].forEach(idx => {
let ch = body.getChild(idx);
if (ch.getType() == DocumentApp.ElementType.TABLE) {
Logger.log(`This is the index I want: ${idx}`);
let tbl = ch.asTable();
[...Array.from(new Array(tbl.getNumRows()).keys())].forEach(ridx => {
let s = tbl.getRow(ridx).getText().split('\n');
//Logger.log(JSON.stringify(s));
vs.push(s);
});
Logger.log(JSON.stringify(vs));
fl = vs.shift();
vs.sort((a, b) => {
vA = Math.floor(Math.random() * 100);
vB = Math.floor(Math.random() * 100);
return vA - vB;
});
vs.unshift(fl);
}
});
Logger.log(JSON.stringify(vs));
body.clear();
let n = body.getNumChildren();
for (let i = 0; i < n - 1; i++) {
if (i == 0) {
body.getChild(i).asText().setText('');
} else {
body.getChild(i).removeFromParent()
}
}
body.appendTable(vs).setAttributes(style1);
}

exceeded maximum execution time, google sheet, how to improve it?

Good morning, everyone,
I come to see you because after having fought hard to make my google script work, on the execution page I see that my script works, however on my google sheet I have an error: "Exceeded maximum execution time". I've seen on the internet that for custom google script functions only leave 30 sec of execution, I'm not sure how to do that? add code to tweak this feature? I confess that I didn't understand the difference between a custom function and a google app script but I know that there is 6 minutes of execution time for scripts... here is an extract of my code:
// Standard functions to call the spreadsheet sheet and activesheet
function GetPipedriveDeals2() {
let ss = SpreadsheetApp.getActiveSpreadsheet();
let sheets = ss.getSheets();
let sheet = ss.getActiveSheet();
//the way the url is build next step is to iterate between the end because api only allows a fixed number of calls (100) this way i can slowly fill the sheet.
let url = "https://laptop.pipedrive.com/v1/products:(id)?start=";
let limit = "&limit=500";
//let filter = "&filter_id=64";
let pipeline = 1; // put a pipeline id specific to your PipeDrive setup
let start = 1;
//let end = start+50;
let token = "&api_token=XXXXXXXXXXXXXXXXXXXXXXXX"
let response = UrlFetchApp.fetch(url+start+limit+token); //
let dataAll = JSON.parse(response.getContentText());
let dataSet = dataAll;
//let prices = prices;
//create array where the data should be put
let rows = [], data;
for (let i = 0; i < dataSet.data.length; i++) {
data = dataSet.data[i];
rows.push([data.id,
GetPipedriveDeals4(data.id)
]);
}
Logger.log( 'function2' ,JSON.stringify(rows,null,8) ); // Log transformed data
return rows;
}
// Standard functions to call the spreadsheet sheet and activesheet
function GetPipedriveDeals4(idNew) {
let ss = SpreadsheetApp.getActiveSpreadsheet();
let sheets = ss.getSheets();
let sheet = ss.getActiveSheet();
//the way the url is build next step is to iterate between the end because api only allows a fixed number of calls (100) this way i can slowly fill the sheet.
let url = "https://laptop.pipedrive.com/v1/products/"+idNew+"/deals:(id,d93b458adf4bf84fefb6dbce477fe77cdf9de675)?start=";
let limit = "&limit=500";
//let filter = "&filter_id=64";
let pipeline = 1; // put a pipeline id specific to your PipeDrive setup
let start = 1;
//let end = start+50;
let token = "&api_token=XXXXXXXXXXXXXXXXXXXXXX"
let response = UrlFetchApp.fetch(url+start+limit+token); //
let dataAll = JSON.parse(response.getContentText());
let dataSet = dataAll;
//Logger.log(dataSet)
//let prices = prices;
//create array where the data should be put
let rows = [], data;
if(dataSet.data === null )return
else {
for (let i = 0; i < dataSet.data.length; i++) {
data = dataSet.data[i];
let idNew = data.id;
rows.push([data.id, data['d93b458adf4bf84fefb6dbce477fe77cdf9de675']]);
}
Logger.log( 'function4', JSON.stringify(rows,null,2) ); // Log transformed data
return rows;
}
}
Thank you all in advance.
EDIT : --------------------------FOR EACH LOOP----------------------------
function getPipedriveDeals(start = 0,apiRequestLimit = 39) {
console.log("start="+start);
//Make the initial request to get the ids you need for the details.
var idsListRequest = "https://laptop.pipedrive.com/v1/products:(id)?start=";
var limit = "&limit=" + apiRequestLimit;
var token = "&api_token=XXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
var response = UrlFetchApp.fetch(idsListRequest + start + limit + token);
var data = JSON.parse(response.getContentText()).data;
//For every id in the response, construct a url (the detail url) and push to a list of requests
var requests = [];
console.log("data="+data);
data.forEach(function(product) {
var productDetailUrl = "https://laptop.pipedrive.com/v1/products/" + product.id + "/deals:(id,d93b458adf4bf84fefb6dbce477fe77cdf9de675)?start=";
requests.push(productDetailUrl + start + limit + token)
});
//With the list of detail request urls, make one call to UrlFetchApp.fetchAll(requests)
var responses = UrlFetchApp.fetchAll(requests);
return [responses,JSON.parse(responses[0].getContentText()).additional_data.pagination.more_items_in_collection];
}
function getAllDeals(){
var allResponses = [];
for(var i = 0; i<500; ){
var deals = getPipedriveDeals(start=i);
deals[0].forEach((response)=>{allResponses.push(response)});
if(deals[1]){
// If there are more items sleep for 1000 milliseconds
Utilities.sleep(1000);
i+=39;
}
else{
console.log("No more items in collection.");
break;
}
}
console.log("allResponses="+allResponses);
return allResponses;
}
About the weird behavior in the logs :
-------------------------------EDIT Number2----------------------------------
Until now when I executed =getPipedriveDeals()it return False (like I was saying in my comment) and also when I try to remove additional_data.pagination.more_items_in_collection (Because it's not very usefull for me) I don't know why but the script won't work anymore, and I have some difficulties to select the data I want to return.
You can use UrlFetchApp.fetchAll(requests) to save in quotas and likely a lot in script execution duration.
I have removed a few redundancies in your code to make this following example showing the use of fetchAll for your case.
Example:
function getPipedriveDeals(start = 0,apiRequestLimit = 50) {
console.log("start="+start);
//Make the initial request to get the ids you need for the details.
var idsListRequest = "https://laptop.pipedrive.com/v1/products:(id)?start=";
var limit = "&limit=" + apiRequestLimit;
var token = "&api_token=xxxxxxxxxxx";
var response = UrlFetchApp.fetch(idsListRequest + start + limit + token);
var data = JSON.parse(response.getContentText()).data;
//For every id in the response, construct a url (the detail url) and push to a list of requests
var requests = [];
console.log("data="+data);
data.forEach(function(product) {
var productDetailUrl = "https://laptop.pipedrive.com/v1/products/" + product.id + "/deals:(id,d93b458adf4bf84fefb6dbce477fe77cdf9de675)?start=";
requests.push(productDetailUrl + start + limit + token)
});
//With the list of detail request urls, make one call to UrlFetchApp.fetchAll(requests)
var responses = UrlFetchApp.fetchAll(requests);
return [responses,JSON.parse(responses[0].getContentText()).additional_data.pagination.more_items_in_collection];
}
Now suppose you have a plan that limits the quota to 50 requests per 2 seconds.
You could make the limit of requests in the fetchAll call to 50, and introduce a delay/sleep of (X) milliseconds to initiate a second request, starting with id=50 like:
function getAllDeals(){
var allResponses = [];
for(var i = 0; i<500; ){
var deals = getPipedriveDeals(start=i);
deals[0].forEach((response)=>{allResponses.push(response)});
if(deals[1]){
// If there are more items sleep for 1000 milliseconds
Utilities.sleep(1000);
i+=50;
}
else{
console.log("No more items in collection.");
break;
}
}
console.log("allResponses="+allResponses);
return allResponses;
}