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.
Related
Goal
Write a script that does the following:
get data from sheet
modify column to flip names from [Last, First] to [First Last]
modify 2 columns to abbreviate company names & statuses
write resulting data to another spreadsheet without changing the format
add timestamp for when data copied
Problem
I can get the data BUT it writes everything back as plain text. Thus instead of dates writing out as "yyyy-MM-dd", they write out as something like this: Mon Oct 19 2020 01:00:00 GMT-0400 (Eastern Daylight Time)
Expectation:
screenshot of dates as "yyyy-MM-dd"
Result:
screenshot of dates as whatever this garble is
I have googled extensively and can't seem to find a solution. I believe my problem is with using toString() in the Array.map. I'm not sure how to restrict the map method to only the columns that need modifying. Right now it affects the whole array.
(I used the code from Google Apps Script for Multiple Find and Replace in Google Sheets to write this part)
//-----FIND AND REPLACE FOR COMPANY & STATUS ABBREVIATIONS
function replaceInSheet(initArray, to_replace, replace_with){
//Loop over rows in array
for(var row in initArray ){
//Use Array.map to execute a replace call on each of the cells in the row.
var replaced_values = initArray[row].map(function(originalValue){
return originalValue.toString().replace(to_replace,replace_with);
});
//Replace the original row values with the replaced values
initArray[row] = replaced_values;
}
}
Question--> How do I get the output of my script to format dates in two of my columns, correctly?
Attempted Solutions that didn't work
I tried swapping the name flip code to happen after the abbreviation code so I could add a setNumberFormat('yyyy-MM-dd') within the name flip for loop. I couldn't figure out how to apply this to columns within my array. Something like initarray[x][5].setNumberFormat("yyyy-MM-dd") gave me an error saying "TypeError: initArrayx.setNumberFormat is not a function"
I tried adding code before (and then even after) .setValues() at the end to change the format. Some resources I referenced:
setNumberFormat('yyyy-MM-dd') from stackoverflow: Set cell format with google apps script
Utilities.formatDate(new Date(), "CST", "yyyy-MM-dd") from stackoverflow: Get today date in google appScript
website post by BLACKCJ: "Cell Number Formatting with Google Apps Script"
google's developer documentation
and all sorts of other articles, blogs, forums, etc.
I tried writing a completely separate function to change the format after my script runs. Nope. I can't get those 2 columns to format as dates
Code & Sample Spreadsheet
Here's the whole code I'm using, modified to work with a sample google sheet I created just for the purposes of this question.
Sample Google Sheet:
https://docs.google.com/spreadsheets/d/1Ys77hQHHajIo-Xaxyom0SVnyVMZ6bKOT8Smpadd2jv4/edit?usp=sharing
Script:
// ==================================================
// FUNCTION TO RUN
// ==================================================
function syncData(){
//Ger Source Data
var ss = SpreadsheetApp.getActiveSpreadsheet();
var thisSheet = ss.getSheetByName("source");
var thisData = thisSheet.getRange("A4:M11");
var initArray = thisData.getValues();
//Get Target Location
var toSheet = ss.getSheetByName("target");
var toRange = toSheet.getRange("A4:M11"); //Range starts at A4
//CHANGE [LAST, FIRST] TO [FIRST LAST]
for (var x = 0; x < initArray.length; x++){
var indexOfFirstComma = initArray[x][0].indexOf(", ");
if(indexOfFirstComma >= 0){
//If comma found, split and update values in the values array
var lastAndFirst = initArray[x][0];
//Update name value in array
initArray[x][0] = lastAndFirst.slice(indexOfFirstComma + 2).trim() + " " + lastAndFirst.slice(0, indexOfFirstComma).trim();
}
}
//ABBREVIATE COMPANY
replaceInSheet(initArray, 'Bluffington School','BLF HS');
replaceInSheet(initArray, 'Honker Burger','HBGR');
replaceInSheet(initArray, 'Funky Town','FT');
//ABBRIVIATE STATUS
replaceInSheet(initArray, 'Regular','Staff');
replaceInSheet(initArray, 'Contractual','Part');
replaceInSheet(initArray, 'Temporary','Temp');
//Clear Target Location
var toClear = toSheet.getRange("A4:M11")
toClear.clearContent();
//Write updated array to target location
toRange.setValues(initArray);
//Write timestamp of when code was last run
setTimeStamp(toSheet);
}
//-----FIND AND REPLACE FOR COMPANY & STATUS ABBREVIATIONS
function replaceInSheet(initArray, to_replace, replace_with){
//Loop over rows in array
for(var row in initArray ){
//Use Array.map to execute a replace call on each of the cells in the row.
var replaced_values = initArray[row].map(function(originalValue){
return originalValue.toString().replace(to_replace,replace_with);
});
//Replace the original row values with the replaced values
initArray[row] = replaced_values;
}
}
//-----ADD TIMESTAMP FOR WHEN THE SCRIPT LAST RAN
function setTimeStamp(toSheet) {
var timestamp = Utilities.formatDate(new Date(), "CST", "yyyy-MM-dd # h:mm a");
toSheet.getRange('F1').setValue(timestamp);
}
setNumberFormat('yyyy-MM-dd') is a good solution but it's a method of a Range of the sheet. Not an array.
To apply the format you need to get a range first. Something like this:
toSheet.getRange('G4:G').setNumberFormat('yyyy-MM-dd');
And there is one more thing ) Try to change this line:
var initArray = thisData.getValues();
to:
var initArray = thisData.getDisplayValues();
I am currently writing a custom function in Google App Scripts. Right now I am struggling. I defined an argument to take input from a date cell and change the format.
e.g 9/16/2010 to 09.16.2010 where a given column has the former date and the function outputs the latter.
The output is a string, but I can't seem to find any information on this specific text editing feature of javascript.
It's also worth mentioning that the date in a given column is based on a form output, I am not calling a specific short date in the code, so rather this is more string manipulation than date formatting
Any help is appreciated.
/**
*Generates a Trip Key
*
*#param DateColumn Date
*#param SchoolColumn School name
*#param LocationColumn Location
*#customfunction
*/
function GENERATEKEY(DateColumn) {
var Date = DateColumn
const dateStr = Date;
const dateArr = dateStr.split('/');
dateArr[0] = ('0' + dateArr[0]).slice(-2);
dateArr[1] = ('0' + dateArr[1]).slice(-2);
const DateEdited = dateArr.join('.');
return neWDateStr; //gives 00.00.0000
//var Key = Date SchoolColumn "#" LocationColumn
}
Date is a built-in object. It should not be used as a variable name.
While const is allowed in Google Apps Script, it's not fully supported (it doesn't work as the ECMAScript states). IMHO it's better to use var to avoid "confusions".
In Google Sheets, based in the spreadsheet settings, change values entered in supported date-time format into serial numbers and use a number format to display it as date, time, date-time or duration. When a serial number displayed as date, date-time, time or duration is passed to a custom function, Google Apps Script convert it to a Date object.
To return a date formatted use Utilities.formatDate(...) Details in https://developers.google.com/apps-script/reference/utilities/utilities#formatdatedate,-timezone,-format
Related
How to format the date in this Google Apps Script
You could simply use inbuilt TEXT function:
=TEXT(A2,"mm.dd.yyyy")
The reason your current script(as provided in one of the previous answers) doesn't work is because the argument DateColumn is not of type String. You can convert the date object to a specific string and format it accordingly or use inbuilt Utilities library.
function DOWHATTEXTDOES(dateColumn) {
return Utilities.formatDate(dateColumn, SpreadsheetApp.getActive().getSpreadsheetTimeZone(), "yyyy.MM.dd")
}
Essential Reading:
Custom function Data type
Date
You can do something like this
"02/05/2009".split('/').join('.');
Get and Set the numberFormat for the active range
Sheet.getRange().setNumberFormat("mm.dd.yyyy");
Here's a dialog and function that I use sometimes for playing around with different formats. I find it a lot easier and quicker that using the spreadsheet functions.
The top function is a dialog that reads and displays the current format for the active range and has a textbox and button for each cell in the in the active range that allows you to set the number format and see the change immediately.
function getandSetActiveRangeFormats() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
var rg=sh.getActiveRange();
var fA=rg.getNumberFormats();
var html='<style>th,td{border:1px solid black;}</style><table><tr><th>Item</th><th>A1 Notation</th><th>Number Format</th><th>Enter Format</th><th>Set Format</th></tr>';
var item=1;
var row=rg.getRow();
var col=rg.getColumn();
fA.forEach(function(r,i){
r.forEach(function(c,j){
var txt=Utilities.formatString('<input type="text" id="RC-%s-%s" />',row+i,col+j);
var btn=Utilities.formatString('<input type="button" value="Set Form" onClick="setFormat(%s,%s);" />',row+i,col+j);
html+=Utilities.formatString('<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>',item++,sh.getRange(row + i,col + j).getA1Notation(),fA[i][j],txt,btn);
});
});
html+='</table><input type="button" value="Exit" onClick="google.script.host.close();" />';
html+='<script>function setFormat(row,col){var f=document.getElementById("RC-"+row+"-"+col).value;google.script.run.setFormat(row,col,f);}</script>';
var ui=HtmlService.createHtmlOutput(Utilities.formatString(html));
SpreadsheetApp.getUi().showModelessDialog(ui, "Display Cell Formats")
}
function setFormat(row,col,format) {
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
sh.getRange(row,col).setNumberFormat(format);
}
Animation:
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");
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
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.