fix(Google Sheets Node): Append exceeding grid limits (#7684)

Github issue / Community forum post (link here to close automatically):
https://community.n8n.io/t/error-appending-data-with-google-sheets/28691
This commit is contained in:
Michael Kret 2023-11-15 11:33:47 +02:00 committed by GitHub
parent 4441ed5116
commit 88efb99587
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 85 additions and 44 deletions

View file

@ -191,6 +191,14 @@ export const description: SheetProperties = [
...handlingExtraData, ...handlingExtraData,
displayOptions: { show: { '/columns.mappingMode': ['autoMapInputData'] } }, displayOptions: { show: { '/columns.mappingMode': ['autoMapInputData'] } },
}, },
{
displayName: 'Use Append',
name: 'useAppend',
type: 'boolean',
default: false,
description:
'Whether to use append instead of update(default), this is more efficient but in some cases data might be misaligned',
},
], ],
}, },
]; ];
@ -228,17 +236,28 @@ export async function execute(
if (setData.length === 0) { if (setData.length === 0) {
return []; return [];
} else if (options.useAppend) {
await sheet.appendSheetData(
setData,
sheetName,
headerRow,
(options.cellFormat as ValueInputOption) || cellFormatDefault(nodeVersion),
false,
undefined,
undefined,
options.useAppend as boolean,
);
} else { } else {
await sheet.appendEmptyRowsOrColumns(sheetId, 1, 0); await sheet.appendEmptyRowsOrColumns(sheetId, 1, 0);
}
await sheet.appendSheetData( await sheet.appendSheetData(
setData, setData,
sheetName, sheetName,
headerRow, headerRow,
(options.cellFormat as ValueInputOption) || cellFormatDefault(nodeVersion), (options.cellFormat as ValueInputOption) || cellFormatDefault(nodeVersion),
false, false,
); );
}
if (nodeVersion < 4 || dataMode === 'autoMapInputData') { if (nodeVersion < 4 || dataMode === 'autoMapInputData') {
return items; return items;

View file

@ -202,6 +202,14 @@ export const description: SheetProperties = [
...handlingExtraData, ...handlingExtraData,
displayOptions: { show: { '/columns.mappingMode': ['autoMapInputData'] } }, displayOptions: { show: { '/columns.mappingMode': ['autoMapInputData'] } },
}, },
{
displayName: 'Use Append',
name: 'useAppend',
type: 'boolean',
default: false,
description:
'Whether to use append instead of update(default), this is more efficient but in some cases data might be misaligned',
},
], ],
}, },
]; ];
@ -394,17 +402,30 @@ export async function execute(
await sheet.batchUpdate(updateData, valueInputMode); await sheet.batchUpdate(updateData, valueInputMode);
} }
if (appendData.length) { if (appendData.length) {
await sheet.appendEmptyRowsOrColumns(sheetId, 1, 0);
const lastRow = sheetData.length + 1; const lastRow = sheetData.length + 1;
await sheet.appendSheetData( if (options.useAppend) {
appendData, await sheet.appendSheetData(
range, appendData,
headerRow + 1, range,
valueInputMode, headerRow + 1,
false, valueInputMode,
[columnNames.concat([...newColumns])], false,
lastRow, [columnNames.concat([...newColumns])],
); lastRow,
options.useAppend as boolean,
);
} else {
await sheet.appendEmptyRowsOrColumns(sheetId, 1, 0);
await sheet.appendSheetData(
appendData,
range,
headerRow + 1,
valueInputMode,
false,
[columnNames.concat([...newColumns])],
lastRow,
);
}
} }
if (nodeVersion < 4 || dataMode === 'autoMapInputData') { if (nodeVersion < 4 || dataMode === 'autoMapInputData') {

View file

@ -247,24 +247,8 @@ export class GoogleSheet {
data: string[][], data: string[][],
valueInputMode: ValueInputOption, valueInputMode: ValueInputOption,
lastRow?: number, lastRow?: number,
useAppend?: boolean,
) { ) {
// const body = {
// range,
// values: data,
// };
// const query = {
// valueInputOption: valueInputMode,
// };
// const response = await apiRequest.call(
// this.executeFunctions,
// 'POST',
// `/v4/spreadsheets/${this.id}/values/${this.encodeRange(range)}:append`,
// body,
// query,
// );
const lastRowWithData = const lastRowWithData =
lastRow || lastRow ||
(((await this.getData(range, 'UNFORMATTED_VALUE')) as string[][]) || []).length + 1; (((await this.getData(range, 'UNFORMATTED_VALUE')) as string[][]) || []).length + 1;
@ -275,6 +259,7 @@ export class GoogleSheet {
valueInputMode, valueInputMode,
lastRowWithData, lastRowWithData,
data.length, data.length,
useAppend,
); );
return response; return response;
@ -286,6 +271,7 @@ export class GoogleSheet {
valueInputMode: ValueInputOption, valueInputMode: ValueInputOption,
row: number, row: number,
rowsLength?: number, rowsLength?: number,
useAppend?: boolean,
) { ) {
const [name, _sheetRange] = sheetName.split('!'); const [name, _sheetRange] = sheetName.split('!');
const range = `${name}!${row}:${rowsLength ? row + rowsLength - 1 : row}`; const range = `${name}!${row}:${rowsLength ? row + rowsLength - 1 : row}`;
@ -299,13 +285,25 @@ export class GoogleSheet {
valueInputOption: valueInputMode, valueInputOption: valueInputMode,
}; };
const response = await apiRequest.call( let response;
this.executeFunctions,
'PUT', if (useAppend) {
`/v4/spreadsheets/${this.id}/values/${this.encodeRange(range)}`, response = await apiRequest.call(
body, this.executeFunctions,
query, 'POST',
); `/v4/spreadsheets/${this.id}/values/${this.encodeRange(range)}:append`,
body,
query,
);
} else {
response = await apiRequest.call(
this.executeFunctions,
'PUT',
`/v4/spreadsheets/${this.id}/values/${this.encodeRange(range)}`,
body,
query,
);
}
return response; return response;
} }
@ -386,6 +384,7 @@ export class GoogleSheet {
usePathForKeyRow: boolean, usePathForKeyRow: boolean,
columnNamesList?: string[][], columnNamesList?: string[][],
lastRow?: number, lastRow?: number,
useAppend?: boolean,
): Promise<string[][]> { ): Promise<string[][]> {
const data = await this.convertObjectArrayToSheetDataArray( const data = await this.convertObjectArrayToSheetDataArray(
inputData, inputData,
@ -393,8 +392,9 @@ export class GoogleSheet {
keyRowIndex, keyRowIndex,
usePathForKeyRow, usePathForKeyRow,
columnNamesList, columnNamesList,
useAppend ? null : '',
); );
return this.appendData(range, data, valueInputMode, lastRow); return this.appendData(range, data, valueInputMode, lastRow, useAppend);
} }
getColumnWithOffset(startColumn: string, offset: number): string { getColumnWithOffset(startColumn: string, offset: number): string {
@ -700,6 +700,7 @@ export class GoogleSheet {
keyRowIndex: number, keyRowIndex: number,
usePathForKeyRow: boolean, usePathForKeyRow: boolean,
columnNamesList?: string[][], columnNamesList?: string[][],
emptyValue: string | null = '',
): Promise<string[][]> { ): Promise<string[][]> {
const decodedRange = this.getDecodedSheetRange(range); const decodedRange = this.getDecodedSheetRange(range);
@ -730,7 +731,7 @@ export class GoogleSheet {
value = item[key] as string; value = item[key] as string;
} }
if (value === undefined || value === null) { if (value === undefined || value === null) {
rowData.push(''); rowData.push(emptyValue as string);
return; return;
} }
if (typeof value === 'object') { if (typeof value === 'object') {