Export / save data to next available row within column - google-apps-script

I'm looking to save data from a particular cell to another sheet. On said sheet I need it to save to the next available row within a defined column.
I have the script below that will save the data to the next available row, but am unsure of how to define the column.
In the example below, I'd need it to be saved into the 'A' column.
function transferList() {
var sourceSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Cancellations");
var sourceData = sourceSheet.getRange("D5").getValues();
var targetSS = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet12");
var targetRangeTop = targetSS.getLastRow();
targetSS.getRange(targetRangeTop+1,1,sourceData.length,sourceData[0].length).setValues(sourceData);
}

Issue:
If I understand you correctly, you want to write this to the first empty cell of a specific column (which may not correspond to the first empty row in the sheet).
Solution:
I'd suggest using Range.getNextDataCell to find the last cell before the first empty one, and Range.offset to get that empty one.
Code sample:
function transferList() {
var columnIndex = 1; // Column A
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getSheetByName("Cancellations");
var sourceData = sourceSheet.getRange("D5").getValue();
var targetSS = ss.getSheetByName("Sheet12");
var a1Range = targetSS.getRange(1,columnIndex);
var targetRange;
if (a1Range.offset(1,0).getValue() !== "") targetRange = a1Range.getNextDataCell(SpreadsheetApp.Direction.DOWN).offset(1,0);
else targetRange = targetSS.getRange(2,columnIndex);
targetRange.setValue(sourceData);
}
Note:
Since you are getting a value from a single cell, there's no need to use getValues and setValues; you can use getValue and setValue instead.

Related

Add date and text at the last row after a copy paste

I'm breaking my head here trying to figure it out a way to achieve this in a simples way.
I got working a code that copies a range from a sheet and paste in another at the last row.
function copyInfo() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("Review");
var pasteSheet = ss.getSheetByName("Log");
// get source range
var source = copySheet.getRange(3,2,15,5);
// get destination range
var destination = pasteSheet.getRange(pasteSheet.getLastRow()+1,3,15,5);
// copy values to destination range
source.copyTo(destination, SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
}
The problem is, at the destination sheet, I still have columns A and B empty. By each row in the source (varies from time to time) copied, I need to place at column A todays date and column B the text "Review".
Like: Date (column A) | Revview (column B) | Pasted Data from Source (column C and other)
Do I need to write a completely new code to check for empty or can I implement both solutions into this code?
The code should fill the two cells before your data. It also caters for the setup where you have three areas in the same sheet.
Each copyInfoXd_button function will be assigned to your button image.
function copyInfo1d_button() {
copyInfo(2, "B1:B");
}
function copyInfo7d_button() {
copyInfo(9, "I1:I");
}
function copyInfo30d_button() {
copyInfo(16, "P1:P");
}
function copyInfo(startingCol, subjectCol)
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("Review");
var pasteSheet = ss.getSheetByName("Log");
const sourceCols = 4; //actual number of columns to copy, not including the empty column H
const destCols = 6; //actual number of columns to write to, from DATE to OBS
//find the last row from a colum
var avals = copySheet.getRange(subjectCol).getValues();
var lastRow = avals.filter(String).length;
var rowsToCopy = lastRow - 2; //skip the first 2 rows as they are headers
// get source range
var source = copySheet.getRange(3,startingCol,rowsToCopy,sourceCols); // row, column, number of rows and number of columns
// get destination range
var destination = pasteSheet.getRange(pasteSheet.getLastRow()+1,1,rowsToCopy,destCols);
var data = [];
var sourceValues = source.getValues();
//construct new data for the destination range
for (var row in sourceValues) {
var destRow = [Utilities.formatDate(new Date(), ss.getSpreadsheetTimeZone(), 'MMMM dd, yyyy'), 'Review'];
destRow = destRow.concat(sourceValues[row]);
data.push(destRow);
}
destination.setValues(data);
}
I made it! I'm so proud! Thank you all for the help!
I'm beginning to do stuff like this!
After the Charles answer I looked for a way to add to each row. However, I know the code might not be too elegant, and I couldn't figured it out a way of doing using script itself, so I added a helper cell inside the sheet in H1 and H2.
Here's the solution:
function copyInfo24() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var copySheet = ss.getSheetByName("Review");
var pasteSheet = ss.getSheetByName("Log");
// get source range
var source = copySheet.getRange(4,2,99,5);
// get destination range
var destination = pasteSheet.getRange(pasteSheet.getLastRow()+1,3,99,5);
// copy values to destination range
source.copyTo(destination, SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
// Sets date at Column A and "Review" at Column B.
var data = [];
for(var i =0; i < copySheet.getRange("H1").getValue(); i++) {
data.push([Utilities.formatDate(new Date(), ss.getSpreadsheetTimeZone(), 'MMMM dd, yyyy'), 'Review']);
}
reviewRange = pasteSheet.getRange(pasteSheet.getLastRow()-copySheet.getRange("H2").getValue(), 1, copySheet.getRange("H1").getValue(), 2)
reviewRange.setValues(data); //set the date and 'Review' data
}

Script to copy a changing range to cell B2

I am trying to write a script to copy a range of cells to cell B2. The range to copy from changes each time so want to highlight the top left cell and then the script takes it from there. What I have so far is:
function CopyToB2() {
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getActiveSheet();
var cellRange = sheet.getActiveCell();
var selectedColumn = cellRange.getColumn();
var selectedRow = cellRange.getRow();
var range = SpreadsheetApp.getActiveSheet().getRange(selectedColumn,selectedRow,2,43);
range.setValues(range);
spreadsheet.getRange('B2').activate();
(spreadsheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);
};
but get the error
Exception: The parameters (SpreadsheetApp.Range) don't match the
method signature for SpreadsheetApp.Range.setValues
Explanation:
The main issue with your code is that you pass a range object in the setValues function and therefore you are getting this error.
A second issue is that you passed the parameters of the getRange(row, column, numRows, numColumns) function in the wrong order. It should be:
getRange(selectedRow,selectedColumn,43,2)
instead of getRange(selectedColumn,selectedRow,2,43)
A third issue is that you need to define the range that the data will be pasted to and that can't be just a single cell B2 in this case. What you need to do is to define B2 as the start of your pasting range and then set the values of your active range.
Solution:
function CopyToB2() {
var spreadsheet = SpreadsheetApp.getActive();
var sheet = spreadsheet.getActiveSheet();
var cellRange = sheet.getActiveCell();
var selectedColumn = cellRange.getColumn();
var selectedRow = cellRange.getRow();
var dataRange = sheet.getRange(selectedRow,selectedColumn,43,2).getValues();
sheet.getRange(2,2,dataRange.length,dataRange[0].length).setValues(dataRange);
};

Get new in put values in a row using App script

How do I get the new input values in google sheet using App Script. I currently get the values when I specify which cells, but I want it to be dynamic. Please help me.
function getValuesinSheet(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
sheet.getRange("B1").setValue("Email");
sheet.getRange("A1").setValue("Amount");
sheet.getRange("C1").setValue("Phone Number");
sheet.getRange("D1").setValue("Email Subject");
sheet.getRange("E1").setValue("Message");
var amount = parseInt(sheet.getRange("A2").getValues()) ;
var email = String(sheet.getRange("B2").getValues());
var snumber = String(sheet.getRange("C2").getValues());
var esubject = String(sheet.getRange("D2").getValues()) ;
var emessage = String(sheet.getRange("E2").getValues());
}
(Option 1)
You can use onEdit Simple Trigger, to execute an apps script function every time a cell is being modified to read/modify your sheets.
Sample Code:
function onEdit(e){
var ss = e.source; //Get the spreadsheet
var cell = e.range; //Get the range of the edited cell
var sheet = ss.getActiveSheet(); //Get the modified sheet
var row = cell.getRow();
var col = cell.getColumn();
//valid cell are within A2:E. If row ==1 or col > 5 do nothing
if(row==1 || col > 5){
return;
}
//Get the current row's first 5 columns
//Change 2-d array to 1-d array using flat()
var rowValues = sheet.getRange(row,1,1,5).getDisplayValues().flat();
if(rowValues.filter(String).length == 5){
Logger.log("DO SOMETHING")
var amount = parseInt(rowValues[0]);
var email = rowValues[1];
var snumber = rowValues[2];
var esubject = rowValues[3];
var emessage = rowValues[4];
Logger.log(amount);
Logger.log(email);
Logger.log(snumber);
Logger.log(esubject);
Logger.log(emessage);
}
}
What it does?
Get the active sheet and active cell using the onEdit() events object
Get the active cell's row and column index (apps script used one-based as index)
Check if modified cell is within A2:E range, by checking row and column index
Get the current row values from column A:E using Sheet.getRange(row, column, numRows, numColumns) and Range.getDisplayValues()
I used Range.getDisplayValues(), since it will return a 2-d array of string. I noticed that you expect your inputs as a string and you plan to convert the amount to int using parseInt()
Use flat() to convert 2-d array to 1-d array
Check the array if all the columns are not empty using filter(), if array length is 5. Then all data in the row is complete
Note:
You can remove the condition in Step 6 if you want to process the current row's column A-E values even if some data are empty.
You can also remove the condition in Step 3 based on your preference. I just included that so that the succeeding process will only be executed when cell being modified are within A2:E
Additional Information
If you are new with Simple Triggers, you cannot debug your code by running it in the Apps Script Editor. If you want to debug your code, you need to modify a specific cell in your sheet then check the latest logs in the Executions tab.
Example:
(Option 2)
If you don't prefer to use onEdit() Simple trigger. You can just use getActiveCell() to get the current selected cell row and column index
Sample Code:
function getRowValues(){
var ss = SpreadsheetApp.getActiveSpreadsheet(); //Get the spreadsheet
var cell = ss.getActiveCell(); //Get the range of the edited cell
var sheet = ss.getActiveSheet(); //Get the modified sheet
var row = cell.getRow();
var col = cell.getColumn();
//valid cell are within A2:E. If row ==1 or col > 5 do nothing
if(row==1 || col > 5){
return;
}
//Get the current row's first 5 columns
//Change 2-d array to 1-d array using flat()
var rowValues = sheet.getRange(row,1,1,5).getDisplayValues().flat();
if(rowValues.filter(String).length == 5){
Logger.log("DO SOMETHING")
var amount = parseInt(rowValues[0]);
var email = rowValues[1];
var snumber = rowValues[2];
var esubject = rowValues[3];
var emessage = rowValues[4];
Logger.log(amount);
Logger.log(email);
Logger.log(snumber);
Logger.log(esubject);
Logger.log(emessage);
}
}

Copy -Paste into next available row in selected column

I am trying to write a script that is tied to a button so that when clicked it copies my selected range into the next available row based on contents in column A. I have formulas in column D and currently when ran it pastes into the next available row but I would like it to paste into the next available row based on if column A has data.
Here is what I have so far
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet ();
var source = ss.getRange ("JOB BUILD!A3:E21");
var destSheet = ss.getSheetByName("JOB IN PROGRESS");
var destRange = destSheet.getRange(destSheet.getLastRow()+1,1);
source.copyTo (destRange, {contentsOnly: false})
}
If you want to paste the values based on the last available row from a certain column, you will have to find the last row of that column.
In order to get the last row of a certain row, you can use this method from this answer. Assuming you want to paste the values based on column A from the destSheet, you can try the below code:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getSheetByName("JOB BUILD");
var sourceData = sourceSheet.getRange("A3:E21");
var destSheet = ss.getSheetByName("JOB IN PROGRESS");
var aRange = destSheet.getRange("A1:A").getValues();
var colA = aRange.filter(String).length;
var destRange = destSheet.getRange(colA, "COL_NO", "NO_OF_ROWS", "NO_OF_COLS");
sourceData.copyTo(destRange, {
contentsOnly: false
})
}
Note
Please bear in mind that depending on the exact structure of your data from the two sheets, you will have to adjust the ranges.
Reference
Determining the last row in a single column;
Apps Script Sheet Class - getRange(row, column, numRows, numColumns).

Re: Copy every row of Data from one sheet that has a given value to another sheet

I saw your answer in an old thread and i wanted to ask for clarification. This is the thread i am referring to: Copy every row of Data from one sheet that has a given value in column K to another sheet
My issue is, I'm using a version of your skeleton script, but i am having some trouble. Instead of the script copying the entire row, it seems to be copying the first column in the conditional rows and pasting the results of the array all in a single row.
Here is my script as is:
function formSubmitCriticalAltThree(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Form Responses");
var lastRow = ss.getLastRow();
var target = ss.getSheetByName("Chad");
var data = sheet.getDataRange().getValues();
var line = new Array();
var targetArray= new Array();
for (n=0;n<data.length;++n){ // iterate rows
if (data[n][10] == "cbellani"){ // if condition is true copy the whole row to target
line.push(data[n]);// copy the whole row
}//if
}//for
if(line.length>0){// if there is something to copy
targetArray.push(line)}// add row to destination
target.getRange(3,1,targetArray.length,targetArray[0].length).setValues(targetArray);
}
Any help on this would be greatly appreciated.
I have not tested this, but I think it should look like this:
function formSubmitCriticalAltThree(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Form Responses");
var lastRow = ss.getLastRow();
var target = ss.getSheetByName("Chad");
var data = sheet.getDataRange().getValues();
var targetArray = new Array();
for (var n = 0; n < data.length; ++n){ // iterate rows
if (data[n][10] == "cbellani") { // if condition is true copy the whole row to target
targetArray.push(data[n])}// add row to destination
}//if
}//for
target.getRange(3,1,targetArray.length,targetArray[0].length).setValues(targetArray);
}