Copy paste if Date = Today Google Sheets API - google-apps-script

I am new to google script (and Javascript in general) and am trying to create a "Macro" which loops through a large table of data (Titled "Form response 1"), searches each row to see if the data in the 'To-arrive-date" column matches todays date. If the dates match, I want to copy-paste it into another sheet titled "Email". Below is the script I have written so far, but I keep getting an error stating that an unexpected "Var" is on line 15. However, I thought this var needed to be there for the variable "SrcRange"? Any help would be wonderful, thank you.
var sSheet = SpreadsheetApp.getActiveSpreadsheet();
var srcSheet = sSheet.getSheetByName("Form Responses 1");
var tarSheet = sSheet.getSheetByName("Email");
var lastRow = srcSheet.getLastRow();
var Tsheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Form Responses 1");
var date = new Date();
Tsheet.getRange(2, 11).setValue(date);
for (var i = 2; i <= lastRow; i++) {
var cell = srcSheet.getRange("C" + i);
var val = cell.getValue();
if (val == SrcSheet.getRange(2, 11).getValues()
var srcRange = srcSheet.getRange("A" + i + ":F" + i);
var tarRow = tarSheet.getLastRow();
tarSheet.insertRowAfter(tarRow);
var tarRange = tarSheet.getRange("A" + (tarRow+1) + ":F" + (tarRow+1));
srcRange.copyTo(tarRange);
}
}
-Evan

Issue
Your IF statement inside the loop is incomplete. It lacks closing parenthesis as well as opening curly brace. I also noticed and commented out unnecessary codes and corrected a few specifically with regards to new Date() method.
Solution
Please see modified code below. Note that I only modified a few part of the code to make it work. I haven't done any optimization(if applicable). Also, this code is working fully on my end.
function myFunction() {
var sSheet = SpreadsheetApp.getActiveSpreadsheet();
var srcSheet = sSheet.getSheetByName("Form Responses 1");
var tarSheet = sSheet.getSheetByName("Email");
var lastRow = srcSheet.getLastRow();
var tSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Form Responses 1");
var date = new Date().toDateString();
tSheet.getRange(2, 11).setValue(date);
for (var i = 2; i <= lastRow; i++) {
var cell = srcSheet.getRange("C" + i);
var val = new Date(cell.getValue().toString()).toDateString();
Logger.log(val+" "+date)
if (val == date){
Logger.log("test")
var srcRange = srcSheet.getRange("A" + i + ":F" + i);
var tarRow = tarSheet.getLastRow();
// tarSheet.insertRowAfter(tarRow);
var tarRange = tarSheet.getRange("A" + (tarRow+1) + ":F" + (tarRow+1));
srcRange.copyTo(tarRange);
}
}
}

Related

Copy Row from one Sheet to another sheet which is linked in the row

I have previously been able to copy rows from one Spreadsheet to another, however what I am trying to do now is copy a row to a specific spreadsheet that is linked on the same row and I can't seem to work it out.
I have around 500 rows of names with data (I cannot share a sheet as my firms Google does not allow for sharing externally but I have a screenshot of dummy data below). I used a formula to find the Unique names and then created a Google Sheet for each person and linked the Sheet back to the master data.
Master Data Sheet (tab is called Sheet1)
I am looking for a script that will work through the sheet, copying the rows to the link that is on the same row but I just can't figure it out - the following script does not work but I am at a loss so any help would be appreciated.
Apologies if I haven't explained myself very well!!
function copyTo(){
var sSheet = SpreadsheetApp.getActiveSpreadsheet();
var srcSheet = sSheet.getSheetByName("Sheet1");
var data = srcSheet.getDataRange().getValues();
for(var i = 1; i < data.length; i++) {
var row = data[i];
var link = row[3];
var id = row[4];
var complete = row[5];
var COMPLETE = "Complete"
if(link !== "" && complete !== "Complete"){
var srcRange = srcSheet.getRange("A" + i + ":C" + i);
var linkID = id.toString()
var tarSS = DriveApp.getFileById(linkID);
var tarSheet = tarSS.getSheetbyName("Sheet1");
var tarRow = tarSheet.getLastRow();
//tarSheet.insertRowAfter(tarRow);
var tarRange = tarSheet.getRange("A" + (tarRow+1) + ":C" + (tarRow+1));
srcRange.copyTo(tarRange);
srcSheet.getRange(i+1,6).setValue(COMPLETE)
}
}};
Try this:
function copyTo() {
var ss = SpreadsheetApp.getActive();
var sh = ss.getSheetByName("Sheet1");
var vs = sh.getDataRange().getValues();
for (var i = 1; i < vs.length; i++) {
var row = vs[i];
var link = row[3];
var id = row[4];
var complete = row[5];
var COMPLETE = "Complete"
if (link !== "" && complete !== "Complete") {
var rg = sh.getRange("A" + i + ":C" + i);
var linkID = id.toString()
var tarSS = SpreadsheetApp.openById(linkID);
var tarSheet = tarSS.getSheetbyName("Sheet1");
var tarRow = tarSheet.getLastRow();
var tarRange = tarSheet.getRange("A" + (tarRow + 1) + ":C" + (tarRow + 1));
rg.copyTo(tarRange);
sh.getRange(i + 1, 6).setValue(COMPLETE)
}
}
};
As much as I understand you question here is the script which will work for you exactly you want .
This will copy data from sheet you want and then create a new spreadsheet and paste into that sheet then link will show of this in same sheet from data copied
Let me know how this worked .
Code.gs
const sendDataToSheet = () => {
const ss = SpreadsheetApp.getActiveSpreadsheet()
const ws = ss.getSheetByName(''paste here your sheet name'')
const newSheet = SpreadsheetApp.create("give new sheet name here")
ws.copyTo(newSheet).setName("Copied Data")
const sheetURL = newSheet.getUrl()
ws.insertRowBefore(1)
ws.getRange(1,1).setValue(sheetURL)
}

Combine multiple Google sheet scripts

I have been trying for weeks now to solve this issue but did not have any luck (I am pretty new to Google Scripting). So I am posting here hoping some of you managed to solve this before me !
I have multiple scripts in Google sheets and I would like to put them all together to run everything on a schedule.
The scripts are running well separately but not together. I see mostly conflict between script 2 and 3
Basically this is to get datas from an URL, and clean them. Here is a description of the script :
1 - Get the data from an URL
2 - Clean column 6
3 - Clean column 3
4 - Change number format
Here is the script :
function importCSVFromWeb() {
// Provide the full URL of the CSV file.
var csvUrl = "https://mycsvdata.testsite";
var csvContent = UrlFetchApp.fetch(csvUrl).getContentText();
var csvData = Utilities.parseCsv(csvContent);
var sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange(1, 1, csvData.length, csvData[0].length).setValues(csvData);
}
// 2 - CLEAN CATEGORIES
function clean() {
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('Sheet1');
var range = sheet.getDataRange();
var pattern = new RegExp("Accessories|case|pouch...");
var columnToSearch = 5;
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();
sheet.deleteRows(numRows + 1, maxRows - numRows);
};
// 3 - CLEAN NAME
function clean2() {
var startTime = new Date().getTime();
var deleteSelectedRows = removeThenSetNewVals2();
var runTime = (new Date().getTime() - startTime) / 1000;
Logger.log("Runtime is: " + runTime + " seconds");
};
function removeThenSetNewVals2(){
var sheet = SpreadsheetApp.getActive().getSheetByName('Sheet1');
var range = sheet.getDataRange();
var pattern = new var pattern = new RegExp("Accessories|case|pouch...");
var columnToSearch = 2;
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();
sheet.deleteRows(numRows + 1, maxRows - numRows);
};
// 4 - CLEAN PRICE
function decimal(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var cell = sheet.getRange("D1:D");
// Always show 3 decimal points
cell.setNumberFormat("00");
}
Thank you very much for any help !
There are two methods that might help you - Spreadsheet.flush() and Lockservice. I cannot tell for sure if it will work without having the insight into your code, but you can try. Wrap each of your method calls into:
const lock = LockService.getScriptLock()
try{
lock.waitLock(30000)
method() // run your method here
SpreadsheetApp.flush()
} finally{
lock.releaseLock()
}
I am curious what you mean by run them together. But it is easy enough to have one function call the other functions and then using a trigger, set sheets to run the main function on the schedule you want
function daily() {
importCSVFromWeb();
clean();
removeThenSetNewVals();
clean2();
removeThenSetNewVals2();
decimal();
}

Force refresh ImportXML

I want to force an importXML to auto-refresh every five minutes. This is the script I am trying to run and getting the error "Bad value (line 7, file "RefreshImports" . I do not know why. I found it here: Periodically refresh IMPORTXML() spreadsheet function
function RefreshImports() {
var lock = LockService.getScriptLock();
if (!lock.tryLock(5000)) return; // Wait up to 5s for previous
refresh to end.
var id = "[YOUR SPREADSHEET ID]";
var ss = SpreadsheetApp.openById(id);
var sheet = ss.getSheetByName("[SHEET NAME]");
var dataRange = sheet.getDataRange();
var formulas = dataRange.getFormulas();
var content = "";
var now = new Date();
var time = now.getTime();
var re = /.*[^a-z0-9]import(?:xml|data|feed|html|range)\(.*/gi;
var re2 = /((\?|&)(update=[0-9]*))/gi;
var re3 = /(",)/gi;
for (var row = 0; row < formulas.length; row++) {
for (var col = 0; col < formulas[0].length; col++) {
content = formulas[row][col];
if (content != "") {
var match = content.search(re);
if (match !== -1) {
// import function is used in this cell
var updatedContent = content.toString().replace(re2, "$2update=" +
time);
if (updatedContent == content) {
// No querystring exists yet in url
updatedContent = content.toString().replace(re3, "?update=" + time +
"$1");
}
// Update url in formula with querystring param
sheet.getRange(row + 1, col + 1).setFormula(updatedContent);
}
}
}
}
// Done refresh; release the lock.
lock.releaseLock();
// Show last updated time on sheet somewhere
sheet.getRange(7, 2).setValue("Rates were last updated at " +
now.toLocaleTimeString())
}
In the code where it says "[YOUR SPREADSHEET ID]", I am to enter the name of my spreadsheet correct? I do not know anything about this.
On [YOUR SPREADSHEET ID] you should add the spreadsheet id, not it's name.
The spreadsheet id for
https://docs.google.com/spreadsheets/d/1Xhgfr3z4EwPtjS4aahytU_3TOVxjNb8JvHo88h3nZaE/edit#gid=14522064
is
1Xhgfr3z4EwPtjS4aahytU_3TOVxjNb8JvHo88h3nZaE
I found it easier to use the URL instead the id, here is the bit of code:
var url = "URL OF SPREADSHEET";
var sheetName = "NAME OF SPECIFIC SHEET";
var ss = SpreadsheetApp.openByUrl(url);
var sheet = ss.getSheetByName(sheetName);

Trying to add an IF statement to an array of objects in Google Apps Script for Sheets

Trying to send an email to a list in a Google Sheet, but only if column N gets marked "Yes." Acceptable data in column N is "Yes" or "No" so I want to test that and send emails only to the rowData that contain "yes" there. Then write the date in the adjacent column on the same row. I can't seem to figure out how to iterate through the array of objects and couldn't find any good resources to explain this. Help greatly appreciated. My best effort was emailing all the rows and then also filling in the date no matter what was in column N (Yes/No/Blank).
function sendEmails() {
validateMySpreadsheet() //a function that checks for "Yes" in column N
var ss = SpreadsheetApp.getActiveSpreadsheet();
var dataSheet = ss.getActiveSheet();
var dataRange = dataSheet.getRange(2, 1, dataSheet.getMaxRows() - 1, 16);
var d = new Date();
var dd = d.getDate();
var mm = d.getMonth() + 1; //Months are zero based
var yyyy = d.getFullYear();
var date = mm + "/" + dd + "/" + yyyy;
var needsaYes = "Yes";
//Gets the email template
var templateSheet = ss.getSheetByName("Template");
var emailTemplate = templateSheet.getRange("A1").getValue();
// Create one JavaScript object per row of data.
objects = getRowsData(dataSheet, dataRange);
//This is where I am stuck - how to check if column N contains a "Yes" before allowing the MailApp.SendEmail command to run.
for (var i = 0; i < objects.length; ++i) {
// Get a row object
var rowData = objects[i];
var values = dataRange.getValues();
for (var j = 0; j < values.length; ++j) {
var row = values[j];
var checkFirst = row[13]; //row J, Column N?
if (checkFirst = needsaYes) { //does column N contain "Yes"?
var emailText = fillInTemplateFromObject(emailTemplate, rowData);
var emailSubject = "mySubject";
MailApp.sendEmail(rowData.email, emailSubject, emailText);
dataSheet.getRange(2 + i, 15).setValue(date); //then write the date
SpreadsheetApp.flush();
}
}
}
}
I didn't check whole code but
if (checkFirst = needsaYes)
It may be the problem, you need to use ==
I figured it out I needed to just use the .getValues() method for my data range rather than the whole sheet and also remove the unnecessary second for loop:
var rowData = objects[i]; var checkData = ss.getActiveSheet().getDataRange().getValues();
var row = checkData[i]
var colN = row[13] if (colN == needsaYes) { //etc.

How to show spreadsheet name in Logger

I am trying to get a chart from spreadsheet A. I take this into a Chart object, and try to put it back in spreadsheet B.
I always get an 'unknown sheetname' error. I have been trying to put new ranges in the new chart, as you can see in the code. When I do a Logger.log(newrange.getSheet()) I indeed get Sheet instead of SHEETNAME, like the chart builder messes with the sheetnames.
What is happening?
function updateCharts() {
var ss = SpreadsheetApp.openById("ID");
var sheet = ss.getSheetByName("SHEETNAME");
var charts = sheet.getCharts();
var ss2 = SpreadsheetApp.openById("NEW ID");
var sheet2 = ss2.getSheetByName("SHEETNAME");
for (var c=0; c<charts.length; c++) {
var chart = charts[c];
var ranges = chart.getRanges();
var type = chart.getType();
var info = chart.getOptions();
var builder = chart.modify();
var range = ranges[0];
builder.removeRange(range);
var startRow = range.getRow();
var startCol = range.getColumn();
var numRows = range.getNumRows();
var numCols = range.getNumColumns();
var newrange = ss2.getSheetByName("statistiek").getRange(startRow, startCol, numRows, numCols);
Logger.log(newrange.getSheet());
builder.addRange(newrange);
var title = chart.getOptions().get('title')
builder.setOption('title', title + " " + p);
var newchart = builder.build();
ss2.getSheetByName("statistiek").insertChart(newchart);
}
}
Logger.log() requires a string, but you're feeding it an object with newrange.getSheet(). Try this instead, if you want the sheet's name:
Logger.log(newrange.getSheet().getName())
To see the names of all sheets in a spreadsheet, try:
var ss = SpreadsheetApp.openById("ID");
var allSheets = ss.getSheets();
for (i in allSheets) {
Logger.log("Sheet " + i + " is named " + allSheets[i].getName());
}