How to set formula by using google spreadsheets app script? - javascript

Actually, question is - how to recreate type of formulas:
ArrayFormula(replace(replace(regexreplace(K1:K&"","[-/,. ()]",""),4,0,"-"),8,0,"-"))
into code. Unfortunately, i didn't find it by myself, so I'm asking for help.
Upd.
Let me clarify just a little.
Part of code which was used by me into script:
value = value.replace(/^ /, '').replace(/[. )]/g, 'a').replace(/[+]/g, '').replace(/(aa)/g, '-').replace(/(a)/g, '-').replace(/[(]/g, '-');
value = value.replace(/^-/, '');
value = value.replace(/-$/, ''); range2.setValue(value);
This is example of a result:
"(22)road.CA" - "22-road-CA";
"22roadCA" - is not(eror).
If we working into google spreadsheets we could use formula's which I'm typed before, and in this case, results will be the:
"(22)road.CA" - "22-road-CA";
"22roadCA" - "22-road-CA".
So, how to create right code for it? Mb I should delete all signs, use looping method for check sign by sign, and insert my variant after some count of cell array?

Simple example :
var formulaTargetCell = SpreadsheetApp
.getActiveSpreadsheet()
.getActiveSheet()
.getRange(1, 1, 1, 1);
formulaTargetCell.setFormula('=ArrayFormula(replace(replace(regexreplace(K1:K&"""",""[-/,. ()]"",""""),4,0,""-""),8,0,""-""))');
//or
var formulaTargetCell = SpreadsheetApp
.getActiveSpreadsheet()
.getActiveSheet()
.getRange('B2');
formulaTargetCell.setFormulaR1C1('=ArrayFormula(replace(replace(regexreplace(K1:K&"""",""[-/,. ()]"",""""),4,0,""-""),8,0,""-""))');
There are still some kind of way to set formula in app script that documented in available API of Range

Related

Parse #Error When Adding Formula with Javascript

I am having a really weird phenomenon happen in Google Sheets, and I've found nothing on this issue in my research. I'm adding a query formula with javascript and getting a #Error on the sheet. After quadruple checking I wasn't messing up the formula string (the first and most obvious thing to cause such an error) and satisfying myself that the formula was correct for syntax, I cut the formula from the formula bar, hit enter to make the cell blank, then pasted the formula I just cut back in, and boom. Correct result, no error. No change to the formula whatsoever.
So is the a bug with the script editor/sheet interaction? Is a bug in Sheets? Am I doing something wrong (can't imagine what)?
I even followed another post's suggestion and replaced the comma argument separator with a semicolon, but no change in behavior. I have pasted the relevant code here, but I have also shared a Google sheet with the link below that demonstrates the issue.
To reproduce, follow these steps:
Go to the sheet via the link below.
Open Script Editor, and run the function "AddFormula"
When the script runs it will add the formula shown below and you will see a #Error (parse error).
Cut the formula from the formula bar on the sheet and press enter, creating the blank cell.
Copy the formula you just cut back into the cell. Here you will see the correct result of the formula displayed instead of the #Error.
For reference, the relevant code is here:
var wbID1 = "1tujKM_cAePTjBVS6q-gzGheSOAVz68vI0yi_LigCvyw";
var wb = SpreadsheetApp.openById(wbID1); //The entire workbook.
var wsT = SpreadsheetApp.openById(wbID1).getSheetByName("TData"); //T=Target Worksheet
function AddFormula() {
wsT.clear();
wsT.getRange(2,1).setValue("AL");
var TargetRange = wsT.getRange(2,1).getValue();
var QueryString = "=QUERY(States!A2:E; \"Select D where B = '" + TargetRange + "'\")";
wsT.getRange(2,3).setFormulaR1C1(QueryString);
}
The constructed formula in question resolves to:
=QUERY(States!A2:E, "Select D where B = 'AL'")
A demo sheet is here that reproduces the issue:
Demo Sheet
It would be great if there was a solution to this issue, but if that is too much to ask, I would love to simply be affirmed that I'm not crazy! Thanks all!
Use Range.setFormula(formula), since your formula uses an A1 notation States!A2:E
If you use Range.setFormulaR1C1(formula), the given formula must be in R1C1 notation.
Example: =SUM(R[-3]C[0]:R[-1]C[0])
Your Code:
function AddFormula() {
wsT.clear();
wsT.getRange(2,1).setValue("AL");
var TargetRange = wsT.getRange(2,1).getValue();
var QueryString = "=QUERY(States!A2:E; \"Select D where B = '" + TargetRange + "'\")";
wsT.getRange(2,3).setFormula(QueryString);
}
Output:

Form's App Script does not replace fields in template accurately

I have a simple script to generate a doc and PDF upon form submission. It worked well on simple template (e.g. Only 1 sentence, First name, Last name and Company name).
However, when I use a template that's longer, having many fields, and formatting, the code runs but replace the text randomly.
I have tried to hardcode the fields of forms in ascending order as the doc template. However it still replace the text randomly
Can anybody points out what have I done wrong?
My code:
function myFunction(e) {
var response = e.response;
var timestamp = response.getTimestamp();
var [companyName, country, totalEmployees,totalPctWomenEmployees,numberNationality,name1,position1,emailAdd1,linkedin1,funFact1,name2,position2,emailAdd2,linkedin2,gameStage,gameStory] = response.getItemResponses().map(function(f) {return f.getResponse()});
var file = DriveApp.getFileById('XXXXX');
var folder = DriveApp.getFolderById('XXXXX')
var copy = file.makeCopy(companyName + '_one pager', folder);
var doc = DocumentApp.openById(copy.getId());
var body = doc.getBody();
body.replaceText('{{Company Name}}', companyName);
body.replaceText('{{Name}}', name1);
body.replaceText('{{Position}}', position1);
body.replaceText('{{Email}}', emailAdd1);
body.replaceText('{{Linkedin}}', linkedin1);
body.replaceText('{{Fun Fact}}', funFact1);
body.replaceText('{{Game Stage}}', gameStage);
body.replaceText('{{Game Story}}', gameStory);
doc.saveAndClose();
folder.createFile(doc.getAs("application/pdf"));}
My template -
Result -
Question - Does that mean the array declaration in line 3 was supposed to match the order of my form responses columns?
You can use Regular Expresion:
body.replace(/{{Company Name}}/g, companyName); // /g replace globaly all value like {{Company Name}}
Finally I found what have went wrong after so many trials and errors!
The reason is because I declared the array variables randomly without following the order of the form responses columns.
The issue is with the part -
var [companyName, country, totalEmployees,totalPctWomenEmployees,numberNationality,name1,position1,emailAdd1,linkedin1,funFact1,name2,position2,emailAdd2,linkedin2,gameStage,gameStory] = response.getItemResponses().map(function(f) {return f.getResponse()});
It's actually pulling responses from the spreadsheet, and should be corrected in order. The wrongly mapped values was what causing the replacement of text went haywire. I corrected the order as per form responses and it is all good now.
Learning points:
If you swapped around the variables, what response.getItemResponses().map(function(f) {return f.getResponse()} does is that it will go through the form responses column by column in order, and it will map the content to the wrong variable. As a result, when you replace your text later using body.replaceText('{{Game Stage}}', gameStage), there might be possibility that whatever stored in gameStage might be name1. Hence the replaced text will be wrong. And you will scratch your head until it bleeds without knowing why.
I saw #Tanaike's comment after I found the answer, but totally spot on!

Google apps script - Mapping arrays

I am working on a project where I take multiple column/row inventory sheets and turn them into a multi-row/2-column format for order picking.
I have a switch for selecting the appropriate inventory sheet and a map() function that copies the imported information from the inventory DataRange().
However, not all the data is in consistent columns. What I would like to do is find an expression that maps the next column in if the column it was mapping has a zero or "" value.
I won't give you the full body of code unless you need it, but hopefully just the important parts.
This is what I have:
var source = SpreadsheetApp.openById("1xixIOWw2yGd1aX_2HeguZnt8G_UfiFOfG-W6Fk8OSTs"); //This sheet
var srcSht = SpreadsheetApp.getActive();
var sourceMenu = srcSht.getRange('A1');//This is the cell cotaining the dropdown
var menuTest = sourceMenu.getValue();
// Variable for the vars sheet. If it doesn't exist, create it
var varsTest = source.getSheetByName('vars');
if (!varsTest){source.insertSheet('vars');}
var importedA1 = varsTest.getDataRange().getA1Notation();
varsTest.clearContents();
var t1Imp = '=ImportRange("test1_Id", "Stock!A1:F11")';
var varsData = varsTest.getRange('A1');// This is the cell we fill with the importRange formula
varsData.setValue(t1Imp);
var imported = varsTest.getDataRange().getValues();
var newOrder = imported.map(function(item) {
if (item[4] !== NaN){return [[item[0]],[item[4]]];};
if (item[4] === NaN){return [[item[0]],[item[3]]];};}
var orderRange = source.getSheetByName('Sheet1').getRange(10,1,newOrder.length, newOrder[0].length);
orderRange.setValues(newOrder);
Logger.log("\t" + newOrder);
Logger.log(newOrder):
[(timestamp omitted)] items1,order,caramel,6,c&c,2,mint,3,PB,0,,,items2,,caramel,,strawberry,,mint,,PB,
It seems to be skipping the if statements, or I told it that I mean to test the index as NaN, which will obviously never be true.
I also tried replacing 'NaN' with 'undefined'. Same result. I tried finding the item[4].Values, but it gave me an error. I also tried the same logic using filter() instead of map() but it copied the entire data set.
I pull these values onto a new 'vars' sheet in the workbook (to minimize calls to the web service):
test1
reduce them to the first and last columns, then output:
test
The cells in the 'order' column for the second set of items in the 'test' sheet are blank. The values for that order column should be in item[3] of that array, but I can't get the script to identify that that the blank cells are blank.
I am new to Google Apps Script and JS, but I am watching a lot of tuts and learning by doing. If I find a solution, I will post it.
Thank you StackOverflow, I could not have learned as much as I have without this community!
I have a working function that does what I want. In short:
I had to create a duplicate of the order column in a new column, so that all the values would line up. It's not technically a JS answer, but was the simplest and follows good spreadsheet rules.
function rmZeroOrderPS(item){
var source = SpreadsheetApp.openById("<sheetId>"); //This sheet
var varsTest = source.getSheetByName('vars');
var imported = varsTest.getDataRange().getValues();
var i=-1;
while (i <= imported.length){
if(item[8]!= 0) {return [item[0],item[8]]};
i+=1;
};

using a variable within a string with Google Sheets

I am using Google Apps for Sheets. I am trying to use a defined variable within a string. I know the variable (lastRow) is the number I want (that number being "11") as I can see it in the logs. I have tried different ways of combining the letter "C" with the variable, but nothing works! I know it works as it is used in the "copyValuesToRange" method. Am I trying to do something that cannot be done, or is there a way to add the variable to the A1 notation so that the range will be read as C1:C11? Thanks from a relatively novice newbie!
var lastRow = sheet.getLastRow();
Logger.log(sheet.getLastRow());
// Inserts 1 column after column A=1 (Seq)
sheet.insertColumnsAfter(1,1);
// New column(s) due to added column(s)
var range = sheet.getRange("C1:ClastRow");
//Copied to Col A=1
range.copyValuesToRange(sheet,1,1,1,lastRow);
While writing this, the "Similar Question" box showed a link to "Google script string with a variable". I looked at that, but did not understand it "(!
You dont do it like that, you need to know concatenation.
var lastRow = 11;
console.log("C"+lastRow);
will output:
C11
which is what you're going for.
var range = sheet.getRange("C1:C"+lastRow);

String number to fixed Integer Google script

I am having trouble to convert a string 'u12345678910' to an integer without scientific notation. So basically, it literally needs to be exactly 12345678910.
How I have approached it:
1. slice the 'u' to get the number i want (after slice its still a string) OR use .replace()
2. tried parseInt(), Number(), both give me a number in scientific notation.
3. parseFloat() & then parseInt(), don't know why but read somewhere that this might work, it didn't.
Why do i need this exact number?
Since it is a chartId of an EmbeddedChart & Google Slides API is giving me the error that the ID needs to be of TYPE_INT32.
Hopefully someone has a solution to this, since its the only thing blocking my project at the moment :(
Please find below some sample code of how to reproduce.
*I am working in Google Apps Script, Chart is in Spreadsheet & I am using the Google Slides API library of Spencer Easton
var ss = SpreadsheetApp.getActiveSpreadsheet(),
allSheets = ss.getSheets();
var chart = allSheets[0].getCharts()[0],
chartId = chart.getId(); // this returns 'u12345678910'
var chartStringNumber = chartId.slice(1); // returns 12345678910 (string)
var chartIdNumber = Number(chartStringNumber); // Here I want the result to be typeof INT & 12345678910, but i keep getting a number incl scientific notation. I have also tried parseInt().
The chartID returned by the built-in SpreadsheetApp service is a string value that can be overridden using setId(), and starts as an arbitrary value - so it's not the id you want.
To use the Slides API you need the 'real' chart ID which is available from the Advanced Spreadsheet Service, or the directly from the Sheets API.
You can use this code to enumerate the sheets and their charts & real ids using the Advanced Service.
var ch = Sheets.Spreadsheets.get(ss.getId(), {
"fields": "sheets(charts/chartId,properties(sheetId,title))"
});
var sheets = ch.sheets.map (function (d) {
return {
id:d.properties.sheetId,
name:d.properties.title,
charts:d.charts
}
});

Categories