Automatically separate and delimit a string in Google sheets - javascript

Google sheets has an option which is selectable from the top menu to separate text into columns when specifying a character. It's possible use a comma or other characters.
I am looking for a script which can do this process automatically for a given column. There are numerous scripts available to do this but I have not been able to accomplish my task using them.
I am using an application on Android which allows me to scan a qr code and send the string of information to Google sheets.
A sample of the information would appear as : 464839|362|2840|927|72|617
I need to separate this information into separate columns when the information is sent to sheets. The process should be automatic.
I have a snip of code which I've found searching however it doesn't work for me.
var range = SpreadsheetApp.getActiveRange();
var cell = range.getCell(1, 1); // Gets the cell A1
var cellValue = cell.getValue(); // Gets the value of the cell A1
var cellArray = cellValue.split("|"); // Splits the cell value by ',' and stores it in array.
//Iterate through the array
for(var i = 0; i < cellArray.length; i++){
Logger.log(cellArray[i]);
}
I'm not very code savvy, please help.

Below would be a code that you place on an installable trigger that runs at a regular interval and iterates through the values of each row in column A and tries to split the value with the pipe symbol and the replace then write those split values along the columns in that row. If this has already been done in the past the function will error when it tries to split the values because no pipe symbol exists but the try/catch will catch that error and allow the function to continue through the loop.
function myFunction() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("NameOFSheet"); //Change "NameOFSheet to the actual name of the sheet.
var col1Values = sheet.getSheetValues(1, 1, sheet.getLastRow(), 1) //Gets 2d (2 dimensional) array of the Values in Column 1 (getSheetValues(startRow, startColumn, numRows, numColumns)_
var splitVals = []; //Instantiate an empty 1d array variable
//Iterate through the 2d array and set the values
for(var i = 0; i < col1Values.length; i++){
try{
splitVals = col1Values[i][0].split("|"); //Creates a 1d array of values split at every occurrence of the pipe symbol ("|").
//If there is no pipe symbol (which would be the case if this operation has already happened then the array will be blank because .split will throw an error which will get "caught" in the try catch and the row will be skipped
//Iterate over the splitVals array and set the values of the columns along the row (i+1) that you are in.
for(var col = 0; col < splitVals.length; col++){
sheet.getRange(i+1, col+1).setValue(splitVals[col])
}
}catch(e){}
}
}
I commented the code for explanation. I would recommend reading up on 2 dimensional arrays to help you understand them and the code above better.

Related

Google Apps Script Better Way to Get Unique Values

I have working code that takes data from two non-adjacent columns in a Google Spreadsheet, looks for unique values in the first column, and if unique creates a new array with the unique value from the first column and corresponding value in the second column. The problem is, the data I am using is already somewhat long (413 rows) and will only get longer over time. It takes about 1-2 minutes for the code to run through it. I've been looking for a shorter way to do this and I've come across the filter() and map() array functions which are supposedly faster than a for loop but I can't get them implemented correctly. Any help with these or a faster method would be greatly appreciated. The code I have right now is below.
function getkhanassignments(rows) {
var assignmentsraw = [];
var temparray = [];
var previousassignment = datasheet.getRange(50,1).getValue();
for(i=0, j=0;i<rows-1;i++) {
if(datasheet.getRange(50+i,1).getValue() != previousassignment) {
previousassignment = datasheet.getRange(50+i,1).getValue();
assignmentsraw[j] = new Array(2);
assignmentsraw[j][0] = datasheet.getRange(50+i,1).getValue();
assignmentsraw[j][1] = datasheet.getRange(50+i,8).getValue();
j++;
}
}
Logger.log(assignmentsraw);
return assignmentsraw;
}
The answers I've found elsewhere involve just getting unique values from a 1d array whereas I need unique values from a 1d combine with corresponding values from another 1d array. The output should be a 2d array with unique values from the first column and their corresponding values in the second column.
Solution:
The best practice of looping through ranges in Google Apps Script is to dump the range values into a 2D array, loop through that array, and then return the output array back to Google Sheets.
This way, there would be no calls to Sheets API inside loops.
Sample Code:
function getkhanassignments(rows) {
var assignmentsraw = [];
var table1 = datasheet.getRange(50,1,rows).getValues();
var table2 = datasheet.getRange(50,8,rows).getValues();
var previousassignment = table1[0][0];
assignmentsraw.push([table1[0][0],table2[0][0]]);
for(i=0; i<rows; i++) {
if (table1[i][0] != previousassignment) {
assignmentsraw.push([table1[i][0],table2[i][0]]);
previousassignment = table1[i][0];
}
}
Logger.log(assignmentsraw);
return assignmentsraw;
}
References:
Class Range
push()

i want to run delete row function if a certain column meets the conditions [duplicate]

This question already has answers here:
Deleting rows in google sheets using Google Apps Script
(10 answers)
Closed 2 years ago.
i want to delete multiple rows of data on condition if column B in that row is equal to CID parameter. but after I run it, the deleted data is incorrect. Sometimes the deleted data is located one row above or below the specified row in the for row loop
here is my code :
if (e.parameter.func == "DeleteRec") {
var rg=ss.getSheetByName("MAIN").getDataRange().getValues();
var lr= ss.getSheetByName("MAIN").getLastRow();
for(var row=1;row<=lr;row++){
var cid=rg[row].toString().split(',');
if(cid[1]==e.parameter.CID){
ss.getSheetByName("MAIN").deleteRow(row-1);
var data=200;
}
}
return ContentService.createTextOutput(data).setMimeType(ContentService.MimeType.TEXT);
}
Explanation:
You need to delete the rows from bottom-up or backwards because after you delete one row you change the structure of the spreadsheet file and therefore rg does not match the new structure of the sheet.
Keep in mind that array indexes in JavaScript start from 0. When variable row is 1 you want to delete row+1 in the sheet, because row=1 is getting the second element of your array.
Calling getSheetByName in a for loop will increase the performance cost of your script. Instead, define the sheet variable before the loop so you can use it every time you need it.
Since you are using getDataRange the length of rg is equal to what getLastRow returns. Therefore lr is not needed.
Not sure why you iteratively assign a fixed value to a variable var data=200 but I kept that part since it is not part of your question.
Solution:
Replace the relevant part with this code:
const sheet = ss.getSheetByName("MAIN");
const rg = sheet.getDataRange().getValues();
for (var row = rg.length - 1; row>0; row--) {
var cid=rg[row].toString().split(',');
if(cid[1]==e.parameter.CID){
sheet.deleteRow(row+1);
var data=200;
}
}

Google Sheets Apps Script Copy Row of Data If date same as tab name

I found some code that almost does what i need and have tried playing around with it to get it to work, but no luck. I get an export with data with dates in the last column on every row.
I simply want to copy the last column rows of dates to the tabs with the same name.
function MoveDate_FourthDEC() {
var ss=SpreadsheetApp.getActive();
var sh1=ss.getSheetByName("Import");
var sh2=ss.getSheetByName("4/12/2020");
var rg1=sh1.getRange(2,1,sh1.getLastRow(),32);//starting at column2
var data=rg1.getValues();
for(var i=0;i<data.length;i++) {
// 13 = collected should be in this column which is column N
if(data[i][31]=="4/12/2020") {
sh2.appendRow(data[i]);
}}}
Explanation:
Your goal is to copy all the rows for which column AF matches the names of the sheets.
To begin with, you can use forEach() to iterate over every sheet. For each sheet, you want to check whether the sheet name matches a date in column AF. If it does, then you need to filter only the rows that contain this date in column AF and store them into an temporary array:
let temp_data = data.filter(r=>r[31]==sh.getName());
Then you can efficiently copy and paste all the relevant rows to the matching sheet:
sh.getRange(sh.getLastRow()+1,1,temp_data.length,temp_data[0].length).setValues(temp_data);
Side notes:
When dealing with date objects you need to consider the display values in the sheet. This is why I am using getDisplayValues instead of getValues.
Since data starts from the second row, you need to deduct one row from the last row with content, to get the correct range:
getRange(2,1,sh1.getLastRow()-1,32)
I am using includes to check if the sheet name matches the last column. In order to use includes you need to flatten the 2D array that is returned by the getDisplayValues function.
Solution:
function MoveDate_FourthDEC() {
const ss = SpreadsheetApp.getActive();
const sh1 = ss.getSheetByName("Import");
const shs = ss.getSheets();
const dts = sh1.getRange('AF2:AF'+sh1.getLastRow()).getDisplayValues().flat();
const data=sh1.getRange(2,1,sh1.getLastRow()-1,32).getDisplayValues();
shs.forEach(sh=>{
if (dts.includes(sh.getName())){
let temp_data = data.filter(r=>r[31]==sh.getName());
sh.getRange(sh.getLastRow()+1,1,temp_data.length,temp_data[0].length).setValues(temp_data);
}});
}

Filter function will not delete my empty rows - Google App Script

I want to import rows from one google sheet to the other, however source sheet imports a number of empty rows. Now I use a filter function to get rid of these rows but they will not disappear, can anyone tell me why?
var a = SpreadsheetApp.openByUrl("url").getSheetByName("Admin Use Only").getRange(4,1,6,21).getValues();
var b = SpreadsheetApp.getActive().getSheetByName('Credit_Detail');
b.getRange(b.getLastRow() +1, 1, a.length,21).setValues(a);
//filter function below:
var otarget=b.getRange(2,1,b.getLastRow()-1, 26).getValues();
var data=otarget.filter(function(r){
return !r.every(function(cell){
return cell === "";});
});
Logger.log(data);
b.getRange("A2:Z").clearContent();
b.getRange(3,1,data.length,data[0].length).setValues(data);
here's how I would do it. First, create an variable to store the array of the source. then run a for loop scanning the first column for empties. something like: for (var i = 0, i < data.length; i++) { if (data[i][0] != '') { XXXX } }
XXXX means that you can either put a code to create a new set of array which can be passed to the target sheet at once or use append row to transfer non blank rows to the target sheet one by one.
Note: Creating a new array to store non-empty rows would speedup the execution time if you are dealing with large data, thousands of rows.

Assign value to each indexOf match

I currently have code that searches through a single Google sheet for indexOf a number, and assigns the row number of a match to an variable. Here's an example:
for(i=0;i<values.length; i++){
itemvalue = values[i][column1-1];
codevalue = values[i][column2-1];
if(itemvalue.indexOf("5019")>-1){
row = i+1; itemcode = 5019; indexes.push(i+1)
}
}
Unfortunately the sheet contains multiple rows of strings that contain "5019". So I'm looking for a way for indexOf to continue searching and assign a new variable for the row number of each match. So if "5019" was found at row 50,51, and 54, then row,row1,row2 will be assigned to each row number.
Appreciate any help on this, also please let me know if I missed providing any information.
Edit:Thanks to the link provided by daniel, I was able to get all the matching row numbers into an array. But I'm still trying to figure out how to assign a variable to each value in the array so I can get the value of the cells that reside at the rows and add them together.
I've found the solution I sought for. Here's what I did:
for(i=0;i<values.length; i++){
itemvalue = values[i][column1-1];
codevalue = values[i][column2-1];
if(itemvalue.indexOf("5019")>-1){
row = i+1; itemcode = 5019; indexes.push(i+1)
}
for(j=k=0;j<indexes.length; j++){
rownumb.push(ss.getRange(indexes[j],qtycol).getValue()); //Get value of the cells using the row numbers from the indexes array
}
for(l=0;l<rownumb.length; l++){
rowtotal += rownumb[l]; //Adds all the values together
}
}
So I made a for loop to get the value of cells in the rows that was in the indexes array, then made a new array called "rownumb" that holds the cell values. I then made another for loop to add all the values in array rownumb together and got exactly what I was looking for.

Categories