线性化 BOM,使用 setValues(result) 而不是 appendRow 时出现问题
Linearize a BOM, issue when using setValues(result) instead of appendRow
输入如下(这是一个简化的例子)
LEVEL
NAME
JOB
1
A
Alpha
2
B
Bravo
3
C
Charlie
4
D
Delta
2
E
Echo
3
F
Foxtrot
2
G
Golf
2
H
Hotel
3
I
India
4
J
Juliet
我必须线性化才能获得该输出
NAME level 1
JOB level 1
NAME level 2
JOB level 2
NAME level 3
JOB level 3
NAME level 4
JOB level 4
A
Alpha
B
Bravo
C
Charlie
D
Delta
A
Alpha
E
Echo
F
Foxtrot
A
Alpha
G
Golf
A
Alpha
H
Hotel
I
India
J
Juliet
我通过使用临时数组 (temp) 和 appendRow 来实现,这有点慢。当我设法使用大数组(结果)和 setValues(结果)时,我只得到最后一行
NAME level 1
JOB level 1
NAME level 2
JOB level 2
NAME level 3
JOB level 3
NAME level 4
JOB level 4
A
Alpha
H
Hotel
I
India
J
Juliet
A
Alpha
H
Hotel
I
India
J
Juliet
A
Alpha
H
Hotel
I
India
J
Juliet
A
Alpha
H
Hotel
I
India
J
Juliet
我不明白我的脚本有什么问题!任何帮助理解都会有用。
https://docs.google.com/spreadsheets/d/1zoT9kk-Am_yUOLCAAvccJOTH0UZ7lrRiLYpPtqb9RXY/copy
function linearize() {
const sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Original')
const data = sh.getRange(2, 1, sh.getLastRow() - 1, sh.getLastColumn()).getDisplayValues()
const nbData = sh.getLastColumn() - 1
const bd1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('BD1') // for test with appendrow
const bd2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('BD2') // for test with result
bd1.clearContents()
bd2.clearContents()
let result = []
let levelMax = 0
let headers = []
data.forEach(r => levelMax = Math.max(levelMax, r[0]))
for (let i = 1; i <= levelMax; i++) {
headers.push(['NAME level ' + i, 'JOB level ' + i])
}
bd1.appendRow(headers.flat())
result.push(headers.flat())
// everything ok until this step ==============
let temp = []
data.forEach(function (r, i) {
// save values
var level = r[0]
for (let x = 0; x < nbData; x++) {
temp[nbData * (level - 1) + x] = r[x + 1]
}
// blank values from level+1 to levelMax
if (level < levelMax) {
for (let y = (level * 1 + 1); y <= levelMax; y++) {
for (let x = 0; x < nbData; x++) {
temp[nbData * (y - 1) + x] = ''
}
}
}
// output when the following level will not increase or at the final row
if (i < data.length - 1) {
if (data[i + 1][0] <= data[i][0]) {
bd1.appendRow(temp)
result.push(temp)
}
}
else {
bd1.appendRow(temp)
result.push(temp)
}
})
bd2.getRange(1, 1, result.length, result[0].length).setValues(result)
}
我相信你的目标如下。
- 通过修改脚本,您想使用
bd2.getRange(1, 1, result.length, result[0].length).setValues(result)
. 实现I have to linearize to obtain that output
的情况
这样的话,下面的修改怎么样?
发件人:
if (i < data.length - 1) {
if (data[i + 1][0] <= data[i][0]) {
bd1.appendRow(temp)
result.push(temp)
}
}
收件人:
if (i < data.length - 1) {
if (data[i + 1][0] <= data[i][0]) {
bd1.appendRow(temp);
result.push([...temp]); // <--- Modified. Or result.push(temp.slice())
}
}
- 我认为在您的脚本中,
temp
用作 pass-by-reference。这样就出现了I only get the last row
的问题。我认为这可能是您遇到问题的原因。因此,在这种情况下,temp
与 [...temp]
and/or temp.slice()
一起复制。这样,它就变成了 pass-by-value.
输入如下(这是一个简化的例子)
LEVEL | NAME | JOB |
---|---|---|
1 | A | Alpha |
2 | B | Bravo |
3 | C | Charlie |
4 | D | Delta |
2 | E | Echo |
3 | F | Foxtrot |
2 | G | Golf |
2 | H | Hotel |
3 | I | India |
4 | J | Juliet |
我必须线性化才能获得该输出
NAME level 1 | JOB level 1 | NAME level 2 | JOB level 2 | NAME level 3 | JOB level 3 | NAME level 4 | JOB level 4 |
---|---|---|---|---|---|---|---|
A | Alpha | B | Bravo | C | Charlie | D | Delta |
A | Alpha | E | Echo | F | Foxtrot | ||
A | Alpha | G | Golf | ||||
A | Alpha | H | Hotel | I | India | J | Juliet |
我通过使用临时数组 (temp) 和 appendRow 来实现,这有点慢。当我设法使用大数组(结果)和 setValues(结果)时,我只得到最后一行
NAME level 1 | JOB level 1 | NAME level 2 | JOB level 2 | NAME level 3 | JOB level 3 | NAME level 4 | JOB level 4 |
---|---|---|---|---|---|---|---|
A | Alpha | H | Hotel | I | India | J | Juliet |
A | Alpha | H | Hotel | I | India | J | Juliet |
A | Alpha | H | Hotel | I | India | J | Juliet |
A | Alpha | H | Hotel | I | India | J | Juliet |
我不明白我的脚本有什么问题!任何帮助理解都会有用。
https://docs.google.com/spreadsheets/d/1zoT9kk-Am_yUOLCAAvccJOTH0UZ7lrRiLYpPtqb9RXY/copy
function linearize() {
const sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Original')
const data = sh.getRange(2, 1, sh.getLastRow() - 1, sh.getLastColumn()).getDisplayValues()
const nbData = sh.getLastColumn() - 1
const bd1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('BD1') // for test with appendrow
const bd2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('BD2') // for test with result
bd1.clearContents()
bd2.clearContents()
let result = []
let levelMax = 0
let headers = []
data.forEach(r => levelMax = Math.max(levelMax, r[0]))
for (let i = 1; i <= levelMax; i++) {
headers.push(['NAME level ' + i, 'JOB level ' + i])
}
bd1.appendRow(headers.flat())
result.push(headers.flat())
// everything ok until this step ==============
let temp = []
data.forEach(function (r, i) {
// save values
var level = r[0]
for (let x = 0; x < nbData; x++) {
temp[nbData * (level - 1) + x] = r[x + 1]
}
// blank values from level+1 to levelMax
if (level < levelMax) {
for (let y = (level * 1 + 1); y <= levelMax; y++) {
for (let x = 0; x < nbData; x++) {
temp[nbData * (y - 1) + x] = ''
}
}
}
// output when the following level will not increase or at the final row
if (i < data.length - 1) {
if (data[i + 1][0] <= data[i][0]) {
bd1.appendRow(temp)
result.push(temp)
}
}
else {
bd1.appendRow(temp)
result.push(temp)
}
})
bd2.getRange(1, 1, result.length, result[0].length).setValues(result)
}
我相信你的目标如下。
- 通过修改脚本,您想使用
bd2.getRange(1, 1, result.length, result[0].length).setValues(result)
. 实现
I have to linearize to obtain that output
的情况
这样的话,下面的修改怎么样?
发件人:
if (i < data.length - 1) {
if (data[i + 1][0] <= data[i][0]) {
bd1.appendRow(temp)
result.push(temp)
}
}
收件人:
if (i < data.length - 1) {
if (data[i + 1][0] <= data[i][0]) {
bd1.appendRow(temp);
result.push([...temp]); // <--- Modified. Or result.push(temp.slice())
}
}
- 我认为在您的脚本中,
temp
用作 pass-by-reference。这样就出现了I only get the last row
的问题。我认为这可能是您遇到问题的原因。因此,在这种情况下,temp
与[...temp]
and/ortemp.slice()
一起复制。这样,它就变成了 pass-by-value.