How to get separate sums per each separate column by Google Script? - javascript

I want to get sums of numeric values for each separate column in the range. What I do wrong?
function countNutrients(){
var sh = SpreadsheetApp.getActiveSheet();
var lastcol = sh.getLastColumn(); //Get last column
var lastcolval = sh.getRange(1, 1, 1, lastcol).getValues();
var lastrowval = sh.getRange("C1:C").getValues(); //Trick to get last row
var lastrow = lastrowval.filter(String).length; //
var sumvalues = sh.getRange(2, 14, lastrow, lastcol).getValues();
(typeof sumvalues === 'number' ? "" : sumvalues);
Logger.log(sumvalues);
for (var j = 13; j < lastcolval.length ; j++) {
var sumcolumnval = sh.getRange(2, [j], lastrow);
var sum = 0;
for (var i in sumcolumnval[0]) {
var sum = sumvalues[0][i] + sum;
}
return sum
Logger.log(sum);
}
return sumcolumnval
}
Columns on the screenshot and 65 more
enter link description here
CSV example

Sum of Columns With a Script
function sumOfCols() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName('Sheet14');
var hA=sh.getRange(1,1,1,sh.getLastColumn()).getValues()[0];
var sum={};
hA.forEach(function(h,i){sum[h]=0;});
var rg=sh.getRange(2,1,sh.getLastRow()-1,sh.getLastColumn());
var v=rg.getValues();
v.forEach(function(r,i){r.forEach(function(c,j){sum[hA[j]]+=c;});});
var html='';
hA.forEach(function(h,i){html+=Utilities.formatString('<br />%s(sum): %s',h,sum[h]);});
var ui=HtmlService.createHtmlOutput(html);
SpreadsheetApp.getUi().showModelessDialog(ui, "Column Sums")
}
Spreadsheet:
Output Dialog:
Data(csv):
COL1,COL2,COL3,COL4,COL5,COL6,COL7,COL8,COL9,COL10
1,2,3,4,5,6,7,8,9,10
2,3,4,5,6,7,8,9,10,11
3,4,5,6,7,8,9,10,11,12
4,5,6,7,8,9,10,11,12,13
5,6,7,8,9,10,11,12,13,14
6,7,8,9,10,11,12,13,14,15
7,8,9,10,11,12,13,14,15,16
A function for your particular Application
This will sum just the six columns that you selected
function countNutrients(){
var sh=SpreadsheetApp.getActiveSheet();
var hA=sh.getRange(1,14,1,6).getValues()[0];
var sum={};
hA.forEach(function(h,i){sum[h]=0;})
var vA=sh.getRange(2,14,sh.getLastRow()-1,6).getValues();
vA.forEach(function(r,i){
r.forEach(function(c,j){
if(!isNaN(c)) {
sum[hA[j]]+=c;
}
});
});
var html="";
var keys=Object.keys(sum);
keys.forEach(function(k,i){
html+=Utilities.formatString('<br />sum[%s]=%s',k,sum[k]);
})
var ui=HtmlService.createHtmlOutput(html);
SpreadsheetApp.getUi().showModelessDialog(ui,'Sums of Cols N through S')
}

Related

Apps Script: how to copy hyperlink from a cell to another sheet

I need to copy this data from one sheet to another but with all the links active, because with this formula, copy just like a text.
I really don't know what do and what do I have to change to copy every data from the original sheet.
function SubmitData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formS = ss.getSheetByName("ProyectStatus");
var dataS = ss.getSheetByName("ToCompleteProyect");
var values = [
[formS.getRange("D1").getValue(), formS.getRange("D2").getValue(), formS.getRange("D3").getValue(), formS.getRange("D4").getValue(), formS.getRange("D5").getValue(), formS.getRange("D6").getValue(), formS.getRange("D7").getValue(), formS.getRange("D8").getValue(), formS.getRange("D9").getValue(), formS.getRange("D10").getValue(), formS.getRange("D11").getValue(), formS.getRange("D12").getValue(), formS.getRange("D13").getValue(), formS.getRange("D14").getValue(), formS.getRange("D15").getValue(), formS.getRange("D16").getValue(), formS.getRange("D17").getValue(), formS.getRange("D18").getValue(), formS.getRange("D19").getValue(), formS.getRange("D20").getValue(), formS.getRange("D21").getValue(), formS.getRange("D22").getValue(), formS.getRange("D23").getValue(), formS.getRange("D24").getValue(), formS.getRange("D25").getValue(), formS.getRange("D26").getValue(), formS.getRange("D27").getValue(), formS.getRange("D28").getValue(), formS.getRange("D29").getValue(), formS.getRange("D30").getValue(), formS.getRange("D31").getValue(), formS.getRange("D32").getValue(), formS.getRange("D33").getValue(), formS.getRange("D34").getValue(), formS.getRange("D35").getValue(), formS.getRange("D36").getValue(), formS.getRange("D37").getValue(), formS.getRange("D38").getValue(), formS.getRange("D39").getValue(), formS.getRange("D40").getValue(), formS.getRange("D41").getValue(), formS.getRange("D42").getValue(), formS.getRange("D43").getValue(), formS.getRange("D44").getValue(), formS.getRange("D45").getValue(), formS.getRange("D46").getValue(), formS.getRange("D47").getValue(), formS.getRange("D48").getValue(), formS.getRange("D49").getValue(), formS.getRange("D50").getValue(), formS.getRange("D51").getValue(), formS.getRange("D52").getValue()]
];
dataS.getRange(dataS.getLastRow() + 1, 1, 1, 52).setValues(values);
ClearCell();
RE-EDIT:
Complete project with Submit, Search and Update buttons!
function ClearCell() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formS = ss.getSheetByName("ProyectStatus");
var RangeToClear = [ "D1:D52"];
for (var i=0; i<RangeToClear.length; i++) {
formS.getRange(RangeToClear[i]).clearContent();
}
}
//-------------------------------------------------------------------------------
function SubmitData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formS = ss.getSheetByName("ProyectStatus");
var dataS = ss.getSheetByName("ToCompleteProyect");
var lastRow = dataS.getLastRow() + 1
formS.getRange("D1:D52").copyTo(dataS.getRange(lastRow, 1, 1, 52), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, true)
dataS.getRange(lastRow,1).clearDataValidations()
ClearCell();
}
//----------------------------------------------------------------------------
function Search() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formS = ss.getSheetByName("ProyectStatus");
var str = formS.getRange("D1").getValue();
var dataS = ss.getSheetByName("ToCompleteProyect")
var values= dataS.getDataRange();
Logger.log(values.getLastRow())
for (var i = 0; i < values.getLastRow(); i++) {
var row = dataS.getRange(i+1,1).getValue();
if (row == str) {
dataS.getRange(i+1,2,1,51).copyTo(formS.getRange("D2:D52"),SpreadsheetApp.CopyPasteType.PASTE_NORMAL, true)
}
}
}
//------------------------------------------------------------------------------
function Update(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formS = ss.getSheetByName("ProyectStatus");
var str = formS.getRange("D1").getValue();
var dataS = ss.getSheetByName("ToCompleteProyect")
var values= dataS.getDataRange();
Logger.log(values.getLastRow())
for (var i = 0; i < values.getLastRow(); i++) {
var row = dataS.getRange(i+1,1).getValue();
if (row == str) {
formS.getRange("D2:D52").copyTo(dataS.getRange(i+1, 2, 1, 51), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, true)
ClearCell();
}
}
}
EDIT:
One simple way to do it is just to copy-paste but not only the values but the cells transposed as one would do with the Copy and Paste Special. It's indeed a much simpler code and it seems to me that does the trick, you just need this line:
formS.getRange("D1:D52").copyTo(dataS.getRange(lastRow, 1, 1, 52), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, true) ---> this last TRUE value is the one which transposes the data
And the full function:
function SubmitData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formS = ss.getSheetByName("ProyectStatus");
var dataS = ss.getSheetByName("ToCompleteProyect");
var lastRow = dataS.getLastRow() + 1
formS.getRange("D1:D52").copyTo(dataS.getRange(lastRow, 1, 1, 52), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, true)
ClearCell();
}
Was it useful??
OLD: If the links is always in the same column/s of the last row, you can then pass them through this second function. I took myself the liberty also of suggesting a way of simplifying grabbing the values of the form ;)
function SubmitData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var formS = ss.getSheetByName("ProyectStatus");
var dataS = ss.getSheetByName("ToCompleteProyect");
var values = formS.getRange("D1:D52").getValues() //Here I took the entire range
values = [values.map(function(n){return n[0]})] // and turn that column into a row
var lastRow = dataS.getLastRow() + 1
dataS.getRange(lastRow, 1, 1, 52).setValues(values);
linkCellContents(dataS.getRange(lastRow, 10, 1, 1)) // assuming you need to make a link the value in column number 10 (J)... repeat this line with each column you need to convert
ClearCell();
}
function linkCellContents(range) {
var value = range.getValue()
var richValue = SpreadsheetApp.newRichTextValue()
.setText(value)
.setLinkUrl(value)
.build();
range.setRichTextValue(richValue);
}

Google Sheets Script to count cells with color with several criteria

In a google sheets table, I use a script that allows me to count the cells in color in a column that displays dates as values. Each date over 11 days is colored in red, and my script works very well.
In another column, I indicate the name of each salesman.
What I would like is to be able to count the number of red cells that belong to each salesman.
The date column is column "G" and the salesman column is column "F" (In my script it doesn't matter because I indicate in which column to count).
My Sheet:
https://docs.google.com/spreadsheets/d/1BFd57xpFOJMOAjuRaiO6_cLCMMxQKDwi_TB6dOCDb9A/edit#gid=0
The formula for my script is:
=CompteCouleurs($G6:$G;C4)
"$G6:$G" is the range to count
"C4" is the sample of the color to search
My script is:
function SommeCouleurs(plage,couleur) {
var activeRange = SpreadsheetApp.getActiveRange();
var activeSheet = activeRange.getSheet();
var formule = activeRange.getFormula();
var laplage = formule.match(/\((.*)\;/).pop();
var range = activeSheet.getRange(laplage);
var bg = range.getBackgrounds();
var values = range.getValues();
var lacouleur = formule.match(/\;(.*)\)/).pop();
var colorCell = activeSheet.getRange(lacouleur);
var color = colorCell.getBackground();
var total = 0;
for(var i=0;i<bg.length;i++)
for(var j=0;j<bg[0].length;j++)
if( bg[i][j] == color )
total=total+(values[i][j]*1);
return total;
};
function CompteCouleurs(plage,couleur) {
var activeRange = SpreadsheetApp.getActiveRange();
var activeSheet = activeRange.getSheet();
var formule = activeRange.getFormula();
var laplage = formule.match(/\((.*)\;/).pop();
var range = activeSheet.getRange(laplage);
var bg = range.getBackgrounds();
var values = range.getValues();
var lacouleur = formule.match(/\;(.*)\)/).pop();
var colorCell = activeSheet.getRange(lacouleur);
var color = colorCell.getBackground();
var count = 0;
for(var i=0;i<bg.length;i++)
for(var j=0;j<bg[0].length;j++)
if( bg[i][j] == color )
count=count+1;
return count;
};
First, expand your area to G and F =CompteCouleurs($F6:$G;C4)
Then as you only take column G into account, you can omit for(var j=0;j<bg[0].length;j++)
Therefore you can check color in G and salesman in F as follows if( bg[i][1] == color && values[i][0] == salesman )
If you want to include the salesman as parameter, you will have to change the regex as follows to retrieve each argument (args will be an array)
var args = formule.match(/\(.*\)/g)[0].match(/[A-Z0-9:]+/g)
I recommand also to add a dummy parameter (checkbox) to update the calculation
Correction of your script:
function compteCouleursSi(plage, couleur, vendeur) {
var activeRange = SpreadsheetApp.getActiveRange();
var activeSheet = activeRange.getSheet();
var formule = activeRange.getFormula();
// array of arguments
var args = formule.match(/(?<=\().*(?=\))/g)[0].split(/[;|,]/)
var laplage = args[0];
if (laplage.includes('!')) {
var range = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(laplage.split('!')[0].replace(/'/g,'')).getRange(laplage.split('!')[1].trim());
}else{
var range = activeSheet.getRange(laplage);
}
var bg = range.getBackgrounds();
var values = range.getValues();
var lacouleur = args[1];
var color = activeSheet.getRange(lacouleur).getBackground();
var salesman = args[2];
var who = activeSheet.getRange(salesman).getValue()
var total = 0;
for (var i = 0; i < bg.length; i++)
if (bg[i][1] == color && values[i][0] == who)
total += 1;
return total;
};
function sommeCouleursSi(plage, couleur, vendeur) {
var activeRange = SpreadsheetApp.getActiveRange();
var activeSheet = activeRange.getSheet();
var formule = activeRange.getFormula();
// array of arguments
var args = formule.match(/(?<=\().*(?=\))/g)[0].split(/[;|,]/)
var laplage = args[0];
if (laplage.includes('!')) {
var range = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(laplage.split('!')[0].replace(/'/g,'')).getRange(laplage.split('!')[1].trim());
}else{
var range = activeSheet.getRange(laplage);
}
var bg = range.getBackgrounds();
var values = range.getValues();
var lacouleur = args[1];
var color = activeSheet.getRange(lacouleur).getBackground();
var salesman = args[2];
var who = activeSheet.getRange(salesman).getValue()
var total = 0;
for (var i = 0; i < bg.length; i++)
if (bg[i][1] == color && values[i][0] == who)
total += values[i][1];
return total;
};

Var not being used in object.var

function myFunction() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('data');
var data = sheet.getDataRange().getValues();
var range = sheet.getRange("A1:L" + data.length);
range.sort(1);
const people = {};
for(var i = 0; i < data.length; i++) {
var name = data[i][0] + data[i][1];
console.log(i);
if (!people.name) {people.name = {rows: [i]};} else {people.name.rows.push(i)}
}
Logger.log(people);
}
What should I be doing differently? At the end, it logs {name={rows=[0.0, 1.0, 2.0, ...]}} instead of having an object for each name...?
In the sheet there's just a first name and last name on columns A and B, for around 80 rows.
Use the bracket syntax if you want to use dynamic names for properties: https://riptutorial.com/javascript/example/2321/dynamic---variable-property-names
In your case:
function myFunction() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('data');
var data = sheet.getDataRange().getValues();
var range = sheet.getRange("A1:L" + data.length);
range.sort(1);
const people = {};
for(var i = 0; i < data.length; i++) {
var name = data[i][0] + data[i][1];
console.log(i);
if (!people[name]) {people[name] = {rows: [i]};} else {people[name].rows.push(i)}
}
Logger.log(people);
}

Cannot convert [object Object] to (class)

I am trying to count the number of rows between two rows containing particular words in google sheets. But I am getting the following error:
Cannot convert [object Object] to (class). (line 41, file "Code")
I have written the following code on the google app script:
function search(SPREADSHEET_ID, SHEET_NAME, word) {
var locatedCells = [];
var ss = SpreadsheetApp.openById(SPREADSHEET_ID);
var searchLocation = ss.getSheetByName(SHEET_NAME).getDataRange().getValues();
//Loops to find the search term.
for (var j = 0, jLen = searchLocation.length; j < jLen; j++) {
for (var k = 0, kLen = searchLocation.length; k < kLen; k++) {
var find = word;
if (find == searchLocation[j][k]) {
locatedCells.push({ 'found': (j + 1)});
}
}
}
// Logger.log(locatedCells);
return(locatedCells)
}
function footerlocation(){
var SPREADSHEET_ID = "1nYBEuMMC4j1A4qryzKKq33PsTRH54ADyJLsEoTmbKh4"
var SHEET_NAME = "Bedding"
var word = "Footers"
var footerlocation = search(SPREADSHEET_ID, SHEET_NAME, word)
//Logger.log(footerlocation);
return(footerlocation)
}
function keywordlocation(){
var SPREADSHEET_ID = "1nYBEuMMC4j1A4qryzKKq33PsTRH54ADyJLsEoTmbKh4"
var SHEET_NAME = "Bedding"
var word = "Keyword Page Redirects to Implement"
var keywordlocation = search(SPREADSHEET_ID, SHEET_NAME, word)
//Logger.log(keywordlocation);
return(keywordlocation)
}
function count(){
var sheet= SpreadsheetApp.openById("1nYBEuMMC4j1A4qryzKKq33PsTRH54ADyJLsEoTmbKh4").getSheetByName("Bedding");
var startrow=footerlocation()
var endrow= keywordlocation()
var range = sheet.getRange(startrow,1,endrow-startrow,1);
var datas = range.getValues();
var count = 0;
for (data in datas) {
for (cell in data) {
//Logger.log(typeof cell) //{
count++;
//}
}
}
Logger.log(data)
}
I would appreciate if someone could help me with this.
I was able to figure out the solution, change the count function to the following:
function count(){
var sheet= SpreadsheetApp.openById("1nYBEuMMC4j1A4qryzKKq33PsTRH54ADyJLsEoTmbKh4").getSheetByName("Bedding");
var startrow=footerlocation()[0]['found']
var endrow= keywordlocation()[0]['found']
var range = sheet.getRange(startrow,1,endrow-startrow,1);
var datas = range.getValues();
var count = 0;
for (data in datas) {
for (cell in data) {
//Logger.log(typeof cell) //{
count++;
//}
}
}
Logger.log(data)
}

Making table in google apps script from array

function arrayMail(){
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Sheet1');
var startRow = 2;
var lastRow = sheet.getLastRow();
var lastColumn = sheet.getLastColumn();
var range = sheet.getRange(startRow,1,lastRow,lastColumn);
var data = range.getValues();
var array = [];
for(var i=0;i<data.length;++i){
var row = data[i];
var rowTemp=[]; //create a blank array that will hold only the desired columns in this row
for (var j=0; j<row.length; j++)//iterates through columns
{
if(j==4||j==3||j==1||j==5){continue;}
rowTemp.push(row[j])
}
var emailPos = row[3];
var date = row[2];
if(emailPos =='example4#gmail.com'&& date == 0){
array.push(rowTemp);
}
}
GmailApp.sendEmail('example1#gmail.com','This is a test',array.join('\n\n'));
}
Above script I used for me sending email when date count is 0 and the email become the reference who to email. I wanted to make the array (which is in plain text if using script above) become a table format. I'm stuck with the table formatting. The question is, how do I make it in table format here? Beginner level in scripting
After reading from book/examples, I came up with below script. But it doesn't work as intended;
function arrayMail(){
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Sheet1');
var startRow = 2;
var lastRow = sheet.getLastRow();
var lastColumn = sheet.getLastColumn();
var range = sheet.getRange(startRow,1,lastRow,lastColumn);
var data = range.getValues();
var tableStart = "<table border=\"1\"><tr>";
var tableEnd = "</tr></table>";
var array = [];
for(var i=0;i<data.length;++i){
var row = data[i];
var rowTemp=[]; //create a blank array that will hold only the desired columns in this row
for (var j=0; j<row.length; j++)//iterates through columns
{
if(j==4||j==3||j==1||j==5){continue;}
rowTemp.push('<td>'+row[j]+'</td>');
}
var emailPos = row[3];
var date = row[2];
if(emailPos =='example4#gmail.com'&& date == 0){
array.push(rowTemp);
}
}
var HTMLbody = tableStart +array.join('')+tableEnd;
GmailApp.sendEmail('example#gmail.com','This is a test',HTMLbody,{htmlBody:HTMLbody});
}
Result:
What I wanted to be is like;
Infusion Pump 0
Infusion Pump 0
This is not a full answer but the code below translates the array to the string you asked about in your Google+ post...
var array = [
['Infusion Pump', 'B', 'C', 'D', 'E', 'F'],
['Another Pump', 'B', 'C', 'D', 'E', 'F'],
['Defib', 'B', 'C', 'D', 'E', 'F']
];
var str = '';
for (var i = 0; i < array.length; i++) {
str = str + '<tr>';
for (var j = 0; j < array[i].length; j++) {
str = str + '<td>' + array[i][j] + '</td>';
}
str = str + '</tr>';
}
console.log(str);
Based on SamScholefield's answer I did modified his code a bit to suit my need and here is the final code:
function arrayMail(){
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Sheet1');
var startRow = 2;
var lastRow = sheet.getLastRow();
var lastColumn = sheet.getLastColumn();
var range = sheet.getRange(startRow,1,lastRow,lastColumn);
var data = range.getValues();
var array = [];
for(var i=0;i<data.length;++i){
var row = data[i];
var rowTemp=[]; //create a blank array that will hold only the desired columns in this row
for (var j=0; j<row.length; j++){ //iterates through columns
if(j==4){continue;}
rowTemp.push(row[j]);
}
var emailPos = row[3];
var date = row[2];
if(emailPos =='example1#gmail.com'&& date == -28){
array.push(rowTemp);
}
}
var str = '';
var bodyEnd = '</table>';
var header = '<table border =1><tr><th>Message</th><th>Date Remind</th><th>Days Left</th><th>Email Address</th><th>Status</th></tr>';
for (var k = 0; k < array.length; k++) {
str = str + '<tr>';
for (var l = 0; l < array[k].length; l++) {
str = str + '<td>' + array[k][l] + '</td>';
}
str = str + '</tr>';
var msg = header+str+bodyEnd;
}
GmailApp.sendEmail(Session.getActiveUser().getEmail(),'This is a test',msg, {htmlBody:msg});
};
Result

Categories