Google Apps Script - can't set formula with concat - javascript

I made an application with google drive and sheets api the problem is that the sheet has some formulas that has conflicts with the created api so I was forced to erase the formulas and write a little app script to autofill the formulas. I was following this [tutorial][1]. But as the formula has strings to concat it throws a syntax error. My code is here:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
ss.getRange("I2").setFormula(CONCAT("problem string";"\n";C2;"\n";F2));
}
Do i need to declare the string as a variable?
EDIT: i am also having problems when using the \n new line character
[1]: https://www.youtube.com/watch?v=cCBtsQGtzoQ

Issues:
setFormula accepts a string but you are passing CONCAT which is not defined nor it is a built in JavaScript method. To make it a string directly, you can use template literals.
also your formula is wrong because CONCAT can concatenate only 2 strings, not 5. You need to use CONCATENATE.
Solution:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
ss.getRange("I2").setFormula(`CONCATENATE("problem string";"\n";C2;"\n";F2)`);
}
Output:

Related

Google Apps Script : How to use the copyTo function with a local string

I came across a problem with my code in Google Apps Script for Sheets. I want to get cell values from 3 different cells, concatenate them in a single string variable, and copy this string variable into a cell of my spredsheet, using the copyto function.
The problem is that Google Apps Script doesn't recognize copyto as a function, because it doesn't work with local string variables (it works fine with other function variables, such as getrange or else). Here is the part of my code that doesn't work :
var prog = f1.getRange("A3");
var jour = f1.getRange("B1");
var heure = f1.getRange("B2");
var texte = prog+" - "+jour+" à "+heure;
heure.copyTo(f2.getRange(1,2))
f1 is properly defined.
Where do I get this wrong ? Is there a workaround for this ?
Cheers
You say that f1 is properly defined and yet this example is complete and works as well.
function copy2test() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Sheet1');
const sh2 = ss.getSheetByName('Sheet2');
sh.getRange('A1').copyTo(sh2.getRange('A2'));
}
Your example is incomplete because I cannot copy it and put it into my code editor and reproduce the same result as you get. So you haven't met the requirement for reproducibility. In my own mind I simply look at your example and assume that you don't know what you're talking about when you say it's defined properly.
You placed it in a snippet. So just run it: It returns an error with the following:
{
"message": "Uncaught ReferenceError: f1 is not defined",
"filename": "https://stacksnippets.net/js",
"lineno": 12,
"colno": 22
}
So you snippet result and I both agree. It's not defined properly.
For anyone coming across the same problem as I was, here is my solution. Because copyTo doesn't work with a string variable such as I had (or at least I don't know how to make it work), I used a different method which produces the same result.
Instead of heure.copyTo(f2.getRange(1,2))
I used f2.getRange(1,2).setValue([texte]);
which does what I wanted and work with a string variable.

Google script - newConditionalFormatRule; whenNumberGreaterThanOrEqualTo not accepting cells?

I'm building a google script but are having trouble with creating the conditional formatting. If I build them in the sheet, there is no issue with setting the range for the conditional format, then set it to "Greater than or equal to" and give it a cell, like =$B$5.
When I build the same thing using the script, it gives me an error that it only accepts numbers and not cells..?
Can anyone help me with this issue? Or is it simply not supported?
// What i want to work, but throws an error, since it doesn't get a number.
formatrules.push(Rule1);
var rule_builder = SpreadsheetApp.newConditionalFormatRule()
.whenNumberGreaterThanOrEqualTo("=$B$9")
.setBackground("#85e085")
.setRanges([currentsheet.getRange("H3:H8")])
.build();
// Something I tried, but it sets it to a static number and not the cell
formatrules.push(Rule1);
var rule_builder = SpreadsheetApp.newConditionalFormatRule()
.whenNumberGreaterThanOrEqualTo(sheet.getRange('B9').getValue())
.setBackground("#85e085")
.setRanges([currentsheet.getRange("H3:H8")])
.build();
Proposed modification
Since you want a dynamic value what about using the .whenFormulaSatisfied(String formula) function?
Here is an example in your application case:
var rule_builder = SpreadsheetApp.newConditionalFormatRule()
.whenFormulaSatisfied("=H3:H8>$B$9")
.setBackground("#85e085")
.setRanges([currentsheet.getRange("H3:H8")])
.build();
Reference
whenFormulaSatisfied(formula)
The parameter in the whenNumberGreaterThanOrEqualTo is of type Number, as specified in the API documentation seen here. You're passing in a string reference to a cell. Instead, you'd have to use SpreadsheetApp.getActiveSheet().getRange("B9").getValue(), as you do in your second attempt. The problem you're running into could be resolved by updating that rule every time the spreadsheet is edited (ie create an onEdit trigger for the function that creates this rule).
The current accepted answer should remain accepted. This is just a complementary post regarding OP's comment:
Seems kind of weird to enter the range again
You can define the range once and then use Template literals to incorporate it into the expression:
var rng = "H3:H8";
var rule_builder = SpreadsheetApp.newConditionalFormatRule()
.whenFormulaSatisfied(`=${rng}>$B$9`)
.setBackground("#85e085")
.setRanges([currentsheet.getRange(rng)])
.build();

Javascript optimizing regex function to extract sentences from a string containing a keyword

I currently have a function to take a string, break it up into sentences, then extract the sentences that contain a user defined keyword and return them:
function getSentencesWithWord(word, text) {
let sentenceArray = text.replace(/([.])\s*(?=[A-Z])/g, "$1|").split("|")
return sentenceArray.filter(sentence => sentence.includes(word))
}
Currently, this function works. However, the amount of text I need to search through with this function is quite large; it is searching through around 30 google docs that could each be up to 75 pages each, and searching for certain terms (such as the word "the") can take up to a minute for the function to complete. Is there a more optimized way to search through and extract this much text?
Edit:
Because someone asked in the comments, the word variable is just a string obtained from a text input on an HTML page and the text variable is a string obtained via this function in a Google Apps Script:
function getText(docID){
let doc = DocumentApp.openById(docID);
let textToSearch = doc.getBody().getText();
return textToSearch;
}
I have an array of all the google doc IDs I need to access and I just iterate over the array and obtain the text for each doc
The replace you've provided, replace(/([.])\s*(?=[A-Z])/g, "$1|"), didn't work for me == got the same string without change...
How about this:
("|"+text.toLowerCase().replace(/\s/g, "|")+"|").includes("|"+word.toLowerCase()+"|")
Or, this:
("|"+text.toLowerCase().split(" ").join("|")+"|").includes("|"+word.toLowerCase()+"|")
Was unable to find a faster method of achieving this with Google Apps Script so I just went back to Node.js and ended up using the Google Drive API to download the files as .txt files, which are much smaller and so I can search through them much faster now

Get URL from image via script on Google Sheets - does this code still work?

I am using Google Sheets.
Cell A1:
=image("address.jpg")
This puts the image in a cell. To get the url from Stack Overflow produced this answer.
I created the script, and Google recognised it in autocomplete. The error I am getting is:
TypeError: Cannot call method "match" of null. (line 10).
I ran the regex through a checker, and it does get what I am looking for i.e the address, but the error seems to indicate that it's coming back with nothing.
Does this still work? Has Google changed something?
My work-around is to create two sheets and have §=image in one sheet, while in the second sheet, I remove § and use a standard Google function.
The linked solution is far better, and I'd like to implement that if I could. I cannot post a comment on the original solution's page as I don't have reputation points.
In your situation, "null" is given as an argument. Because the formula cannot be directly retrieved by =getImageUrl(A1). By this, the error of Cannot call method "match" of null. occurs. The formula can be retrieved by getFormula(). This is also mentioned at Eric Koleda's answer. So for example, the script can be modified as follows.
Modified script:
function getImageUrl(range) {
var formula = SpreadsheetApp.getActiveSheet().getRange(range).getFormula(); // Added
var regex = /=image\("(.*)"/i;
var matches = formula.match(regex);
return matches ? matches[1] : null;
}
Note:
If =image("URL") is put in "A1", when you use this like =getImageUrl("A1"). Please enclose A1 by the double quotes. By this, the string of "A1" is given to the function and is used as the range.
Reference:
getFormula()

"Unique" is not defined

I am a beginning Google sheets script writer, though I've done javascript and coding for years. I am trying to do some simple sorting on arrays, but can't get the UNIQUE or the SORT function to work. Any reference to them and I get:
ReferenceError: "UNIQUE" is not defined.
I'm starting to think I am missing a library or module or something needs to be enabled in sheets. I did enable the Google sheets API, through the Resources tab on the script editor.
Here is my script:
function fcnImportStockData() {
var i=1;
var arrStockSymbols = [];
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Sheet2");
// get last cell of the range
while (sheet.getRange("C"+i).getValue() != "" ) {
sheet.getRange("d15").setValue(i);
i++;
}
arrStockSymbols = UNIQUE("C1:C"+i);
}
On a side note, I couldn't get the function ISBLANK to work either, to simplify the While loop looking for the first blank cell in the column to set the range for sorting.
I think I am missing something simple or big picture. I have scoured the web for similar situations, and found nothing much.
TIA!
First, keep in mind that Google Sheets Script is nothing more then Javascript.
UNIQUE() is not a valid JS function, but it's a spreadsheet function that can be used inside a formula.
To use it, you must set a formula into some cell:
SpreadsheetApp.getActiveSheet().getRange("X9").setFormula("=UNIQUE(C1:C" + i + ")");

Categories