Get total values in google apps script - javascript

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);

Related

How do I iterate through my google sheets rows, update an array, and show results in another sheet?

I am trying to write a Google Apps Script function which scans every row of my spreadsheet, and if column 36 has a specific string, will look at column 31, column 23, etc. of that row to create an array with the data in these columns.
I think it will ultimately require an array updating function inside an if statement inside a loop.
Loop through every row of column 36
If string matches target string
Add row's data to an array
Update another sheet with data from this array
Thank you!
Here is what I've tried so far:
`
function myFunction() {
var sheet = SpreadsheetApp.getActive().getSheetByName("Database");
var range = sheet.getRange(2, 36).getValue();
Logger.log(range);
}
`
Here is the code, replace the string of Target Sheet Name, the specific String and etc on your own.
function myFunction() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
// DataBase sheet:
const dbSheet = ss.getSheetByName("Database");
// Target sheet for placing your outputs:
const tgSheet = ss.getSheetByName("Target Sheet Name");
// Get all values as a 2D array from DataBase sheet:
const sourceValues = dbSheet.getDataRange().getValues();
// Declare result array.
const results = [];
// Loop through every row:
for (const row of sourceValues) {
const specificString = 'Your String';
// check the value of column 36 of each row.
const check = row[36] === specificString;
// if condition check returns true, form an array with column 31, column 23 and 'etc' of this row, than push it into the result array.
if(check) results.push([row[31],row[23],'etc']);
}
// print the result onto your Target Sheet, start from A1.
tgSheet.getRange(1,1,results.length,results[0].length).setValues(results);
}
Move selected rows to another sheet
function elfunko(specificvalue) {
const ss = SpreadsheetApp.getActive();
const vs = ss.getSheetByName("Database").getDataRange().getValues().filter(r => r[35] == specificvalue);
const sh = ss.getSheetByName("Sheet1");
sh.getRange(sh.getLastRow() + 1, 1, vs.length, vs[0].length).setValues(vs);
}

Google Sheets, stack report from multiple workbooks

Goal: To stack data from 90+ google workbooks, all with the same sheet name, into the one master sheet for reporting
Info:
All worksheets have the same number of columns.
I have the following script but it does not run properly, I think the issue is with how I am caching / Pushing the data to the array before pasting to the output sheet.
I am trying to build an array then paste it in one go.
The tables I am stacking have 47 columns, unknown number of rows.
The part that opens the sheets is all working perfectly.
// Get the data from the worksheets
var indexsheet = SpreadsheetApp.getActive().getSheetByName("Index");
var outputsheet = SpreadsheetApp.getActive().getSheetByName("Output");
var response = SpreadsheetApp.getUi().prompt('Current Cycle', 'Enter Cycle Name Exactly in YY-MMM-Cycle# format', SpreadsheetApp.getUi().ButtonSet.OK_CANCEL)
var CurrentCycleName = response.getResponseText()
// Assign datasets to variables
var indexdata = indexsheet.getDataRange().getValues();
// For each workbook in the index sheet, open it and copy the data to a cache
indexdata.forEach(function(row, r) {
try {
//open Entity specific workbook
var workbookid = indexsheet.getRange(r + 1, 7, 1, 1).getValues();
var Entityworkbook = SpreadsheetApp.openById(workbookid)
// Open workhseet
Entitysheet.getSheetByName(CurrentCycleName)
// Add PR Data to cache - stacking for all countrys
var PRDataCache = Entitysheet.getDataRange().push()
} catch {}
})
// Set the all values of the sheet at once
outputsheet.getRange(r + 1, 14).setValue('Issue Splitting Data')
Entitysheet.getRange(2, 1, PRDataCache.length || 1, 47).setValues(PRDataCache)
};
This is the index tab where we are getting the workbookid from to open each file
This is the output file, we are stacking all data from each country
I believe your goal is as follows.
You want to retrieve the Spreadsheet IDs from the column "G" of "Index" sheet.
You want to give the specific sheet name using a dialog.
You want to retrieve all values from the specification sheet in all Spreadsheets. In this case, you want to remove the header row.
You want to put the retrieved values on "Output" sheet.
In this case, how about the following sample script?
Sample script:
function myFunction() {
var ss = SpreadsheetApp.getActive();
var indexsheet = ss.getSheetByName("Index");
var outputsheet = ss.getSheetByName("Output");
var response = SpreadsheetApp.getUi().prompt('Current Cycle', 'Enter Cycle Name Exactly in YY-MMM-Cycle# format', SpreadsheetApp.getUi().ButtonSet.OK_CANCEL);
var CurrentCycleName = response.getResponseText();
var ids = indexsheet.getRange("G1:G" + indexsheet.getLastRow()).getValues();
var values = ids.reduce((ar, [id]) => {
try {
var [, ...values] = SpreadsheetApp.openById(id).getSheetByName(CurrentCycleName).getDataRange().getValues();
ar = [...ar, ...values];
} catch (e) {
console.log(`"${id}" was not found.`);
}
return ar;
}, []);
if (values.length == 0) return;
// If the number of columns is different in all Spreadsheets, please use the following script.
// var maxLen = Math.max(...values.map(r => r.length));
// values = values.map(r => r.length < maxLen ? [...r, ...Array(maxLen - r.length).fill("")] : r);
outputsheet.getRange(outputsheet.getLastRow() + 1, 1, values.length, values[1].length).setValues(values);
}
Note:
When the number of Spreadsheet IDs is large, the processing time might be over 6 minutes. I'm worried about this. At that time, how about separating the Spreadsheet IDs?
Reference:
reduce()

Remove multiple columns from Google Sheets avoiding expensive loop

I am trying to avoid the following code because it is too slow:
for (var c = 25; c>2; c--){
if (sheet2.getRange(1,c).getValue() == 0)
{sheet2.deleteColumn(c)}
}
Instead I tried to find a list of columns I want to delete from the array and then set the array. (I recently figure out that deleting rows/columns in a loop is very expensive: google script loop performance)
I found this Removing columns of data in javascript array and try to apply it to my code, but it is not working.
Here is the code.
var ary = sheet2.getRange(2,1,outData.length+1,outData[0].length).getValues();
var indexesToRemove = [];
for (var c = 25; c>2; c--){
if (sheet2.getRange(1,c).getValue() == 0)
{
indexesToRemove.push(c);
}
}
The part above works well. What is not working is the function to remove the columns from the array once I found the indexes to remove. The array _row is not what I am looking for. What am I doing wrong?
removeColumns(ary, indexesToRemove);}
function removeColumns(data, indexes) {
return data.map(function (row) {
// when we remove columns, the indexing gets off by 1 each time, keep track of how many to adjust
var indexAdjustment = 0;
// copy row w/ .slice so we do not modify the original array
var _row = row.slice();
indexes.forEach(function (colIndex) {
// remove column
_row.splice(colIndex - indexAdjustment, 1);
// add 1 to adjustment to account for the column we just removed
indexAdjustment++
});
return _row;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet2 = ss.getSheetByName('Cache');
sheet2.clear();
sheet2.getRange(2,1,_row.length,_row[0].length).setValues(_row);
});
}
BTW, I have also tried this before, but still not working:
var ary = sheet2.getRange(2,1,outData.length+1,outData[0].length).getValues();
for (var c = 25; c>2; c--){
if (sheet2.getRange(1,c).getValue() == 0)
{ ary = ary.map(function(item){
return item.splice(0,c)});
}
}
You want to delete the columns that the value of is 0 in the cells C1:Y1.
You want to reduce the process cost of the script.
You want to achieve this without using Sheets API.
Pattern 1:
In this pattern, at first, the cells which have the value of 0 from the cells C1:Y1 using TextFinder, and the columns are deleted from the retrieved cells using deleteColumn().
Sample script:
const sheet = SpreadsheetApp.getActiveSheet();
sheet.getRange("C1:Y1")
.createTextFinder(0)
.matchEntireCell(true)
.findAll()
.reverse()
.forEach(e => sheet.deleteColumn(e.getColumn()));
Pattern 2:
In this pattern, at first, all values are retrieved from "C1" to the last column for the all data rows, and delete the columns in the array and clear the range, and then, the values are put to the sheet. The method for directly processing the retrieved values has already been proposed. So as other pattern, I proposed the method which uses the transpose.
Sample script:
const sheet = SpreadsheetApp.getActiveSheet();
const range = sheet.getRange(1, 3, sheet.getLastRow(), sheet.getLastColumn() - 2);
const values = range.getValues();
const t = values[0].reduce((ar, r, i) => {
if (r != 0) ar.push(values.map(c => c[i]));
return ar;
}, []);
const v = t[0].map((_, i) => t.map(c => c[i]));
range.clearContent();
sheet.getRange(1, 3, v.length, v[0].length).setValues(v);
Pattern 3:
In this pattern, the request body for the batchUpdate method of Sheets API is created using the 1st row values, and the request body is used for requesting to Sheets API. By this, several columns can be deleted by one API call.
Before you run the script, please enable Sheets API at Advanced Google services.
Sample script:
const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
const sheet = spreadsheet.getActiveSheet();
const sheetId = sheet.getSheetId();
// Create rerequests for DeleteDimensionRequest.
const requests = sheet.getRange("C1:Y1")
.createTextFinder(0)
.matchEntireCell(true)
.findAll()
.reverse()
.map(e => {
const col = e.getColumn();
return {deleteDimension: {range: {sheetId: sheetId, dimension: "COLUMNS", startIndex: col - 1, endIndex: col}}}
});
// Request to the batchUpdate method using the request body.
Sheets.Spreadsheets.batchUpdate({requests: requests}, spreadsheet.getId());
In this case, requests is created using the method of pattern 1. Each request is as follows. You can see about this structure at the document.
{
"deleteDimension": {
"range": {
"sheetId": "###",
"dimension": "COLUMNS",
"startIndex": ##,
"endIndex": ##
}
}
}
References:
Class TextFinder
Advanced Google services
Method: spreadsheets.batchUpdate
DeleteDimensionRequest
function runOne() {
var d=0;
var ss=SpreadsheetApp.getActive();
var sh=ss.getActiveSheet();
var hA=sh.getRange(1,1,1,sh.getLastColumn()).getValues()[0];//header array
var vs=sh.getRange(2,1,sh.getLastRow()-1,sh.getLastColumn()).getValues();//data array
vs.forEach(function(r,j){
var d=0;
hA.forEach(function(h,i){
if(h==0)r.splice(i-d++,1);//removes elements in columns whose headers are == 0
});
});
Logger.log(vs);
}
Try using Sheets Advanced Service and batchUpdate.
Related
Remove all grouped rows / columns in a spreadsheet
Reference
https://developers.google.com/sheets/api/samples/rowcolumn#delete_rows_or_columns

Incorrect Range Height - Google Apps Scripts

I am currently trying to get grab values from another spreadsheet and then paste it into a destination spreadsheet. The problem I am running into is that I am getting incorrect range height and incorrect range widths when I run this code. I read something about 2d arrays but I believe I already have a 2d array here to paste to the spreadsheet. Thank you for your time.
function GmailToDrive_StaticTest(gmailSubject, importFileID){
var threads = GmailApp.search('subject:' + gmailSubject + ' -label:uploaded has:attachment'); // performs Gmail query for email threads
for (var i in threads){
var messages = threads[i].getMessages(); // finds all messages of threads returned by the query
for (var j in messages){
var attachments = messages[j].getAttachments(); // finds all attachments of found messages
var timestamp = messages[j].getDate(); // receives timestamp of each found message
var timestampMinusOne = new Date(timestamp.getTime() - (86400000)); // sets the received timestamp to exactly one day prior (# in milliseconds)
var date = Utilities.formatDate(timestampMinusOne, "MST", "yyyy-MM-dd"); // cleans the timestamp string
for (var k in attachments){
var blobs = {
dataType: attachments[k].getContentType(), // retrives the file types of the attachments
data: attachments[k].copyBlob(), // creates blob files for every attachment
fileName: attachments[k].getName()
};
var tempFile = DriveApp.createFile(blobs.data.setContentType('text/csv')).setName(blobs.fileName.split("-", 1).toString() + date); // creates csv files in drive's root per blob file
var tempFileConverted = Drive.Files.copy( {}, tempFile.getId(), {convert: true} ); // converts created files to gsheets
var importData = {
file: tempFileConverted,
ID: tempFileConverted.getId(),
Sheet1: SpreadsheetApp.openById(tempFileConverted.getId() ).getActiveSheet(),
Sheet1_Values: SpreadsheetApp.openById(tempFileConverted.getId() ).getActiveSheet().getDataRange().getValues()
};
tempFile.setTrashed(true);
var importData_Sheet1_Rows = importData.Sheet1.getMaxRows(); - 2;
var importData_Sheet1_Columns = importData.Sheet1.getMaxColumns(); - 2;
var destSheet = SpreadsheetApp.openById(importFileID).getSheets()[0];
destSheet.clearContents();
Logger.log(importData.Sheet1_Values)
destSheet.getRange(1, 1, importData_Sheet1_Rows, importData_Sheet1_Columns).setValues(importData.Sheet1_Values);
DriveApp.getFileById(importData.ID).setTrashed(true);
}
}
}
}
getMaxRows() and getMaxColumns() return the maximum number of column and rows in a sheet, while getDataRange().getValues() return all the values in a sheet that contain data .
So, unless all the cells in a sheet have data the dimensions won't match !
The best you could do is to get the actual size of the data array and use that to set the range for the values in the destination sheet.
It goes (more) simply like this :
destSheet.getRange(1, 1, importData.Sheet1_Values.length, importData.Sheet1_Values[0].length).setValues(importData.Sheet1_Values);
you don't need the other values for rows and columns, just ignore that in your script.

How to print multiple calls to Google Analytics API to Google Sheets with Apps Script

I'm trying to print multiple results from multiple calls into the same Google sheet. I'm using Google Apps Script to call the Google Analytics API.
I'm currently able to print two sets of data, but the second set coerces to my first call. It's almost like the results of the second call are overridden by the first call. I'm sure my problem is towards the bottom in my attempt to print both sets of results.
Here is my code:
function getReportDataForProfile(firstProfile) {
var profileId = firstProfile;
var tableId = 'ga:' + profileId;
var startDate = getMonthsAgo(3); // Months ago.
var endDate = getEndDate (0); // Today.
var optArgs = {
'dimensions': 'ga:month', // Comma separated list of dimensions.
'segment':'gaid::-lPvLp6LTbyDv3jOuYgEQA', // Female 18-24
'start-index': '1',
'max-results': '250' // Display the first 250 results.
};
var optArgs1 = {
'dimensions': 'ga:month', // Comma separated list of dimensions.
'segment':'gaid::Uu6nRXdoQxipnELhe94ejg', //Female 25 - 30
'start-index': '1',
'max-results': '250' // Display the first 250 results.
};
// 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:goal19Completions', // Comma seperated list of metrics.
optArgs);
if (results.getRows()) {
return results;
} else {
throw new Error('No views (profiles) found');
};
var results1 = 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:goal19Completions', // Comma seperated list of metrics.
optArgs1);
if (results1.getRows()) {
return results1;
} else {
throw new Error('No views (profiles) found');
};
}
function outputToSpreadsheet(results) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
// Print the headers.
var headerNames = [];
for (var i = 0, header; header = results.getColumnHeaders()[i]; ++i) {
headerNames.push(header.getName());
}
sheet.getRange(1, 1, 1, headerNames.length)
.setValues([headerNames]);
// Print the rows of data.
sheet.getRange(2, 1, results.getRows().length, headerNames.length)
.setValues(results.getRows());
}
function outputToSpreadsheet(results1) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
// Print the headers.
var headerNames = [];
for (var i = 0, header; header = results1.getColumnHeaders()[i]; ++i) {
headerNames.push(header.getName());
}
sheet.getRange(1, 3, 1, headerNames.length)
.setValues([headerNames]);
// Print the rows of data.
sheet.getRange(2, 3, results1.getRows().length, headerNames.length)
.setValues(results1.getRows());
}
Any help would be appreciated.
your javascript logic is not right.
you get your first result and then have:
if (x)
return y;
else
throw exception
so it will never get past that.
use the debugger and step each line. you will see its impossible to get to the 2nd query.

Categories

Resources