Google Sheet Script Editor - setValues for array - javascript

I`m trying to replace old values with new values using setValues in Google sheet script.
The data is in the below link...
https://docs.google.com/spreadsheets/d/1pSUVkxM9FhSNgizedHbY2MnYGTnC2iiYLfrWsoPmDks/edit?usp=sharing
I`m basically trying to remove first 14 characters and the last 12 characters under "Tracker" column
Below is the code I tried..
function URLReplacement() {
var ss = SpreadsheetApp.getActive().getSheetByName("transformer");
var rng = ss.getRange("G:G");
var data = rng.getValues();
for (var items in data)
{
var newer = data[items][0].substring(14)
// Turn these strings into an array
var newerr = newer.split(" ")
// Turn this into 2 dimensional array to use setValues
ss.getRange("G:G").setValues([newerr])
Logger.log([newer]);
}
}
But now, I get errors with the setValues statement
Saying the range I set there do not match the data
What am I doing wrong here..?
Can anyone please provide me with suggestions / advice?

You want to convert from IMAGE_SUFFIX_"http://google.com"<xxxnouse>" to http://google.com at the column "G".
The format of IMAGE_SUFFIX_"http://google.com"<xxxnouse>" is constant.
If my understanding is correct, how about this modification? The reason of your error is that [newer] is not 2 dimensional array for using setValues(). If this error was removed, the header is removed by overwriting the empty value. So I would like to modify as follows.
Modification points:
When getLastRow() is used, the data size retrieved by it can be reduced from that retrieved by "G:G". By this, the process cost can be reduced.
Header is not retrieved by getRange(2, 7, ss.getLastRow(), 1).
From the format of IMAGE_SUFFIX_"http://google.com"<xxxnouse>", split() was used for parsing this value.
The converted data was put by setValues(). By this, the process cost can be also reduced.
Modified script:
function URLReplacement() {
var ss = SpreadsheetApp.getActive().getSheetByName("transformer");
var rng = ss.getRange(2, 7, ss.getLastRow(), 1); // Modified
var data = rng.getValues();
var convertedData = data.map(function(e) {return e[0] ? [e[0].split('"')[1]] : e}); // Added
rng.setValues(convertedData); // Added
}
Note:
In your shared sample Spreadsheet, the sheet name is "Sheet1". But your script uses "transformer" as the sheet name. Please be careful this.
If the format of actual values in your Spreadsheet is different from your shared Spreadsheet, this might not be able to be used.
References:
split()
setValues()
If this was not the result you want, I apologize.

Related

Copy filtered range from one spreadsheet to another - Google app script

I have a large google sheet with 30275 rows and 133 columns in a google sheet. I want to filter the data and copy column AZ to another spreadsheet.
Link to spreadsheet: https://docs.google.com/spreadsheets/d/1aiuHIYzlCM7zO_5oZ0aOCKDwPo06syXhWvhQMKgJE2I/edit?usp=sharing
I have been trying to follow this link
I am not that familiar with javascript and the code is designed to exclude items from filter rather than including items on filter. I have 500+ items to exclude so need to work out something that will be efficient in filtering large dataset in short time before execution limit is reached.
Here is my code so far. Any help to get this working would be appreciated.
NOTE: Filter/ Query with importrange formulas dont work due to the large volume of data. So I need an efficient script to filter large dataset and move them to another sheet before execution time limit.
function filtered() {
var ss = SpreadsheetApp.openById('1u9z_8J-tvTZaW4adO6kCk7bkWeB0pwPcZQdjBazpExI');
var sheet = ss.getSheetByName('Sheet1');
var destsheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('JockeyList');
var demosheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Betting data - Demo');
var jockey = demosheet.getRange('L14').getValues();
// Get full (non-filtered) data
var values = sheet.getRange('A:EC').getValues();
// Apply filter criteria here
//Logger.log(jockey);
var hiddenValues = jockey;
values = values.filter(function(v) {
return hiddenValues.indexOf(v[51]) == 1;
});
Logger.log(values.length);
// Set filtered data on the target sheet
destsheet.getRange(10, 5, values.length, 2).setValues(values);
}
Ok so it seems like you want to copy only the values from AZ in 'Sheet1' that are equal to whatever string value is contained in cell L14 of sheet 'Betting data - Demo.' If that is the case, then here is a change to your original code that will accomplish that:
function filtered() {
var ss = SpreadsheetApp.openById('1u9z_8J-tvTZaW4adO6kCk7bkWeB0pwPcZQdjBazpExI');
var sheet = ss.getSheetByName('Sheet1');
// this assumes that your destsheet and demosheet are in the same spreadsheet. Keep in mind that opening spreadsheets with SpreadsheetApp is costly so you want to minimize your calls to new sheets.
var destsheet = ss.getSheetByName('JockeyList');
var demosheet = ss.getSheetByName('Betting data - Demo');
var jockey = demosheet.getRange('L14').getValue();
var searchTerm = new RegExp(jockey);
// Get full (non-filtered) data
var values = sheet.getRange('A:EC').getValues();
// Apply filter criteria here and return ONLY THE VALUE IN COLUMN AZ
var filteredValues = values.reduce(function(resultArray, row) {
if (searchTerm.test(row[51])) resultArray.push([row[51]]);
return resultArray;
}, [])
// Set filtered data on the target sheet
// Note* not clear why you are starting at row 10, but as is this will overwrite all of the data in column 5 of destsheet starting from row 10 every time this function runs
destsheet.getRange(10, 5, filteredValues.length, 1).setValues(filteredValues);
}
As it says in the code sample, this will only copy and paste the value in column AZ of 'sheet1'. It does not alter 'sheet1' in any way. If that is really all you want to do, then this function works, but it's overkill. Since you are just filtering values in AZ against a single string value, it would be more efficient to simply count the number of times that string occurs in column AZ and then add the string that number of times to your destination sheet.
Also note that your original function is pasting values into destsheet into a constant row (row 10). That means that every time your function runs, the data from row 10 on will be overwritten by whatever data you are copying from 'sheet1'

Google Appscript using for loop with if

The aim of my script is to loop through one column of data (Col 2 in my example) and where the cell says 'Approved' then adjust the formula which is sitting in the corresponding Col1 to be saved as a value. The script below achieves this but runs awfully slowly - can anyone help in speeding it up?
var ss = SpreadsheetApp.getActiveSpreadsheet();
var data = ss.getSheetByName('data');
var tracker = ss.getSheetByName('Tracker');
var rowlength = tracker.getLastRow();
for (r=2; r<rowlength+1; r++) {
var ApprovedCell = tracker.getRange(r,2).getValue();
if (ApprovedCell == 'Approved'){
var FormulaCell = tracker.getRange(r,1);
FormulaCell.copyTo(FormulaCell,{contentsOnly:true});
}}
}
Explanation:
The issue with your current solution is that you are iteratively using getValue, getRange and copyTo which is an extremely inefficient approach especially when the size of the data becomes large.
Instead you can use getValues() and getFormulas() to get all the values and the formulas respectively, of the given range, and then use setValues() to set all the desired values/formulas back to the sheet.
The following script will iterate over the values with a forEach() loop and will store the value, if cell in column B is 'Approved', otherwise store the formula, to an empty array repAr.
Then you can efficiently use a single line of code to set all the values/formulas back to column A:
tracker.getRange(2,1,repAr2D.length,1).setValues(repAr2D);
Solution:
function myFunction(){
const ss = SpreadsheetApp.getActiveSpreadsheet();
const tracker = ss.getSheetByName('Tracker');
const vals = tracker.getRange('A2:B'+tracker.getLastRow()).getValues();
const formulas = tracker.getRange('A2:A'+tracker.getLastRow()).getFormulas().flat();
const repAr = [];
vals.forEach((r,i)=>
repAr.push(r[1]=='Approved'?r[0]:formulas[i]));
const repAr2D = repAr.map(r=>[r]);
tracker.getRange('A2:A'+tracker.getLastRow()).clearContent();
tracker.getRange(2,1,repAr2D.length,1).setValues(repAr2D);
}
Bonus info:
Instead of a regular if condition, I used a ternary operator to make the code more clear.
getFormulas() returns a 2D array and this is why I am using flat() to convert it to a 1D array. This is more convenient given that the range is a single column and you can just slice the array with a single index.
It is a good practice to clear the content before you set data to a range that already contains some data.

SpreadsheetApp.openById error using appscript

I'm importing data from one sheet to another sheet using Google Appscript. However when I run the code there's an error occuring.
function importdata() {
var mainfile = SpreadsheetApp.getActive().getSheetByName('Data1');
var secondfile = SpreadsheetApp.openById('1232131231231abcc').getSheetByName('RAW');
var datas = secondfile.getRange('C:C').getValues();
var paste = mainfile.getRange('A:A').setValues(datas);
}
Message details
Exception: The number of rows in the data does not match the number of rows in the range. The data has 27441 but the range has 27509. (line 6, file "Code")
setValues expects your range to have the same length as the length of data you are trying to set (must match dimensions of your range).
try something like
var datas = mainfile.getRange('A:A').getValues()
var range = secondfile.getRange(1,1,datas.length);
range.setValues(datas);
Update: I actually think you might have "hidden" rows in your dataset, this might cause range to be confused with length.

How to use if then in google app scripts?

I'm working on an app that scans data into Google sheets. i have two sheets: sheet1 and sheet2. In sheet1 the data is entered into it after a scan is performed. But before the scan data can be entered, i would like to do an if function to check if there is a similar type of data in sheet2 before entering the data. if there isn't one then a message will be displayed such as "There is no such person in the database". I would also like to specify the column to check for similarity in sheet2 e.g A2:A100
Below is the script code
function doGet(e){
var ss = SpreadsheetApp.openByUrl("google sheet url");
//Give your Sheet name here
var sheet = ss.getSheetByName("Sheet1");
return insert(e,sheet);
}
function doPost(e){
var ss = SpreadsheetApp.openByUrl("google sheet url");
//Give your Sheet name here
var sheet = ss.getSheetByName("Sheet1");
return insert(e,sheet);
}
function insert(e,sheet){
// reciving scanned data from client i.e android app
var scannedData = e.parameter.sdata;
var d = new Date();
var ctime= d.toLocaleString();
sheet.appendRow([scannedData,ctime]);
return ContentService
.createTextOutput("Success")
.setMimeType(ContentService.MimeType.JAVASCRIPT);
}
Thanks.
Google Apps Script is in essence JavaScript with different libraries. So your if statements are in essence all the same as there:
if (a1 == a2) {
a1 = 0
}
else if (a1 != a3) {
a1 = 1
}
else {
a1 = 'String'
}
Check on logic operators to find what you can do if you are unfamiliar with that and also read about the switch satement as it's also sometimes useful in place of if statements (not in your case, but might as well read up on it while you are on the topic).
EDIT:
As per your comment, to compare the data from specific columns it's quite simple and there are multiple ways of doing it. Think of it as a structure Spreadsheet → Sheet → Range → Value. So if you already have an object for the sheet you can do range = sheet1.getRange(1,1) which will get you the cell A1. Or you can use A1 notation for the getRange('A1'). If your range is a single cell you can then do range.getValue() which will return the value inside the cell.
Now you want to find if the data exists in another sheet, going 1 by 1 will not be effective as getValue() will bloat the script very quickly. Instead you might want to do vals = sheet2.getDataRange().getValues(). This will return a 2D array of all the values inside of the sheet. If you want to only check a specific column and you know you do not care about the rest you can just replace getDataRange() with something like .getRange(C:C) or the same would be getRange(1, 3, sheet2.getLastRow(), 1).
Then you will simply loop through the 2D array with vals[rowNum][colNum].
If the value is added manually to 1 cell and the script fires with an onEdit trigger, you can also get the value directly from the event object e where it's in onEdit(e).
Read up on getRange() (read those bellow as well) as well as getValue() (and getValues bellow that). Google has excellent documentation, just logically follow the structure for what you want to achieve.

Google Apps Scripting - Generic Headers in Spreadsheet

Quick look where I normally bother people tells me here is the new place to ask questions!
I have been making a script to create documentation generated from spreadsheet data which was in turn generated from a Google form. (Hope that makes sense...)
Anyway, I have been very successful with a lot of searching and bit of help but now I want to make my script homogeneous so I don't need to tinker with it when I want to setup new forms etc.
I have the getRowData function going from Googles script tutorials but instead of calling the row data from the normalised Headers i would like these to be generic i.e. Column1, Column2 etc.
I've pasted the tutorial function below, it passes the data to another function which normalizes the headers to use as objects, I was thinking thats where I could make them generic but I'm not sure how to get started on it...
Any help would be greatly appreciated!!
Thanks,
Alex
// getRowsData iterates row by row in the input range and returns an array of objects.
// Each object contains all the data for a given row, indexed by its normalized column name.
// Arguments:
// - sheet: the sheet object that contains the data to be processed
// - range: the exact range of cells where the data is stored
// - columnHeadersRowIndex: specifies the row number where the column names are stored.
// This argument is optional and it defaults to the row immediately above range;
// Returns an Array of objects.
function getRowsData(sheet, range, columnHeadersRowIndex) {
columnHeadersRowIndex = columnHeadersRowIndex || range.getRowIndex() - 1;
var numColumns = range.getEndColumn() - range.getColumn() + 1;
var headersRange = sheet.getRange(columnHeadersRowIndex, range.getColumn(), 1, numColumns);
var headers = headersRange.getValues()[0];
// Browser.msgBox(headers.toSource());
return getObjects(range.getValues(), normalizeHeaders(headers));
// return getObjects(range.getRowIndex);
}
If you want to get the columns using their index, why parse them to object at all? Just use the plain getValues!
var values = sheet.getDataRange().getValues();
var row2 = values[1];
var cell_in_col4 = row2[3];
It looks like you are missing "var" when declaring your columnHeadersRowIndex variable.

Categories

Resources