Copy and Paste the Row based on condition in another Sheet - google-apps-script

I've been looking on this website and others for an answer but can't find anything relevant and was wondering if someone could help please.
I've using Apps Script - Google Sheets.
The main sheet was called "M-Front". So it got quotation number with revision number. If new quotation, the revision will be zero. If we revise the quotation once, the revision number will be 1.
For example, GE-2108-0271-Rev.0 is new quotation.
If we revise once, it would be GE-2108-0271-Rev.1.
I have other sheet called "M-Items".
Let say for GE-2108-0271-Rev.0, we have three rows for that quotation number represent three items for that quotation.
My intention is , if new revision was made in "M-Front". It will be GE-2108-0271-Rev.1. But how to detect the last row from "M-Front" quotation number and in "M-Items" we copy and paste the rows. In this case, 3 rows/items. and make the quotation in "M-Items" from GE-2108-0271-Rev.0 to GE-2108-0271-Rev.1.
M-Front
M-Items
The Script i've stuck
function CopyRange() {
var sourcespread = SpreadsheetApp.openById('1Zgs1jzjIeaBpd5Ms7emQgxhVJBMtlEOlDNDfxlhSRiY'); //replace with source ID
var sourcesheet = sourcespread.getSheetByName('M-Front'); //replace with source Sheet tab name
var destspread = SpreadsheetApp.openById('1Zgs1jzjIeaBpd5Ms7emQgxhVJBMtlEOlDNDfxlhSRiY'); //replace with destination ID
var destsheet = destspread.getSheetByName('M-Items'); //replace with destination Sheet tab name
var testrange = sourcesheet.getRange('M:M').getLastRow;
var testvalue = (testrange.getValues());
var data = [];
var j =[];
for (i=0;i<testvalue.length;i++) {
if (testvalue[i] /= 0) {
data.push.apply(data,sourcesheet.getRange('A:A').getValues());
//Copy matched ROW numbers to j
j.push(i);
}
}
//Copy data array to destination sheet
destsheet.getRange(destsheet.getLastRow()+1,1,data.length,data[0].length).setValues(data);
}

You might want to try the below script:
function CopyRange() {
var sourcespread = SpreadsheetApp.openById('1Zgs1jzjIeaBpd5Ms7emQgxhVJBMtlEOlDNDfxlhSRiY'); //replace with source ID
var sourcesheet = sourcespread.getSheetByName('M-Front'); //replace with source Sheet tab name
var destsheet = sourcespread.getSheetByName('M-Items'); //replace with destination Sheet tab name
var mcol= sourcesheet.getRange('M1:M').getValues();
var acol = sourcesheet.getRange('A1:A').getValues();
var ccol = destsheet.getRange('C1:C').getValues();
var acol2 = destsheet.getRange('A1:A').getValues();
var mvalues = mcol.filter(String);
var avalues = acol.filter(String);
var cvalues = ccol.filter(String);
var avalues2 = acol2.filter(String);
for (let i=1; i<mvalues.length; i++) {
if (mvalues[i][0] != 0) {
if (avalues[i][0] == avalues2[i][0] && mvalues[i][0] == cvalues[i][0] - 1)
var valuescopy = sourcesheet.getRange("RANGE_FOR_THE_VALUES_TO_COPY").getValues();
destsheet.getRange("RANGE_WHERE_TO_PASTE").setValues(valuescopy);
cvalues[i][0]++;
}
}
}
It is important to note the following points:
getLastRow will return the last row for the entire range - this means that the rows which have no values are also included this;
In order to retrieve the rows which contain a value, the filter has been used.
getValues method will return a 2D array, so you will have to access an element in this way array[i][j].
Moreover, please bear in mind that you will have to adjust the ranges properly such that they match your needs accordingly; more specifically, the range from where you want to copy the values and also the destination range.
Reference
getLastRow();
getValues();
getRange(row, column, numRows, numColumns).

Related

Google table script: filter by value, copy and paste individual columns, not the entire range

Good health to all! In this case, the row contains 136 columns, we filter by the 8th column, then we need to copy and paste into another file, for example, columns 134-136. I set the range var rng = sht.getRange(3,134,10000,3), I thought it would be similar to the FILTER() function, but no - the script works only if the range contains a column by which we filter... There was also a decision to insert all 136 columns and delete unnecessary 133, but this is generally, as it seems to me, inhumane.
Can you tell me what needs to be changed in the existing code so that you can copy and paste a filtered range that does not contain the column that is being filtered?
How can the script be modified so that it can be filtered by two or more columns?
Here I found a piece of code that filters the Google table by value and inserts the selected rows into the specified sheet.
I would be grateful for a tip on the optimal solutions for each issue
function CopyPaste()
{//the quantity is written
const SOURCE1 = SpreadsheetApp.openById("Here is the Google table ID");
const sht = SOURCE1.getSheetByName("Sales");
var ss = SpreadsheetApp.getActive();
var sheet2 = ss.getSheetByName("Monitor"); //settings sheet
var diap = sheet2.getRange("A1").getValue(); //value for the filter
var rng = sht.getRange(3,1,10000,136);// filtered range
var PasteSht = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet 3');// sheet for inserting data in the current workbook
var rngA = rng.getValues();//this is where a fragment of someone else's code came from (I didn't rename variables)
var yesesA = []
for(var i=0;i<rngA.length;i++)
{
if(rngA[i][7]==diap)
{
yesesA.push(rngA[i])
}
}
var yesesRng = PasteSht.getRange(3, 1, yesesA.length, yesesA[0].length);
yesesRng.setValues(yesesA);
}
Try this
Code.gs
function CopyPaste() { //the quantity is written
const SOURCE1 = SpreadsheetApp.openById("Here is the Google table ID");
const sht = SOURCE1.getSheetByName("Sales");
var ss = SpreadsheetApp.getActive();
var sheet2 = ss.getSheetByName("Monitor"); //settings sheet
var diap = sheet2.getRange("A1").getValue(); //value for the filter
var rng = sht.getDataRange(); // filtered range
var PasteSht = ss.getSheetByName('Sheet 3');// sheet for inserting data in the current workbook
var rngA = rng.getValues();//this is where a fragment of someone else's code came from (I didn't rename variables)
var yesesA = rngA.filter( row => row[7] === diap ); // filter out all rows including diap
ysesA = yesesA.map( row => row.slice(132,136) ); // Array.slice(from,to(not including)) columns 133-136
var yesesRng = PasteSht.getRange(3, 1, yesesA.length, yesesA[0].length);
yesesRng.setValues(yesesA);
}
Reference
Array.filter()
Array.map()
Arrow function expression

Apps Script Copy and Paste Rows if Condition is Met In Few Pages

Now, I’m using Apps Script in Google Sheet.
I’ve a few pages with respective details for each quotation number.
How to Copy and Paste specific rows from specific sheets to its same sheet at the bottom(after last row) when condition is met.
Let say, I need all details for GE-2108-0271-Rev.0 quotation number in few pages to be copy and paste at the same sheet itself.
And the quotation number increment by 1 . So it would be GE-2108-0271-Rev.1 after paste it.
To be exact, here is an example:
Page 1:
to be exact I need the number increment by 1 from GE-2108-0271-Rev.0 to GE-2108-0271-Rev.1 (column 2)
Page 2:
let say got 3 items
Page 3:
Let say got 1 item
Here, I try to make it happen for one sheet : M-Items
This is where i stuck
function CopyRange() {
var sourcespread = SpreadsheetApp.openById('2032798963'); //replace with source ID
var sourcesheet = sourcespread.getSheetByName('M-Front'); //replace with source Sheet tab name
var destspread = SpreadsheetApp.openById('977978664'); //replace with destination ID
var destsheet = destspread.getSheetByName('M-Items'); //replace with destination Sheet tab name
var testrange = sourcesheet.getRange('M:M');
var testvalue = (testrange.setNumberFormat("0").getValues());
var data = [];
var j =[];
for (i=0;i<testvalue.length;i++) {
if (testvalue[i] /= 0) {
data.push.apply(data,sourcesheet.getRange(i+1,1,1,3).getValues());
//Copy matched ROW numbers to j
j.push(i);
}
}
//Copy data array to destination sheet
destsheet.getRange(destsheet.getLastRow()+1,1,data.length,data[0].length).setValues(data);
}

Find cells based off search, change their value, then add to a list on new sheet?

Ok, title might be confusing. I mean, I'm confused just trying to make this work.
I essentially have 3 sheets.
The Search Sheet - Has a search box & macro button.
The Data Sheet - self explanatory.
The Target Sheet - Sorted into columns.
So, what I'm needing to happen is: when a user enters a value in the Search Sheet & hits the "go" button, it searches the Data sheet for any cells in column B that match. On a match, it modifies the matched cell so it won't match on another search, then copies the adjacent cell 'A' value into the first column of the Target Sheet, contuingin down the sheet & adding each match to the same column.
On a new search, the results will show in the 2nd column, etc...
Search1 = "L1" | Search 2 = "L3"
Data Sheet:
DataSheet
Result Sheet:
Result Sheet
Here's my shitty attempt at scripting it. I probably defined the wrong things & didn't define right things. I'm trying to wrap my head around it, but I think I've gotten into the deep end too fast.
function moveTest() {
var ss = SpreadsheetApp.getActiveSpreadsheet(); //Spreadsheet
var source = ss.getSheetByName("Close"); //Input Sheet
var sourceData = ss.getSheetByName("Raw_Data"); //Data Sheet (List of all data)
var target = ss.getSheetByName("Pallet_Data"); //Target Sheet
var dataRange = data.getRange("B:B").getValues; //Range To Search on Data Sheet
var lastcolumn = target.getLastColumn(); //Last Column of Target
var searchval = [[source.getRange("A2").getValue()]]; //Search String
var targetRange = target.getRange("A"+(lastcolumn+1)+":C"+(lastcolumn+1)); //Define New Range n+1
//var rIndex = getRowIndex(); //row index of Data
//var cIndex = getColumnindex(); //column index of Data
while (dataRange has_data) { // For each row that has data in column B...
if (Bn = searchval) { // If B in row 'n' matches the search value
var rIndex = sourceData.getRowIndex(); // Define that row
var match = sourceData.getActiveCell // Defines B of matched row
var firstcell = rIndex.getRange(??) // Define cell A of that row
match.setValue('Moved'); // Change value of B in matched row so it won't match on new search
firstcell.copyTo(lastcolumn) //Copy Cell A of defined row into last column of target sheet
//Add next match to bottom of SAME Column then start NEW Column when function is run again.
}
}
Thanks
Solution:
Your script could look like this:
function cellMatch() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName("Data");
var sheet2 = ss.getSheetByName("Result");
var sheet3 = ss.getSheetByName("Search");
var lr = sheet1.getLastRow();
var data = sheet1.getRange(2,1,lr-1,2).getValues();
var lc = sheet2.getLastColumn()+1;
var key = sheet3.getRange("B1").getValue();
var matched = [["Search "+lc]];
for (var i=0; i<lr-1; i++) {
if (data[i][1] == key) {
var temp = [];
temp.push(data[i][0]);
matched.push(temp);
}
}
var result = sheet2.getRange(1,lc,matched.length);
result.setValues(matched);
}
This should take the search key from Search sheet, compare it with the Data sheet, and place the results into Result sheet.
Sample Data:
This is the result after executing the script twice, for L1 and L3.

Google Sheets Macro for deleting columns in specific tabs based on header

I wrote a macro that creates sheet tabs and populates them based on specific criteria. For example, if I want to isolate rows indicating Closed Won, and move them to a new tab. I will run this function on my main tab called 'data' and create a new tab called 'Closed Won'.
This new tab will duplicate the same header as in 'data', and then it will populate with all rows with "Closed Won" in column L.
However, this new tab has more data than I need. I want to delete specific columns IF they have a column name AND tab name (so it does not delete the columns in my original data tab).
I am having trouble with the IF. Can someone help with a simple script that I can add to the end of the original function?
function closed_won() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('1:1').activate();
spreadsheet.insertSheet(1);
spreadsheet.getRange('1:1').activate();
spreadsheet.getActiveSheet().setName('closed_won');
spreadsheet.getRange('data!1:1').copyTo(spreadsheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('data');
var testrange = sheet.getRange('L:L');
var testvalue = (testrange.getValues());
var csh = ss.getSheetByName('closed_won');
var data = [];
var j =[];
for (i=0; i<testvalue.length;i++) {
if ( testvalue[i] == 'Closed Won') {
data.push.apply(data,sheet.getRange(i+1,1,1,25).getValues());
j.push(i);
}
}
csh.getRange(csh.getLastRow()+1,1,data.length,data[0].length).setValues(data);
// THIS IS WHERE I WANT TO ADD THE DELETE COLUMN CODE
}
You want to delete columns where the header name matches a sheet name - though obviously not on the current sheet.
The process is:
get the sheets and their names; save them in an array
get the header row. This will be a 2D array, so "flatten" it to 1D for easier matching
loop through the headers and look for a match with sheet names. The code uses indexOf for this.
3.1 when you find a match of header name and column name, make sure that its not the match for the current sheet
3.2. create an array of the column numbers to be deleted.
After the loop, reverse the order of the array so that the "highest" to-be-deleted column numbers are listed first.
Loop through the to-be-deleted column numbers, and delete the columns
function SO5819343001() {
var spreadsheet = SpreadsheetApp.getActive();
// get sheets names
var thesheets = [];
var sheets = spreadsheet.getSheets();
if (sheets.length > 1) {
for (var i=0; i<sheets.length;i++){
thesheets.push(sheets[i].getName());
}
}
// move to 'closed_won'
var csh = spreadsheet.getSheetByName('closed_won');
// get the headers
//last column for range
var cshLC = csh.getLastColumn();
var headers = csh.getRange(1,1,1,cshLC).getValues();
// flatten headers from 2D to 1D
var flatheaders = headers.reduce(function(a, b){return a.concat(b);});
// Logger.log(flatheaders); DEBUG
// create variables for loop
var cshname = csh.getName();
var deletions = [];
// loop through the headers and compare to sheet names
for (var h = 0; h<cshLC;h++){
var idx = thesheets.indexOf(flatheaders[h]);
// Logger.log("DEBUG: h = "+h+", header = "+flatheaders[h]+", match = "+idx)
// is this a match?
if (idx !=-1){
// found a match for column name and sheet name
// make sure it is not this sheet
if (flatheaders[h] != cshname){
// Logger.log("DEBUG: the match is NOT on this sheet. Proceeding")
// create an array of the column numbers to be deleted
deletions.push(h+1);
}
else{
Logger.log("the match IS on this sheet. Abort.")
}
}
}
// Logger.log(deletions); DEBUG
// reverse the column order
var rev_deletions = deletions.reverse();
// Logger.log(rev_deletions); // DEBUG
// loop through the 'to-be-deleted' columns and delete them
for (d = 0;d<deletions.length;d++){
csh.deleteColumn(rev_deletions[d]);
}
}

Copy a row with specific cells to another spreadsheet

I have been searching for a way to copy certain cells from a row and paste them into another spreadsheet, but all I can seem to find are ways to do that just from sheet to sheet within one spreadsheet or questions that deal with code way above my head. I'm just now learning to code in Google Spreadsheets and I can't seem to get it right. Here is my code for now, I'm working on just copying one cell first and after I can do that I'll get a loop to iterate through the row and pick the cells I want to copy.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var master = SpreadsheetApp.openById('0AgcCWQn-aoI1dFpLVE4tSENwcThrYnlMUzhuRmdWU2c');
var target = SpreadsheetApp.openById('0AgcCWQn-aoI1dF96X2dBT2dVVFZ2SU1NRWdYTDJhT2c');
var master_sheet = master.getSheetByName("Steve2");
var target_sheet = target.getSheetByName("Corbin1");
var master_range = master_sheet.getRange("A1");
var target_range = target_sheet.getRange("A1");
master_range.copyTo(target_range);
Right now it is giving me an error saying that it cannot call the getRange method of null. I'm not sure if I'm using OpenById correctly or if I can even use that in this situation.
OK I've got it working now. It copies the row perfectly and it copies only the cells I want. Now I need help with the pasting part. It copies everything fine and puts it into the other sheet great, but I need it to copy into the next available row and into the first available columns. So if row 5 is the last column of data, I need it to paste into row 6 and take up the first 6 or so columns.
This is what I have so far.
function menuItem1() {
var sss = SpreadsheetApp.openById('0AgcCWQn-aoI1dFpLVE4tSENwcThrYnlMUzhuRmdWU2c'); // sss = source spreadsheet Steve2
var ss = sss.getSheetByName('Sheet1'); // ss = source sheet
//Message box asking user to specify the row to be copied
var answer = Browser.inputBox('What row would you like to copy?');
var range = parseInt(answer);
var array = [1,2,3,9,12,30];
//Runs a loop to iterate through array, using array elements as column numbers
for(var i = 0; i < array.length; i++){
var SRange = ss.getRange(answer,1,1,array[i]);
//get A1 notation identifying the range
var A1Range = SRange.getA1Notation();
//get the data values in range
var SData = SRange.getValues();
}
var tss = SpreadsheetApp.openById('0AgcCWQn-aoI1dF96X2dBT2dVVFZ2SU1NRWdYTDJhT2c'); // tss = target spreadsheet Corbin1
var ts = tss.getSheetByName('Sheet1'); // ts = target sheet
//set the target range to the values of the source data
ts.getRange(A1Range).setValues(SData);
//Confirmation message that the row was copied
Browser.msgBox('You have successfully copied Row: ' + answer);
}
You are getting this error maybe because your spreadsheet does not have a sheet called Steve2 or Cobin1. Try using the method master.getSheets()[0], this way you will get the first sheet without using their name.
You can algo use this piece of code to check the sheets names:
for(var x in master.getSheets()) {
Logger.log(master.getSheets()[x].getSheetName());
}
best,