First, here is the link from my Google Sheet:
https://docs.google.com/spreadsheets/d/1vROojeTBYnSQy0IeYY0vkzump-CPoDd5fyFuLwRZsjQ/edit?usp=sharing
I have 2 sheets: one (Sheet1) which contains a list of machines with an IP address, a Hostname and a switch port. The objective of my script is to read the switch and the port of sheet 1, then put a note in the corresponding cell in sheet 2 (sheet 2 contains the diagram of the switches available with their 48 ports), the note must contain hostname and IP address.
The script works but adds the notes one by one, and it might take more than 30 minutes if my number of machines increases.
Do you have an idea to speed up the process?
CodePudding user response:
Issue:
You're currently iterating through the source values in Sheet1
and using TextFinder to find the corresponding cells in Sheet2
. Using TextFinder
iteratively greatly increases the amount of requests to the spreadsheet, and that slows down the script a lot (see Minimize calls to other services).
Along the same lines, you are setting the notes for each cell individually via setNote, instead of setting all of them at once with setNotes(notes), as Sergey said.
Solution:
I'd like to propose an alternative approach to minimize calls to the spreadsheet and so make the script considerably faster:
- Retrieve the useful data from
Sheet1
(note
,switch
andport
), converting it to an array of objects for easier later retrieval. - Retrieve all the data in
Sheet2
using getDataRange() and getValues(). - Using map, iterate through the data in
Sheet2
, and for each row, check if either column A of the current row (for oddport
numbers) or from two rows above (for evenport
numbers) contain a validswitch
name (you can use find for that). - If no valid
switch
name is found, return an array ofnull
for thismap
iteration (since providingnull
as a parameter tosetNote
removes the note). - If a valid
switch
name is found, iterate through that row's ports usingmap
, and for eachport
, look for the valid combination ofswitch
andport
in the source data. - If a valid combination of
switch
andport
is found, return the correspondingnote
for thatmap
iteration. - If a valid combination is not found (that is,
Sheet1
doesn't contain data for that combination), returnnull
for that iteration. - Once you have build the 2D array of
notes
using the corresponding nestedmaps
, set those notes to theport
columns fromSheet2
, usingsetNotes
.
Code sample:
function actualiserNP2(){
const SWITCH_COL = 1;
const PORT_FIRST_COL = 4;
const PORT_LAST_COL = 27;
const ss = SpreadsheetApp.getActiveSpreadsheet();
const Sheet2 = ss.getSheetByName('Sheet2');
const Sheet1 = ss.getSheetByName('Sheet1');
const tabGeneral = Sheet1.getRange(10,2, Sheet1.getLastRow(), Sheet1.getLastColumn()).getValues();
const sourceData = tabGeneral.filter(row => row[7].includes("#")).map(row => {
const [sw1a, sw1b] = row[7].split("#");
const data = {
"note": `${row[0]}\n\n${row[5]}`,
"switch": sw1a,
"port": sw1b
}
return data;
});
const targetData = Sheet2.getDataRange().getValues();
const notes = targetData.map((row,i) => {
const sourceSwitch = sourceData.find(sourceRow => sourceRow["switch"] === row[SWITCH_COL-1] || (i > 1 && sourceRow["switch"] === targetData[i-2][SWITCH_COL-1]));
if (sourceSwitch) {
const currentSwitch = sourceSwitch["switch"];
const ports = row.slice(PORT_FIRST_COL-1, PORT_LAST_COL);
const rowNotes = ports.map(port => {
const sourceRow = sourceData.find(row => row["switch"] === currentSwitch && Number(row["port"]) === Number(port));
if (sourceRow) return sourceRow["note"];
else return null;
});
return rowNotes;
} else {
return new Array(PORT_LAST_COL-PORT_FIRST_COL 1).fill(null);
}
});
Sheet2.getRange(1, PORT_FIRST_COL, Sheet2.getLastRow(), PORT_LAST_COL-PORT_FIRST_COL 1).setNotes(notes);
}
CodePudding user response:
I modified lamblichus's script to adapt it to the 3 ports. It works with this new script :
function actualiserNP1()
{
const SWITCH_COL = 1;
const PORT_FIRST_COL = 4;
const PORT_LAST_COL = 27;
const ss = SpreadsheetApp.getActiveSpreadsheet();
const Sheet2 = ss.getSheetByName('Sheet2');
const Sheet1 = ss.getSheetByName('Sheet1');
const tabGeneral = Sheet1.getRange(10,2, Sheet1.getLastRow(), Sheet1.getLastColumn()).getValues();
const data = [];
const sourceData = tabGeneral.filter(row => row[7].includes("#") || row[11].includes("#") || row[15].includes("#")).map(row => { // On filtre les lignes ayant au moins un port
//§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ 001
if(row[7]=='' && row[11]=='' && row[15]!='')
{
if(row[13]!=''){
const [sw3a, sw3b] = row[15].split("#");
data.push({
"note": `${row[0]}\n\n${row[13]}`,
"switch": sw3a,
"port": sw3b
})
}else{
const [sw3a, sw3b] = row[15].split("#");
data.push({
"note": `${row[0]}\n\n${row[5]}`,
"switch": sw3a,
"port": sw3b
})
}
}
//§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ 010
if(row[7]=='' && row[11]!='' && row[15]=='')
{
if(row[9]!=''){
const [sw2a, sw2b] = row[11].split("#");
data.push({
"note": `${row[0]}\n\n${row[9]}`,
"switch": sw2a,
"port": sw2b
})
}else{
const [sw2a, sw2b] = row[11].split("#");
data.push({
"note": `${row[0]}\n\n${row[5]}`,
"switch": sw2a,
"port": sw2b
})
}
}
//§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ 011
if(row[7]=='' && row[11]!='' && row[15]!='')
{
if(row[9]!=''){
const [sw2a, sw2b] = row[11].split("#");
data.push({
"note": `${row[0]}\n\n${row[9]}`,
"switch": sw2a,
"port": sw2b
})
}else{
const [sw2a, sw2b] = row[11].split("#");
data.push({
"note": `${row[0]}\n\n${row[5]}`,
"switch": sw2a,
"port": sw2b
})
}
// $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
if(row[13]!=''){
const [sw3a, sw3b] = row[15].split("#");
data.push({
"note": `${row[0]}\n\n${row[13]}`,
"switch": sw3a,
"port": sw3b
})
}else{
const [sw3a, sw3b] = row[15].split("#");
data.push({
"note": `${row[0]}\n\n${row[5]}`,
"switch": sw3a,
"port": sw3b
})
}
}
//§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ 100
if(row[7]!='' && row[11]=='' && row[15]=='')
{
const [sw1a, sw1b] = row[7].split("#");
data.push({
"note": `${row[0]}\n\n${row[5]}`,
"switch": sw1a,
"port": sw1b
})
}
//§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ 101
if(row[7]!='' && row[11]=='' && row[15]!='')
{
if(row[13]!=''){
const [sw3a, sw3b] = row[15].split("#");
data.push({
"note": `${row[0]}\n\n${row[13]}`,
"switch": sw3a,
"port": sw3b
})
}else{
const [sw3a, sw3b] = row[15].split("#");
data.push({
"note": `${row[0]}\n\n${row[5]}`,
"switch": sw3a,
"port": sw3b
})
}
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
const [sw1a, sw1b] = row[7].split("#");
data.push({
"note": `${row[0]}\n\n${row[5]}`,
"switch": sw1a,
"port": sw1b
})
}
//§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ 110
if(row[7]!='' && row[11]!='' && row[15]=='')
{
if(row[9]!=''){
const [sw2a, sw2b] = row[11].split("#");
data.push({
"note": `${row[0]}\n\n${row[9]}`,
"switch": sw2a,
"port": sw2b
})
}else{
const [sw2a, sw2b] = row[11].split("#");
data.push({
"note": `${row[0]}\n\n${row[5]}`,
"switch": sw2a,
"port": sw2b
})
}
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
const [sw1a, sw1b] = row[7].split("#");
data.push({
"note": `${row[0]}\n\n${row[5]}`,
"switch": sw1a,
"port": sw1b
})
}
//§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§§ 111
if(row[7]!='' && row[11]!='' && row[15]!='')
{
if(row[9]!=''){
const [sw2a, sw2b] = row[11].split("#");
data.push({
"note": `${row[0]}\n\n${row[9]}`,
"switch": sw2a,
"port": sw2b
})
}else{
const [sw2a, sw2b] = row[11].split("#");
data.push({
"note": `${row[0]}\n\n${row[5]}`,
"switch": sw2a,
"port": sw2b
})
}
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
if(row[13]!=''){
const [sw3a, sw3b] = row[15].split("#");
data.push({
"note": `${row[0]}\n\n${row[13]}`,
"switch": sw3a,
"port": sw3b
})
}else{
const [sw3a, sw3b] = row[15].split("#");
data.push({
"note": `${row[0]}\n\n${row[5]}`,
"switch": sw3a,
"port": sw3b
})
}
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
const [sw1a, sw1b] = row[7].split("#");
data.push({
"note": `${row[0]}\n\n${row[5]}`,
"switch": sw1a,
"port": sw1b
})
}
return data;
});
console.log(data)
//console.log(sourceData);
const targetData = Sheet2.getDataRange().getValues();
const notes = targetData.map((row,i) => {
const sourceSwitch = data.find(sourceRow => sourceRow["switch"] === row[SWITCH_COL-1] || (i > 1 && sourceRow["switch"] === targetData[i-2][SWITCH_COL-1]));
if (sourceSwitch)
{
const currentSwitch = sourceSwitch["switch"];
const ports = row.slice(PORT_FIRST_COL-1, PORT_LAST_COL);
const rowNotes = ports.map(port => {
const sourceRow = data.find(row => row["switch"] === currentSwitch && Number(row["port"]) === Number(port));
if (sourceRow) return sourceRow["note"];
else return null;
});
return rowNotes;
} else {
return new Array(PORT_LAST_COL-PORT_FIRST_COL 1).fill(null);
}
});
Sheet2.getRange(1, PORT_FIRST_COL, Sheet2.getLastRow(), PORT_LAST_COL-PORT_FIRST_COL 1).setNotes(notes);
}
I am a begginer so i did instructions for each possible case.