getting code to run on multiple sheets in a spreadsheet - javascript

I have 4 sheets in my GoogleSheets spreadsheet.
I need the code below to run on every sheet EXCEPT the one called "MRS summary".
I can't seem to get that 'for' loop (the one with the 'g' variable) to work though, because the code only runs for the ACTIVE sheet. But I do know that the Logger.log(g) line is picking up the right indexes...so I think the 'for g' loop is working in the sense that it knows what sheets to look at, but the rest of the code only does what it's supposed to do on the ACTIVE sheet....but I need it to run on every sheet except the one called "MRS summary". Any thoughts?
function SearchCols()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
skip = ['MRS summary'];
for (var g = 0, len3 = sheets.length; g < len3; g++)
{
var name = sheets[g].getName()
if (skip.indexOf(name) > -1) continue;
{
var expen = ss.getSheetByName("MRS summary")
var sheet1 = expen.getRange("A13:A210").getValues();
var searchCol1 = expen.getRange ('B13:B210').getValues();
var searchCol2 = expen.getRange ('A13:A210').getValues();
var searchCol3 = expen.getRange('C13:C210').getValues();
var searchCol4 = expen.getRange('D13:D210').getValues();
var searchCol = ss.getRange('A13:A210').getValues();
var searchVal = ss.getRange('B4').getValue();
for (var i = 0, len = searchCol2.length; i < len; i++)
for (var j = 0, len2 = searchCol1.length; j < len2; j++)
{
if (searchCol2[j][0] == searchVal && searchCol1[j][0] ==
searchCol[i][0])
{
col1[g].getRange(i + 13, 4).setValue(searchCol3[j][0])
col1[g].getRange(i + 13, 5).setValue(searchCol4[j][0])
}
}
}
Logger.log(g);
}
}

Related

Null value returned by a Google sheet regex

I am trying to write a script in Google sheet that should extract a piece of a string using a regex.For example if I have "test test $1.00 test test" I would like to extract only "1.00"
What I have done so far is:
function myFunction() {
var regExp = new RegExp("\$(.*)\s+");
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var range = sheet.getDataRange();
var values = range.getValues();
var item_description = 0;
var quantity = 1;
var quantity_flat = [];
var item_flat = [];
for (var j = 0; j < values[quantity].length; j++) {
if (values[quantity][j] == "") {
quantity_flat.push(0);
} else {
quantity_flat.push(values[quantity][j]);
}
}
for (var j = 0; j < values[item_description].length; j++) {
var test = regExp.exec(values[item_description][j]);
item_flat.push(test);
}
}
When I check the type of test, I get that it is an Object and has a value of null.
Not sure where is the error. Ideally, I would like to get back a number so that I can push it in an array.
Thanks!

Concatenation Code runs excruciatingly slowly google script

My Concatenation function is running excruciatingly slow, on only 28 rows of data it takes almost 4 minutes to run and I have other code I need to run so I hit the Max execution time in Google sheets
If I was running a similar process in Excel this would take maybe 15-30 sec
Everything is in memory, I can't see (with my limited knowledge of javascript) why my code is so slow
Thanks
A Google sheet with data
//Sheet Name
//Values in Range to be overwritten by Header names
//List of Header names
//New Header Name 1
//New Header Name 2
function AsAboveSoBelow_Offers_Asks() {
AsAboveSoBelow('Elements',
["I can offer", "I have a ask"],
["Header1","Header2","Header3","Header4","Header5","Header6",
"Header7","Header8","Header9","Header10","Header11",
"Header12","Header13","Header14"],
"Offers",
"Asks");
}
function AsAboveSoBelow(shtName, arrPBV, arrHeaders, newHeader1, newHeader2) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName(shtName);
var LC = s.getLastColumn();
var r = s.getDataRange();
var v = r.getValues();
var start = new Date();
var temp ="";
//Dim A
var A = [];
for (var i = 0; i < v.length; i++) {
A[i] = [];
for (var j = 0; j <= arrPBV.length - 1; j++) {
A[i][j] = '';
}
}
for(var e = 0; e <= arrPBV.length - 1; e++) {
var search_Term = arrPBV[e];
for(var row = 0; row < v.length; row++) {
for(var col = 0; col <= arrHeaders.length - 1; col++) {
var col2 = HTN(shtName,arrHeaders[col])
var replace_Term = arrHeaders[col];
if(v[row][col2-1].toString().indexOf(search_Term) > -1) {
temp = temp + replace_Term + "|"
}
}
//remove trailing pipe
A[row][e] = temp.replace(/\|(?=\s*$)/, '')
temp = ""
}
}
A[0][0]= newHeader1
A[0][1]= newHeader2
s.getRange(1, v[0].length +1, v.length,A[0].length).setValues(A);
var end = new Date();
var executiontime = end - start;
Logger.log(executiontime);
};
//Helper function
function HTN(shtName,cheader){
var headers =
SpreadsheetApp.getActiveSpreadsheet().getSheetByName(shtName).getDataRange().getValues().shift();
var colindex = headers.indexOf(cheader);
return colindex+1;
}
You want to reduce the process cost of your script.
If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
Modification point:
In your script, HTN() is used as the for loops. And the function includes SpreadsheetApp.getActiveSpreadsheet().getSheetByName(shtName).getDataRange().getValues().shift();. In your script, the Spreadsheet and sheetName are not changed. So headers is always same. I thought that this might be the main modification point.
Modified script:
Please modify your script as follows.
function AsAboveSoBelow_Offers_Asks() {
AsAboveSoBelow(
'Elements',
["I can offer", "I have a ask"],
["Header1","Header2","Header3","Header4","Header5","Header6","Header7","Header8","Header9","Header10","Header11","Header12","Header13","Header14"],
"Offers",
"Asks"
);
}
function AsAboveSoBelow(shtName, arrPBV, arrHeaders, newHeader1, newHeader2) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName(shtName);
// var LC = s.getLastColumn(); // It seems that this is not used.
var r = s.getDataRange();
var v = r.getValues();
var start = new Date();
var temp ="";
//Dim A
var A = [];
for (var i = 0; i < v.length; i++) {
A[i] = [];
for (var j = 0; j <= arrPBV.length - 1; j++) {
A[i][j] = '';
}
}
var h = s.getRange(1, 1, 1, s.getLastColumn()).getValues()[0]; // Added
for(var e = 0; e <= arrPBV.length - 1; e++) {
var search_Term = arrPBV[e];
for(var row = 0; row < v.length; row++) {
for(var col = 0; col <= arrHeaders.length - 1; col++) {
var col2 = h.indexOf(arrHeaders[col]) + 1; // Modified
var replace_Term = arrHeaders[col];
if(v[row][col2-1].toString().indexOf(search_Term) > -1) {
temp = temp + replace_Term + "|"
}
}
//remove trailing pipe
A[row][e] = temp.replace(/\|(?=\s*$)/, '')
temp = ""
}
}
A[0][0]= newHeader1
A[0][1]= newHeader2
s.getRange(1, v[0].length +1, v.length,A[0].length).setValues(A);
var end = new Date();
var executiontime = end - start;
Logger.log(executiontime);
};
Note:
In my environment, the process time of the modified script was about 5 seconds.
If this was not the direct solution, I apologize.

Altering find and replace Google Sheets script

I have the following script, though I would like to change it to only find and replace on a specific sheet (Sheet4!A:AB).
How would I go about doing this:
function fandr() {
var ss=SpreadsheetApp.getActiveSpreadsheet();
var s=ss.getActiveSheet();
var r=s.getDataRange();
var vlst=r.getValues();
var i,j,a,find,repl;
find="abc";
repl="xyz";
for (i in vlst) {
for (j in vlst[i]) {
a=vlst[i][j];
if (a==find) vlst[i][j]=repl;
}
}
r.setValues(vlst);
}
I think that pnuts's comment is helpful for your situation. If you are still looking for your solution, how about this answer? You want to find and replace the values in Sheet4!A:AB. If my understanding is correct, I would like to propose 2 patterns. I think that there are several solution for your situation. So please think of this as one of them.
Pattern 1
This modification is a simple modification. It modified the range for retrieving values to Sheet4!A:AB.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var r = ss.getRange("Sheet4!A:AB");
var vlst = r.getValues();
var i, j, a, find, repl;
find = "abc";
repl = "xyz";
for (var i = 0; i < vlst.length; i++) {
for (var j = 0; j < vlst[i].length; j++) {
a = vlst[i][j];
if (a == find) vlst[i][j] = repl;
}
}
r.setValues(vlst);
Pattern 2
In the case of pattern 1, the values retrieved by getRange("Sheet4!A:AB") includes the empty rows. By this, the search speed becomes slow. So in this pattern 2, the data range of "A1:AB" is retrieved using getLastRow().
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName("Sheet4");
var r = s.getRange("A1:AB" + s.getLastRow());
var vlst = r.getValues();
var i, j, a, find, repl;
find = "abc";
repl = "xyz";
for (var i = 0; i < vlst.length; i++) {
for (var j = 0; j < vlst[i].length; j++) {
a = vlst[i][j];
if (a == find) vlst[i][j] = repl;
}
}
r.setValues(vlst);
References :
getSheetByName()
getRange(a1Notation)
getLastRow()
If I misunderstand what you want, please tell me. I would like to modify it.

Get the first empty row in multidimensionnal array

I have a question about a function where I'm trying to get a first look at a multidimensional array.
To explain my problem: In a sheet, I manage my roadmap with projects. A project is composed by 4 rows where I have some information (Project Name, Estimated Team, Timeline ...).
And In my timeline, I need to retrieve the first empty rows in multiple arrays (the first non empty is the startDate).
The problem, I have 4 teams in this multidimensional array, and (for example), the start date can be in the 1st team array for the project A, but the start date can be also in the 3rd team array for the project B.
In my function, I'm trying to get to the start date, but my first step is to check the first array ... (projectRange and after in the code)
So ... I think the best way should be check every rows in the first column, and continue like this to the getLastColumn, right?
So, how can I manage my Loop with this way?
function findLastRow(column) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName(roadmapSS);
var startRow = 11;
var startCol = 11;
var dataLength = sheet.getLastRow()-(startRow+2);
var rangeData = sheet.getRange(startRow, 2, sheet.getLastRow(), sheet.getLastColumn());
var dataValues = rangeData.getValues();
var projectsList = rangeData.getValues();
var projectDatas = {};
var projectRange = null;
var projectName = null;
var projectPlan = {};
var realStart = null;
for (var i = 0; i < dataLength; i+=4) {
projectDatas = projectsList[i];
var step = startRow+i;
var realStartRange = startRow+i+1
for (var j = 0; j < 1; j+=4) {
projectName = projectDatas[j];
}
projectRange = ([step, startCol, 4, sheet.getLastColumn()]).toString();
var projectPlan = sheet.getRange(step, startCol, 4, sheet.getLastColumn()).getValues();
for (var k = 0; k < projectPlan.length; ++k) {
realStart = projectPlan[k];
for (var l = 0; l < realStart.length; ++l) {
if (realStart[l] != '') {
break;
}
}
}
//sheet.getRange(realStartRange, 2).setValue(columnToLetter([l]))
console.log(projectName, [l], columnToLetter([l]));
}
}
In fact, i'm trying to get the first column of B in this example (because it's the first non empty occurence :
var projectTimeline = [
['','','A','A','','A'],
['','B','B','','B',''],
['','','','C','C',''],
['','','','','D','D']
]
I found my solution :
I throughed the column first, and then the row. It worked, I founded the column :)
function findFirstDate (timeline) {
for (var col = 0; col < timeline[0].length; col++) {
for (var row = 0; row < 4; row++) {
if (timeline[row][col] != '') {
return [col];
}
}
}
}

how to set two variables for a for loop - Javascript

I want to set two variables in a for loop in JavaScript.
function onOpen(cf) {
var ss = SpreadsheetApp.getActive();
var startRow = 2; // First row of data to process
var numRows = 4;
var sheet1 = ss.getSheetByName("Sheet1");
//for (var n in ss.getSheets()){ {
for (var ree = startRow, n in ss.getSheets(); ree <= numRows; ree++){ {
var rangeToCheck = sheet1.getRange(ree, 1);// column D in row ree
var accesslist = sheet1.getRange(ree,2);
var namee = rangeToCheck.getValue();
var folder = DriveApp.createFolder(namee);
This doesn't seem to work. Does anyone know any alternatives?
So you just need one variable, because they are proportional:
var sssheets=ss.getSheets();//performance improvement
var ssoffset=0;// i think its -1 in your examples
for(var ree=1;ree<=numRows && ree-ssoffset<sssheets.length; ree++){
var sheet = sssheets[ree-ssofset];
...
}

Categories