Date is copied as "Range" in Google Sheets Macro/Script - google-apps-script

I am struggling with a potential minor issue in google Sheets. I simply want to copy a date value to another cell, without changing the date format, etc.
However, if I save the date in a var, the Logger finds "Range". I also tried formatting, but I ended up with wrong dates, current dates, or just nothing at all.
Hint: Cell 63,4 contains a date value, formatted as a date in the spreadsheet.
function test() {
var as = SpreadsheetApp.getActiveSpreadsheet();
var ss = as.getActiveSheet();
var start = ss.getRange(63,4);
var row = start.getRow();
var col = start.getColumn();
Logger.log(start);
start = new Date(0);
ss.getRange('C2').setValue(start);
...
}
After running this code, the log shows "RANGE".
Do you have an idea how to solve this? I think I am not saving the cell correctly, but I did not find any further ideas.

Explanation / issue:
That is because you are not getting the value and getRange
returns an instance of the range class.
Keep in mind that if the value is a date you might want to use
getDisplayValue().
Solution:
Replace:
var start = ss.getRange(63,4);
with:
var start = ss.getRange(63,4).getDisplayValue();
and remove that part:
start = new Date(0);
since this will overwrite the current value that is assigned to start which is the desired date you want to get.
Code snippet:
function test() {
var as = SpreadsheetApp.getActiveSpreadsheet();
var ss = as.getActiveSheet();
var start = ss.getRange(63,4).getDisplayValue(); // cell D63
ss.getRange('C2').setValue(start);
}

Related

Google Apps Script - Function Changes Cell Value Dynamically Based On Other Cells

This will likely be an easy question to answer but its an issue I run into often. Most built in google sheet functions change dynamically when cell values are updated, I need my function to do the same rather than needing to run the function to check the dates. The following script is likely messy to anyone who knows what they're doing, but it works. It is built to scan if todays date matches any in the range named "Dates" and return the value in that objects column and row of the active cell. However, this only activates when I first plug the function into the cell. I need it to change the cells value whenever one of those dates matches todays date or when none of them match todays date.
function getClass() {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getActiveSheet();
var dateRanges = ss.getRangeByName("Dates");
var dateValues = dateRanges.getValues();
var studentRow = sheet.getActiveCell().getRow();
var todaysDate = Utilities.formatDate(new Date(),"00:00:00", "MM/dd/yyyy");
var datesWithCells = [];
for (i=0;i<=dateRanges.getNumColumns() -1;i++){
var date = [Utilities.formatDate(dateValues[0][i], "00:00:00", "MM/dd/yyyy")];
var col = [dateRanges.getColumn() + i]
datesWithCells.push([col,date]);
};
for (i=0;i<=dateRanges.getNumColumns() -1;i++){;
var dataCol = datesWithCells[i][0];
if (datesWithCells[i][1] == todaysDate){
return sheet.getRange(studentRow,dataCol).getValue();
} else {
return "N/A";
};
};
}
Image shows the cells correctly displaying N/A as no dates match todays date. If todays date did match, it would not change value because the function has already ran and will not update this value as needed
It is unclear why you would want to do that with a custom function, because a plain vanilla spreadsheet formula would seem to suffice:
=hlookup(today(), D2:Z, row() - row(D2) + 1, false)
To answer your question, you should not hard-code the location of the data in the custom function. Instead, pass the values to the custom function through parameters. The formula that uses a custom function will update its result automatically when its parameters change.

How can I change the value of the cell A2 to "Today()" when I make any change in the cell A1?

I am doing my project management in a Google Spreadsheet. A script that automates changes in my comment field to my change_date-field =TODAY() would help me to save some time and also use this function for other scripts I might need in the future.
When I make changes in a comment-field currently, I have to manually enter the change date in my change_date-field which is something that could be easily automated, I think.
Unfortunately I have no clue how to write the code for this.
When I am making any changes in my column named "comment" I want to return the value "=TODAY()" in the column named "change_date". Can you guys help me out with a script that does this job for me automatically?
It might be helpful if you could share a version of the spreadsheet you are referring to to help us answer more accurately.
Based on the information provided some ideas that might help you might be:
1. Use setFormula to change the requested cell to today(). Something like
function setToday() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange('B1'); //Set the cell here
range.setFormula('=today()');
}
2. Add the date in using the script directly
function newDate() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange('B1'); //Set the cell here
var today = Utilities.formatDate(new Date(),Session.getScriptTimeZone(),'dd//MM/yy');
range.setValue(today);
}
You could use an onEdit trigger to update the cells when a specific cell is edited.
function onEdit(e){
var sheet = SpreadsheetApp.getActiveSheet();
var range = e.range;
var column = range.getColumn();
var row = range.getRow();
if (column==2) { //Replace 2 with the column number of your comments cell//
var newRange = sheet.getRange(row,column+1); //If the date is in the next column
newRange.setFormula('=today()');
}
Sorry I couldn't be more specific.

Random string generator randomizing too often

I'm looking for input on a small random string generator project.
I'm trying to create a random string generator that puts three words together, where I can then save strings that I like to another sheet.
I'm using a basic script to assign a RANDBETWEEN formula to 3 specific cells, which works great to generate the strings, but it keeps recalculating with each additional step in the script it seems. I'd like to run one function then if I like the string I would run another function to store the string. However, when I try that it has already recalculated the RANDBETWEEN formulas and it saves something completely different.
I have an example sheet here:
https://docs.google.com/spreadsheets/d/1TWziyjjLQJJApkHCqrLzNGMFU0sf-vNEOOSatuhHURo/edit?usp=sharing
And here is the code I'm using for the "Go" and "Save" buttons, respectively:
function generateString() {
var ss = SpreadsheetApp.openById('1b9rP39sgZDOZqu7AmZhOxX9J8CMukmUw7NPY3Qzuq78');
var sheet = ss.getSheetByName('Randomizer');
var cell = sheet.getRange('D4');
var cell2 = sheet.getRange('E4');
var cell3 = sheet.getRange('F4');
cell.setValue('=INDEX(A:A,RANDBETWEEN(1,counta(A:A)))');
cell2.setValue('=INDEX(A:A,RANDBETWEEN(1,counta(A:A)))');
cell3.setValue('=INDEX(A:A,RANDBETWEEN(1,counta(A:A)))');
var cell4 = sheet.getRange('P4');
cell4.copyTo (sheet.getRange ('P5'), {contentsOnly: true}); //an attempt to paste values to record the random string
}
function saveString() {
var ss = SpreadsheetApp.openById('1b9rP39sgZDOZqu7AmZhOxX9J8CMukmUw7NPY3Qzuq78');
var sheet = ss.getSheetByName('Randomizer'); //replace with source Sheet tab name
var range = sheet.getRange('P4'); //assign the range you want to copy
var data = range.getValues();
var tss = SpreadsheetApp.openById('1b9rP39sgZDOZqu7AmZhOxX9J8CMukmUw7NPY3Qzuq78');
var tsheet = tss.getSheetByName('Saved Strings'); //replace with destination Sheet tab name
tsheet.getRange(tsheet.getLastRow()+1, 1, 1, 1).setValues(data);
}
Please let me know if anyone has some ideas on how to make this work properly. Thanks!
RANDBETWEEN the same as RAND are volatile functions. That means that their results changes every time that spreadsheet is recalculated.
If you need to keep the randomized to result be "freezed" for a while instead of this functions one alternative to consider is the use of a custom function as they are recalculated only when at least one of its arguments changes.
Related
Refresh data retrieved by a custom function in Google Sheet

When using setFormulas I get error Cannot find function error "object function getFontColor() {/* */}."

I'm trying to create a script that copies down formula the length of the sheet (stitched together on the back of other SO posts I found while researching):
var originRange = ss.getSheetByName('data_prep').getRange('C6:I6');
var formulas = originRange.getFormulas();
var target = ss.getSheetByName('data_prep').getRange('C7:I');
for(i in target) {
target[i].setFormulas(formulas);
}
When I run this function I get:
TypeError: Cannot find function setFormulas in object function getFontColor() {/* */}.Dismiss
What I had hoped/expected was for all the formulas in C6:I6 to be copied into each row starting C7 down the length of the sheet.
The function works for one row at a time. So if I set target as just C7:I7 and get rid of the for loop it works.
Why am I getting this getFont error?
How can I get my script to copy the formulas in C6:I6 down the entire sheet?
As an alternative to 2, how can I get my script to copy down as far as while there is data in column A?
Maybe try something like this:
var ss= SpreadsheetApp.getActiveSpreadsheet();
var dataPrepSheet = ss.getSheetByName('data_prep')
var originRange = dataPrepSheet.getRange('C6:I6');
var everyRow = dataPrepSheet.getMaxRows().toString();
var target = dataPrepSheet.getRange('C7:I' + everyRow);
originRange.copyTo(target);
SpreadsheetApp.flush();
Use the getMaxRows() method to get every every row in the spreadsheet, whether it's got content or not. That returns an integer, so convert it to a string then use a text formula to create the A1 notation.
Then, don't set the formulas, use copyTo()

insertRowsBefore() Method causing error: cannot convert (range) to class

I was trying to write a script in google spreadsheets that, will read a range from a defined cell, take its value and Insert as many rows as the range would indicate, and then copy and paste an specific range also given by a range value in a cell.
Apparently the copy and paste range value works, but the range value for the insertRowsBefore is unable to convert the range value, any idea why this happens? I get this error
cannot convert (range) to class
here is how the scripts looks like:
function CopyActualvsWMS() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("ActualVsSystem");
var value0 = sheet.getRange('T4');
var r1 = value0.getValue();
var insert =ss.getSheetByName("DataBase").insertRowBefore(r1);
var value1 = sheet.getRange('T3');
var cr1 = value1.getValue();
var source = ss.getRange(cr1);
source.copyTo(ss.getRange("DataBase!a2"), {contentsOnly: true});
}
The problem is coming from this line:
var insert =ss.getSheetByName("DataBase").insertRowBefore(r1);
You are putting a variable name r1 into the parameter, but the parameter must be a number (integer), not a string or a range reference. The variable r1 doesn't evaluate to an integer. It's probably a string.
Google Documentation - insertRowBefore()