Regexp Match Google Script inside a loop? - regex

I've been on this problem for a couple of hours, I'm new to coding, so excuse me if it's a very simple question.
So I have a list of text and I want to find if there is one of the regular expression from the other sheet in every cell.
If yes, paste the regular expression next to the text.
Example:
For the first row:
7063 BIO PLANET LIEGE.
--> i'd like it to write "BIO PLANET" in the cell to the right. (Because BIO PLANET is one of the regular expression to test from the second sheet).
I wrote something like this, but couldn't really figure out what needs to be fixed:
function ExpenseMatching() {
var spreadsheet = SpreadsheetApp.getActive();
var sheet1 = spreadsheet.getSheetByName("Import2");
var sheet2 = spreadsheet.getSheetByName("Regular Expression");
for ( i =1; i<24 ; i++)
{
//Browser.msgBox(i)
var test1 = sheet2.getRange("A"+ i);
var test2 = sheet1.getRange("A2");
var test = new RegExp(test1).test(test2);
if (regexp==true)
{
test1.copyTo(sheet1.getRange("I2"));
Browser.msgBox(test)
}
else
{
}
}
}
Thanks is advance for your help guys !

You want to retrieve the values of the column "A" on the sheet Import2 and the values of the column "A" on the sheet Regular Expression.
You want to check whether the values of Import2 includes the values of Regular Expression. When the values of Import2 includes the values of Regular Expression, you want to put the value of Regular Expression to the column "B" on Import2.
You want to achieve this using Google Apps Script.
If my understanding is correct, how about this answer?
Modification points:
In your script,
if (regexp==true) doesn't work and an error occurs. Because regexp is not declared.
This has already been mentioned by Rubén's comment.
From your question, I thought that you want to put the result value to the column "B" of Import2. But it seems that your script puts the value to the column "I" from test1.copyTo(sheet1.getRange("I2")).
Your script checks only "A2" of Import2.
Each row is checked and copy the value in the for loop. In this case, the process cost will be high.
When above points are reflected to your script, how about the following modified script?
Modified script:
function ExpenseMatching() {
var spreadsheet = SpreadsheetApp.getActive();
var sheet1 = spreadsheet.getSheetByName("Import2");
var sheet2 = spreadsheet.getSheetByName("Regular Expression");
const values1 = sheet1.getRange(`A2:A${sheet1.getLastRow()}`).getValues();
const values2 = sheet2.getRange(`A2:A${sheet2.getLastRow()}`).getValues();
const res = values1.map(([r1]) => {
for (let i = 0; i < values2.length; i++) {
if (new RegExp(values2[i][0]).test(r1)) {
return [values2[i][0]];
}
}
return [""];
});
sheet1.getRange(2, 2, res.length, 1).setValues(res);
}
I think that in your situation, you can also use if (r1.includes(values2[i][0])) { instead of if (new RegExp(values2[i][0]).test(r1)) {. This might be able to reduce more cost.
Note:
In this modification, the result values are put to the column "B" of Import2.
Please run the script with enabling V8.
References:
map()
setValues()

Related

get ranges inside formula

I would like to know if there is a practical way of extracting the cells that are used in a formula in google scripts?
For an example:
Let's say A1 has a formula as below
=page1!C2*0,8+page2!B29*0,15+page3!C144*0,05
I would like var myCellsrecord the data of
page1!C2
page2!B29
page3!C144
Please let me know how would you make this.
Thanks in advance
Description
Here is an sample script that can parse equations as shown into the reference cells.
Note this only works for the specific formula you specified.
Code.gs
function test() {
try {
let spread = SpreadsheetApp.getActiveSpreadsheet();
let sheets = spread.getSheets().map( sheet => sheet.getName() );
// for this test
sheets = ["page1","page2","page3"];
let sheet = spread.getSheetByName("Sheet1");
let formula = sheet.getRange("A1").getFormula();
console.log(formula);
// break into parts
let parts = formula.split("*"); // but notice this is for specific case of *
parts.pop() // the last part doesn't contain any cell reference
console.log(parts);
let i = 0;
let results = [];
parts.forEach( part => { let j = sheets.findIndex( sheet => part.indexOf(sheet) >= 0 )
// remove sheet from range
let k = part.split('!')[1]; // this give cell A1 notation
results.push(sheets[j]+k)
}
);
console.log(results);
}
catch(err) {
console.log(err);
}
}
Execution log
6:54:44 AM Notice Execution started
6:54:46 AM Info =page1!C2*0,8+page2!B29*0,15+page3!C144*0,05
6:54:46 AM Info [ '=page1!C2', '0,8+page2!B29', '0,15+page3!C144' ]
6:54:46 AM Info [ 'page1C2', 'page2B29', 'page3C144' ]
6:54:45 AM Notice Execution completed
Reference
Array.map
Range.getFormula()
String.split()
Array.pop()
Array.forEach()
Array.findIndex()
Use range.getFormula() to get the formula and then use regex with String.match to get the cells:
/*<ignore>*/console.config({maximize:true,timeStamps:false,autoScroll:false});/*</ignore>*/
const f =
'=page1!C2:C*0,8+page2!B29*0,15+page3!C144*0,056+sheet1!c:c* Sheet56!D10:D-D5:G10';
const matched = f.match(/(\w+!)?[A-Za-z]+\d*(:[A-Za-z]+\d*)?/g);
console.log(JSON.stringify(matched));
<!-- https://meta.stackoverflow.com/a/375985/ --> <script src="https://gh-canon.github.io/stack-snippet-console/console.min.js"></script>
(\w+!)? - [?optional]Matches one or more word followed by ! for sheet name(eg: page1!)
[A-Za-z]+\d* - Matches one or more letters [A-Z] followed by zero or more digits \d* for range string(eg: C2)
(:[A-Za-z]+\d*)? - [optional] another range string match preceded by a :(eg: :C50)

How to remove all short code (almost similar) from a column on Google sheet [duplicate]

This question already has an answer here:
Reference - What does this regex mean?
(1 answer)
Closed 2 years ago.
I have a Google sheet array with a column of 63 rows (column C) with short codes,
[audio mp3:="https/...." ][/audio]
Each line has this tag but with a different link.
but always with this
[audio mp3:="https/...." ][/audio]
C1: [mp3 audio:="https/upload/content/file1.mp3"][/audio]
C2: [mp3 audio:="https/upload/content/file2.mp3"][/audio]
How do I find and delete all terms that start with " [mp3 audio" and end with "[/audio]" on all 63 rows in column C`?
A sample script using REGEX
function deleteTerms() {
// REGEX pattern
let pattern = /mp3 audio\:="http.+"]\[\/audio]/;
// Initialize Spreadsheet, Sheet, Range, Values
let ss = SpreadsheetApp.getActive();
let sh = ss.getSheetByName("Sheet1"); // Replace with sheet name.
let range = sh.getDataRange();
let values = range.getValues(); // Returns 2D array
// Temporary store of values to delete
let indicesToDelete = [];
// Go through 2D array to find matches to pattern
// and add to store of values to delete
values.forEach((row, rowIndex) => {
row.forEach((cell, cellIndex) => {
if (pattern.exec(cell) != null) {
indicesToDelete.push([rowIndex, cellIndex]);
}
});
});
// Go through store of values, and replace them with ""
indicesToDelete.forEach((item) => {
values[item[0]][item[1]] = "";
});
// Write values to sheet
range = range.offset(0,0, values.length, values[0].length)
range.setValues(values)
}
Make sure the Sheet name is right before you run it.
You can adapt this script to do what you like once you find the results. Whether that is to delete the column, to move the values elsewhere, or just delete the value, as I have done.
This script will find the value whether its in column C or anywhere in the sheet.
References
Apps Script
Sheets Guide
Tutorials
Sheets Reference
JavaScript Regex

Replace first occurrence of text using replaceText(searchPattern, replacement)

I am trying to replace the first occurrence of a paragraph in Google Doc using the function replaceText(searchPattern, replacement), but I can't seem to find the right RegEx expression.
If someone could help me I would really appreciate it.
body.replaceText("^"+paragraph.getText()+"$"," ");
The body.ReplaceText() function replaces all instances of a pattern, not just the first instance ( link ).
A better option may be to loop through the paragraphs to find the first with matching text, like so:
function deleteParagraph(textToRemove) {
var body = DocumentApp.getActiveDocument().getBody();
// gets all paragraphs as an array
var paragraphs = body.getParagraphs()
for (var i = 0; i < paragraphs.length; i++){
if (paragraphs[i].getText() === textToRemove){
paragraphs[i].clear()
Logger.log(textToRemove + " was removed")
//stops it looping through any more paragraphs
break;
}
}
}
If you want to practice with regular expressions then www.regexr.com is very handy.

How to find and replace a list of strings through out the spreadsheet with google script

Items I have:
A large list A of strings in column A (unsorted)
name1 pattern1 pattern4
name5 pattern2
name4 pattern4
name2 pattern3 pattern1
name4 pattern4
A large list B of different string patterns that I want to remove from string in column A (include punctuation and special characters)
pattern1
pattern2
pattern3
Once I compare each pattern in B with the string in A, it should output:
name1 pattern4
name5
name4 pattern4
name2
name4 pattern4
Now I have 2 difficulties. I have a very simple test code, assuming there is only 1 pattern in list, the program executed error free however nothing happens in my google spreadsheet, which I can't explain why
function removeS(){
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange("A1:A");
var data = range.getValues();
for(i in data){
data[i].toString().replace(pattern,"");
}
}
Also secondly are there anyways I can accomplish my task without doing nested loop? (One loop through everything in column A and another loop for list of patterns) It seems so inefficient as I am dealing with large data. In Excel macro you can do sth like:
With ActiveSheet.UsedRange
.Replace pattern1, ""
.Replace pattern2, ""
and takes care of the need of using nested loops, although it takes manual work to add the patterns.
Here is an option. Although I'm not sure a more eloquent way than nested loops, without converting the returned spreadsheet values from a 2d to a 1d array.
I set a constant for the last row of the patterns column, assuming it was the short of the two columns (see comments in code for rational).
function cleanMe(){
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange("A1:A" + sheet.getLastRow());
var data = range.getValues();
// get the array of patterns (all ranges returned as 2d array)
// because .getLastRow() or .getDataRange returns the last row in the spreadsheet with data
// not the last row of the range with data
// hardcoded the last row in column be so as not to
// have to use conditions to check if values exist in range
var patternLastRow = 3;
var patterns = sheet.getRange("B1:B" + patternLastRow).getValues();
// 2d array to replace data in row A using range.setValues(newRange)
var newRange = [];
for(var i = 0; i < data.length; i++){
// use encodeURIComponent to contend with special charactes that would need escaping
var newValue = encodeURIComponent(data[i][0].toString());
for(var p = 0; p < patterns.length; p++){
var pattern = encodeURIComponent(patterns[p][0]);
var index = newValue.indexOf(pattern);
if(index >=0){
newValue = newValue.replace(pattern,'');
}
}
newRange.push([decodeURIComponent(newValue)]);
}
range.setValues(newRange);
}

Using regular expressions to add numbers using find and replace in Notepad++

I have a SPROC which is having the multiple instances of string Say '#TRML_CLOSE'.
I want to make them to be concatenated with a sequence of numbers.
Eg:
Search and find string '#TRML_CLOSE'
And
Replace the 1st Instance with '#TRML_CLOSE_1',
Replace the 2nd Instance with '#TRML_CLOSE_2',
Replace the 3nd Instance with '#TRML_CLOSE_3',
and so on.
How do I achieve this in Notepad++ using expressions.
I don't know the extent you can script Notepad++, but I do know you can throw together a quick JavaScript snippet to do what you want. http://jsfiddle.net/x4eSr/
Just go to the JS fiddle, and hit the button.
document.getElementById("btn").onclick = function() {
var elm = document.getElementById("txt");
var val = elm.value;
var cnt = 1;
val = val.replace(/#TRML_CLOSE(?!=[_])/g, function(m) {
return m + "_" + cnt++;
});
elm.value = val;
};
Using JavaScript's string.replace(regex, function(){}) which calls the function on each match and a globally incremented "cnt" variable.