How to loop through each cell in column? - google-apps-script

The script simply adds 1 to the cell in a specific column, but I'd like it to +1 to every cell in a specific column with a set delay.
This is what I've gathered so far, but need that extra step.
function plus() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var yesCount = ss.getRange("B4");
var yesAdd = yesCount.getValue();
if(yesAdd != ""){
yesCount.setValue(yesAdd+1);
Utilities.sleep(1000);
}
}
Basically B4 should be the entire B column and I'd like to step through each (non-empty) cell wait for one or two second and move on to the next cell.

Note that the spreadsheet may not be updated immediately every time you change the value.
function plus() {
const row = 4;
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName('Sheet Name');
const rows = sheet.getLastRow() - row + 1;
const range = sheet.getRange(row, 2, rows, 1);
const values = range.getValues().flat();
const matches = {};
values.forEach((value, i) => {
if (value !== '') {
sheet.getRange(row + i, 2).setValue(value + 1);
Utilities.sleep(1000);
}
});
}

Related

Script to copy contents of cell (in a2) and paste this into 1st empty (of text and formulas) cell on row 2

I am trying to write a script to copy contents of cell (in a2) and paste this into the 1st empty (of text and formulas) cell on row 2.
Ones that I have tried to copy and use are to do similar but finding the next row in a column.
I have also tried functions that should do this but they find the first cell in the row that contains a formula, I need it to be empty of text and formulas.
Can anyone help please?
Thanks
Copy A2 to end of row2 + 1 col
function copy() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Your Sheet Name");
const v = sh.getRange("A2").getValue();
sh.getRange(2, getRowWidth(2,sh,ss) + 1).setValue(v);
}
function getRowWidth(row, sh, ss) {
var ss = ss || SpreadsheetApp.getActive();
var sh = sh || ss.getActiveSheet();
var row = row || sh.getActiveCell().getRow();
var rcA = [];
if(sh.getLastColumn()){rcA = sh.getRange(row, 1, 1, sh.getLastColumn()).getValues().flat().reverse();}
let s = 0;
for (let i = 0; i < rcA.length; i++) {
if (rcA[i].toString().length == 0) {
s++;
} else {
break;
}
}
return rcA.length - s;
}
Use getValues to check whether there's some text in your cells.
Use getFormulas to check whether there are formulas in your cells.
Code sample:
function copyToFirstEmptyCell() {
const rowIndex = 2;
const sheet = SpreadsheetApp.getActiveSheet();
const row = sheet.getRange(`${rowIndex}:${rowIndex}`);
const values = row.getValues()[0];
const a2Value = values.shift();
const formulas = row.getFormulas()[0];
const columnIndex = values.findIndex((value,i) => !value.length && !formulas[i+1].length) + 2;
const foundCell = sheet.getRange(rowIndex, columnIndex);
foundCell.setValue(a2Value);
foundCell.activate();
}

How to search columns for a specific value and move the target row to the top?

I am trying to search column E for a cell starting with "X". I then want to move that entire row up to the top.
This is what I've created so far, using IndexOf:
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var Today = spreadsheet.getSheetByName("Today");
var TodayList = Today.getRange('E:E').getValues();
var i = TodayList.indexOf("X", 0);
Today.moveRows(Today.getRow(i), 1);
In your situation, how about the following modification?
In the case of Array.prototype.indexOf(), the values cannot be directly checked from the 2-dimensional array. But, in your situation, I thought that the 1st character can be directly checked using the index as follows.
Modified script:
function myFunction() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var Today = spreadsheet.getSheetByName("Today");
var TodayList = Today.getRange('E1:E' + Today.getLastRow()).getValues();
TodayList.forEach(([e], i) => {
if (e[0] == "X") {
var row = i + 1;
Today.moveRows(Today.getRange(`${row}:${row}`), 1);
}
});
}
When this script is run, the values are retrieved from column "E". And, each cell value is checked from the retrieved values. When the 1st character of the cell value is "X", the row is moved to the 1st row.
In this modification, the lower rows are moved to the upper row. If you want to do this with the reverse, please modify it as follows.
From
TodayList.forEach(([e], i) => {
if (e[0] == "X") {
var row = i + 1;
Today.moveRows(Today.getRange(`${row}:${row}`), 1);
}
});
To
var len = TodayList.length;
var offset = 0;
TodayList.reverse().forEach(([e], i) => {
if (e[0] == "X") {
var row = len - i + offset;
Today.moveRows(Today.getRange(`${row}:${row}`), 1);
offset++;
}
});
References:
forEach()
moveRows(rowSpec, destinationIndex)
Find X rows and move to top
function funko() {
const ss = SpreadsheetApp.getActive();
const tsh = ss.getSheetByName("Today");
const tvs = tsh.getRange(1, 1, tsh.getLastRow(), tsh.getLastColumn()).getValues();
let a = [];
let d = 0;
tvs.forEach((r, i) => {
if (r[4] == "X") {
a.push(r)
tsh.deleteRow(i + 1 - d++);
}
});
tsh.insertRowsBefore(1,a.length)
a.reverse();
tsh.getRange(1,1,a.length,a[0].length).setValues(a);
}

Copy Data from Source Sheet to Target Sheet IF SourceSheet: Column A data does not exists in Target Sheet

I want to copy data from Source Sheet to Target Sheet by using the following code taken from other thread of this site. How ever its not helping with desired output.
I want to copy data from source sheet to target sheet. Source sheet data is changing dynamically hence, I want to copy Source sheet rows if Source sheet Column A data does not exists in Target sheet Column A.
please help me to modify the code.
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sourceSheet = ss.getSheetByName("Source");
const targetSheet = ss.getSheetByName("Target");
const startRow = 2;
const APPENDED = 'APPENDED';
function appendToRecords() {
const numRows = sourceSheet.getLastRow() - 1; // Number of rows to process
const dataRange = sourceSheet.getRange(startRow, 1, numRows, sourceSheet.getLastColumn()); // Fetch the range of cells being used
const sourceData = dataRange.getValues(); // Fetch values for each row in the Range.
const lastColumn = sourceData[0].length;
//if (dataRange > 2) {
for (var i = 0; i < sourceData.length; ++i) {
var row = sourceData[i];
if (row[1]=="" && row[lastColumn-1] ==APPENDED) {
sourceSheet.getRange(startRow + i, 9 ).setValue("");
}
else if (row[lastColumn-1] != APPENDED) {
///you should not do this line by line, but all at oncw with an array
//row[lastColumn-1] = APPENDED;
row[8] = APPENDED; // to avoid incremental appending
var lastRow = targetSheet.getLastRow();
targetSheet.getRange(lastRow + 1, 1, 1, row.length).setValues([row]);
sourceSheet.getRange(startRow + i, 9 ).setValue("APPENDED");
}
}
}
Sample data sheet
https://docs.google.com/spreadsheets/d/13NGHmUjnISK76wri8x9PoyU34KPLdW2TrOXVvoY5kuM/edit#gid=2100307022
Issue:
You want to copy all rows from the source sheet in which column A is not found in target data.
Solution:
Filter the source rows according to whether column A value is found in any row in the target sheet, using filter and some.
Add the filtered rows to the target sheet via Range.setValues.
Code sample:
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sourceSheet = ss.getSheetByName("Source");
const targetSheet = ss.getSheetByName("Target");
const startRow = 2;
const CHECK_COLUMN = 1; // Column A
function appendToRecords() {
const numRows = sourceSheet.getLastRow() - 1; // Number of rows to process
const numCols = sourceSheet.getLastColumn();
const lastTargetRow = targetSheet.getLastRow();
const dataRange = sourceSheet.getRange(startRow, 1, numRows, sourceSheet.getLastColumn()); // Fetch the range of cells being used
const sourceData = dataRange.getValues(); // Fetch values for each row in the Range.
let targetData = [];
if (lastTargetRow > 1) targetData = targetSheet.getRange(startRow, 1, lastTargetRow-startRow+1, numCols).getValues();
const newData = sourceData.filter(sourceRow => {
const columnA = sourceRow[CHECK_COLUMN-1];
return !targetData.some(targetRow => targetRow[CHECK_COLUMN-1] === columnA);
});
if (newData.length) {
targetSheet.getRange(lastTargetRow+1, 1, newData.length, newData[0].length).setValues(newData);
}
}
The script above assumes there's a header row in the target sheet. If that's not the case, replace:
if (lastTargetRow > 1) targetData = targetSheet.getRange(startRow, 1, lastTargetRow-startRow+1, numCols).getValues();
With this:
if (lastTargetRow > 0) targetData = targetSheet.getRange(1, 1, lastTargetRow, numCols).getValues();
Note:
Avoid using setValue in a loop, this slows down your script a lot. See Use batch operations.

Append only non empty cells to another sheet google script

I want to copy only non-empty cells in column C & E & append all of them in "Update" Sheet 1st column. Below is what i tried for copy non-empty cells but it doesnt append
here is Dummy Sheet for reference
function emaillFilter(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ws = ss.getSheetByName("Email");
var updateSheet = ss.getSheetByName("Update");
var range = ws.getRange(1,5,ws.getLastRow());
var emptycells = SpreadsheetApp.newFilterCriteria().setHiddenValues(['']).build();
var filter = range.getFilter() || range.createFilter();
filter.setColumnFilterCriteria(5, emptycells);
var data = ws.getRange(2,5,ws.getLastRow()).getValues();
var array = [];
for (var i = 0; i < data.length; i++){
if(!ws.isRowHiddenByFilter(i+1)){
array.push(data[i]);
}
}
updateSheet.getRange(updateSheet.getLastRow()+1, 1, array.length).setValues(array);
}
input sheet Column C & E
desired output - paste column C & append E without blanks in column A of another sheet
How about this:
function emaillFilter(){
const ss=SpreadsheetApp.getActive();
const sh=ss.getSheetByName("Email");
const ush=ss.getSheetByName("Update");
const data=sh.getRange(2,1,sh.getLastRow(),5).getValues();
var array=[];
data.forEach(function(r,i){
if(r[2] && r[4]) {
array.push(r);
}
});
ush.getRange(ush.getLastRow()+1, 1, array.length,array[0].length).setValues(array);
}
Okay I think you want this based upon your comment:
desired output - paste column C & append E without blanks in column A of another sheet
But I must admit that I don't see that reflected in your example second image so we may need another iteration.
function emaillFilter(){
const ss=SpreadsheetApp.getActive();
const sh=ss.getSheetByName("Email");
const ush=ss.getSheetByName("Update");
const data=sh.getRange(2,1,sh.getLastRow(),5).getValues();
var array=[];
data.forEach(function(r,i){
//is columnC and columnE both truth
if(r[2] && r[4]) {
array.push([r[2] + ',' + r[4]]);
//is columnC truthy and columnE falsy
}else if(r[2] && !r[4]) {
array.push([r[2]]);
}
});
ush.getRange(ush.getLastRow()+1, 1, array.length,array[0].length).setValues(array);
}
Okay I think this is it:
function emaillFilter(){
const ss=SpreadsheetApp.getActive();
const sh=ss.getSheetByName("Email");
const ush=ss.getSheetByName("Update");
const data=sh.getRange(2,1,sh.getLastRow(),5).getValues();
var array1=[];
var array2=[];
data.forEach(function(r,i){
if(r[2]) {
array1.push([r[2]]);
}
if(r[4]) {
array2.push([r[4]]);
}
});
var array=array1.concat(array2);
ush.getRange(ush.getLastRow()+1, 1, array.length,array[0].length).setValues(array);
}
Thanks for the images. They really helped.
truthy
falsy

Get Selected Row's Specific Col Value via script (Google Sheets)

I've been trying to get this one to work without success so far.
I need to get the TaskNumber on the first column of the row I'm on and bring it to the destination sheet, so that I can update it there.
I have the following, which I'm tweaking to achieve my goal, but I guess I've bumped into my limitation walls:
function jump() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var TaskNumberSheet = ss.getSheetByName('To-Do List');
var TaskNoRow = TaskNumberSheet.getActiveCell();
var TaskNoCol = TaskNoRow.getColumn() == 1
var TaskNo = TaskNoCol.getValue;
var sheet = ss.getSheetByName('Updates');
//var Tasks = ss.getSheetByName("To Do List").getActiveRange(Tasks.getColum(1)).getValue();
var values = sheet.getRange("B:B").getValues();
var maxIndex = values.reduce(function(maxIndex, row, index) {
return row[0] === "" ? maxIndex : index;
}, 0);
sheet.setActiveRange(sheet.getRange(maxIndex + 2,2)).setValue(TaskNo);
}
Any help is appreciate.
Cheers,
A
If I understood you correctly, you want to:
Get the value in column A from the currently active row (in sheet To-Do List).
Find the first empty cell in column B (in sheet Updates) (start looking at row #8).
Copy the value that was retrieved in step 1 to the cell retrieved in step 2.
Set the cell retrieved in step 2 as the active cell.
If that's the case, you can do the following:
function jump() {
var ss = SpreadsheetApp.getActive();
// Step 1:
var TaskNumberSheet = ss.getSheetByName('To-Do List');
var TaskNoRow = TaskNumberSheet.getActiveCell().getRow();
var TaskNoCol = 1;
var TaskNo = TaskNumberSheet.getRange(TaskNoRow, TaskNoCol).getValue();
// Step 2:
var sheet = ss.getSheetByName('Updates');
var firstRow = 8;
var column = 2;
var numRows = sheet.getLastRow() - firstRow + 1;
var values = sheet.getRange(firstRow, column, numRows).getValues().map(function(value) {
return value[0]
});
var i = 0;
for (i; i < values.length; i++) {
if (values[i] === "") break;
}
var targetRange = sheet.getRange(i + firstRow, column);
targetRange.setValue(TaskNo); // Step 3
sheet.setActiveRange(targetRange); // Step 4
}
function jump() {
var TargetRow=?;//Fillin target row
var TargetCol=?;//Fillin target column
var ss=SpreadsheetApp.getActive();
var TaskNumberSheet=ss.getSheetByName('To-Do List');
var TaskNoRow=TaskNumberSheet.getActiveCell().getRow();//Getting row from active cell
var TaskNoCol=1
var TaskNo=TaskNumberSheet.getRange(TaskNoRow,TaskNoCol).getValue();
ss.getSheetByName('Updates').getRange(targetRow,targetCol).setValue(TaskNo);
}