Count Reoccuring Values in Column of Google Spreadsheet Using Script - google-apps-script

I'd like to count the number of times a value reoccurs in a specific column of my spreadsheet using a script so that it populates a different column (same row) with the count when a form is submitted. These are the values in Column B that I'd like to count:
6 ACM
5 ACM
4 ACM
5 CGC
7 CGC
6 ACM
7 ACM
7 ACM
so that if the calculation were working correctly Column C would be populated with these numbers:
1
1
1
1
1
2
1
2
I know how to read the data and how to write to the spreadsheet, but I don't know how to actually count the values. Here is what I have so far:
function countif() {
var ss = null;
try {
ss = SpreadsheetApp.openById("0AliYViHYAwaNdHQyMXlKT2Q5UElQY184T3BWYTRiM2c");
} catch (ex) {
ss = SpreadsheetApp.getActiveSpreadsheet();
}
var sheet = ss.getSheetByName("Sheet1");
var lastLine = sheet.getLastRow();
var data = sheet.getRange("B2:B").getValues();
var count = 0;
//need help here
sheet.getRange(lastLine,3).setValue(count);
}
Thank you!

Put this piece of code in your //need help section.
for (var i = 0 ; i < lastLine ; i++){
var count = 1;
for ( var j = 0 ; j < i ; i ++) {
if (data[j][0] == data[i][0] ){
count++;
}
}
sheet.getRange('C' + (i+1).toString()).setValue(count);
}

Just as an alternative, you can achieve this with a spreadsheet function, entered in C1:
=ArrayFormula(IF(ROW(B:B)=1;"Count";IF(LEN(B:B);MMULT((ROW(B:B)>=TRANSPOSE(ROW(B:B)))*(B:B=TRANSPOSE(B:B));SIGN(ROW(B:B)));IFERROR(1/0))))

Related

Code Error Pop Up inside cell as #DIV/0! after code runs through all cells

I am working on macro scripting where Finance formula is used also inside the worksheet
I am able to receive the result values when there are different values in Row1 but when there are transpose values of Column 1, then I receive Error.
Please see the code below and attached two screenshots also
function MyFunction(){
var sd = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('SD');
var cr = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('CORRELATION');
var lr = cr.getLastRow();//find last row
var lc = cr.getLastColumn();//find last column
var data = cr.getRange(1, 1, lr, lc).getValues();
var data1 = sd.getRange(1, 1, 999,9999).getValues();
var c = 2
for ( var i = 1; i <= lc - 1; i++ ){
var r = 2
for ( var j = 1; j <= lr - 1; j++ ){
//Logger.log(data[0][i] + " - " +data[j][0])
sd.getRange("B1").setValue(data[0][i])
sd.getRange("S1").setValue(data[j][0])
cr.getRange(r, c).setValue(sd.getRange("H8").getValue())//error comes here
r = r + 1
}
c = c+ 1
}
SpreadsheetApp.getActiveSpreadsheet().toast('Task Completed!', 'Status');
}
Picture 01
Picture 02
I'm guessing that you incrementing your column or row outside of the limits of your sheet. Start with the following code and rewrite your function:
function MyFunction(){
var ss=SpreadsheetApp.getActive();
var sd=ss.getSheetByName('SD');
var cr=ss.getSheetByName('CORRELATION');
var data=cr.getRange(1, 1, cr.getLastRow(), cr.getLastColumn()).getValues();
var data1=sd.getRange(1, 1, sd.getLastRow(),sd.getLastColumn()).getValues();
for(var i=0;i<data.length;i++) {
for(var j=0;j<data[i].length;j++) {
}
}
}

Sum up the time values corresponding to same date

In my sheet column A is date and column B is time duration values, I want to find the dates which are repeated and sum up the corresponding time values of the repeated dates and show the sum in the last relevant repeated date. And delete all the other repeated dates. ie if 18/07/2019 is repeated 4 times i have to sum up all the four duration values and display the sum value in the 4th repeated position and delete the first three date 18/07/2019. I have to do this all those dates that are repeated. I have wrote code to my best knowledge
function countDate() {
var data = SpreadsheetApp.getActive();
var sheet = data.getSheetByName("Sheet5");
var lastRow = sheet.getLastRow();
var sh = sheet.getRange('A1:A'+lastRow);
var cell = sh.getValues();
var data= sheet.getRange('B1:B'+lastRow).getValues();
for (var i =0; i < lastRow; ++i){
var count = 0;
var column2 = cell[i][0];
for (var j =0; j < i; j++)
{
var p=0;
var column4 = cell[j][0];
if (column4 - column2 === 0 )
{
var value1 = data[j][0];
var value2 = data[i][0];
var d = value2;
d.setHours(value1.getHours()+value2.getHours()+0);
d.setMinutes(value1.getMinutes()+value2.getMinutes());
sheet.getRange('C'+(i+1)).setValue(d).setNumberFormat("[hh]:mm:ss");
sheet.deleteRow(j+1-p);
p++;
}
}
}
}
The copy of the sheet is shown
column C is the values I obtain through the above code AND column D is the desired value
After computing the sum I need to delete the repeated rows till 15 here
Answer:
You can do this by converting your B-column to a Plain text format and doing some data handling with a JavaScript dictionary.
Code:
function sumThemAllUp() {
var dict = {};
var lastRow = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0].getLastRow();
var dates = SpreadsheetApp.getActiveSpreadsheet().getRange('A1:A' + lastRow).getValues();
var times = SpreadsheetApp.getActiveSpreadsheet().getRange('B1:B' + lastRow).getValues();
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
sheet.getRange(1, 1, sheet.getLastRow(), sheet.getLastColumn()).setNumberFormat("#");
for (var i = 0; i < dates.length; i++) {
if (!dict[dates[i][0]]) {
dict[dates[i][0]] = times[i][0];
}
else {
var temp = dict[dates[i][0]];
var hours = parseInt(temp.split(':')[0]);
var minutes = parseInt(temp.split(':')[1]);
var additionalHours = parseInt(times[i][0].split(':')[0]);
var additionalMinutes = parseInt(times[i][0].split(':')[1]);
var newMinutes = minutes + additionalMinutes;
var newHours = hours + additionalHours;
if (newMinutes > 60) {
newHours = newHours + 1;
newMinutes = newMinutes - 60;
}
dict[dates[i][0]] = newHours + ':' + newMinutes;
}
}
SpreadsheetApp.getActiveSpreadsheet().getSheets()[0].getRange('A1:B' + lastRow).clear();
var keys = Object.keys(dict);
for (var i = 0; i < keys.length; i++) {
SpreadsheetApp.getActiveSpreadsheet().getSheets()[0].getRange('A' + (i + 1)).setValue(keys[i]);
SpreadsheetApp.getActiveSpreadsheet().getSheets()[0].getRange('B' + (i + 1)).setValue(dict[keys[i]]);
}
}
Assumptions I made:
There are a few assumptions I made when writing this, you can edit as needed but I figured I should let you know:
There are only dates in Column A and only times in Column B.
The times in column B are either Hours:Minutes or Minutes:Seconds. Either way, if the value to the right of the : hits 60, it adds one to the left value and resets.
The Sheet within the Spreadsheet is the first sheet; that which is returned by Spreadsheet.getSheets()[0].
References:
w3schools - JavaScript Objects
Spreadsheet.getSheets()
w3schools - JavaScript String split() Method
MDN web docs - parseInt() method
Google Sheets > API v4 - Date and Number Formats

Google Sheets Add row based on cell number value

I'm trying to make a google sheet script that adds a row based on cell value, basically if I have in the Quantity (Column D) 7x laptops, I want the script to add 6 additional rows below if Column H is marked as "Yes" through data validation.
What I was able to find and to do is only duplicate that row but is without data validation and I would prefer to add the data validation and possible make each quantity split to 1 (instead of 7) after the duplication.
`function autoDup() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var data = sheet.getDataRange().getValues();
var newData = [];
for(var n in data){
newData.push(data[n]);
if(!Number(data[n][3])){continue};// if column 3 is not a number then do nothing
for(var c=1 ; c < Number(data[n][3]) ; c++){ // start from 1 instead of 0 because we have already 1 copy
newData.push(data[n]);//store values
}
}
sheet.getRange(1,1,newData.length,newData[0].length).setValues(newData).sort({column: 1, ascending: false});// write new data to sheet, overwriting old data
}`
Hope someone is able to help me.
Thank you,
Column D contains a qty and goods description. If Column H = "Yes", you want to insert a number of rows below Col D equal to the qty minus one. If Column H <> "Yes, then take no action.
Sample data - Before
Sample data - After
function so5925663201() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetname = "59256632";
var sheet = ss.getSheetByName(sheetname);
var row = 7;
// get value of Column H
var colHValue = sheet.getRange(row,8).getValue();
if (colHValue === "Yes"){
//Logger.log("DEBUG: Col H = yes. do something")
// get value of Column D
var Value = sheet.getRange(row,4).getValue();
var searchterm = "x";
var indexOfFirst = Value.indexOf(searchterm);
//Logger.log("DEBUG: the first instance of 'x' is "+indexOfFirst);
// get the quantity and convert from a string to a number
var qty = Value.substring(0, indexOfFirst);
var qtynum = +qty;
// var newtype = typeof qtynum; // DEBUG
//Logger.log("DEBUG: the quantity is "+qtynum+", new type = "+newtype)
// This inserts rows after
sheet.insertRowsAfter(row, qtynum-1);
}
else{
//Logger.log("DEBUG: col H <> Yes. do nothing");
}
}

Google App Script within Google Sheets - Find same value in a column and get the data rows as variables

I have Google Sheets just like this below:
Column1 Column2
444 111
444 222
444 333
999 111
999 222
888 111
I need to get return data in Column2 as variable: 111 return as var1, 222 return as var2 and so on, if the same value found in Column1.
I already try some of couple loop to get the variable:
function certificate(e) {
var sh = SpreadsheetApp.getActive().getSheetByName('sheetname'); //define the sheet name
var rg = sh.getDataRange();
var rows = rg.getLastRow(); //Get the number of last line
var values = rg.getValues(); //Put the data in array
var matchline;
for (var i = 1; i < rows; i++) {
var targetmr = values[i][0];
for (var m = 2; m < rows; m++) {
var targetmr2 = values[m][1];
if (targetmr == targetmr2 ) {
if (targetmr == values[i-1][0]) {
matchline++;
//Logger.log(targetmr + "is match" + matchline + "row"); //second and subsequent is in here
sh2.getRange(matchline+1,10).setValue(values[i][1]);
sh2.getRange(matchline+1,11).setValue(values[i][2]);
sh2.getRange(matchline+1,12).setValue(values[i][3]);
} else {
//Logger.log(targetmr + "is match" + m + "row");
matchline = m; //the same quotation number is in here
sh2.getRange(m+1,10).setValue(values[i][1]);
sh2.getRange(m+1,11).setValue(values[i][2]);
sh2.getRange(m+1,12).setValue(values[i][3]);
}
break; //Process only the first match
}
}
}
}
What code should I use to do this in Google Apps Script?
Help would be appreciated,
Sincerely
Ruhul

Delete row values in more than 1 sheet if exists in another sheet

The code below is from an answer from this post regarding copying row values to a new sheet if it exist in another sheets.
Now, what if instead of copying the duplicate values to sheet 3, I want to delete them from sheets 1 and 2 if it exists in Sheet 3. With the same spreadsheet, I have 3 sheets. The unique value that will be compared on the first 2 sheets is the first column, "ID NUMBER".
Given the values, 784 | John Steep | I.T Department, which exists in all 3 sheets, the same row value should be deleted in Sheet 1 and 2 and retain the same value on Sheet 3.
function copyRowtoSheet3() {
var s1 = SpreadsheetApp.openById("ID").getSheetByName('Sheet1');
var s2 = SpreadsheetApp.openById("ID").getSheetByName('Sheet2');
var s3 = SpreadsheetApp.openById("ID").getSheetByName('Sheet3');
var values1 = s1.getDataRange().getValues();
var values2 = s2.getDataRange().getValues();
var resultArray = [];
for(var n=0; n < values1.length ; n++){
var keep = false;
for(var p=0; p < values2.length ; p++){
Logger.log(values1[n][0]+' =? '+values2[p][0]);
if( values1[n][0] == values2[p][0] && values1[n][3] == values2[p][4]){
resultArray.push(values1[n]);
Logger.log('true');
break ;// remove this if values are not unique and you want to keep all occurrences...
}
}
}
s3.getRange(+1,1,resultArray.length,resultArray[0].length).setValues(resultArray);
}
Can't seem to find the right solution. Tried several scripts but failed to make it work.
Thank you for any advice/suggestion.
Although the other answer works (I didn't test but I guess it does) it uses a lot of spreadsheetApp calls and might be slow if you have a lot of data.
It is possible to get this result using only arrays (if you don't need to keep sheet formatting and/or formulas).
The approach is slightly different as it is easier to keep data instead of removing it.
There are for sure many possible solutions, below is the one I tried : I created a special array that contains only the first column of sheet3 to make the duplicate search simpler.
function removeDupsInOtherSheets() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s1 = ss.getSheetByName("Sheet1").getDataRange().getValues();
var s2 = ss.getSheetByName("Sheet2").getDataRange().getValues();
var s3 = ss.getSheetByName("Sheet3").getDataRange().getValues();
// iterate s3 and check in s1 & s2 if duplicate values exist
var nS1 = [];
var nS2 = [];
var s3Col1 = [];// data in column1 of sheet3
for(var n in s3){
s3Col1.push(s3[n][0]);
}
for(var n in s1){ // iterate sheet1 and test col 1 vs col 1 in sheet3
var noDup1 = checkForDup(s1[n],s3Col1)
if(noDup1){nS1.push(noDup1)};// if not present in sheet3 then keep
}
for(var n in s2){ // iterate sheet2 and test col 1 vs col 1 in sheet3
var noDup2 = checkForDup(s2[n],s3Col1)
if(noDup2){nS2.push(noDup2)};// if not present in sheet3 then keep
}
Logger.log(nS1);// view result
Logger.log(nS2);
ss.getSheetByName("Sheet1").getDataRange().clear();// clear and update sheets
ss.getSheetByName("Sheet2").getDataRange().clear();
ss.getSheetByName("Sheet1").getRange(1,1,nS1.length,nS1[0].length).setValues(nS1);
ss.getSheetByName("Sheet2").getRange(1,1,nS2.length,nS2[0].length).setValues(nS2);
}
function checkForDup(item,s){
Logger.log(s+' = '+item[0]+' ?')
if(s.indexOf(item[0])>-1){
return null;
}
return item;
}
Sheet1
ID NUMBER NAME DEPARTMENT
784 John Steep I.T.
901 Liz Green H.R.
Sheet2
ID NUMBER NAME DEPARTMENT
784 John Steep I.T.
653 Bo Gore Marketing
Sheet3
ID NUMBER NAME DEPARTMENT
784 John Steep I.T.
999 Frank White Sales
121 Abid Jones Engineering
901 Liz Green H.R.
Script
function main() {
var ss = SpreadsheetApp.openById("ID");
var s1 = ss.getSheetByName("Sheet1");
var s2 = ss.getSheetByName("Sheet2");
var s3 = ss.getSheetByName("Sheet3");
var idCol = 1; // Assuming location of ID column is same in all sheets.
var s1RowCount = s1.getLastRow();
for (var i = 2; i <= s1RowCount; i++) { // Start at var i = 2 to skip the
// first row containing the header.
var id = s1.getRange(i, idCol, 1, 1).getValue();
deleteDuplicates(s2, id);
deleteDuplicates(s3, id);
}
}
function deleteDuplicates(sheet, id) {
var idCol = 1; // Assuming location of ID column is same in all sheets.
var rowCount = sheet.getLastRow();
for (var i = 2; i <= rowCount; i++) {
var data = sheet.getRange(i, idCol, 1, 1).getValue();
if (data === id) {
// Use this to test out the function.
Logger.log("Duplicate of ID " + id + " in sheet " +
sheet.getSheetName() + " at row " + i);
// Uncomment the next line when ready.
// sheet.deleteRow(i);
}
}
}
Logging Output
[14-11-04 09:16:04:551 PST] Duplicate of ID 784 in sheet Sheet2 at row 2
[14-11-04 09:16:04:587 PST] Duplicate of ID 784 in sheet Sheet3 at row 2
[14-11-04 09:16:04:727 PST] Duplicate of ID 901 in sheet Sheet3 at row 5