Substring comparison across columns within Google Apps Script - google-apps-script

I have a large dataset pasted into Google Sheets. I want to compare two columns in this sheet.
The first column is filled with long strings, I only care about the first character in each cell in this column.
The second column is text-based. I want to paste data into a new sheet if the string in column A starts a number (not a letter) and the text in column B is "Early".
My challenge is using Javascript to get only the substring of 1 character for column A. The error is "TypeError: str.substring is not a function." I have also tried slice() as well to no effect. Is this not supported in Apps Script?
How can I isolate those first characters and then compare alongside the other column?
I also then need to push the rows that meet this criteria in both columns to a new tab.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('data');
var str = sheet.getRange('A:A').getValues();
var char = str.substring(0,2);
var stage = sheet.getRange('B:B');
var endColumn = sheet.getLastColumn();
var value_stage = (stage.getValues());
var value_char = (char.getValues());
var csh = ss.getSheetByName('new_sheet'); //destination sheet
var data = [];
var j =[];
for (i=0; i<value_char.length;i++) {
if
(
(
( value_char[i] == '0') ||
( value_char[i] == '1') ||
( value_char[i] == '2') ||
( value_char[i] == '3') || etc... )
&&
( value_stage[i] == 'Early')
)
data.push.apply(data,sheet.getRange(i+1,1,1,endColumn).getValues());
j.push(i);
}
}
csh.getRange(csh.getLastRow()+1,1,data.length,data[0].length).setValues(data);
SAMPLE DATA BELOW:
**ID** **Stage** **Name**
A texthere Early Bob
B abcdefgh Late Sally
52 texthere Early Jim
C thesdfas Late Allan
00 tsdfsdfd Late Susan
11 qqwerrww Early Ryan
Q tsdfsagd Early Sarah
98 fdsafads Early Evan
09 fdasfdsa Early Paul
10 abcdefgh New Megan
10 abcdefgh Early Cooper
NOTE: in the real dataset, columns A and B are actually K & L
And the ID column has those spaces between the early part of the string and the end. This is what I am trying to slice off

Try this:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh=ss.getSheetByName('data');
var svs=sh.getRange(1,2,sheet.getLastRow(),2).getValues();
var csh=ss.getSheetByName('new_sheet');
var data=[];
var j=[];
svs.forEach(function(r,i){
if((r[0].slice(0,1)=='1' || r[0].slice(0,1)=='2') && r[1]=='Early') {
//do what you want in here
}
});

Related

How to ignore empty cells and change column order when copying data using Google Apps Script

I'm trying to write a script to paste rows of cells from one sheet to another while ignoring rows with blank cells in Column A. The script would also swap the order of Columns B and C. Here is what I am trying to do:
INPUT Sheet....................................OUTPUT Sheet
A1= ID B1= Last Name C1 = MI A1= ID B1 = MI C1= Last Name
A2= 1 B2= Stewart C2= M................A2= 1 B2= M C2= Stewart
A3= B3= Smith C3= R................A3= 4 B3= V C3= Holland
A4= 4 B4= Holland C4= V................A4= 3 B4= B C4= Young
A5= 3 B5= Young C5= B
Here is what I have:
function removeEmptyRows() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Input");
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Output");
var data = sheet.getRange("A2:D").getValues();
var newData = new Array();
for(i in data){
var row = data[i];
var empty = false;
for(i in data){
if(row[0] == ""){
empty = true;
}
}
if(!empty){
newData.push(row);
}
sheets.getRange(2, 1, newData.length, newData[0].length).setValues(newData);
};}
I have not been able to figure out how to incorporate changing the order of columns.
I was not able to apply previous posts to this problem, although this one came closest.
I would really appreciate any help you can provide. Thank you!

Copy row into new sheet(s) if two different cell values are within a defined range

I would like to create a Google Spreadsheets document that maintains:
Sheet 1 (All Entries): Unfiltered
Sheet 2 (1st Level Filter): Copies rows from Sheet 1 that Column B >/= 5000 OR Column C >/= 50000
Sheet 3 (2nd Level Filter): Copies rows from Sheet 1 that Column B >/= 5000 AND Column C >/= 50000
I created a sample doc for reference that's editable here.
Fairly limited programming/script experience.
In case you were looking for a script. This is what it'll look like although you'll have to do the mapping yourself. I haven't opened your doc but this will make it work if you need a script to do your bidding.
function sheetMaintain()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s1 = ss.getSheetByName("Sheet1");
var s2 = ss.getSheetByName("Sheet2");
var s3 = ss.getSheetByName("Sheet3");
var r1 = s1.getDataRange();
var r2 = s2.getDataRange();
var r3 = s3.getDataRange();
var data1 = r1.getValues();
for (var i=0; i<r1.getLastRow(); i++)
{
if (data1[i][1]>=5000 || data[i][2]>=50000)
{
var colB = data[i][1];
var colC = data[i][2];
var lr2 = r2.getLastRow();
s2.getRange(lr2+1, 1).setValue(colB); //Mapping Col B value to Col A of Sheet 2
s2.getRange(lr2+1, 2).setValue(colC); //Mapping Col C value to Col B of Sheet 2
}
if (data1[i][1]>=5000 && data[i][2]>=50000)
{
var colB = data[i][1];
var colC = data[i][2];
var lr3 = r3.getLastRow();
s3.getRange(lr3+1, 1).setValue(colB); //Mapping Col B value to Col A of Sheet 3
s3.getRange(lr3+1, 2).setValue(colC); //Mapping Col C value to Col B of Sheet 3
}
}
}
if you'd like to not have any duplicates (from running the function time and again) in Sheet2 or Sheet3 I would also suggest you look into using the clear() function and set your Sheet2 and Sheet3 to clear before you parse through Sheet1 again.
I have added a formula to both sheets to achieve something like you may want
i.e. the first one below is the OR and the second is the AND
=filter('Sheet 1 - All Entries'!A:C,(('Sheet 1 - All Entries'!B:B>=5000) + ( 'Sheet 1 - All Entries'!C:C >=5000)))
=filter('Sheet 1 - All Entries'!A:C,(('Sheet 1 - All Entries'!B:B>=5000) * ( 'Sheet 1 - All Entries'!C:C >=5000)))
PS... I am not sure if a formula is sufficient for you or if you wanted this done through script

Delete row values in more than 1 sheet if exists in another sheet

The code below is from an answer from this post regarding copying row values to a new sheet if it exist in another sheets.
Now, what if instead of copying the duplicate values to sheet 3, I want to delete them from sheets 1 and 2 if it exists in Sheet 3. With the same spreadsheet, I have 3 sheets. The unique value that will be compared on the first 2 sheets is the first column, "ID NUMBER".
Given the values, 784 | John Steep | I.T Department, which exists in all 3 sheets, the same row value should be deleted in Sheet 1 and 2 and retain the same value on Sheet 3.
function copyRowtoSheet3() {
var s1 = SpreadsheetApp.openById("ID").getSheetByName('Sheet1');
var s2 = SpreadsheetApp.openById("ID").getSheetByName('Sheet2');
var s3 = SpreadsheetApp.openById("ID").getSheetByName('Sheet3');
var values1 = s1.getDataRange().getValues();
var values2 = s2.getDataRange().getValues();
var resultArray = [];
for(var n=0; n < values1.length ; n++){
var keep = false;
for(var p=0; p < values2.length ; p++){
Logger.log(values1[n][0]+' =? '+values2[p][0]);
if( values1[n][0] == values2[p][0] && values1[n][3] == values2[p][4]){
resultArray.push(values1[n]);
Logger.log('true');
break ;// remove this if values are not unique and you want to keep all occurrences...
}
}
}
s3.getRange(+1,1,resultArray.length,resultArray[0].length).setValues(resultArray);
}
Can't seem to find the right solution. Tried several scripts but failed to make it work.
Thank you for any advice/suggestion.
Although the other answer works (I didn't test but I guess it does) it uses a lot of spreadsheetApp calls and might be slow if you have a lot of data.
It is possible to get this result using only arrays (if you don't need to keep sheet formatting and/or formulas).
The approach is slightly different as it is easier to keep data instead of removing it.
There are for sure many possible solutions, below is the one I tried : I created a special array that contains only the first column of sheet3 to make the duplicate search simpler.
function removeDupsInOtherSheets() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s1 = ss.getSheetByName("Sheet1").getDataRange().getValues();
var s2 = ss.getSheetByName("Sheet2").getDataRange().getValues();
var s3 = ss.getSheetByName("Sheet3").getDataRange().getValues();
// iterate s3 and check in s1 & s2 if duplicate values exist
var nS1 = [];
var nS2 = [];
var s3Col1 = [];// data in column1 of sheet3
for(var n in s3){
s3Col1.push(s3[n][0]);
}
for(var n in s1){ // iterate sheet1 and test col 1 vs col 1 in sheet3
var noDup1 = checkForDup(s1[n],s3Col1)
if(noDup1){nS1.push(noDup1)};// if not present in sheet3 then keep
}
for(var n in s2){ // iterate sheet2 and test col 1 vs col 1 in sheet3
var noDup2 = checkForDup(s2[n],s3Col1)
if(noDup2){nS2.push(noDup2)};// if not present in sheet3 then keep
}
Logger.log(nS1);// view result
Logger.log(nS2);
ss.getSheetByName("Sheet1").getDataRange().clear();// clear and update sheets
ss.getSheetByName("Sheet2").getDataRange().clear();
ss.getSheetByName("Sheet1").getRange(1,1,nS1.length,nS1[0].length).setValues(nS1);
ss.getSheetByName("Sheet2").getRange(1,1,nS2.length,nS2[0].length).setValues(nS2);
}
function checkForDup(item,s){
Logger.log(s+' = '+item[0]+' ?')
if(s.indexOf(item[0])>-1){
return null;
}
return item;
}
Sheet1
ID NUMBER NAME DEPARTMENT
784 John Steep I.T.
901 Liz Green H.R.
Sheet2
ID NUMBER NAME DEPARTMENT
784 John Steep I.T.
653 Bo Gore Marketing
Sheet3
ID NUMBER NAME DEPARTMENT
784 John Steep I.T.
999 Frank White Sales
121 Abid Jones Engineering
901 Liz Green H.R.
Script
function main() {
var ss = SpreadsheetApp.openById("ID");
var s1 = ss.getSheetByName("Sheet1");
var s2 = ss.getSheetByName("Sheet2");
var s3 = ss.getSheetByName("Sheet3");
var idCol = 1; // Assuming location of ID column is same in all sheets.
var s1RowCount = s1.getLastRow();
for (var i = 2; i <= s1RowCount; i++) { // Start at var i = 2 to skip the
// first row containing the header.
var id = s1.getRange(i, idCol, 1, 1).getValue();
deleteDuplicates(s2, id);
deleteDuplicates(s3, id);
}
}
function deleteDuplicates(sheet, id) {
var idCol = 1; // Assuming location of ID column is same in all sheets.
var rowCount = sheet.getLastRow();
for (var i = 2; i <= rowCount; i++) {
var data = sheet.getRange(i, idCol, 1, 1).getValue();
if (data === id) {
// Use this to test out the function.
Logger.log("Duplicate of ID " + id + " in sheet " +
sheet.getSheetName() + " at row " + i);
// Uncomment the next line when ready.
// sheet.deleteRow(i);
}
}
}
Logging Output
[14-11-04 09:16:04:551 PST] Duplicate of ID 784 in sheet Sheet2 at row 2
[14-11-04 09:16:04:587 PST] Duplicate of ID 784 in sheet Sheet3 at row 2
[14-11-04 09:16:04:727 PST] Duplicate of ID 901 in sheet Sheet3 at row 5

Google Script: Delete row if a value in it exists in more than one sheet

I had posted a question months ago regarding deleting a row if a value in it exists in another sheet.
This is the accepted answer in my previous post.
function deleteRowInSheet1() {
var s1 = SpreadsheetApp.openById("SS_ID").getSheetByName('Sheet1');
var s2 = SpreadsheetApp.openById("SS_ID").getSheetByName('Sheet2');
var values1 = s1.getDataRange().getValues();
var values2 = s2.getDataRange().getValues();
var resultArray = [];
for(var n in values1){
var keep = true
for(var p in values2){
if( values1[n][0] == values2[p][0] && values1[n][1] == values2[p][1]){
keep=false ; break ;
}
}
if(keep){ resultArray.push(values1[n])};
}
s1.clear()
s1.getRange(1,1,resultArray.length,resultArray[0].length).setValues(resultArray);
}
Now, my question is what if there are more than 1 sheet to be compared to. Let's say I have 4 sheets.
Sheet1:
NAME | PLACE | AGE
Carl | Florida | 45
Mike | Florida | 41
Suzy | Florida
Sheet 2:
NAME | PLACE | AGE
Mike | Florida | 41
Sheet 3:
NAME | PLACE | AGE
Mike | Florida | 41
Sheet 4:
NAME | PLACE | AGE
Mike | Florida | 41
The script should delete Mike Florida row in Sheet 2 to 4 since it has duplicate data in Sheet 1. Column 1 and 2, again are the basis to compare all the data in the 4 sheets since the values will be unique. I tried to modify the answered script but I can't seem to make it run. I understood the logic but not sure which part I missed:
This is my code:
function deleteRowInSheets1to3() {
var s1 = SpreadsheetApp.openById("SS_ID").getSheetByName('Sheet1'); //this is the basis of all sheets. values to be compared is column 2
var s2 = SpreadsheetApp.openById("SS_ID").getSheetByName('Sheet2');
var s3 = SpreadsheetApp.openById("SS_ID").getSheetByName('Sheet3');
var s4 = SpreadsheetApp.openById("SS_ID").getSheetByName('Sheet4');
var values1 = s1.getDataRange().getValues();
var values2 = s2.getDataRange().getValues();
var values3 = s3.getDataRange().getValues();
var values4 = s4.getDataRange().getValues();
var resultArray = [];
for(var n in values1){
var keep = true
for(var p in values2){
if( values1[n][0] == values2[p][0] && values1[n][1] == values2[p][1]){
keep=false ; break ;
}
for(var q in values3){
if( values1[n][0] == values3[q][0] && values1[n][1] == values3[q][1]){
keep=false ; break ;
}
for(var r in values4){
if( values1[n][0] == values4[r][0] && values1[n][1] == values4[r][1]){
keep=false ; break ;
}
}
}
}
if(keep){ resultArray.push(values1[n])};
}
s1.clear()
s1.getRange(1,1,resultArray.length,resultArray[0].length).setValues(resultArray);
}
Thanks a bunch for any advice! :)
I think we almost have the same situation. This is a possible duplicate question. See this post.
The answer provided was below (not my code):
function removeDupsInOtherSheets() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s1 = ss.getSheetByName("Sheet1").getDataRange().getValues();
var s2 = ss.getSheetByName("Sheet2").getDataRange().getValues();
var s3 = ss.getSheetByName("Sheet3").getDataRange().getValues();
// iterate s3 and check in s1 & s2 if duplicate values exist
var nS1 = [];
var nS2 = [];
var s3Col1 = [];// data in column1 of sheet3
for(var n in s3){
s3Col1.push(s3[n][0]);
}
for(var n in s1){ // iterate sheet1 and test col 1 vs col 1 in sheet3
var noDup1 = checkForDup(s1[n],s3Col1)
if(noDup1){nS1.push(noDup1)};// if not present in sheet3 then keep
}
for(var n in s2){ // iterate sheet2 and test col 1 vs col 1 in sheet3
var noDup2 = checkForDup(s2[n],s3Col1)
if(noDup2){nS2.push(noDup2)};// if not present in sheet3 then keep
}
Logger.log(nS1);// view result
Logger.log(nS2);
ss.getSheetByName("Sheet1").getDataRange().clear();// clear and update sheets
ss.getSheetByName("Sheet2").getDataRange().clear();
ss.getSheetByName("Sheet1").getRange(1,1,nS1.length,nS1[0].length).setValues(nS1);
ss.getSheetByName("Sheet2").getRange(1,1,nS2.length,nS2[0].length).setValues(nS2);
}
function checkForDup(item,s){
Logger.log(s+' = '+item[0]+' ?')
if(s.indexOf(item[0])>-1){
return null;
}
return item;
}
Hope this helps.

Count Reoccuring Values in Column of Google Spreadsheet Using Script

I'd like to count the number of times a value reoccurs in a specific column of my spreadsheet using a script so that it populates a different column (same row) with the count when a form is submitted. These are the values in Column B that I'd like to count:
6 ACM
5 ACM
4 ACM
5 CGC
7 CGC
6 ACM
7 ACM
7 ACM
so that if the calculation were working correctly Column C would be populated with these numbers:
1
1
1
1
1
2
1
2
I know how to read the data and how to write to the spreadsheet, but I don't know how to actually count the values. Here is what I have so far:
function countif() {
var ss = null;
try {
ss = SpreadsheetApp.openById("0AliYViHYAwaNdHQyMXlKT2Q5UElQY184T3BWYTRiM2c");
} catch (ex) {
ss = SpreadsheetApp.getActiveSpreadsheet();
}
var sheet = ss.getSheetByName("Sheet1");
var lastLine = sheet.getLastRow();
var data = sheet.getRange("B2:B").getValues();
var count = 0;
//need help here
sheet.getRange(lastLine,3).setValue(count);
}
Thank you!
Put this piece of code in your //need help section.
for (var i = 0 ; i < lastLine ; i++){
var count = 1;
for ( var j = 0 ; j < i ; i ++) {
if (data[j][0] == data[i][0] ){
count++;
}
}
sheet.getRange('C' + (i+1).toString()).setValue(count);
}
Just as an alternative, you can achieve this with a spreadsheet function, entered in C1:
=ArrayFormula(IF(ROW(B:B)=1;"Count";IF(LEN(B:B);MMULT((ROW(B:B)>=TRANSPOSE(ROW(B:B)))*(B:B=TRANSPOSE(B:B));SIGN(ROW(B:B)));IFERROR(1/0))))