-
Notifications
You must be signed in to change notification settings - Fork 36
Expand file tree
/
Copy pathUpdatingRowsInChunks.ts
More file actions
125 lines (108 loc) · 4.12 KB
/
UpdatingRowsInChunks.ts
File metadata and controls
125 lines (108 loc) · 4.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
function main(workbook: ExcelScript.Workbook) {
const sheet = workbook.getActiveWorksheet();
let data: (string | number | boolean)[][] = [];
// Number of rows in the random data (x 6 columns)
const sampleRows = 100000;
console.log(`Generating data...`)
// Dynamically generate some random data for testing purpose.
for (let i = 0; i < sampleRows; i++) {
data.push([i, ...[getRandomString(5), getRandomString(20), getRandomString(10), Math.random()], "Sample data"]);
}
console.log(`Calling update range function...`);
const updated = updateRangeInChunks(sheet.getRange("B2"), data);
if (!updated) {
console.log(`Update did not take place or complete. Chech and run again.`)
}
return;
}
function updateRangeInChunks(
startCell: ExcelScript.Range,
values: (string | boolean | number)[][],
cellsInChunk: number = 10000
): boolean {
const startTime = new Date().getTime();
console.log(`Cells per chunk setting: ${cellsInChunk}`);
if (!values) {
console.log(`Invalid input values to update.`);
return false;
}
if (values.length === 0 || values[0].length === 0) {
console.log(`Empty data -- nothing to update.`);
return true;
}
const totalCells = values.length * values[0].length;
console.log(`Total cells to update in the target range: ${totalCells}`);
if (totalCells <= cellsInChunk) {
console.log(`No need to chunk -- updating directly`);
updateTargetRange(startCell, values);
return true;
}
const rowsPerChunk = Math.floor(cellsInChunk / values[0].length);
console.log("Rows per chunk " + rowsPerChunk);
let rowCount = 0;
let totalRowsUpdated = 0;
let chunkCount = 0;
for (let i = 0; i < values.length; i++) {
rowCount++;
if (rowCount === rowsPerChunk) {
chunkCount++;
console.log(`Calling update next chunk function. Chunk#: ${chunkCount}`);
updateNextChunk(startCell, values, rowsPerChunk, totalRowsUpdated);
rowCount = 0;
totalRowsUpdated += rowsPerChunk;
console.log(`${((totalRowsUpdated / values.length) * 100).toFixed(1)}% Done`);
}
}
console.log(`Updating remaining rows -- last chunk: ${rowCount}`)
if (rowCount > 0) {
updateNextChunk(startCell, values, rowCount, totalRowsUpdated);
}
let endTime = new Date().getTime();
console.log(`Completed ${totalCells} cells update. It took: ${((endTime - startTime) / 1000).toFixed(6)} seconds to complete. ${((((endTime - startTime) / 1000)) / cellsInChunk).toFixed(8)} seconds per ${cellsInChunk} cells-chunk.`);
return true;
}
/**
* A Helper function that computes the target range and updates.
*/
function updateNextChunk(
startingCell: ExcelScript.Range,
data: (string | boolean | number)[][],
rowsPerChunk: number,
totalRowsUpdated: number
) {
const newStartCell = startingCell.getOffsetRange(totalRowsUpdated, 0);
const targetRange = newStartCell.getResizedRange(rowsPerChunk - 1, data[0].length - 1);
console.log(`Updating chunk at range ${targetRange.getAddress()}`);
const dataToUpdate = data.slice(totalRowsUpdated, totalRowsUpdated + rowsPerChunk);
try {
targetRange.setValues(dataToUpdate);
} catch (e) {
throw `Error while updating the chunk range: ${JSON.stringify(e)}`;
}
return;
}
/**
* A Helper function that computes the target range given the target range's starting cell and selected range and updates the values.
*/
function updateTargetRange(
targetCell: ExcelScript.Range,
values: (string | boolean | number)[][]
) {
const targetRange = targetCell.getResizedRange(values.length - 1, values[0].length - 1);
console.log(`Updating the range. ${targetRange.getAddress()}`);
try {
targetRange.setValues(values);
} catch (e) {
throw `Error while updating the whole range: ${JSON.stringify(e)}`;
}
return;
}
// Credit: https://www.codegrepper.com/code-examples/javascript/random+text+generator+javascript
function getRandomString(length: number): string {
var randomChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var result = '';
for (var i = 0; i < length; i++) {
result += randomChars.charAt(Math.floor(Math.random() * randomChars.length));
}
return result;
}