writing a count program to find the number of repeatitions - google-apps-script

I am writing a code to count the number of times a time duration in column B is repeated.After writing a code according to my logic I am still getting error or no output. Here's the app script code I have written. Help me out.
function count() {
var data = SpreadsheetApp.getActive();
var sheet = data.getSheetByName("Sheet4");
var lastRow = sheet.getLastRow();
var sh = sheet.getRange('B1:B' + lastRow);
var cell = sh.getValues();
var count = 0;
for (var i = 0; i < lastRow; j++) {
var column2 = cell[i][1];
for (var j = 0; j < i; j++) {
var column4 = cell[j][1];
if (column4 == column2) {
count++;
}
}
sheet.getRange('F' + (i + 1).toString()).setValue(count);
}
}
This is the intended output instead of column F i put the sample output in column C

Issue(s):
Outer loop's increment variable doesn't change.
for (var i = 0; i < lastRow;/*i never changes =>*/ j++)
Date/Time are retrieved as JavaScript objects and cannot be compared with ==:
if (column4 == column2) {//Date objects cannot be compared
cell doesn't have a value at array index [1]
Solution:
Increment all variables in the for -loop
Compare value of date objects instead
Array indexes start at [0]
Snippet:
for (var i = 0; i < lastRow; ++i) {
var column2 = cell[i][0];
/*....*/
var column4 = cell[j][0];
if (column4 - column2 === 0) {//#see https://stackoverflow.com/questions/492994

Related

Counting non empty cells with matching font color in Google Sheets

I'm using a custom function to count the number of cells with a matching font color in a range.
function countIfFont(countRange,fontRef,rangeSum) {
var activeRange = SpreadsheetApp.getActiveRange();
var activeSheet = activeRange.getSheet();
var range = activeSheet.getRange(countRange);
var rangeHeight = range.getHeight();
var rangeWidth = range.getWidth();
var fc = range.getFontColors();
var fontCell = activeSheet.getRange(fontRef);
var font = fontCell.getFontColor();
var count = 0;
for(var i = 0; i < rangeHeight; i++)
for(var j = 0; j < rangeWidth; j++)
if(fc[i][j] == font)
count = count+1;
return count;
};
It works, but it is counting blank cells and I want it to exclude blank cells. How do I check if the cell is blank?
In your script, how about the following modification?
From:
for(var i = 0; i < rangeHeight; i++)
for(var j = 0; j < rangeWidth; j++)
if(fc[i][j] == font)
count = count+1;
To:
var values = range.getDisplayValues();
for (var i = 0; i < rangeHeight; i++)
for (var j = 0; j < rangeWidth; j++)
if (fc[i][j] == font && values[i][j])
count = count + 1;
By this modification, when fc[i][j] == font and the cell is not empty, count = count + 1 is run.

How to Include more sheets to write incremental number

I am using this function which works upon submitting the entry via Google Forms. Currently the below script is adding increment number to the Sheet1 Last empty row
I want to include two more sheets where same incremental number will be added to last empty row.
Column will be same where increment number is pasting that is Column A but Sheet1 data starts from Row2 and Sheet2 and Sheet3 Data starts from row6.
Your help will be much appreciated.
function uPDATEiT() {
var aiColumnName = 'A'; //Sheet1,Sheet2,Sheet3 same column
var requieredColName = 'C' //it is just for Sheet1
var ss = SpreadsheetApp.getActiveSpreadsheet()
var worksheet = ss.getSheetByName('Sheet1','Sheet2','Sheet3')
var aiColRange = worksheet.getRange(aiColumnName + '1:' + aiColumnName + '1000');
var aiCol = aiColRange.getValues();
var aiColIndex = aiColRange.getColumn();
var reqCol = worksheet.getRange(requieredColName + '1:' + requieredColName + '1000').getValues();
var maxSeq = 0;
for (var i = 0; i <= aiCol.length; i++) {
if (parseInt(aiCol[i], 10) > maxSeq) { maxSeq = aiCol[i]; }
}
for (var i = 0; i <= aiCol.length; i++) {
if (('' + reqCol[i]).length > 0 && ('' + aiCol[i]).length === 0) {
maxSeq++;
worksheet.getRange(i + 1, aiColIndex).setValue(maxSeq);
}
}
}
You can use this formula in Sheet2!A4 and Sheet3!A4:
={"ID's";ARRAYFORMULA(IF(B5:B<>"",vlookup(B5:B,{'Data Sheet (Sheet1)'!$B$2:$B,'Data Sheet (Sheet1)'!$A$2:$A},2,false),""))}
What it does?
Check if column B is not empty, then get the id from Sheet1 based on the matched name(column B) as a key in the vlookup()
Output:
Original Sheet2:
Sheet 2 using the formula:
Update
If you just want to append your maxSeq in Sheet2, you can use this:
Code:
function uPDATEiT() {
var aiColumnName = 'A'; //Sheet1,Sheet2,Sheet3 same column
var requieredColName = 'C' //it is just for Sheet1
var ss = SpreadsheetApp.getActiveSpreadsheet()
var worksheet = ss.getSheetByName('Data Sheet (Sheet1)')
var sheet2 = ss.getSheetByName('Sheet2')
Logger.log(worksheet)
Logger.log(sheet2.getLastRow())
var aiColRange = worksheet.getRange(aiColumnName + '1:' + aiColumnName + '1000');
var aiCol = aiColRange.getValues();
var aiColIndex = aiColRange.getColumn();
var reqCol = worksheet.getRange(requieredColName + '1:' + requieredColName + '1000').getValues();
var maxSeq = 0;
for (var i = 0; i <= aiCol.length; i++) {
if (parseInt(aiCol[i], 10) > maxSeq) { maxSeq = aiCol[i]; }
}
for (var i = 0; i <= aiCol.length; i++) {
if (('' + reqCol[i]).length > 0 && ('' + aiCol[i]).length === 0) {
maxSeq++;
worksheet.getRange(i + 1, aiColIndex).setValue(maxSeq);
sheet2.getRange(sheet2.getLastRow()+1,aiColIndex).setValue(maxSeq);
}
}
}
Get the last row in the sheet that contains data using getLastRow() , then increment it by 1.
Output:

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

How to exchange values using temporary 2D array

I am currently trying to exchange values between two columns (G and H)
The first sheet column G values don't move if they are found in a first column table reference in another sheet.
if they are found in second column table reference,
they have to swap values with the first sheet column H values the same index.
This code works for column G but not for column H. It gives the elements but not in order.
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet29'); //au cas ou ca bug
var lr = spreadsheet.getLastRow();
var lc = spreadsheet.getLastColumn();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet1 = ss.getSheetByName('Sheet29');
var sheet2 = ss.getSheetByName('Tabs of applications and firmwares');
var range1 = sheet1.getRange(2, 7, sheet1.getLastRow(), 9);
var range2 = sheet2.getRange(2, 1, sheet2.getLastRow(), 4);
var values1 = range1.getValues();
var values2 = range2.getValues();
var compteurBon = 0;
var compteurMauvais = 0;
var tempArray1 = [];
for (var i = 0; i < values1.length; i++) {
for (var j = 0; j < values2.length; j++) {
if (values1[i][0] === values2[j][0]) {
compteurBon++;
} else if (values1[i][0] == values2[j][2]) {
compteurMauvais++;
var tempArrayValue1 = values1[i][0];
tempArray1.push(tempArrayValue1);
values1[i][0] = values1[i][1];
values1[i][1] = tempArray1; // here it doesn't take the right value
}
}
}
range1.setValues(values1);
};
Okay, I think your code is in the good direction but it can be simplified. First of all, I understand that we have two sheets (“Sheet 29” and “Tabs of applications and firmwares”), and you want to copy the values from H to G in case G equals B from the second sheet. As I said in my comment, in case you want to just get two columns in the same range, you should use sheetx.getRange(2, col, sheet1.getLastRow(), 2); This last '2' is the number of columns you are getting into the range (G and H, A and B respectively). If we stick to your approach, we will need another tempArray variable:
for (var i = 0; i < values1.length - 1; i++) {
tempArray1.push(values1[i].toString().split(","));
tempArray2.push(values2[i].toString().split(","));
}
What we are doing here is putting the 4 columns in those two arrays. Each one of them is 2D, so tempArray1 contains all the rows from G and H and the same for tempArray2 with A and B. You can access the data with [x][0] and [x][1] respectively.
After this you can just compare the values of temparray1 and temparray2, and write the values from G (temparray[i][1]) to H (temparray[i, 7])
if (tempArray1[i][0] == tempArray2[i][0]) {
compteurBon++;
} else if (tempArray1[i][0] == tempArray2[i][1]) {
sheet1.getRange(i+2 , 7).setValue(tempArray1[i][1]);
}

Search for values in arrays

I've a spreadsheet with two sheets (Foglio1, Foglio2)
Foglio1 has five rows of numeric values in two columns, Foglio2 2 has five rows of numeric values in the first column.
I'd like to search for the Foglio2 values in Foglio1 and if it finds something copy the respective value of Foglio1, column2 into Foglio2, column2.
This is what I've got so far but it doesn't seems to work, basically it doesn't find anything so the result array remains empty
function cercaCopia() {
var ss = SpreadsheetApp.openById('myfileIDhere');
var data1 = ss.getSheetByName('Foglio2').getRange(1, 1, 5).getValues();
var data2 = ss.getSheetByName('Foglio1').getRange(1, 1, 5, 2).getValues();
var result = new Array(4);
for (var i = 0; i < 5; i++) {
for (var j = 0; j < 5; j++) {
if (data1[i] == data2[j, 0]) {
result[i] = data2[j, 1]
}
}
}
}
This works:
function myFunction() {
var ss = SpreadsheetApp.openById('sheetid');
var data1 = ss.getSheetByName('Foglio2').getRange(1, 1, 5).getValues();
var data2 = ss.getSheetByName('Foglio1').getRange(1, 1, 5, 2).getValues();
for (var j=0; j<5;j++){
for (var i = 0; i < 5; i++) {
if (data1[j][0]==data2[i][0]){
var range= ss.getSheetByName('Foglio2').getRange(1,1,5,5);
range.getCell(j+1,2).setValue(data2[i][1]);
}
}
}
}
I get this as a result:
In Foglio1 I had this: