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);
}
}
Related
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);
}
We use google sheets for our invoice system. Once we pull the order, we fill in the invoice and anything that we do not have we backorder. We type BO in column I. In excel, we used a button that we could click to copy those cells to our 2nd sheet. We need cells A & B to copy to sheet 2 (which is an exact copy of sheet 1) if column I says BO. Here's what I have so far. This almost works... It deletes everything above the rows with data though and copies the data even if column I doesn't have BO.
I need it to just copy Column A & B if column I says BO to sheet 2 (which is a duplicated of sheet 1) I'm sure there's a simple way, but I can't seem to figure it out.
function Backorder() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Carolina Fireworks Order Form");
var columnToSearch = 9; // I column
Logger.log(sheet.getLastRow());
var range =sheet.getRange(1,columnToSearch,sheet.getLastRow(),columnToSearch);
var destination = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Back Order");
var values = range.getValues();
//Destination
var numberOfColumns = 12;
var numberOfRows = 223 ;
var startColumn = 1;
var startRow = 12;
// equivalent to destination.getRange('A1:L223');
var destinationRange= destination.getRange(startRow, startColumn,numberOfRows,numberOfColumns);
var count = '0';
for(var i=0;i<values.length;i++){
Logger.log("i is now: " +i);
Logger.log("Current row value: " +values[i][0])
if(values[i][0] == 'BO'){
Logger.log("*** Value found in column: " +values[i][0] +"**** \n Count: " +i);
count++;
var rangeToCopy = sheet.getRange(i, 1,numberOfRows,numberOfColumns);
rangeToCopy.copyTo(destinationRange);
}
}
}
SOLUTION
**Updated **
The updated script below will loop through the sourceSheet on every row and it specifically checks if every row on column I says "BO".
If there's a match on that specific row of column I, the row # from the loop will be added to rangeToCopy variable (e.g. range "A(row #):B(row #)" in A1 notation). Then, the rangeToCopy will be copied to the destination in the same exact range of rangeToCopy, given that the destination is the same exact copy of sourceSheet.
function backOrder(){
var sheet = SpreadsheetApp.getActive();
var sourceSheet = sheet.getSheetByName("Carolina Fireworks Order Form");
var destination = sheet.getSheetByName("Back Order");
var lastRow = sourceSheet.getDataRange().getLastRow();
//LOOP THROUGH SOURCE SHEET
for(var row=1; row<=lastRow; row++){
//CHECK FOR "BO" ON EVERY ROWS OF COL I ON SOURCESHEET
if(sourceSheet.getRange(row,9).getValue() == "BO"){
Logger.log("CELL I"+row+" has \"BO\""+"\n=================\n"+"RANGE TO COPY:\n"+ "\"A"+row+":B"+row+"\"");
var rangeToCopy = "A"+row+":B"+row;
sourceSheet.getRange(rangeToCopy).copyTo(destination.getRange(rangeToCopy));
sourceSheet.getRange(row,9).setValue("- BO").setHorizontalAlignment("right");
}
}
}
RESULT
Sample filled out Carolina Fireworks Order Form sheet:
The Back Order sheet after running the script:
Execution logs result for review:
I come from a VB background and am having some trouble implementing a scripts solution for Sheets, I imagine the function is fairly basic but am not yet sure how to express it in JS. The goal is to loop through each cell in a range (Sheet 1, Q3:Q1000), get the row number where the cell in that range has the value "TRUE", copy/cut the entirety of each row on Sheet 1 that meets that qualification (or simply store the values and skip the copy/paste step), paste the values to the first unused row on a separate sheet (Sheet2), then delete the original row on Sheet1.
So far, I have managed to put together this crude function which successfully finds the row number of the first cell in the given range containing the specified value, but it returns NaN if there is more than one occurrence of the value in the range. Any indication as to what I am doing wrong will be helpful, thank you.
function onEditTesting(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName("Sheet1");
const range = "Q3:1000";
var whereTrue = "TRUE";
var range = sheet.getRange("Q3:Q1000");
var rangeValues = sheet.getRange(range).getValues();
var i = [];
for (var y = 0; y < rangeValues.length; y++) {
if(rangeValues[y] == whereTrue){
i.push(y);
}
}
var Row = Number(i)+Number(range.getRow());
}
function moveData() {
const ss=SpreadsheetApp.getActive();
const ssh=ss.getSheetByName('Sheet1');
const dsh=ss.getSheetByName('Sheet2');
const vs=ssh.getRange(3,1,ssh.getLastRow()-2,ssh.getLastColumn()).getValues();
let oA=[];
let d=0;
vs.forEach((r,i)=>{
if(r[16]=='TRUE') {
oA.push(r);
ssh.deleteRow(i+3-d++);
}
});
dsh.getRange(dsh.getLastRow()+1,1,oA.length,oA[0].length).setValues(oa);
}
Here is another approach using onEdit() Simple Trigger.
Sample Code:
function onEdit(e) {
var ss = e.source;
var cell = e.range;
var sourceSheet = ss.getActiveSheet();
var destinationSheet = ss.getSheetByName("Sheet2");
var col = cell.getColumn();
var row = cell.getRow();
var lastCol = sourceSheet.getLastColumn();
Logger.log("row: "+row+" maxCol: "+lastCol+" col: "+col+" val: "+cell.getDisplayValue()+" sheet: "+sourceSheet.getName());
//Check if modified cell is in column Q (index 17) in Sheet1 has a value of TRUE
if(sourceSheet.getName() == "Sheet1" && col == 17 && cell.getDisplayValue() == "TRUE"){
//Append current row to the destination sheet
var values = sourceSheet.getRange(row,1,1,lastCol).getValues();
Logger.log(values);
destinationSheet.appendRow(values.flat());
//Delete current row
sourceSheet.deleteRow(row);
}
}
What it does?
Get the sourceSheet and cell modified using e.range event object
Check the cell modified if it is in column Q (index 17) of Sheet1 having a value of "TRUE". I used Range.getDisplayValue() to get the actual string value of the cell because when I test it using Range.getValue() it gave me a boolean object
Get the row values from the first column up to the last column of the current row using Sheet.getLastColumn() and Sheet.getRange(row, column, numRows, numColumns)
Append the current row values of the source sheet to your destination sheet using Sheet.appendRow(rowContents) where rowContents is a 1-d array and since the Range.getValues() returns a 2-d array, I used array.flat() to convert 2-d array to 1-d array
Delete the current row using Sheet.deleteRow(rowPosition)
Output:
Before (Sheet1):
After (Sheet1):
After (Sheet2):
How do I find the data in a column within an active row that is already defined in Google Apps Script?
I have an on edit function that sends an email when a column f is edited to a specific value. I need to find out the value in column b in order to include the value in the body of the message.
I have tried to use a range, but I am not understanding how i can define the second column for the active range that is already defined in the row variable. Here is what my code looks like. var called Values is the row of code I need help with. The row var is looking at the correct row. Any help is greatly appreciated.
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var sheetName = sheet.getName();
var cell = sheet.getActiveCell().getA1Notation();
var row = sheet.getActiveRange().getRow();
var cellvalue = sheet.getActiveCell().getValue().toString();
var values = row.getcell()[0,2].getvalue().toString();
var recipients = "kel...#trafficbuilders.us";
var message = '';
if(cellvalue === '✔'){
message = 'All Items have been received for .';
var subject = 'All Items have been received for ' ;
var body = message + ' Visit ' + ss.getUrl() + ' to view the changes';
MailApp.sendEmail(recipients, subject, body);
}
}
To fetch a certain data/value from a certain cell, here's what you can do:
First identify the cell where data is located using getRange(). There are several ways to use getRange.
Sample from the docs:
// Get a range A1:D4 on sheet titled "Invoices"
var ss = SpreadsheetApp.getActiveSpreadsheet();
var range = ss.getRange("Sheet!A1:D4");
// Get cell A1 on the first sheet
var sheet = ss.getSheets()[0];
var cell = sheet.getRange("A1");
To actually fetch the content/data, use getValues() or getValue()
sample snippets:
// The code below gets the values for the range C2:G8
// in the active spreadsheet. Note that this is a JavaScript array.
var values = SpreadsheetApp.getActiveSheet().getRange(2, 3, 6, 4).getValues();
Logger.log(values[0][0]);
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
// Passing only two arguments returns a "range" with a single cell.
var range = sheet.getRange(1, 1);
var values = range.getValues();
Logger.log(values[0][0]);
I have the following script (some of which I found and modified to my needs:
function onedit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var targetSheetName = "Completed";
var sourceSheetName = "Eligibility & Pre-Auths"
var targetSheet = ss.getSheetByName(targetSheetName);
var sourceSheet = ss.getActiveSheet();
var sourceRow = sourceSheet.getActiveRange().getRow();
var targetRow = targetSheet.getLastRow() + 1;
if (sourceSheet.getName() == SourceSheetName) {;
if (sourceRow[22]=="Yes") {;
if (targetRow > targetSheet.getMaxRows()) targetSheet.insertRowAfter(targetRow - 1);
sourceSheet.getRange(sourceRow, 1, 1, sourceSheet.getLastColumn()).copyTo (targetSheet.getRange(targetRow, 1));
sourceSheet.deleteRow(sourceRow);
};
};
}
Everything seems to working except my condition - if (sourceRow[22]=="Yes")
I am new to this, so I know I am just not referencing it correctly.
I am just trying to check if the text "Yes" is in column 22 of the current row. I am executing this script on edit. So basically, when a "Yes" is entered in this fieild, I am moving this record to the sheet called "Completed"
the statement getRow() returns an integer, the number of the row of that range, what you want is the value of the 22cd cell in that row , so try
var sourceRow = sourceSheet.getActiveRange().getRow();
var sourceRowValue = sourceSheet.getRange(sourceRow,1,1,sourceSheet.getMaxColumn()).getValues();
and then to get the cell value condition :
if (sourceRowValue[0][21]=="Yes") {;
...
The result of getValues() is always a 2 dimension array, that's the reason for the [0] and is 0 indexed >> changed to 21
Note that I guess your code could be simpler if you use sourceSheet.getActiveCell().getValue() which returns directly the value of the cell you are writing to...
try this small example where I get the Value and the column index:
function onEdit(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var cellValue = ss.getActiveCell().getValue()
ss.getRange('A1').setValue(cellValue+' in col '+ss.getActiveCell().getColumn())
}