Move Rows En Masse Contingent on Value in One Column - google-apps-script

I have a script setup that moves all the records in a sheet into another sheet. However, I would like to add functionality to only move records that have the value "Approved" in a specific column (column I for my current situation). I've seen some other questions/answers to move individual rows based on values, but I haven't figured out how to leverage these scripts to run across a full spreadsheet. My guess is I can use a for loop but how?
Current script:
function MoveRecords(){
//Original Sheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Example Input")
//Calculate # of Rows Ignoring Blank Array Values
var Rows = ss.getRange("A2:A").getValues();
var NumRows = Rows.filter(String).length;
/*Add a For Loop here to only get the rows with Approved in Column I?*/
//Parsed Data to Move
var rangeValues1 = sheet.getRange(2,1,NumRows,1).getValue();
var rangeValues2 = sheet.getRange(2,2,NumRows,5).getValues();
//Destination of Parsed Data
var DestinationSS = SpreadsheetApp.openById('ID');
var DestinationSheet = DestinationSS.getSheetByName('Approved');
var DestinationLastRow = DestinationSheet.getLastRow()+1;
//Move the Data
DestinationSheet.getRange(DestinationLastRow,3,NumRows,1).setValue(rangeValues1);
DestinationSheet.getRange(DestinationLastRow,5,NumRows,5).setValues(rangeValues2);
};
Any help is greatly appreciated!

You can get all values, filter every row for Approved then write those rows into destination sheet.
function MoveRecords() {
//Original Sheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Example Input');
var values = sheet.getDataRange().getValues();
/*Add a For Loop here to only get the rows with Approved in Column I?*/
// col I = index 8
var res = values.filter(function(row) {
return row[8] == 'Approved';
});
//Parse Data to Move
var rangeValues1 = res.map(function(row) {
return [row[0]];
});
var rangeValues2 = res.map(function(row) {
row.shift();
while (row.length > 5) row.pop();
return row;
});
//Destination
var DestinationSS = SpreadsheetApp.openById('ID');
var DestinationSheet = DestinationSS.getSheetByName('Approved');
var DestinationLastRow = DestinationSheet.getLastRow() + 1;
//Move the Data
DestinationSheet.getRange(DestinationLastRow, 3, rangeValues1.length, 1).setValues(rangeValues1);
DestinationSheet.getRange(DestinationLastRow, 5, rangeValues2.length, 5).setValues(rangeValues2);
}

Related

How to copy a dynamic range or data to another sheet using google sheets script

I have created a named ranged called MW_DATA in my sheet which covers the range U12:AA105
Based on the data present there could be a variable number of rows of data in U12:AA105 every time I copy the data to a Games_Log sheet and clear the data in the cells.
I need to improve the code so the filteredData variable is a dynamic range of rows each time (e.g. it could be U12:AA12 or U12:AA75)
current code:
function SaveMWData() {
var dataSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Games_Log");
var dataRange = dataSheet.getDataRange();
var dataLocation = dataRange.getLastRow();
var mwData = sheet.getRange("MW_DATA");
mwData.copyTo(dataSheet.getRange(dataLocation + 1,1),{contentsOnly:true});
}
Above code keeps copying all rows, including blank rows into the Games_Log sheet
Code I can't figure out:
function SaveMWData() {
var unfilteredData = sheet.getRange("MW_DATA");
var filteredData = ??
filteredData.copyTo(dataSheet.getRange(dataLocation + 1,1),{contentsOnly:true});
}
Filtered data would only copy over the rows with data
I believe I got it working as follow:
function SaveMWData() {
var dataSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Games_Log");
var dataRange = dataSheet.getDataRange();
var dataLocation = dataRange.getLastRow();
var row = sheet.getRange("MW_ROW").getValue();
var column = sheet.getRange("MW_COLUMN").getValue();
var numrows = sheet.getRange("MW_NUMROWS").getValue();
var numcolumns = sheet.getRange("MW_NUMCOLUMNS").getValue();
var mwData = sheet.getRange(row,column,numrows,numcolumns);
mwData.copyTo(dataSheet.getRange(dataLocation + 1,1),{contentsOnly:true});
}

Getting Specific Rows from Another Google Sheet via App Script Based on Multiple Cell Values

I would like to fetch data from another google sheet, then retrieve all columns(been successful with this one). As for the rows, I would only like to retrieve all rows with these values, "Mrm1, Mrm2, Mrm3" from Measurement Column.
For example, I have these on another sheet,Original Data
And on another sheet, I want the result to be like this: Expected Retrieved Data
So far, I have this, but I'm not sure how to apply what I need on the rows. This script is retrieving everything.
function Country A() {
var sss = SpreadsheetApp.openById("19-idD8PWuNxnvzRVqBlKhju2RkKxOe8nUQaf9ZMAcgk"); // Source spreadsheet - replace with actual key
var ss = sss.getSheetByName('Compiled'); // Source sheet - change to actual name
var numRows = ss.getLastRow() // get last row with data
var numColumn = ss.getLastColumn(); // get last column with data
var srange = ss.getRange(2,1,numRows,numColumn); // Source range - change to actual range
var values = srange.getDisplayValues();
var lss = SpreadsheetApp.getActiveSpreadsheet(); // Local spreadsheet - the one this script is in
var targetnumRows = lss.getSheetByName('Country A').getMaxRows();
var targetnumcolumns = lss.getSheetByName('Country A').getMaxColumns();
var ls = lss.getSheetByName('Country A').getRange(2,1,numRows,numColumn); // Local sheet - change to actual name and Local range - change to actual range
var TargetRange = lss.getSheetByName('Country A').getRange(2,1,targetnumRows,targetnumcolumns); // Local sheet - change to actual name and Local range - change to actual range
TargetRange.clear() //Clear Sheet Content
ls.setValues(values); // Copy from source sheet to local sheet
var sheet = lss.getSheetByName('Country A');
var maxColumns = sheet.getMaxColumns();
var lastColumn = sheet.getLastColumn();
var maxRows = sheet.getMaxRows();
var lastRow = sheet.getLastRow();
if (maxColumns-lastColumn != 0){sheet.deleteColumns(lastColumn+1, maxColumns-lastColumn)};
if (maxRows-lastRow != 0){sheet.deleteRows(lastRow+1, maxRows-lastRow)};
var TargetHour = lss.getSheetByName('Country A').getRange(1,1).setValue(Utilities.formatDate(new Date(), "CST", "MM-dd-yyyy HH:mm:ss"));
}
Please help me. Thank you.
The script stores the values in a 2D array. You have to iterate through the elements and delete the elements where column E (Col number 4) (A=0, B=1,...E=4) is not equal to "Mrm1, Mrm2, Mrm3".
Then you paste the modified array in the second sheet.
Here is an example. You need to adapt it to your code.
function copyData() {
var ss = SpreadsheetApp.openById("YOUR-ID");
// Stores data as a 2D Array
var data = ss.getSheetByName("Sheet1").getRange("A1:M10").getValues();
// Remove rows where column E not equals "Mrm1, Mrm2, Mrm3"
for (var i = 0; i < data.length; i++) {
if (data[i][4] !== "Mrm1" && data[i][4] !== "Mrm2" && data[i][4] !== "Mrm3") {
data.splice(i,1);
i--;
}
}
// Paste data in sheet 2
var pasteRange = "A1:M" + (data.length);
ss.getSheetByName("Sheet2").getRange(pasteRange).setValues(data);
}

Add Timestamp if row is not empty

I have a script on a nightly trigger which does the following three things:
copies the contents of one spreadsheet (spreadsheet 1) to another (spreadsheet 2).
adds a timestamp column to column A each time the script is run.
deletes rows if there are certain values in column D.
The first time the script runs, everything works fine (i.e. when the new spreadsheet 2 is still blank). The subsequent times it runs it encounters issues.
With some research I have discovered that is because any blank rows in the source sheet (spreadsheet 1) are copied to the new spreadsheet (spreadsheet2) and a timestamp is placed in the blank rows. This leaves a bunch of rows that only have a timestamp. By the time the script gets to the part where it is supposed to delete rows based on values it gets thrown by these rows that only have a timestamp.
I am new to google script and was unable to find anything in the forum. Is there a way to modify the script so that the timestamp is only placed on rows where there is data?
var sourceSpreadsheetID = "spreadsheet1 ID";
var sourceWorksheetName = "BusinessDetails";
var targetSpreadsheetID = "spreadsheet2 ID";
var targetWorksheetName = "Sheet5";
function importBusinessDetailsData(){
var thisSpreadsheet = SpreadsheetApp.openById("spreadsheet1 ID");
var thisWorksheet = thisSpreadsheet.getSheetByName("BusinessDetails");
var thisData = thisWorksheet.getDataRange();
var toSpreadsheet = SpreadsheetApp.openById("spreadsheet2 ID");
var toWorksheet = toSpreadsheet.getSheetByName("Sheet5");
var toRange = toWorksheet.getRange(1,2, thisData.getNumRows(), thisData.getNumColumns())
toRange.setValues(thisData.getValues());
setTimeStamp()
main()
removeThenSetNewVals()
}
function setTimeStamp() {
SpreadsheetApp.getActive().getSheetByName('Sheet5')
.getRange('A2:A').setValue(new Date())
};
function main() {
var startTime = new Date().getTime();
var deleteSelectedRows = removeThenSetNewVals();
var runTime = (new Date().getTime() - startTime) / 1000;
Logger.log("Runtime is: " + runTime + " seconds");
};
function removeThenSetNewVals(){
var sheet = SpreadsheetApp.getActive().getSheetByName('Sheet5');
var range = sheet.getDataRange();
var pattern = new RegExp("value1|value2|value3");
var columnToSearch = 3;
var newRangeVals = range.getValues().filter(r => r[0] && !pattern.exec(r[columnToSearch]))
range.clearContent();
var numRows = newRangeVals.length;
var newRange = sheet.getRange(1,1, numRows, newRangeVals[0].length).setValues(newRangeVals);
var maxRows = sheet.getMaxRows();
}
As far as I understand, you only want to write entries to the new sheet which fit a particular condition. Basically, you want to filter the records before you write them, therefore consider the following:
var thisData = thisWorksheet.getDataRange();
var rowsWithData = thisData.filter( row => row[3] )
This states that only rows which contain truthy data will be considered, but feel free to fit the condition according to your needs.
References
filter()
truthy

Running an IF script across multiple ranges

I've put together a script that takes the values of 4 cells in a row ,A23:E23, and duplicates those values in another sheet if a specific (H3) cell in that row contains the text "Live".
The script needs to run daily, which I understand I can do with ease, but it also needs to work with every row below row 23 that contains values, with the reportData and ifd variables working respectively. i.e.
var reportData = reportSheet.getRange("A24...A25...A26:E24...E25...E26").getValues();
var lastRow = recordsSheet.getLastRow();
var ifd = reportSheet.getRange("H24...H25...H25").getValue();
The idea behind this script is to capture a daily snapshot of the values that are in Sheet1 as the values are constantly updated, but as cumulative figures. I need to capture a daily record of these cumulative figures.
function appendToRecords() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var reportSheet = ss.getSheetByName("Sheet1");
var recordsSheet = ss.getSheetByName("database")
var reportData = reportSheet.getRange("A23:E23").getValues();
var lastRow = recordsSheet.getLastRow();
var ifd = reportSheet.getRange("H23").getValue();
if (ifd == "Live"){
recordsSheet.getRange("A2:E2")
.setValues(reportData); }}
Can anyone suggest a way to do this?
Here's a sample sheet that the script works with: https://docs.google.com/spreadsheets/d/1FMlj_9l7Sm0QMKcFpbC4iExbATgPL0jIWoVrvV_Vcfw/edit?usp=sharing
Thanks!
You can easily log all "live" rows to your database like this:
function appendToRecords() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var reportSheet = ss.getSheetByName("Sheet1");
var recordsSheet = ss.getSheetByName("database")
var reportData = reportSheet.getRange("A8:H").getValues();
// Get only rows that are "Live"
// And only get the first five colums
var toWrite = reportData.filter(function(row) {
return row[7] === "Live";
}).map(function(row) {
return row.splice(0, 5);
});
if(!toWrite.length) {return;} // Return if nothing to write
recordsSheet
.getRange(recordsSheet.getLastRow() + 1, 1,
toWrite.length, toWrite[0].length)
.setValues(toWrite);
}

Add data to a spreadsheet from another using script.

I iterate through the rows and get the value of a certain cell like so:
for (var i = 2; i < lastRow; i++) {
if (sheet.getRange(i, getColIndexByName("Department Concerned")).getValue() == "HR") {
// Do some stuff
}
}
I copy data to another sheet like so:
// select the Spreadsheets
var ss = SpreadsheetApp.getActiveSpreadsheet();
var target = SpreadsheetApp.openById("Spreadsheet ID");
// select the Sheets from the Spreadsheets
var source_sheet = ss.getSheetByName("Logs");
var target_sheet = target.getSheetByName("Sheet3");
// select the range from the Sheets
var source_range = source_sheet.getRange("A2:J500");
var target_range = target_sheet.getRange("A2:J500");
// get the values from the source sheet
var values = source_range.getValues();
// set the values to the destination sheet
target_range.setValues(values);
What I need is to copy that data and add it to the same range of the other Spreadsheet depending on the cell value that I just took in my "for loop".
Thank you.
What you think was right, but need to find better approach.
Select values from source sheet
Check each rows, column Department Concerned for "HR" value
Select rows that fulfill above condition
Paste it in target sheet
I combined those scenarios as this,
function myFunction()
{
// select the Spreadsheets
var ss = SpreadsheetApp.getActiveSpreadsheet();
var target = SpreadsheetApp.openById("Spreadsheet ID");
// select the Sheets from the Spreadsheets
var source_sheet = ss.getSheetByName("Logs");
var target_sheet = target.getSheetByName("Sheet3");
// select the range from the Sheets
var source_range = source_sheet.getRange("A2:J500");
// get the values from the source sheet
var values = source_range.getValues();
// an array for selected rows
var selectedRows = [];
for(var row in values)
{
// thinking 5th column is Department Concerned
if(values[row][4] =='HR')
{
//add add entire row to selected 2d array
selectedRows.push(values[row]);
}
}
// set the values to the destination sheet
target_sheet.getRange(2, 1, selectedRows.length,10).setValues(selectedRows);
}