Javascript in Google Sheets script: help using setNumberFormat - javascript

Hoping this is a simple problem for you lot. I have no coding knowledge at all. But been using the below script in a Google Sheet to grab changing data from another sheet and log it daily, appending as it goes. Can't remember where I found the script - if I did I'd go back and ask its creator. It's been working fine; only thing is I have to manually copy paste my preferred date format every day. So I'd like the script to print the date in "dd/MM/yyyy" format (while retaining hours and minutes data inside the cell). I've been reading and searching online, and experimenting for ages but can't figure it out. This is the base code:
function recordHistory() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("History");
var source = sheet.getRange("A2:C2");
var values = source.getValues();
values[0][0] = new Date();
sheet.appendRow(values[0]);
};
I've tried placing setnumberformat in various places and nearly always get an error. Perhaps my best attempt, inspired by other examples I've seen, was to add these new lines:
function recordHistory() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("History");
var source = sheet.getRange("A2:C2");
var values = source.getValues();
values[0][0] = new Date();
sheet.appendRow(values[0]);
var cell = SpreadsheetApp.getActiveSheet().getRange(2, 1, 979);
cell.setNumberFormat("dd/MM/yyyy");
};
I hoped this would format the entire date row (Row A) after appending the new data. Probably a clunky solution even if it worked, but it didn't. It's my only attempt so far that doesn't return an error! So, yay? But it doesn't change the date format. So I give up. Any ideas?

To specify the format for a specific cell
var cell = sheet.getRange("A2");
cell.setNumberFormat("dd/MM/yyyy");
To specify the format for a range of cells
var cells = sheet.getRange("A2:C2");
cells.setNumberFormat("dd/MM/yyyy");
Please see the documentation for Range and formats.

Just in case you need the time as well, follow this code.
var cell = sheet.getRange("A2");
cell.setNumberFormat("dd/MM/yyyy h:mm:ss AM/PM");

Related

I don't understand why I am getting this error

I am completely unfamiliar with JavaScript but I am trying to create a script that makes a formatted timestamp in a specific cell when a button is pressed.
I have gotten it to work with a true/false in sheets however I don't know how to make this in JavaScript. This is as far as I have gotten so far and I'm already hitting errors I do not understand.
Can someone help me understand or link me resources on how to figure out some of these problems? I've spent several hours googling and reading Google developer pages trying to learn but I haven't had any luck thus far.
The error:
function myFunction() {
var sheet = SpreadsheetApp.getActiveSheet()
var date = new Date(); var timeStamp = date.getTime(); // Unix Timestamp
var currentTime = date.toLocaleTimeString(); // eg. 10:23:30 AM HKT
sheet.setValue(currentTime);
}
While the accepted answer gives you a completely valid solution, I thought I would walk you through my own process for figuring this out pretty quickly using the documentation (without necessarily having any previous experience with google apps scripts).
The SpreadsheetApp.getActiveSheet() method returns the active Sheet object.
We can browse the docs for the Sheet class to see which methods are available and which might be useful to us.
getActiveRange() looks interesting. It:
Returns the selected range in the active sheet, or null if there is no active range.
So again, searching through the docs for the Range class to see what methods are available to the range class, we can find setValue.
function myFunction() {
var date = new Date();
var timeStamp = date.getTime();
var currentTime = date.toLocaleTimeString();
var sheet = SpreadsheetApp.getActiveSheet();
var activeRange = sheet.getActiveRange();
if (activeRange) {
activeRange.setValue(currentTime);
}
}
Hopefully this answer teaches you a bit more of a step-by-step approach in figuring these kind of problems out in the future.
You need to set the value on a cell, not the entire sheet. To do it on the cell at the very top left, you would select A1 for example:
function myFunction() {
var date = new Date();
var timeStamp = date.getTime(); // Unix Timestamp
var currentTime = date.toLocaleTimeString(); // eg. 10:23:30 AM HKT
var sheet = SpreadsheetApp.getActiveSheet(); // Sheet
var cell = sheet.getRange('A1'); // Cell <------------------------
cell.setValue(currentTime); // <--------------------------------------------
}

Extract month and year from Date and display as MMM-YY

I am new to google apps script, I am having a hard time with date format conversion
my source column has data in the format "mm/dd/yyyy". I would like to change this to "MMM-YY" i.e. I just need to extract Month and year.
Below is my unsuccessful attempt
// Get all values in column A on sheet titled "Transactions"
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sourcesheet = ss.getSheetByName("Transactions");
var targetsheet = ss.getSheetByName("stage");
// get source range
var source = sourcesheet.getRange("A:J");
//get the data and place in array
var alldata = sourcesheet.getRange("A:I").getValues();
Logger.log(alldata.length) ;
//********************************************************************************//
// loop through date column and change format
for(var i=1; i<alldata.length; i++)
{
alldata[i][0]= new Date(alldata[i][0]);
var Mnth = alldata[i][0].getMonth() ;
var Year = alldata[i][0].getYear() ;
var Day = alldata[i][0].getDay() ;
var Day2 = new Date(Year,Mnth,Day);
alldata[i][10] = Utilities.formatDate(Day2, Session.getScriptTimeZone(), "MMM-YY");
}
//********************************************************************************//
// get destination range
var destination = targetsheet.getRange(2, 1, alldata.length, 11);
// clear contents of destination sheet
destination.clear();
// copy values to destination range
destination.setValues(alldata);
}
Example
Source column value = "01/06/2019" value written to output column "1/19/2019" but it displays as "Jan-19"
Replace
alldata[i][10] = Utilities.formatDate(Day2, Session.getScriptTimeZone(), "MMM-YY");
by
alldata[i][10] = "'" + Utilities.formatDate(Day2, ss.getSpreadsheetTimeZone(), "MMM-yy");
Explanation
Prepend an apostrophe to prevent that Google Sheets from interpreting the values of the form MMM-YY as MMM-dd
Replace YY by yy
Replace Session.getScriptTimeZone() by ss.getSpreadsheetTimeZone()
NOTES
YY means weak year that could lead to some errors in certain dates of the year. To prevent this, instead use yy.
Some letters used for date format in Google Sheets and in Google Apps Script could mean different things. See the references to use them properly.
The script time zone and the spreadsheet time zone could be different. Since you will passing the values to the spreadsheet, it's better to use its time zone instead of the one from the script.
The solution to get the dates displayed as MMM-yy as date values instead of text (string) values, doesn't require to use Google Apps Script, instead use the Google Sheets number format feature (click on Format > Number > More Formats > More date and time formats), well you could use Google Apps Script to set the number format by using setNumberFormat(numberFormat)
References
Date and Number Formats
In Google Sheets
https://developers.google.com/sheets/api/guides/formats
In Utilities.formatDate(date,timezone,format)
https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
This works with the format as MMM-yy
function myFunction1() {
var ss=SpreadsheetApp.getActiveSpreadsheet();
var ssh=ss.getSheetByName("Transactions");
var tsh=ss.getSheetByName("stage");
var srg=ssh.getRange(1,1,ssh.getLastRow(),11);
var data=srg.getValues();
data.forEach(function(r,i){r[10]=Utilities.formatDate(new Date(data[i][0]),Session.getScriptTimeZone(), "MMM-yy");});
var destination=tsh.getRange(1,1,data.length,11);
destination.clear();
destination.setValues(data);
}
reference
You just copy date values to the target sheet without any changes whatsoever and the apply custom number format to the target range.
var datesRange = sheet.getRange("A1:A");
var values = datesRange.getValues();
var destination = targetSheet.getRange("A1:A");
destination.setValues(values).setNumberFormat("mmm-yy");
As Ruben pointed out, you can simply change the number format in UI (no need for scripting) so his solution is probably the best one.

Google Script to copy and archive Form Responses in New Sheet on Weekly Basis

So I'll start out by saying I just started learning Javascript 4 days ago. Now that that's out of the way, my intention with this script.
I'd like to automate the process of moving Google Form Responses, which are collected in a spreadsheet, to a new sheet within the same workbook as an archive.
I'd like this to happen on a weekly basis, and for each archive sheet that is created to have only 1 weeks responses. This should be between 12:01AM-1:00AM on Sundays, it really doesn't matter during that hour when it happens.
I would also like to then delete all of those responses from the primary collection sheet(Current_Responses), but if I have to manually delete these later it's fine (and probably good, because then I can review that the script worked properly).
I feel like I have a pretty solid start on doing this, but since I am new to all this, I would really appreciate it if a more experienced scripter could look over my code and tell me if this will work how I intend it to, and if not, where the mistakes are and how to correct them. I'm happy to make mistakes, and then learn from them so any advice will be deeply honored.
I researched several topics and scripts across three websites to help put this together. Thanks in advance for any help and advice!
// function to copy from Current_Responses to new sheet 'Archived_Responses
//(UTC Date)' placed after Current_Responses
function CreateCopySheetWeekly() {
//source info
var ss = SpreadsheetApp.getActiveSpreadsheet();
var templateSheet = ss.getSheetByName('Current_Responses');
var range = ss.getRange ('A:I'); //replace column length as needed
var data = range.getValues ();
//creates target sheet to copy responses to
var ts = 'Archived_Responses '+formatDate();
ss.insertSheet(sheetName, ss.getSheets().length, {template: templateSheet});
ts.getRange(ts.getLastRow()+1, 1, data.length, data[0].length).setValues(data);
}
//end of primary function
//function to determine and format UTC Date for CreateCopySheetWeekly function
function formatDate() {
var month, day, d = new Date();
month = ('0'+(d.getUTCMonth()+1)).slice(-2);
day = ('0'+(d.getUTCDate()).slice(-2);
return d.getUTCFullYear()+'-'+month+'-'+day;
}
//end of date function
//check every hour to determine when to perform newSheetLast function. Intended for Sunday
//between 0001-0100
window.setInterval (onSunday(){
var today = new Date();
if (today.getDay() == 0 && today.getHours() === 12) {
CreateCopySheetWeekly();
}, 600000);
Go easy on me since I am new at this, but constructive criticism never hurt anyone.
If you run this once a week we can make the simplifying assumption that you want all responses backed up once a week and then clear the main response sheet.
Let's go through the functions step by step and optimize it.
First of all you are already getting all rows, if you want all data you can just getDataRange() and not have to worry about extending.
Also we won't need the actual data.
function CreateCopySheetWeekly() {
//source info
var ss = SpreadsheetApp.getActiveSpreadsheet();
var templateSheet = ss.getSheetByName('Current_Responses'); // Current Responses
var range = ss.getDataRange();
formatDate() is just creating a ISO8601 representation of the current date if I understand correctly so you can remove the function and instead use
var ts = 'Archived_Responses '+ new Date().toISOString().slice(0,10);
Insert sheet with a template already copies all the data so you only need
ss.insertSheet(ts, ss.getSheets().length, {template: templateSheet});
Then we want to clean up our main response sheet.
If we just clear the range the form will keep appending after what would be the last row if we had never cleared because it remembers how many responses it got so we need to delete all rows but the headers.
templateSheet.deleteRows(2, range.getNumRows() - 1);
Making the final script
function CreateCopySheetWeekly() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var templateSheet = ss.getSheetByName('Current_Responses');
var range = ss.getDataRange();
var ts = 'Archived_Responses '+ new Date().toISOString().slice(0,10);
ss.insertSheet(ts, ss.getSheets().length, {template: templateSheet});
templateSheet.deleteRows(2, range.getNumRows() - 1);
}
Lastly you can schedule it by going to Resources > Current Project's Triggers and set up a time based trigger.

Google apps script getting wrong duration values

friends! In my sheet I have a column with duration format.
http://dl1.joxi.net/drive/0007/2131/485459/150902/fc427ebb50.jpg
I'm trying to get values of this column with this function:
function getSheetValues(startRow, startCmn, maxColumn) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var mainSheet = ss.getSheets()[0];
var range = mainSheet.getRange(startRow, startCmn, mainSheet.getMaxRows(), maxColumn);
return range.getValues();
}
var mainSheetData = getSheetByNameValues(2, 1, 9);
var test = mainSheetData[2][6];
Logger.log(test);
As the result I get wrong values. Example: for third row (00:23:00.000) I get this: Sat Dec 30 02:13:47 GMT+05:53 1899. Probably due to date auto formatting. How can I avoid this? is there any ways to get value (00:23:00.000) as planar text, without changing format of the column itself?
Hope for your help, friends.
Assuming you have full control over the spreadsheet...If you truly just want the string representation of '00:20:00.000' the easiest thing to do is to set the format of that column in the actual spreadsheet itself, to be plain text, i.e.
Select the column
Format -> Number -> Plain Text
Then it won't be converted to a date and you should get the raw string value you're after.
If you can't control (or otherwise guarantee) what the format of that column is, you're going to have to end up doing something like what jeremy has suggested in his comment.
You could also do it all programatically, copying the range to another cell, set numberFormat to text, then delete this copied range (or leave it):
function go(){
var ss = SpreadsheetApp.getActiveSheet(), rang1 = ss.getRange('A11'), rang2 = ss.getRange('A12');
rang1.copyTo(rang2);
Logger.log(rang2.setNumberFormat('#STRING#').getValue());
rang2.clear();
};
This of course can be done to entire ranges at once.
If you have a duration in your cell (B2 = 02:00 for example), and you want to get the same value as a result (02:00), you can use this script :
var s = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('name_of_sheet');
var l = SpreadsheetApp.getActiveSpreadsheet();
var duration = s.getRange("value_duration").getValue();
var d = Utilities.formatDate(duration, l.getSpreadsheetTimeZone(), "HH:mm");
Logger.log(d);
I gave a name to "B2" : value_duration

Google Apps Script: How do I pull data entered today from one spreadsheet and transpose it to another?

Okay, I've been working on this for about a month. I've tried numerous different ways of doing this, and I think I'm close. I'm not an expert, but here is what I'm trying to do. I've created a form that allows me to capture behavior data for my son. (He's autistic, which is why this is important.) I can get the data from the form into a results spreadsheet and I can transfer the data to a new report style pre formatted spreadsheet. What I can't do is filter the dates effectively. My script is below.
function onOpen() {
var rawdata=SpreadsheetApp.openById("0AtkuL_H_DshvdFU5U1dBLVI1NWhlWXdSNjBXOHdIaUE");
var sheet1=rawdata.getSheetByName("FormResponses");
var maxrows=sheet1.getMaxRows();
var lastcol = sheet.getLastColumn();
var vals=sheet1.getRange(1,1,maxrows,1).getValues();
var date = new Date();
var newDate = date.setDate(date.getDate()+1);
var Sdate=Utilities.formatDate(date,"GMT-0400","yyyy:MM:dd");
var newerDate=Utilities.formatDate(newDate,"GMT-0400","yyyy:MM:dd");
var filter=ArrayLib.filterByDate(vals,1,Sdate,newerDate);
var range1 = sheet1.getRange(1,1,filter,lastcol);
var values = range1.getValues();
var target = SpreadsheetApp.openById("0AtkuL_H_DshvdGxWNGJ0ZjA2VU5zV01iaVNacDZQYWc")
var sheet2 = target.getSheetByName("Sheet1");
var range2 = sheet2.getRange(4,1,i,7);
SpreadsheetApp.setActiveSpreadsheet(rawdata);
values
SpreadsheetApp.setActiveSpreadsheet(target);
range2.setValues(values);
}
//for (var i = 0; i < maxrows; i++) if (Date.parse(vals[i]).valueOf() >= todaydt.valueOf() );
The last line is a prior way I tried to filter the dates. That's the part I can't quite get to work. Part of my challenge is that I don't quite understand the "for" command yet. I'm doing the CodeAcademy java course, but since I work, have a family, and don't do this for a living its slow going. I've searched about a thousand websites and tried numerous ways to filter the dates, but I can't get any of them to work. Any help is appreciated.
I assume arraylib.filterbydate takes dates but you are passing strings. Try passing dates.
Or just filter by string if that lib allows it. Since you are formatting the date strings as yyyymmdd your string comparisons could work.

Categories