Regex in Google App Script to enclose each word inside an Array inside quotes - regex

For example I want to enclose each word in the following array inside quotes.
{seguridad=0, funcionalidad=1, instalaciones=si, observaciones=si,
areas=Pasillos, limpieza=no, pintura=tal vez}
Into:
{"seguridad"="0", "funcionalidad"="1", "instalaciones"="si",
"observaciones"="si", "areas"="Pasillos", "limpieza"="no",
"pintura"="tal vez"}
This is my unsuccesful script so far.
function Enclose() {
var doc = SpreadsheetApp.openById(SCRIPT_PROP.getProperty("1iXQxyL3URe1X1FgbZ76mEFAxLnxegyDzXOMF6WQ5Yqs"));
var sheet = doc.getSheetByName("json");
var sheet2 = doc.getSheetByName("tabla de frecuencias");
var rows = sheet.getDataRange();
var numRows = rows.getNumRows();
var values = rows.getValues();
var prelast = sheet.getRange("A1:A").getValues();
var last = prelast.filter(String).length;
var json = sheet2.getRange("B11").getValues();
var regExp = new RegExp("/[\w]+", "g");
/* var match = json.replace(regExp,""); */
var match = regExp.exec(match);
sheet2.getRange("C11").setValue("\"" + match + "\"");
}

You may try the following approach :
First you wrap all , and = by quotes "" by using the following regex:
/(\s*[,=]\s*)/
Then you replace the opening brackets separately using the following two regex:
/(\s*{)/gm
/(\s*})/gm
const str = `{seguridad=0, funcionalidad=1, instalaciones=si, observaciones=si, areas=Pasillos, limpieza=no, pintura=tal vez}`;
var result = str.replace(/(\s*[,=]\s*)/gm,`"$1"`);
result=result.replace(/(\s*{)/gm,`$1"`);
result=result.replace(/(\s*})/gm,`"$1`);
console.log(result);

How about this sample?
Sample script :
var json = "{seguridad=0, funcionalidad=1, instalaciones=si, observaciones=si, areas=Pasillos, limpieza=no, pintura=tal vez}";
var res = json.replace(/(\d+|[a-zA-Z]+)=(\d+|[a-zA-Z\s]+)/g, "\"$1\"=\"$2\"");
Logger.log(res)
Result :
var json = "{seguridad=0, funcionalidad=1, instalaciones=si, observaciones=si, areas=Pasillos, limpieza=no, pintura=tal vez}";
var res = json.replace(/(\d+|[a-zA-Z]+)=(\d+|[a-zA-Z\s]+)/g, "\"$1\"=\"$2\"");
console.log(res)
When this is reflected to your script, the modified script is as follows.
Modified script :
function Enclose() {
var doc = SpreadsheetApp.openById(SCRIPT_PROP.getProperty("1iXQxyL3URe1X1FgbZ76mEFAxLnxegyDzXOMF6WQ5Yqs"));
var sheet = doc.getSheetByName("json");
var sheet2 = doc.getSheetByName("tabla de frecuencias");
var rows = sheet.getDataRange();
var numRows = rows.getNumRows();
var values = rows.getValues();
var prelast = sheet.getRange("A1:A").getValues();
var last = prelast.filter(String).length;
var json = sheet2.getRange("B11").getValue();
// var regExp = new RegExp("/[\w]+", "g");
// /* var match = json.replace(regExp,""); */
// var match = regExp.exec(match);
match = json.replace(/(\d+|[a-zA-Z]+)=(\d+|[a-zA-Z\s]+)/g, "\"$1\"=\"$2\"");
sheet2.getRange("C11").setValue("\"" + match + "\"");
}

Related

Google Sheet Script - if else, checking if cells match

looking for some help with the function below. I'm trying to have it check if a file has been updated in Google Drive before running a import script. I have it down to checking if two dates/times match in a sheet, but I can't seem to get it to correctly register whether they match. It should either be when S3 <> T3 or when U3 = FALSE. Any help would be greatly appreciated!!
function syncCSVtransactions() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sh = ss.getSheetByName("LOOKUP")
var cell_trnsnew = sh.getRange("S3");
var cell_trnsold = sh.getRange("T3");
var cell_trnscheck = sh.getRange("U3");
if( cell_trnsnew != cell_trnsold ){ //this is the line giving trouble
var source_file = DriveApp.getFilesByName("data_export.csv").next();
var csvData = Utilities.parseCsv(source_file.getBlob().getDataAsString());
var sheet2 = ss.getSheetByName('trs');
sheet2.getRange(1, 1, csvData.length, csvData[0].length).setValues(csvData);
cell_trnsnew.copyTo(cell_trnsold, {contentsOnly:true});
chartupdate();
} else {
}
}
I think that in your script, var cell_trnsnew = sh.getRange("S3");, var cell_trnsold = sh.getRange("T3"); and var cell_trnscheck = sh.getRange("U3"); can be written by one call. And, although I'm not sure about the values of your "LOOKUP" sheet, how about the following 2 patterns?
Pattern 1:
In this pattern, it supposes that the values of "S3", "T3" and "U3" are the date object, the date object and boolean, respectively.
From:
var cell_trnsnew = sh.getRange("S3");
var cell_trnsold = sh.getRange("T3");
var cell_trnscheck = sh.getRange("U3");
if( cell_trnsnew != cell_trnsold ){
To:
var [cell_trnsnew, cell_trnsold, cell_trnscheck] = sh.getRange("S3:U3").getValues()[0];
if (cell_trnsnew.getTime() != cell_trnsold.getTime() || cell_trnscheck === false) {
Pattern 2:
In this pattern, the values of "S3", "T3" and "U3" are used as the string values.
From:
var cell_trnsnew = sh.getRange("S3");
var cell_trnsold = sh.getRange("T3");
var cell_trnscheck = sh.getRange("U3");
if( cell_trnsnew != cell_trnsold ){
To:
var [cell_trnsnew, cell_trnsold, cell_trnscheck] = sh.getRange("S3:U3").getDisplayValues()[0];
if (cell_trnsnew != cell_trnsold || cell_trnscheck == "FALSE") {
References:
getValues()
getDisplayValues()

Google Script, how can use variables with regex search?

Very inexperienced coder here, I have recently gotten a script working that uses regex to search for two different words occurring within a certain word limit. So I can search for "the" and "account" occurring within 10 words of each other, then my script prints the sentence it occurs in. However, my work requires me to search for lots of different work combinations and it has become a pain having to enter each word manually into the string /\W*(the)\W*\s+(\w+\s+){0,10}(account)|(account)\s+(\w+\s+){0,10}(the)/i; for example.
I would like to have something in the script where I can enter the words I want to search for just once, and they will be used in the string above. I have tried, what I think is, declaring variables like this:
var word1 = the
var word2 = account
/\W*(word1)\W*\s+(\w+\s+){0,10}(word2)|(word2)\s+(\w+\s+){0,10}(word1)/i;
But, again, very experienced coder so I'm a little out of my depth. Would really like something like the script snippet above to work in my full script listed below.
Here is my full working script without my attempt at declaring variables mentioned above:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var historySheet = ss.getSheetByName('master');
var resultsSheet = ss.getSheetByName('results');
var totalRowsWithData = historySheet.getDataRange().getNumRows();
var data = historySheet.getRange(1, 1, totalRowsWithData, 3).getValues();
var regexp = /\W*(the)\W*\s+(\w+\s+){0,10}(account)|(account)\s+(\w+\s+){0,10}(the)/i;
var result = [];
for (var i = 0; i < data.length; i += 1) {
var row = data[i];
var column = row[0];
if (regexp.exec(column) !== null) {
result.push(row); }}
if (result.length > 0) {
var resultsSheetDataRows = resultsSheet.getDataRange().getNumRows();
resultsSheetDataRows = resultsSheetDataRows === 1 ? resultsSheetDataRows : resultsSheetDataRows + 1;
var resultsSheetRange = resultsSheet.getRange(resultsSheetDataRows, 1, result.length, 3);
resultsSheetRange.setValues(result);}}
I tried this solution but not sure I have done it correctly as it only enters results in logs and not printing in the "results" sheet:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var historySheet = ss.getSheetByName('Sheet1');
var resultsSheet = ss.getSheetByName('Results1');
var totalRowsWithData = historySheet.getDataRange().getNumRows();
var data = historySheet.getRange(1, 1, totalRowsWithData, 3).getValues();
const regexpTemplate = '\W*(word1)\W*\s+(\w+\s+){0,10}(word2)|(word2)\s+(\w+\s+){0,10}(word1)';
var word1 = 'test1';
var word2 = 'test2';
var regexpString = regexpTemplate.replace(/word1/g, word1).replace(/word2/g, word2);
var regexp = new RegExp(regexpString, 'i');
Logger.log(regexp); // /W*(the)W*s+(w+s+){0,10}(account)|(account)s+(w+s+){0,10}(the)/i
var result = [];
for (var i = 0; i < data.length; i += 1) {
var row = data[i];
var column = row[0];
if (regexp.exec(column) !== null) {
result.push(row); }}
if (result.length > 0) {
var resultsSheetDataRows = resultsSheet.getDataRange().getNumRows();
resultsSheetDataRows = resultsSheetDataRows === 1 ? resultsSheetDataRows : resultsSheetDataRows + 1;
var resultsSheetRange = resultsSheet.getRange(resultsSheetDataRows, 1, result.length, 3);
resultsSheetRange.setValues(result);}}
Use the RegExp contructor.
const regexpTemplate = '\\W*(word1)\\W*\\s+(\\w+\\s+){0,10}(word2)|(word2)\\s+(\\w+\\s+){0,10}(word1)';
var word1 = 'the';
var word2 = 'account';
var regexpString = regexpTemplate.replace(/word1/g, word1).replace(/word2/g, word2);
var regexp = new RegExp(regexpString, 'i');
Logger.log(regexp); // /\W*(the)\W*\s+(\w+\s+){0,10}(account)|(account)\s+(\w+\s+){0,10}(the)/i
You can put this into a function to easily generate your new regular expression whenever you want to update the words.
/**
* Generate the regular expression with the provided words.
* #param {String} word1
* #param {String} word2
* #returns {RegExp}
*/
function generateRegExp(word1, word2) {
const regexpTemplate = '\\W*(word1)\\W*\\s+(\\w+\\s+){0,10}(word2)|(word2)\\s+(\\w+\\s+){0,10}(word1)';
var regexpString = regexpTemplate.replace(/word1/g, word1).replace(/word2/g, word2);
return new RegExp(regexpString, 'i');
}
/**
* Test the generateRegExp() function.
*/
function test_generateRegExp() {
var word1 = 'the';
var word2 = 'account';
var regexp = generateRegExp(word1, word2); // /\W*(the)\W*\s+(\w+\s+){0,10}(account)|(account)\s+(\w+\s+){0,10}(the)/i
// Use regexp just as you do in your script
// i.e. if (regexp.exec(column) !== null) { result.push(row); }
}
Your final script could look something like this.
function printSentences() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var historySheet = ss.getSheetByName('Sheet1');
var resultsSheet = ss.getSheetByName('Results1');
var totalRowsWithData = historySheet.getDataRange().getNumRows();
var data = historySheet.getRange(1, 1, totalRowsWithData, 3).getValues();
var result = [];
var regexp = generateRegExp("the", "account");
for (var i = 0; i < data.length; i += 1) {
var row = data[i];
var column = row[0];
if (regexp.exec(column) !== null) {
result.push(row);
}
}
if (result.length > 0) {
var resultsSheetDataRows = resultsSheet.getDataRange().getNumRows();
resultsSheetDataRows = resultsSheetDataRows === 1 ? resultsSheetDataRows : resultsSheetDataRows + 1;
var resultsSheetRange = resultsSheet.getRange(resultsSheetDataRows, 1, result.length, 3);
resultsSheetRange.setValues(result);
}
}
/**
* Generate the regular expression with the provided words.
* #param {String} word1
* #param {String} word2
* #returns {RegExp}
*/
function generateRegExp(word1, word2) {
const regexpTemplate = '\\W*(word1)\\W*\\s+(\\w+\\s+){0,10}(word2)|(word2)\\s+(\\w+\\s+){0,10}(word1)';
var regexpString = regexpTemplate.replace(/word1/g, word1).replace(/word2/g, word2);
return new RegExp(regexpString, 'i');
}

Making a list using api in google sheets

I am attempting to pull faction information from torns api but it puts all data into a single cell rather than listing. heres what ive got so far.
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Faction members')
.addItem('Pulls faction member info','callNumbers')
.addToUi();
}
function callNumbers() {
var response = UrlFetchApp.fetch("https://api.torn.com/faction/42911?selections=basic&key=xFtPCG2ygjbhmKWI");
Logger.log(response.getContentText());
var fact = response.getContentText();
var sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange(1,2).setValue([fact]);
}```
You could try to parse the information using JSON.parse. Something like:
function callNumbers() {
var response = UrlFetchApp.fetch("https://api.torn.com/faction/42911?selections=basic&key=xFtPCG2ygjbhmKWI");
Logger.log(response.getContentText());
var fact = response.getContentText();
var myObject = JSON.parse(fact);
// define an array of all the object keys
var headerRow = Object.keys(myObject);
// define an array of all the object values
var row = headerRow.map(function(key){ return myObject[key]});
// define the contents of the range
var contents = [
headerRow,
row
];
// select the range and set its values
var ss = SpreadsheetApp.getActive();
var rng = ss.getActiveSheet().getRange(1, 1, contents.length, headerRow.length )
rng.setValues(contents)
}

the difference the regexp result

Why ghi's result is different with abc or def?
abc's result is abc: a-b-c-d-e-f
def's result is def: a-b-c-d-e-f
ghi's result is ghi: a-{1}-c-{3}-e-{5}
What is the reason?
function abc(){
var lang = "{0}-{1}-{2}-{3}-{4}-{5}";
var args = ["a","b","c","d","e","f"];
var exp = /\{(\d+)\}/;
var matches = exp.exec(lang);
while (matches) {
var index = parseInt(matches[1], 10);
lang = lang.replace(matches[0], args[index]);
matches = exp.exec(lang);
}
console.log('abc: ' + lang);
}
abc();
function def(){
var lang = "{0}-{1}-{2}-{3}-{4}-{5}";
var args = ["a","b","c","d","e","f"];
var exp = /\{(\d+)\}/g;
var matches = exp.exec(lang);
while (matches) {
var exp = /\{(\d+)\}/g;
var index = parseInt(matches[1], 10);
lang = lang.replace(matches[0], args[index]);
matches = exp.exec(lang);
}
console.log('def: ' + lang);
}
def();
function ghi(){
var lang = "{0}-{1}-{2}-{3}-{4}-{5}";
var args = ["a","b","c","d","e","f"];
var exp = /\{(\d+)\}/g;
var matches = exp.exec(lang);
while (matches) {
var index = parseInt(matches[1], 10);
lang = lang.replace(matches[0], args[index]);
matches = exp.exec(lang);
}
console.log('ghi: ' + lang);
}
ghi();
Function ghi() needs to reset RegExp object's lastIndex inside the loop:
function ghi(){
var lang = "{0}-{1}-{2}-{3}-{4}-{5}";
var args = ["a","b","c","d","e","f"];
var exp = /\{(\d+)\}/g;
while (matches = exp.exec(lang)) {
var index = parseInt(matches[1], 10);
lang = lang.replace(matches[0], args[index]);
exp.lastIndex = 0;
}
console.log('ghi: ' + lang);
}
Because of exp.lastIndex = 0; call now output will be same.
JavaScript's RegExp object is stateful. When global flag is used, and you call a method the same RegExp object, it will start on the next index from the end of the last match.

Regex query with Google spreadsheet scripts

I'm trying to finish off a Google Apps Script to reformat a field that I would ideally like to turn into a hyperlink.
This is the common format of the text in the spreadsheet:
tistaff: other sections: person: randomname
This is how I would like it to appear:
<li>randomname</li>
I've done most of the work except the end bit, which I just can't work out. Can anyone help.
Here's my script:
function HTMLtransform() {
var sheet = SpreadsheetApp.getActiveSheet();
for(var c=1; c<sheet.getLastRow(); c++){
var rng = sheet.getRange("B"+c);
var rplc = sheet.getRange("F"+c);
var value = String(rng.getValue());
var replVal = new String('test');
var target = 'test'; // this variable is designed to capture the unique bit of the variable
target = value.replace(/tistaff: other sections:[a-z]*: ([a-z]*)$/, '$1');// this variable is designed to capture the unique bit of the variable
replVal = value;
replVal = replVal.replace(/ company:/, 'company/');
replVal = replVal.replace(/ person:/, 'person/');
replVal = replVal.replace(/ place:/, 'place/');
replVal = replVal.replace(/tistaff: other sections:/, '<li><a href="http://www.thisisstaffordshire.co.uk/topics/');
replVal = replVal.replace(/ ([a-z]*)$/, '');
replVal = replVal + target + '">' + target + '</a></li>';
rplc.setValue(replVal);
}
}
It works to a point, but this is the output:
**<li>tistaff: other sections: person: randomname</li>**
What am I doing wrong?
Here's the finished code:
I didn't realise that you could insert a subpattern more than once.
function HTMLtransform() {
var sheet = SpreadsheetApp.getActiveSheet();
for(var c=1; c<sheet.getLastRow(); c++){
var rng = sheet.getRange("B"+c);
var rplc = sheet.getRange("F"+c);
var value = String(rng.getValue());
regexFormat = /tistaff: other sections: (place|company|person): ([a-z]*)$/
// var replVal = new String('test');
replVal = value.replace(regexFormat, '<li>$2</li>');
rplc.setValue(replVal);
}
}