I've tried searching all over the web but could only find how to reassign cell values.
A little background for my code:
The input sheet contains data in columns A through U, but columns R and S are purposefully empty. I need to set & sort the Data Range from columns A through Q ONLY, and the number of rows may change every time I run the code (so the row index needs to be dynamic). When I run my code, the variable does not update, and I don't get any errors. Why is the code not updating my variable for input data. Any help would be greatly appreciated!
Thanks!
function SortUpdate() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var input = ss.getSheetByName("Input");
var inputData = input.getDataRange();
var lastRow = inputData.getNumRows();
inputData = input.getRange(2, 1, lastRow, 17);
for(var i = 9; i<=(15);i++){
inputData.sort({column: i, ascending: false});
}
}
So far you have assigned two different ranges to inputData but you have not collected any data. Take a look at the range.getValues() function here.
function SortUpdate() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var input = ss.getSheetByName("Input");
var inputData = input.getDataRange();//This returns a range not data
var lastRow = inputData.getNumRows();
inputData = input.getRange(2, 1, lastRow, 17);//The inputData variable has received two assignments which one do you want? Both are ranges and do not have any data.
for(var i = 9; i<=(15);i++){
inputData.sort({column: i, ascending: false});
}
}
It would be helpful to see some of your data.
I looked at the range.sort command and some of the examples and I'm wondering if you don't think that it was intended to be used like this:
inputData.sort([{column: 9 ascending: false},{column: 10, ascending: false},{column: 11, ascending: false},{column: 12 , ascending: false},{column: 13, ascending: false},{column: 14, ascending: false},{column: 15, ascending: false}]);
I put the command into the function like below. You won't be able to get this to run because I'm using some of my own utilities to store a global variable in an array in a file so that I can toggle the ascending argument between true and false every time I run it. But this is what it looks like and it definitely is sorting columns A through Q not including the header row.
function SortUpdate()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var input = ss.getSheetByName("Input");
var inputData = input.getDataRange();//This returns a range not data
var lastRow = inputData.getNumRows();
inputData = input.getRange(2, 1, lastRow, 17);//The inputData variable has received two assignments which one do you want?
var dirA=myUtilities.getArrayByName('Params');
inputData.sort([{column: 9, ascending: dirA.state=='true'},{column: 10, ascending: dirA.state=='true'},{column: 11, ascending: dirA.state=='true'},{column: 12 , ascending: dirA.state=='true'},{column: 13, ascending: dirA.state=='true'},{column: 14, ascending: dirA.state=='true'},{column: 15, ascending: dirA.state=='true'}]);
dirA['state'] = (dirA['state']=='true')?false:true;
myUtilities.saveArray('Params', 'DICT', dirA);
}
Instead of using the sheet.getDataRange() and sheet.getNumRows(), you can use the sheet.getLastRow() method, who will return the value of the last row use on the sheet. More about the getLastRow method : https://developers.google.com/apps-script/reference/spreadsheet/sheet#getLastRow()
For the sort method part, you can use the code write by Cooper which is working, or send us a exemple of what kind of sort method you want.
Related
I am trying to build a form that can recall data based on a specific number being inputted using Google Scripts and JavaScript. When a number is inputted the JavaScript should call the Google Scripts so that it can locate the values I need based on the number. For example bellow is a google sheets. I want when the user inputs a number it searches for that value in column C and then grabs the data from that row. Ex. if the number is 14 then values: 2021-05-12, 5, 6 and 7 are returned to the JavaScript.
UPDATED:
Everything I want is working however, when I try to retrieve the date from the array in the JavaScript it does not work. The numbers are the only thing functioning. I know the date is in the array as I can see it in the logs.
JavaScript:
function callDataRetriever(){
var number = document.getElementById("number").value;
google.script.run.withSuccessHandler(dataRetriever).retreiveData(number);
}
function dataRetriever(data){
document.getElementById("location").value = data[0]; //This works
document.getElementById("dateOpened").value = data[1]; //This does not work. Stops the function from continuing its task.
document.getElementById("value1").value = data[2]; //Without the date everything here down works
document.getElementById("value2").value = data[3];
document.getElementById("value2").value = data[4];
document.getElementById("value4").value = data[5];
//...
}
Google Scripts (I have 28 total values) Everything here works perfectly as seen in the logs bellow.
function retreiveData(number){
var url = "urlToSpreadsheet";
var ss = SpreadsheetApp.openByUrl(url);
var ws = ss.getSheetByName("Data");
var data = ws.getRange(1,1, ws.getLastRow(), ws.getLastColumn()).getValues();
var dataValues = [];
var filterData = data.filter(
function(r){
if(r[2] == number){
var i = 3;
while(i < 29){
dataValues.push(r[i]);
i++;
}
}
}
)
return dataValues;
}
I am not sure if the problem lies in the way the date is formatted.
Thank you!
You can use filter to perform the operation you want
var filterData = data.filter(
function(r){
//Select the index init in 0 in your case is 2
return r[0] == 'YOUR_SEARCH_VALUE'
}
)
// Use your filter data
ui.alert(filterData[0]) //data[row][column]
I believe your goal as follows.
When number is given and run the function retreiveData, you want to search the value of number from the cells "C4:C" of "Data" sheet, and want to retrieve the values of the columns "D", "E" and "F" for the searched row.
In this case, I would like to propose to use TextFinder. When the TextFinder is used, searching value is run in the internal server side. By this, the process cost will be a bit low. Ref
When this is reflected to your script, it becomes as follows.
Modified script:
In this case, please modify retreiveData at Google Apps Script side as follows.
function retreiveData(number){
var url = "linkToSpreadsheet";
var ss = SpreadsheetApp.openByUrl(url);
var ws = ss.getSheetByName("Data");
var data = ws.getRange("C4:C" + ws.getLastRow()).createTextFinder(number).matchEntireCell(true).findNext();
if (data) {
return data.offset(0, 1, 1, 4).getValues()[0];
}
return Array(4).fill("No value");
}
And, please modify dataRetriever at Javascript side as follows.
function dataRetriever(data){
console.log(data) // Here, you can check the value from `retreiveData` at the console.
data.forEach((v, i) => {
document.getElementById(`value${i + 1}`).value = v;
});
}
Note:
In this case, when the search value of number is not found, No value is put to the input tags of value1 to value4. When you want to modify this, please modify return Array(4).fill("No value"); for your actual situation.
References:
Benchmark: Process Costs for Searching Values in Spreadsheet using Google Apps Script
Class TextFinder
There are two ways:
var data = [
[1, 55, 5545, 54, 51],
[2, 45, 541, 848, 1215],
[3, 323, 3232, 215, 3051],
[4, 13, 5151, 1513, 2315]
]
number = 3;
// via object where the 'numbers' are keys
var data_obj = Object.fromEntries(data.map(d => [d[0], d.slice(1,)]));
console.log(data_obj[number]); // [ 323, 3232, 215, 3051 ]
// via filter (about the same as #macorreag's answer)
var res = data.filter(d => d[0] == number)[0].slice(1,);
console.log(res); // [ 323, 3232, 215, 3051 ]
An object makes sense in the cases when you need to extract info from the same data several times. For single requests a filter looks better, I think.
And if the numbers always start from 1 and go sequentially 2, 3, 4, 5, ... etc, the simpliest solution is an array and its indexes:
var data = [
[1, 55, 5545, 54, 51],
[2, 45, 541, 848, 1215],
[3, 323, 3232, 215, 3051],
[4, 13, 5151, 1513, 2315]
]
var number = 3;
var data_array = data.map(d => d.slice(1,));
console.log(data_array[number-1]); // [ 323, 3232, 215, 3051 ]
In this case you don't even need the first column 'numbers' at all. You can just extract the next four columns and get the rows by indexes (-1): number 1 is data[0], number 2 is data[1] etc.
Basically I have an array of information that I can currently append into google sheets, the thing is that a lot of the information is not necessary for my need so I wanted to find a way to just append the columns I need.
The picture above shows how everything looks,
basically the idea is to make it looks like in the following picture.
so basically I only need to append columns 4,5,7
currently why I do is this!
if (tozip.getContentType() == "application/zip"){ //for ZIP files
var unZip = Utilities.unzip(tozip); //assigns the unzipped file to a new variable
var table = Utilities.parseCsv(unZip[0].getDataAsString());// assigns the data to variable
for (var i = 0; i < table.length; i++) {//loops trought the array an appends the data as it goes.
sheet.appendRow(table[i]);
}
the data comes from a csv file and looks like this.
[[isApplication, applicationDate, isQualified, Funded_Date, isFunded, requested_loan_amount, amountFunded], [1, 2020-02-03, 1, 2020-02-03, 1, , 1300.0000], [1, 2019-12-29, 1, 2019-12-30, 1, 3000.0000, 2000.0000], [1, 2020-01-27, 1, 2020-01-28, 1, , 800.0000], [1, 2020-01-08, 1, 2020-01-10, 1, 2500.0000, 2500.0000], [1, 2020-02-04, 1, 2020-02-10, 1, , 1400.0000], [1, 2020-01-21, 1, 2020-01-21, 1, 5000.0000, 2000.0000], [1, 2020-02-06, 1, 2020-02-06, 1, 1100.0000, 1400.0000], [1, 2020-02-01, 1, 2020-02-04, 1, 1500.0000, 601.0000], [1, 2020-02-11, 1, 2020-02-11, 1, 500.0000, 800.0000]]
so yeah a lot of messy csv data.
I tried adding this to the code and a few variations of it so It can select the inside data
for (var i = 0; i < table.length; i++) {//loops trought the array an appends the data as it goes.
var columns = [];
columns.push(3);
columns.push(4);
columns.push(6);
sheet.appendRow(table[i][columns]);
}
but it does not work I'm super new to this type of stuff, so I'm pretty sure that's not the correct way to try and select the information I want from the array.
let me know if I need to elaborate more on this, I'm not super good at explaining this stuff.
Thank you in advance for the answers I really appreciate the help on this.
You want to retrieve the columns "D", "E" and "G" from the data retrieved by parsing the CSV data.
In your script, table of var table = Utilities.parseCsv(unZip[0].getDataAsString()); is the 2 dimensional data shown in your question.
You want to put the retrieved values to the Spreadsheet.
You want to achieve this using Google Apps Script.
If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
Modification points:
table of var table = Utilities.parseCsv(unZip[0].getDataAsString()); is 2 dimensional array.
When for (var i = 0; i < table.length; i++) {} is used, each row can be retrieved by table[i]. And the values from the columns "D", "E" and "G" can be retrieved by table[i][3], table[i][4], table[i][6].
In this modification, var values = [] is prepared, and each row is put with values.push([table[i][3], table[i][4], table[i][6]]).
When the method of appendRow() is used in the for loop, the process cost becomes high. So in this case, an array is created in the for loop. And the array is put to the Spreadsheet using setValues(). By this, the cost can be reduced.
When above points are reflected to your script, it becomes as follows.
Modified script:
var table = Utilities.parseCsv(unZip[0].getDataAsString());
// I modified below script.
var values = [];
for (var i = 0; i < table.length; i++) {
values.push([table[i][3], table[i][4], table[i][6]]);
}
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
sheet.getRange(sheet.getLastRow() + 1, 1, values.length, values[0].length).setValues(values);
Above script, the values are put to "Sheet1". If you want to change this, please modify getSheetByName("Sheet1").
In this case, table is var table = Utilities.parseCsv(unZip[0].getDataAsString()).
Note:
When var table = Utilities.parseCsv(unZip[0].getDataAsString()) doesn't return the array of CSV data, above modified script cannot be used. Please be careful this.
References:
parseCsv(csv)
getRange(row, column, numRows, numColumns)
setValues(values)
If I misunderstood your question and this was not the direction you want, I apologize.
I have values in an array which are:
[8:00 AM, 9:00 AM] //result of another function
And I would like to find their values inside this 2-Dimensional Array:
[
[8:00 AM],
[9:00 AM],
[10:00 AM],
[11:00 AM],
[12:00 NN],
[1:00 PM],
[2:00 PM],
[3:00 PM]
]
and change the their values "Not Available"
The array log are the values from google sheet using this code:
function testRow(){
var lookDate = "Aug 28, 2019";
var ss = SpreadsheetApp.openByUrl(url);
var ts = ss.getSheetByName("Time_Select");
var checkData = ts.getRange(1, 1, 1, ts.getLastColumn()).getDisplayValues()[0];
var index = checkData.indexOf(lookDate)+1;
var timeValues = ts.getRange(2, index, ts.getLastRow()-1, 1).getValues();
Logger.log(timeValues)
/*var checkSplit = dateValues.join().split(",");
var checkMe = checkSplit.indexOf(dataDisable[1]);
var timeValues = ts.getRange(checkMe, index).getValue();*/
}
I tried to use this code (as you can see in the above google script code):
var checkSplit = dateValues.join().split(",");
var checkMe = checkSplit.indexOf(dataDisable[1]);
var timeValues = ts.getRange(checkMe, index).getValue();
but it was giving me a wrong value. Do you have any suggestions or solutions on how can I search the values inside the 2 dimensional array then go to its location in google sheet and change its value to "Not Available"? Thank you very much in advance for the help.
here is the link for my google sheet:
https://docs.google.com/spreadsheets/d/1lEfzjG1zzJVPMN8r-OpeZm6q9_IqSwk9DNCEY-q7ozY/edit?usp=sharing
The output from your timeValues are strings. If the contents of [8:00 AM, 9:00 AM] are also strings, this is how you can compare them and set the rescpective cell values to "Not Available" in case of coincidence:
function testRow(){
var lookDate = "Aug 28, 2019";
var ss = SpreadsheetApp.openByUrl(url);
var ts = ss.getSheetByName("Time_Select");
var checkData = ts.getRange(1, 1, 1, ts.getLastColumn()).getDisplayValues()[0];
var index = checkData.indexOf(lookDate)+1;
// I called your array resulting from another function 'times'
var times=['8:00 AM', '9:00 AM'];
var timeValues = ts.getRange(2, index, ts.getLastRow()-1, 1).getValues();
for(var i=0;i<times.length;i++){
for(var j=0;j<timeValues.length;j++){
if(times[i]==timeValues[j][0]){
timeValues[j][0]="Not Available"
}
}
}
ts.getRange(2, index, ts.getLastRow()-1, 1).setValues(timeValues);
}
Basically, you loop through both arrays and when the contents coincide you replace the respective entry of timeValues with "Not Available". After exiting the loops you assign to your range the values of the updated timeValues array.
How about:
var result = timeValues.map((_tv) => { return [_tv]; });
I am writing a script for google sheet validation on localization tests. I've gotten stuck on some of the logic. The purpose of the script is to 1) Iterate through all tabs. 2) Find the column on row 2 that has the text "Pass/Fail". Lastly, 3) Iterate down that column and return the rows that say Fail.
The correct script to look at is called combined(). Step 1 is close to being correct, I think. Step 2 has been hard coded for the moment and is not dynamic searching the row for the text. Step 3 is done.
Any help would be great :)!!! Thanks in advance.
https://docs.google.com/spreadsheets/d/1mJfDtAi0hHqhqNB2367OPyNFgSPa_tW9l1akByaTSEk/edit?usp=sharing
/*This function is to cycle through all spreadsheets.
On each spreadsheet, it will search the second row for the column that says "Pass/Fail".
Lastly, it will take that column and look for all the fails and return that row*/
function combined() {
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
var r =[];
for (var i=0 ; i<sheets.length ; i++){//iterate through all the sheets
var sh = SpreadsheetApp.getActiveSheet();
var data = sh.getDataRange().getValues(); // read all data in the sheet
//r.push("test1"); //Testing to make sure all sheets get cycled through
/*I need something here to find which column on row two says "Pass/Fail"*/
for(i=3;i<data.length;++i){ // iterate row by row and examine data in column A
//r.push("test2"); //Testing to make sure the all
if(data[i][7]=='Fail'){ r.push(data[i])}; // if column 7 contains 'fail' then add it to the list
}
}
return r; //Return row of failed results on all tabs
}
At first, it retrieves data at column g. It retrieves a result from the data. The result is 2 dimensional array. The index of each element of the 2D array means the sheet index. If the sheet doesn't include values in column g, the element length is 0.
For example, in the case of following situation,
Sheet 0 doesn't include values in column g.
Sheet 1 includes values in column g. There are "Fail" value at the row number of 3, 4, 5.
Sheet 2 includes values in column g. There are "Fail" value at the row number of 6, 7, 8.
The result (return r) becomes below.
[[], [3, 4, 5], [6, 7, 8]]
Sample script 1:
function combined() {
var sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
var data =[];
sheets.forEach(function(ss){
try { // In the case of check all sheets, if new sheet is included in the spreadsheet, an error occurs. This ``try...catch`` is used to avoid the error.
data.push(ss.getRange(3, 7, ss.getLastRow(), 1).getValues());
} catch(e) {
data.push([]);
}
});
var r = [];
data.forEach(function(e1, i1){
var temp = [];
e1.forEach(function(e2, i2){
if (e2[0] == "Fail") temp.push(i2 + 3);
});
r.push(temp);
});
return r;
}
If I misunderstand your question, I'm sorry.
I'm trying to use "totalsForAllResults" method in google apps script to push out total values for each metrics.
I printed out result of each metrics by each dimension to a spreadsheet. And I'd like to see the total values at the end of the row. I tried many times but cat't get it work. I'll be happy if anybody give me advice.
The problem is the last paragraph. This code worked for get analytics data but "totalsForAllResults" doesn't work.
var results = ChannelReportPC(firstProfile);
 outputToSpreadsheet(results);
function ChannelReportPC(firstProfile) {
var profileId = firstProfile.getId();
var tableId = 'ga:' + profileId;
var startDate = electiveStartDate('SD');
var endDate = electiveEndDate('ED');
var optArgs = {
'dimensions': 'ga:medium', // Comma separated list of dimensions.
'sort': '-ga:sessions',
'segment': 'sessions::condition::ga:deviceCategory==desktop,ga:deviceCategory==tablet', // Process desktop or tablet traffic.
'start-index': '1',
'max-results': '20'
};
// Make a request to the API.
var results = Analytics.Data.Ga.get(
tableId, // Table id (format ga:xxxxxx).
startDate, // Start-date (format yyyy-MM-dd).
endDate, // End-date (format yyyy-MM-dd).
'ga:sessions,ga:percentNewSessions,ga:bounceRate,ga:pageviewsPerSession,ga:avgSessionDuration,ga:transactions,ga:transactionRevenue,ga:transactionsPerSession', // Comma seperated list of metrics.
optArgs
);
var sheet = SpreadsheetApp.getActiveSpreadsheet().insertSheet("media");
}
function outputToSpreadsheet(results) {
sheet = SpreadsheetApp.getActiveSheet()
// Print the headers.
var headerNames = [];
for (var i = 0, header; header = results.getColumnHeaders()[i]; ++i) {
headerNames.push(header.getName());
}
sheet.getRange(1, 2, 1, headerNames.length)
.setValues([headerNames])
.setBackground('#eeeeee');
// Print the rows of data.
sheet.getRange(2, 2, results.getRows().length, headerNames.length)
.setValues(results.getRows());
sheet.getRange(getRows().length+1, 2, 1, headerNames.length)
.setValues(results.totalsForAllResults);
}
I believe your results.totalForAllresults contains array of values. If it is, try to convert it into array of array. Try to follow these steps for your code,
data = [];
data.push(results.totalsForAllResults);
sheet.getRange(getRows().length+1, 2, 1, headerNames.length).setValues(data);