I'm trying to start a project using Tasker(an app developed for android) It has lots of useful plugins and I have stumbled upon google spreadsheet plugin.
With this plugin i can easily read from a spreadsheet.
But my problem is writing into the spreadsheet. I want to use the spreadsheet as a database for my tasker app.
This means it will write simple values to the Spreadsheet examples
A2 = Nexus5/off:1:8:1
A3 = Nexus6/on:2:3:4
I am now trying to script a search and replace within google scripts. And im getting stuck.
What i want it to do is if my Nexus5 turns on it will send to the spreadsheet in A1 Nexus5/on:1:8:1.
The script has to search for Nexus5/ in column A and replace the cell value with the new value. After that it has to delete A1 so new input can be put in. Beneath is the script i got so far it can search for an input I put in A1 and replace it in the list with test. But I can't seem to get it search just for the first part.
function replaceInSheet(sheet, to_replace, replace_with) {
//get the current data range values as an array
var values = sheet.getDataRange().getValues();
//loop over the rows in the array
for(var row in values){
//use Array.map to execute a replace call on each of the cells in the row.
var replaced_values = values[row].map(function(original_value){
return original_value.toString().replace(to_replace,replace_with);
});
//replace the original row values with the replaced values
values[row] = replaced_values;
}
//write the updated values to the sheet
sheet.getDataRange().setValues(values);
}
function onChange(e){
var sheet = SpreadsheetApp.getActiveSheet()
replaceInSheet(sheet,val,'test');
}
You want to use regexes to crack this nut. There is a comprehensive set of answers here.
In short, set your search to /^Nexus5\// (either with that raw regex declaration, or creating a new RegExp() object) & just use string.replace(), then write the updated values back as required.
e.g.
var myString = “Nexus5/1.2.3”;
var newValue = myString.replace(/^nexus5\/.+/i, “my new value”);
So, here we’re looking for a string beginning with “Nexus5/“ & replacing it with “my new value”. (^ anchors the search to the beginning of the string, .+ means 1 or more characters other than a line-end, we need to escape the slash - \/ - so it’s not interpreted as the end of the regex & the i after the pattern sets the search to case-insensitive.) We can now write newValue back to the source sheet however you need using the range.setValue() or range.setValues() method of the spreadsheet.
Related
I am using Google scripts to try and output 2 .txt files by reading in the information from Sheet 1.
I want my files to look like below one for just titles and the other for footnotes:
Therefore the ‘|’ character in the footnote column needs to split onto a new line with the same program name listed as above.
The attached sheet is a basic example, but I need guidance which would also work if the footnote column had multiple ‘|’ characters.
Any help is appreciated.
Solution
Use the split() JS String method to obtain your strings in a single array.
When obtaining the values from a Spreadsheet the Apps Script methods will arrange them in multidimensional Arrays using this fashon: sheet[rows][columns].
In this example I will use the 3rd column, but you can of course adapt this method to whatever column serves you best:
function splitter() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var thirdColumnValues = ss.getDataRange().getValues().flatMap(row => row[2].split('|'));
var text = thirdColumnValues.join("\n"); //Just concatenate the values with the "return" symbol
}
Reference
getValues()
JS String
My plan is to calculate how many days between 2 given dates by using function DATEDIF in Google Spreadsheet and the function must be from Google Apps Script. I can get it by below.
sheet.getRange(x,10).setFormula('datedif(K32,L32,"d")');
However, as the row is increasing by AppendRow whenever GAS calls spreadsheet so I tried to use variable x to get the last row. It makes me know where the target row is. My trouble is that I could not let setFormula to use variable as below, where start and due are A1Notation of the 2 given cells with date.
sheet.getRange(x,9).setFormula('datedif([start],[due],"d")');
MY code is as below.
var x = sheet.getLastRow();
sheet.getRange(x,11).setValue("2020/05/20");
sheet.getRange(x,12).setValue("2020/07/21");
start = sheet.getRange(x,11).getA1Notation();
due = sheet.getRange(x,12).getA1Notation();
sheet.getRange(x,9).setFormula('datedif([start],[due],"d")');
sheet.getRange(x,10).setFormula('datedif(K32,L32,"d")');
Answer:
You need to concatenate the cells' A1 notations into your string in setFormula().
Code Modification:
As of V8, you can use template literals inside Google Apps Script. You can do this as below:
start = sheet.getRange(x,11).getA1Notation();
due = sheet.getRange(x,12).getA1Notation();
sheet.getRange(x,9).setFormula(`datedif(${start},${due},"d")`);
References:
Template literals (Template strings) - JavaScript | MDN
As we have find and replace logic in Excel and many other documents, how to implement the same using Handsontable? I tried to find the same in the Handsontable site but could not find. All i could find was "search" using searchbox.
Im new to Handsontable. Any help on this would be great.
You can easily reuse the search function already present in the Handsontable documentation example for the first part of the problem.
You then have to add a field where you can put the value you want to replace the cells that have been match, and use the below simple function to replace those values by the new one :
Handsontable.dom.addEvent(Replace, 'click', function() {
// Replace the value of every cell that have been match by the search query
for (row = 0, r_len = queryResult.length; row < r_len; row++) {
hot.setDataAtCell(queryResult[row].row, queryResult[row].col, replace);
}
// Reset all the fields
SearchField="";
ReplaceField="";
queryResult="";
document.getElementById('Search').value='';
document.getElementById('ReplaceWith').value='';
});
See this working jsFiddle example.
Adding to https://stackoverflow.com/a/50228873/9230481
Note that this fail if you enable any form of sorting or filtering (e.g. columnSorting: true) because the matches in „visual indices“, which change after sorting. To solve this you need map the indices to physical ones right after the search finished. See https://handsontable.com/docs/api/core/#tophysicalrow and https://handsontable.com/docs/api/core/#tophysicalcolumn
In the replace function you need to map physical indices back to visual indices as setDataAtCell expects visual indices: https://handsontable.com/docs/api/core/#setdataatcell
I'm using Google App Script. I have a spreadsheet with questions on it for energy auditors about buildings they visit. The auditor is asked to put their answers to the spreadsheet's questions in certain cells. Then they can use a script I wrote to generate a more formal looking Google Document report. The report is generated via these steps: Each cell the auditor inputs an answer into is a defined range. For instance, let's say Cell B10 is defined as "buildingAddress" in spreadsheet. The auditor is asked to put the building address in that cell - let's say he inputs "55 Sample Drive, Portland". When the auditor clicks to generate a Document report, the script runs these lines:
var buildingAddress = sheet.getRangeByName('buildingAddress').getValue();
copyBody.replaceText("<buildingAddress>", buildingAddress);
The place holder in my (Document file) report template is <buildingAddress>. So the code finds this in the report template and replaces it with "55 Sample Drive, Portland" - the value the auditor entered into the spreadsheet cell.
Unfortunately, there are A LOT of such cell values I need to pull from the spreadsheet and push to a placeholder in the report document. They all fit the structure of this:
var buildingAddress = sheet.getRangeByName('buildingAddress').getValue();
copyBody.replaceText("<buildingAddress>", buildingAddress);
So, I'm wondering, can I achieve the same result but use a lot less code by using an array and for loop??? Let's say the array looks like this:
var array = ["buildingAddress", "buildingOwner", "auditorName"];
How do I set up a for loop???
Thank you!!!!!
a loop will not give you gains its exactly the same except cleaner code.
debug it and see where the slow parts are (see execution transcript or log at key steps).
For example if its slow to get a range by name, and all those named ranges are contiguous, instead make a single named range for those cells. get the range (will return array) and get the values from there. this makes a single "get range" call instead of the N you have now.
from your "how to write a loop" question, seems you are just beginning programming. Id suggest a tutorial and more practicing as stackoverflow assumes you know those basics.
Thanks! If anyone's interested, here's what worked for me. I made an array of string objects. Each string was same text as a defined range in my spreadsheet. Then I used this for loop:
for(var i = 0; i < simpleCopyReplaceArray.length; i++){
var definedRangeCellName = simpleCopyReplaceArray[i];
var cellValue = ss.getRangeByName(definedRangeCellName).getValue();
var placeHolder = "<" + definedRangeCellName + ">";
if( cellValue != ""){
copyBody.replaceText(placeHolder, cellValue);
}else{
copyBody.replaceText(placeHolder, "");}
}
I'm trying to use a spreadsheet as a database, where each sheet would be a table and the name of a person is used as a primary key (It seems not to be the best solution, but the good spreadsheet interface makes me prefer this solution rather than trying to use ScriptDB.)
And I want to do the following: When you select a name on a sheet and press a button on the menu I added, a function performs a search in another table and a screen and shows all the results of that query in the other table, showing properties records that only that table contains (later I want to add the possibility to generate a text file from a GDocs template).
My questions is:
1) Considering this screen/panel UI has a variable length (because the record number may vary in other tables), what is the best way to create this panel/UI in Google Apps Script? (I don't want to use the Logger.log because I want to add a button to convert the query into a file)
2) In addition to this solution (a search in the resulting 2D array):
function test(){ // to test the find function with an argument, 'any' in this case
var result = findItem('any');
if(result){Logger.log(result.getA1Notation())}else{Logger.log('no luck !')};
}
function findItem(item){
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var data = ss.getDataRange().getValues()
for(var n = 0;n<data.length;++n){
if(data[n].indexOf(item)>-1){ // this is a "strict" find, ie the value must be the entire search item. If you want to do partial match you should compare differently...
return (ss.getRange(n+1,data[n].indexOf(item)+1)); // if found return the range. note the +1 because sheets have 1 index while arrays have 0 index
}
}
return false;// if we come to the end of sheet without result...
}
There is an alternative method to perform queries like this?
THANKS for any help!
Create a UI instance. Then a scrollable panel inside a main panel is the best way of doing this and then using array's to search through the data. I typically create header body and footer panels with the body being scrollable