Google Sheet add increment numbers for duplicates - google-apps-script

Hello how to get a increment numbers for duplicate with array function.
Example in below picture if we search a word in entire A row if there is any duplicates it will add numbers in B.

Try
=arrayformula(if(A1:A="",,
A1:A&if(countif(A1:A,A1:A)=1,,
"-"&text(countifs(A1:A,A1:A,row(A1:A),"<="&row(A1:A)),"00"))))
Or...
=A1&if(countif(A$1:A,A1)=1,,
"-"&text(countif(A$1:A1,A1),"00"))
...and dragdown.

Count duplicates
function countdups() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Sheet0");
const vs = sh.getRange(1,1,sh.getLastRow(),2).getValues();
let uA = [];
let obj = {pA:[]};
vs.forEach(r => {
if(!~uA.indexOf(r[0])) {
uA.push(r[0]);
obj[r[0]] = 1;
obj.pA.push(r[0]);
} else {
obj[r[0]] += 1;
}
});
let vo = obj.pA.map(p => [`${p}-${obj[p]}`]);
sh.getRange(1,2,vo.length,1).setValues(vo);
}
COL1
COL1-1
7
7-2
6
6-1
9
9-1
11
11-3
16
16-1
4
4-1
15
15-1
19
19-3
11
2-1
2
10-3
10
18-1
11
5-1
10
0-1
18
19
19
10
5
0
7

Related

Google Sheets - Script to move columns given the column header

Given this table schema:
Col_France
Col_Argentina
Col_Croatia
Col_Morocco
x
x
x
x
x
x
x
x
I want to create a Google Script that rearranges the columns so the order is always:
Col_Argentina -> Column 1
Col_France -> Column 2
Col_Croatia -> Column 3
Col_Morocco -> Column 4
Because the original column orders of the given table is not always as described above, I cannot simply use:
var sheet = SpreadsheetApp.getActiveSheet();
// Selects Col_France.
var columnSpec = sheet.getRange("A1");
sheet.moveColumns(columnSpec, 2);
and so on... In other words, the table schema can possibly be:
Col_Morocco
Col_Croatia
Col_France
Col_Argentina
x
x
x
x
x
x
x
x
but the desired outcome should always be the defined above. The script should be scalable. In the future, more than 4 columns should be rearranged.
My approach would be:
Define the range of columns to rearrange (they are all together)
For the first column, get the value of the column header
Depending on the value, move the column to a predefined index
Move to the next column and repeat
Iterate until end of range
Can somebody please point me to the required functions?
In your situation, when moveColumns is used, how about the following sample script?
Sample script:
function myFunction() {
var order = ["Col_Argentina", "Col_France", "Col_Croatia", "Col_Morocco"]; // This is from your question.
var sheet = SpreadsheetApp.getActiveSheet();
var obj = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0].reduce((ar, h, i) => [...ar, { from: i + 1, to: order.indexOf(h) + 1 }], []).sort((a, b) => a.to > b.to ? 1 : -1);
for (var i = 0; i < obj.length; i++) {
if (obj[i].from != obj[i].to) {
sheet.moveColumns(sheet.getRange(1, obj[i].from), obj[i].to);
obj.forEach((e, j) => {
if (e.from < obj[i].from) obj[j].from += 1;
});
}
}
}
When this script is run, the columns are rearranged by order you give. In this case, the text and cell format are also moved.
When moveColumns(columnSpec, destinationIndex) is used, the indexes of columns are changed after moveColumns(columnSpec, destinationIndex) was run. So, please be careful about this. In the above script, the changed indexes are considered.
References:
moveColumns(columnSpec, destinationIndex)
reduce()
forEach()
Order Columns:
function ordercols() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Sheet0");
const [h,...vs] = sh.getDataRange().getValues();
const idx = {};
h.forEach((h,i) => idx[h]=i);
const o = vs.map(r => [r[idx['COL4']],r[idx['COL3']],r[idx['COL2']],r[idx['COL1']]]);
sh.clearContents();
o.unshift(['COL4','COL3','COL2','COL1']);
sh.getRange(1,1,o.length,o[0].length).setValues(o);
}
Data:
COL1
COL2
COL3
COL4
24
5
2
9
16
0
13
18
22
24
23
16
12
12
4
17
6
20
17
14
7
13
4
2
2
20
4
22
3
5
3
4
16
5
7
23
ReOrdered:
COL4
COL3
COL2
COL1
9
2
5
24
18
13
0
16
16
23
24
22
17
4
12
12
14
17
20
6
2
4
13
7
22
4
20
2
4
3
5
3
23
7
5
16

How to unpivot table in Google Sheets? [duplicate]

This question already has answers here:
How do you create a "reverse pivot" in Google Sheets?
(10 answers)
Closed 6 months ago.
I would like to unpivot the pink table to display as shown in the green table in the image linked below.
[transpose pink table to desired green table]
Pivoting in Google Sheets didn't work as columns B, C and D are separate.
Any ideas on how to get this to work using apps script and/or Google Sheets query?
Unpivot
function unpivot() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Sheet0");
const osh = ss.getSheetByName("Sheet1");
const [h, ...vs] = sh.getRange(1, 1, sh.getLastRow(), sh.getLastColumn()).getValues();
let n = 0;
let obj = { pA: [] }
vs.forEach((r, i) => {
if (!obj.hasOwnProperty(r[0])) {
obj[r[0]] = { sA: [] };
obj.pA.push(r[0]);
} //collect the first column as properties
r.forEach((c, j) => {
if (j > 0) {
if (!obj[r[0]].hasOwnProperty(h[j])) {
obj[r[0]][h[j]] = c;
obj[r[0]].sA.push(h[j])
} //collecting the first row as properties and assigning the value to each subproperty
}
});
});
let oA = [];
obj.pA.forEach(p => {
obj[p].sA.forEach(s => oA.push([p,s,obj[p][s]]));
});//separating them into a two dimensional array
//Logger.log(JSON.stringify(oA));
oA.sort((a,b) => new Date(a[1]).valueOf() - new Date(b[1]).valueOf());//sorting by date
osh.clearContents();
osh.getRange(1,1,oA.length,oA[0].length).setValues(oA);//displaying
}
Sheet0:
Group
1/1/2022
2/1/2022
3/1/2022
A
1
5
9
B
2
6
10
C
3
7
11
D
4
8
12
Sheet1:
A
1/1/2022
1
B
1/1/2022
2
C
1/1/2022
3
D
1/1/2022
4
A
2/1/2022
5
B
2/1/2022
6
C
2/1/2022
7
D
2/1/2022
8
A
3/1/2022
9
B
3/1/2022
10
C
3/1/2022
11
D
3/1/2022
12

How can I build an array of column D where column A = Arg

"Entries" is a sheet that I enter individual tasks with the date, name, start time, end time. It calculates total time per task
"Days" is a generated sheet that gets dates from Entries and calculates total time worked on all tasks for each unique day in Entries
I would like Days to have a column that uses the date from column A, looks in Entries, and returns the earliest start time from any row in Days that is for that date.
function startTime(theDate) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ent = ss.getSheetByName("Entries");
ent.activate();
var rng = ent.getRange(rownumber, 1, 1, numberofcolums)
var rangeArray = rng.getValues();
}
calling using :
=startTime(A1)
where A1 contains the Date that I want the check-in time for.
The array of columnA where A = 'Arg'
function colDWhereAisArg() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Sheet0');
let o = sh.getRange(2,1,sh.getLastRow() - 1,4).getValues().map(r => {
if(r[0] == 'Arg') {
return [r[3]];
}
}).filter(e => e);
Logger.log(JSON.stringify(o));
}
Execution log
4:29:59 PM Notice Execution started
4:30:00 PM Info [[5],[8],[13]]
4:30:00 PM Notice Execution completed
My Data:
COL1
COL2
COL3
COL4
1
2
3
4
Arg
3
4
5
3
4
5
6
4
5
6
7
Arg
6
7
8
6
7
8
9
7
8
9
10
8
9
10
11
9
10
11
12
Arg
11
12
13

Printing rows with certain text in column 2 with app script

I need to print off certain rows in a google sheet depending on what is in column 2 of that row. I know how to find the rows with a for loop but the rest eludes me. Perhaps my googling skills are rusty.
This is what I have.
var app = SpreadsheetApp;
var rows = app.getActive().getSheetByName("Sheet").getMaxRows().toString();
var rows = rows.replace(".0","");
function findRows(){
for (var counter = 1; counter <= rows; counter = counter+1){
if(app.getActive().getSheetByName("Sheet").getRange(counter, 2) == "example" || "example2"){
}
}
Find the correct rows
function findrows() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Sheet0");
const osh = sh.getSheetByName("Sheet1");
const vs = sh.getDataRange().getValues();
let s = vs.map(r => {
if(r[1] == "Example" || r[1] == "example2") {
return r;
}
}).filter(e => e);
Logger.log(JSON.stringify(s));
//you can output to a sheet with something like
//sheet.getRange(1,1,s.length,s[0].length).setValues(s);
osh.getRange(1,1,s.length,s[0].length).setValues(s);//put on another sheet
}
Execution log
4:56:34 PM Notice Execution started
4:56:35 PM Info [[2,"Example",4,5],[5,"Example",7,8],[9,"Example",11,12],[12,"Example",14,15]]
4:56:35 PM Notice Execution completed
Data:
COL1
COL2
COL3
COL4
1
2
3
4
2
Example
4
5
3
4
5
6
4
5
6
7
5
Example
7
8
6
7
8
9
7
8
9
10
8
9
10
11
9
Example
11
12
10
11
12
13
11
12
13
14
12
Example
14
15
13
14
15
16
BTW Printing is not easily done from Javascript or Google Apps Script

Google Sheets script - For each used cell in range 1, if cell value exists in range 2, get range 2 match's row number

I feel I have this script almost working as intended, but I am unsure as to where to place certain components of the procedure within the for loop to achieve the desired result. Tunnel vision is very much in effect right now, it's entirely possible I am overthinking a simple task. Please let me know if I can describe the issue more clearly. Any suggestions or pointers towards an existing resource are helpful.
Setup: Sheet one contains a dynamic vertical list of text values starting in cell I3 going down. Sheet two contains a dynamic vertical list of text values starting in range A2 going down, and has a similar set of text values in the same rows in column B.
Goal:
Get the value of each used cell in Sheet1 column I (range one)
Get the value of each used cell in Sheet2 column A (range two)
For each used cell in range one, check the value of each range one
cell to see if the value exists in range two
If a match exists, get the row number of the cell in range two that
contains the value (there will only ever be a single match if a match
exists)
Get the value of the cell on that same row in Sheet2 column B
Set the above value as the cell value in the row containing the value
found in both ranges on Sheet1 Column M
Below is what I have been able to come up with. I am able to get it to function up to the last step. It seems the matching rowNumber variable is not updating with each for loop.
// Get values of range one
var lastRowRangeOne = sheetone.getRange('I3').getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow();
var rangeOneValues = sheetone.getRange('I3:I' + lastRowClientColumn).getValues();
// Get values of range two
var sheettwo = spreadsheet.getSheetByName('Sheet2');
var sheettwoLastRow = sheettwo.getLastRow();
var sheettwoList = sheettwo.getRange('A2:A' + sheettwoLastRow).getValues();
var sheettwoListFlat = sheettwoList.map(function(row) {return row[0];});
for (var i = 0; i< rangeOneValues.length ; i++){ // for each row in range one
if (sheettwoListFlat[i] == rangeOneValues[i]) { // if the range one value exists in range two
var rowNumber = sheettwoListFlat.indexOf(rangeOneValues[i]) + 3; // get the row number of the matching value found in range two
var sheetOneColumnMValue = sheettwo.getRange('B' + rowNumber).getValue(); // get the cell value of the same row in sheet two column B
var sheetOneRowNumber = i + 3; // get the row number of the range one value
sheetone.getRange('M' + sheetOneRowNumber).setValue(sheetOneColumnMValue); // set the cell value of sheet one column M row x, where x is sheetOneRowNumber
}
}
If you print the value of sheettwoListFlat, it has only 5 elements. Once the iterator of for loop reaches 5 or more it will automatically set if (sheettwoListFlat[i] == rangeOneValues[i]) { to false. Also the statement will only work if the elements of the same index of both arrays are equal.
It would be also more efficient if you search the Sheet1 using the values of Sheet2 since Sheet2 has lesser value.
Here I used TextFinder to find the text within a range.
Using Sheet2 values as search key
Code:
function myFunction() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheetone = spreadsheet.getSheetByName('Sheet1');
var lastRowRangeOne = sheetone.getRange('I2').getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow();
var rangeOneValues = sheetone.getRange('I2:I' + lastRowRangeOne);
var sheettwo = spreadsheet.getSheetByName('Sheet2');
var sheettwoLastRow = sheettwo.getLastRow();
var sheettwoList = sheettwo.getRange('A2:B' + sheettwoLastRow).getValues();
for (var i = 0; i < sheettwoList.length; i++){
var find = rangeOneValues.createTextFinder(sheettwoList[i][0]).findNext()
if(find){
var sheetOneRowNumber = find.getRow();
sheetone.getRange('M' + sheetOneRowNumber).setValue(sheettwoList[i][1]);
}
}
}
Using Sheet1 values as search key
Code:
function myFunction() {
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheetone = spreadsheet.getSheetByName('Sheet1');
var lastRowRangeOne = sheetone.getRange('I2').getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow();
var rangeOneValues = sheetone.getRange('I2:I' + lastRowRangeOne).getValues();
var sheettwo = spreadsheet.getSheetByName('Sheet2');
var sheettwoLastRow = sheettwo.getLastRow();
var sheettwoList = sheettwo.getRange('A2:B' + sheettwoLastRow);
for (var i = 0; i< rangeOneValues.length ; i++){ // for each row in range one
var find = sheettwoList.createTextFinder(rangeOneValues[i][0]).findNext();
if(find){
var rowNumber = find.getRow()
var sheetOneColumnMValue = sheettwo.getRange('B' + rowNumber).getValue(); // get the cell value of the same row in sheet two column B
var sheetOneRowNumber = i + 2;
sheetone.getRange('M' + sheetOneRowNumber).setValue(sheetOneColumnMValue);
}
}
}
Output:
Note: Both produce the same output but using Sheet2 values as search key is more faster than the other.
function compareTwoCols() {
const c1 = 'COL1';//column names
const c2 = 'COL3';
const ss1 = SpreadsheetApp.openById(gobj.globals.datagenid);//data set 1
const sh1 = ss1.getSheetByName('Sheet1');
const [hd1, ...vs1] = sh1.getDataRange().getValues();
let col1 = {};
hd1.forEach((h, i) => { col1[h] = i });
const ds1 = vs1.map((r, i) => {
return r[col1[c1]];
});
const ss2 = SpreadsheetApp.openById(gobj.globals.ssid);//data set 2
const sh2 = ss2.getSheetByName('Sheet0');
const [hd2, ...vs2] = sh2.getDataRange().getValues();
let col2 = {};
hd2.forEach((h, i) => { col2[h] = i });
const ds2 = vs2.map((r, i) => {
return r[col2[c2]]
});
let matches = { pA: [] };
let idx = -1;
ds1.forEach((e, i) => {
let from = '';
do {
idx = ds2.indexOf(e, from);
if (~idx) {
if (!matches.hasOwnProperty(e)) {
matches[e] = [];
matches[e].push({ val1: e, row1: i + 2, col1: col1[c1] + 1, row2: idx + 2, col2: col2[c2] +1 });
matches.pA.push(e);
} else {
matches[e].push({ val1: e, row1: i + 2, col1: col1[c1] + 1, row2: idx + 2, col2: col2[c2] + 1});
}
from = idx + 1;
}
} while (~idx);
});
Logger.log(JSON.stringify(matches));
}
Spreadsheet1 Sheet1:
COL1
COL2
COL3
COL4
COL5
3
4
2
3
4
2
6
6
1
4
5
1
7
5
5
9
8
7
9
5
7
9
0
8
1
8
2
8
7
9
5
8
7
9
9
1
2
0
8
6
2
7
4
0
3
8
2
0
2
6
Spreadsheet2 Sheet0:
COL1
COL2
COL3
COL4
COL5
5
1
2
7
6
4
5
7
8
2
6
3
8
1
5
0
7
6
3
6
4
7
6
1
7
5
6
9
2
1
3
0
2
2
8
4
5
0
8
1
1
3
9
2
2
3
6
7
0
3
Matches Object:
{
"2":[
{
"val1":2,
"row1":3,//ds1 row 3
"col1":1,
"row2":2,//ds2 row 4
"col2":3
},
{
"val1":2,
"row1":3,//ds1 row 3
"col1":1,
"row2":8,//ds2 row 8
"col2":3
},
{
"val1":2,
"row1":10,
"col1":1,
"row2":2,
"col2":3
},
{
"val1":2,
"row1":10,
"col1":1,
"row2":8,
"col2":3
}
],
"7":[
{
"val1":7,
"row1":6,
"col1":1,
"row2":3,
"col2":3
},
{
"val1":7,
"row1":6,
"col1":1,
"row2":11,
"col2":3
}
],
"8":[
{
"val1":8,
"row1":7,
"col1":1,
"row2":4,
"col2":3
},
{
"val1":8,
"row1":11,
"col1":1,
"row2":4,
"col2":3
}
],
"9":[
{
"val1":9,
"row1":5,
"col1":1,
"row2":7,
"col2":3
},
{
"val1":9,
"row1":5,
"col1":1,
"row2":10,
"col2":3
}
],
"pA":[//just an array of all of the matches
2,
9,
7,
8
]
}