Google Sheets script does not fully complete on time trigger - javascript

Modified script .. works when run manually, setvalue(date) does not work when run on time trigger. Needs another tweak ... ideas please?
function getData() {
var queryString = Math.random();
var ss = SpreadsheetApp.openByUrl('spreadsheet URL');
var cellFunction = '=IMPORTHTML("stats URL' + queryString + '","table",1)';
var timezone = "GMT+1";
var timestamp_format = "EEE, MMM d '#' HH:mm"; // Timestamp Format.
var date = Utilities.formatDate(new Date(), timezone, timestamp_format);
Logger.log(ss.getName());
SpreadsheetApp.getActiveSheet().getRange('AH1').setValue(date);
SpreadsheetApp.getActiveSheet().getRange('AF1').setValue(cellFunction);

There is no "ActiveSheet" when running on time trigger, hence it becomes undefined, use one of these methods from SpreadsheetApp to retrive the spreadsheet:
open(file)
Spreadsheet Opens the spreadsheet that corresponds to the given
openById(id)
Spreadsheet Opens the spreadsheet with the given ID.
openByUrl(url)
Spreadsheet Opens the spreadsheet with the given url.
and after it get the sheet with one of the following methods:
getSheetByName(name) Returns a sheet with the given name.
getSheets()[ indexOfTheSheet ] Returns a sheet with the given 0 based index

Related

Google App Script : Pasting Values only in new spreadsheet

I have a dashboard on a gsheet spreadsheet, with one sheet being an overview. It has tables generated by various QUERY Functions. I want to create a script that would make a copy of this sheet only, and save it into a new Spreadsheet, stored on a Google Drive folder.
I managed to do this, but then the result does not display my queries, it just copies the formula.
Here is my code :
function CopyToSpreadSheet() {
//Source sheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getSheetByName("MTS");
//Name new sheet in target SpreadSheet
var formattedDate = Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd' 'HH:mm:ss");
var name = SpreadsheetApp.getActiveSpreadsheet().getName() + " Archive " + formattedDate;
//Create new spreadsheet
var newss = SpreadsheetApp.create(name);
var newss_id = newss.getId();
var newfile = DriveApp.getFileById(newss_id);
newfile.moveTo(DriveApp.getFolderById('1EUFJcySQ_Mv8qD8OzYUX1QniXQy2gjw0'));
//open target SpreadSheet
var target = SpreadsheetApp.openById(newss_id);
//CopyTo...
var targetSheet = sourceSheet.copyTo(target);
targetSheet.setName(name);
return;
}
So, i've been trying the CopyTo parameters {contentsOnly:true} and SpreadsheetApp.CopyPasteType.PASTE_VALUES, which gives me The parameters (SpreadsheetApp.Spreadsheet,(class)) don't match the method signature for SpreadsheetApp.Sheet.copyTo for the ContentsOnly parameter, and The parameters (SpreadsheetApp.Spreadsheet,SpreadsheetApp.CopyPasteType) don't match the method signature for SpreadsheetApp.Sheet.copyTo for the CopypasteType.
At this point, I have no idea how to fix this, but it is clearly coming from me not knowing how to handle this. I've also tried to use .makeCopy, but there was no parameter to force the copy to use the Values and not the formula in itself.
Any ideas? I'm open to anything at this point!
Thanks in advance :)
I believe your goal is as follows.
From your title of Google App Script : Pasting Values only in new spreadsheet and I want to create a script that would make a copy of this sheet only, and save it into a new Spreadsheet, stored on a Google Drive folder., you want to copy only the values from the source sheet to the target sheet in a new Spreadsheet by using Google Apps Script.
Modification points:
First, about the reason for your issue of So, i've been trying the CopyTo parameters {contentsOnly:true} and SpreadsheetApp.CopyPasteType.PASTE_VALUES, which gives me The parameters (SpreadsheetApp.Spreadsheet,(class)) don't match the method signature for SpreadsheetApp.Sheet.copyTo for the ContentsOnly parameter, and The parameters (SpreadsheetApp.Spreadsheet,SpreadsheetApp.CopyPasteType) don't match the method signature for SpreadsheetApp.Sheet.copyTo for the CopypasteType., I thought that you might have used the method of copyTo(destination, options) of Class Range to Class Spreadsheet. If my understanding is correct, such an error occurs and the reason for this is due to it.
In order to copy only the values from a source sheet to a destination sheet, I thought that there might be the following 2 patterns.
Pattern 1:
In this pattern, getValues and setValues are used.
function CopyToSpreadSheet() {
// Source sheet side.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getSheetByName("MTS");
var range = sourceSheet.getDataRange();
// This is from your script.
var formattedDate = Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd' 'HH:mm:ss");
var name = ss.getName() + " Archive " + formattedDate;
var newss = SpreadsheetApp.create(name);
var newss_id = newss.getId();
var newfile = DriveApp.getFileById(newss_id);
newfile.moveTo(DriveApp.getFolderById('1EUFJcySQ_Mv8qD8OzYUX1QniXQy2gjw0'));
// Destination sheet side.
var target = SpreadsheetApp.openById(newss_id);
var targetSheet = target.getSheets()[0];
targetSheet.setName(sourceSheet.getSheetName()); // If you don't want to rename sheet name, please remove this line.
targetSheet.getRange(range.getA1Notation()).setNumberFormats(range.getNumberFormats()).setValues(range.getValues());
}
When this script is run, only the values are copied from the source sheet to the destination sheet. In this sample, the number format is also copied.
Pattern 2:
In this pattern, copyTo methods of Class Sheet and Class Spreadsheet are used.
function CopyToSpreadSheet() {
// Source sheet side.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourceSheet = ss.getSheetByName("MTS");
var tempSheet1 = sourceSheet.copyTo(ss);
var tempRange1 = tempSheet1.getDataRange();
tempRange1.copyTo(tempRange1, { contentsOnly: true });
// This is from your script.
var formattedDate = Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd' 'HH:mm:ss");
var name = ss.getName() + " Archive " + formattedDate;
var newss = SpreadsheetApp.create(name);
var newss_id = newss.getId();
var newfile = DriveApp.getFileById(newss_id);
newfile.moveTo(DriveApp.getFolderById('1EUFJcySQ_Mv8qD8OzYUX1QniXQy2gjw0'));
// Destination sheet side.
var target = SpreadsheetApp.openById(newss_id);
var tempSheet2 = tempSheet1.copyTo(target);
var targetSheet = target.getSheets()[0];
targetSheet.setName(sourceSheet.getSheetName()); // If you don't want to rename sheet name, please remove this line.
const tempRange2 = tempSheet2.getDataRange();
tempRange2.copyTo(targetSheet.getRange("A1"));
// Remove temp sheets.
ss.deleteSheet(tempSheet1);
target.deleteSheet(tempSheet2);
}
When this script is run, not only the values but also background colors, font styles, and so on are copied from the source sheet to the destination sheet.
References:
getValues()
setValues(values)
copyTo(spreadsheet) of Class Sheet
copyTo(destination, options) of Class Range
Since no example given I'm assuming you are using the Query function without importrange which only works within the same spreadsheet.
Try:
=query(importrange("URL", "Dashboard!A1:A"), "select Col1", 0)
Replace the URL with your Source Spreadsheet URL and the Range to refer to.
Source Spreadsheet:
Result:
This is the result I got using your code, only the drive folder ID was changed. I am able to get the actual data/values not only the formula.
Explanation:
The reason is using the normal Query function it can only get data from the same Spreadsheet file. Same with normally pasting your Query formula in a different spreadsheet, it will not be able to get the data. For it to be able to Query data from other Spreadsheet you need to use it with importrange.
Also don't forget to change access to the file so those who use it for Query will actually be able to retrieve the data.
Reference:
Query From Another Spreadsheet

automatic timestamp script for each row

I'm looking for a script for google sheet that automatically inserts a timestamp for each row. and the date and time will be updated every time any of the rows gets edited. Timestamp will be put on column 1 and the rows can be the whole rows after the row 1, no specific number of rows. Please help I am very new at this. Need it badly. Thank you
You can use an onEdit trigger from Google Apps Script.
To do that, open a script bound to your spreadsheet by clicking Tools > Script editor, copy the following code and save the project:
function onEdit(e) {
var row = e.range.getRow();
if (row > 1) { // Check edited row is not first one
var formattedDate = Utilities.formatDate(new Date(), e.source.getSpreadsheetTimeZone(), "yyyy-MM-dd'T'HH:mm:ss'Z'"); // Format you want the timestamp, edit accordingly
e.range.getSheet().getRange(row, 1).setValue(formattedDate);
}
}
Reference:
Date
onEdit
Utilities.formatDate(date, timeZone, format)

Extracting data from API to Spreadsheet using Google Appscript

I'm trying to build a spreadsheet based around DataDT's excellent API for 1-minute Forex data. It's simple: for a given date & time, I need the Open and Close price from DataDT. For example, in the following cases, Date+time are the input and Open and Close would be the output.
In other words, it would go from this:
Date Time Pair Open Close
04/03/2019 20:30 USDJPY
04/03/2019 21:30 USDJPY
04/03/2019 22:41 USDJPY
to this:
Date Time Pair Open Close
04/03/2019 20:30 USDJPY 111.478 111.475
04/03/2019 21:30 USDJPY 111.482 111.465
04/03/2019 22:41 USDJPY 111.456 111.458
(Link to the GSpreadsheet)
I've been trying to fetch the data from the API following Ben Collins' excellent tutorial on connecting api's to GSpreadsheets, but given that the objects in this API have quite a different format, I haven't figured a way to handle them.
This is my Google Appscript code so far:
function callDataDT() {
// Call the DataDT API
var response = UrlFetchApp.fetch("http://www.datadt.com/api/data/AUDCAD/1/20190403/20190404?api_token=s3MoVn4GAJRJhKcdNJ6zZugFN2C92SBv");
var json = response.getContentText();
var data = JSON.parse(json);
}
function displayFXData() {
// pick up the search term from the Google Sheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var datetime = sheet.getRange(2,13).getValue();
var forexArray = [data]
Logger.log(forexArray);
}
To resume, I'm trying to understand how to 1) fetch only objects with a date_time equal to the date_time in the spreadsheet, 2) Output the Open and Close values for that object in the spreadsheet, and 3) Iterate for every non-empty line.
I apologize in advance if this question comes off as too basic. I'm still a beginner with Javascript but I've been trying for days to try to understand how to solve this, to no avail. I appreciate any tips you might give me.
As a side note, I wonder if it's possible to modify the URL directly so that it only outputs objects with a given date_time, but I don't think it's possible.
Thank you for reading,
David.-
This one uses your filter value
function getDataDT1(filter) {
var sr=3
var filter=filter||'';//You can test this function by providing a default here like '2019-04-03 20:28:00'
var r=UrlFetchApp.fetch("http://www.datadt.com/api/data/AUDCAD/1/20190403/20190404?api_token=s3MoVn4GAJRJhKcdNJ6zZugFN2C92SBv");
var data=JSON.parse(r.getContentText("UTF-8"));
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
sh.clearContents();
var pair='USDJPY';
var a=[['','','Without V8','',''],['Date','Time','Pair','Open','Close']];
if(filter) {//if the filter is null then no filtering takes place
var dat=new Date(filter);
var dtv=new Date(dat.getFullYear(),dat.getMonth(),dat.getDate(),dat.getHours(),dat.getMinutes()).valueOf();
}
data.forEach(function(r,i){
var dt=r.DATE_TIME.split(' ');
var sd=new Date(r.DATE_TIME);
var sdv=new Date(sd.getFullYear(),sd.getMonth(),sd.getDate(),sd.getHours(),sd.getMinutes()).valueOf();
if(sdv==dtv || !filter) {//no filtering if filter is null
var d=dt[0].split('-');
var t=dt[1].split(':');
var ds=Utilities.formatString('%s/%s/%s',d[1],d[2],d[0]);
var ts=Utilities.formatString('%s:%s',t[0],t[1]);
a.push([ds,ts,pair,data[i].OPEN.toFixed(3),data[i].CLOSE.toFixed(3)]);
}
});
if(a) {
sh.getRange(sh.getLastRow()+1,1,a.length,a[0].length).setValues(a);
}else{
SpreadsheetApp.getUi().alert('No items found');
}
}

Google Script Copying part of a cell to another sheet

Goal: Trying to copy part of some text from one cell on a spread sheet and pasting it on to another one.
I am still new to Javascript to please forgive if im going about this all wrong.
So on one spread sheet some information gets populated automatically from a service I use. I want to take part of that information and copy and paste it onto another spread sheet.
For this example the date gets populated in the cell A1 "February 28, 2017 at 10:38AM." I want to only copy the date February 28, 2017 and paste it onto another google sheet.
This is what my current code looks like:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var target = SpreadsheetApp.openById("abc1234");
var source_sheet = ss.getSheetByName("Text");
var target_sheet = target.getSheetByName("Bills");
var sheet = ss.getSheets()[0];
var range = sheet.getRange("A1:D4");
var cell = range.getCell(1, 1);
var string1 = cell.getValue();
var string2 = string1.split(" ", 2);
var target_range = target_sheet.getRange("J4");
string2.copyTo(target_range);
//Logger.log(string2);
}
The error I receive when i do this is:
TypeError: Cannot find function copyTo in object February,28,. (line 13, file "Test")
This maybe something simple i jsut cont figure it out
You need to use .setValue() to set the value of the range. So to set your range to the value in string2 you would replace line 13 with:
target_range.setValue(string2);
See the Tutorials for some examples of scripts. Especially the Workflows and end-to-end examples.

Add a timestamp programmatically

I am trying to create a code to Google Spreadsheets . In VBA code it is very simple. My goal is, when a particular cell is filled , another cell displays the date and time of completion .
In VBA:
Function DateTime()
DateTime = NOW
End Function
Based on your most recent comment stating that you want to call a custom function from the Google Sheet frontend, all you will need in your Script Editor (backend) is:
function timeStamp() {
return new Date();
}
You can then call that function from a formula in your Sheet, very similar to what you wrote already:
=IF( ISBLANK(A1), "", timeStamp() )
This is the code that will help you out of what you are trying to achieve.
Code below will add the date in the very next column of whichever field you will input a value into.
//onEdit is the default "on edit event handler" provided by google app script
function onEdit(e){
var spreadSheet = e.source;
var sheet = spreadSheet.getActiveSheet();
var range = e.range;
//only add the date in the next column if value in cell is not empty
if(range.getValue() != ""){
var col = range.getColumn();
var row = range.getRow();
//get the very next column
var newRange = sheet.getRange(row, col + 1);
newRange.setValue(new Date());
}
}
Hope this will help.
NB: Please note this code will work with scripts bound to google apps only.

Categories

Resources