mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
fix(Google Sheets Node): Fix for append operation if no empty rows in sheet
This commit is contained in:
parent
6d4e959884
commit
741c7da8b1
|
@ -24,15 +24,15 @@ export async function router(this: IExecuteFunctions): Promise<INodeExecutionDat
|
|||
|
||||
const googleSheet = new GoogleSheet(spreadsheetId, this);
|
||||
|
||||
let sheetWithinDocument = '';
|
||||
let sheetId = '';
|
||||
if (operation !== 'create') {
|
||||
sheetWithinDocument = this.getNodeParameter('sheetName', 0, undefined, {
|
||||
sheetId = this.getNodeParameter('sheetName', 0, undefined, {
|
||||
extractValue: true,
|
||||
}) as string;
|
||||
}
|
||||
|
||||
if (sheetWithinDocument === 'gid=0') {
|
||||
sheetWithinDocument = '0';
|
||||
if (sheetId === 'gid=0') {
|
||||
sheetId = '0';
|
||||
}
|
||||
|
||||
let sheetName = '';
|
||||
|
@ -41,17 +41,22 @@ export async function router(this: IExecuteFunctions): Promise<INodeExecutionDat
|
|||
sheetName = spreadsheetId;
|
||||
break;
|
||||
case 'delete':
|
||||
sheetName = sheetWithinDocument;
|
||||
sheetName = sheetId;
|
||||
break;
|
||||
case 'remove':
|
||||
sheetName = `${spreadsheetId}||${sheetWithinDocument}`;
|
||||
sheetName = `${spreadsheetId}||${sheetId}`;
|
||||
break;
|
||||
default:
|
||||
sheetName = await googleSheet.spreadsheetGetSheetNameById(sheetWithinDocument);
|
||||
sheetName = await googleSheet.spreadsheetGetSheetNameById(sheetId);
|
||||
}
|
||||
|
||||
operationResult.push(
|
||||
...(await sheet[googleSheets.operation].execute.call(this, googleSheet, sheetName)),
|
||||
...(await sheet[googleSheets.operation].execute.call(
|
||||
this,
|
||||
googleSheet,
|
||||
sheetName,
|
||||
sheetId,
|
||||
)),
|
||||
);
|
||||
} else if (googleSheets.resource === 'spreadsheet') {
|
||||
operationResult.push(...(await spreadsheet[googleSheets.operation].execute.call(this)));
|
||||
|
@ -60,6 +65,15 @@ export async function router(this: IExecuteFunctions): Promise<INodeExecutionDat
|
|||
if (this.continueOnFail()) {
|
||||
operationResult.push({ json: this.getInputData(0)[0].json, error: err });
|
||||
} else {
|
||||
if (
|
||||
err.message &&
|
||||
(err.message.toLowerCase().includes('bad request') ||
|
||||
err.message.toLowerCase().includes('uknown error')) &&
|
||||
err.description
|
||||
) {
|
||||
err.message = err.description;
|
||||
err.description = undefined;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -154,6 +154,7 @@ export async function execute(
|
|||
this: IExecuteFunctions,
|
||||
sheet: GoogleSheet,
|
||||
sheetName: string,
|
||||
sheetId: string,
|
||||
): Promise<INodeExecutionData[]> {
|
||||
const items = this.getInputData();
|
||||
const dataMode = this.getNodeParameter('dataMode', 0) as string;
|
||||
|
@ -176,6 +177,12 @@ export async function execute(
|
|||
setData = mapFields.call(this, items.length);
|
||||
}
|
||||
|
||||
if (setData.length === 0) {
|
||||
return [];
|
||||
} else {
|
||||
await sheet.appendEmptyRowsOrColumns(sheetId, 1, 0);
|
||||
}
|
||||
|
||||
await sheet.appendSheetData(
|
||||
setData,
|
||||
sheetName,
|
||||
|
|
|
@ -160,6 +160,7 @@ export async function execute(
|
|||
this: IExecuteFunctions,
|
||||
sheet: GoogleSheet,
|
||||
sheetName: string,
|
||||
sheetId: string,
|
||||
): Promise<INodeExecutionData[]> {
|
||||
const items = this.getInputData();
|
||||
const valueInputMode = this.getNodeParameter('options.cellFormat', 0, 'RAW') as ValueInputOption;
|
||||
|
@ -248,8 +249,9 @@ export async function execute(
|
|||
} else {
|
||||
const valueToMatchOn = this.getNodeParameter('valueToMatchOn', i) as string;
|
||||
|
||||
const fields = (this.getNodeParameter('fieldsUi.values', i, {}) as IDataObject[]).reduce(
|
||||
(acc, entry) => {
|
||||
const fields = (
|
||||
(this.getNodeParameter('fieldsUi.values', i, {}) as IDataObject[]) || []
|
||||
).reduce((acc, entry) => {
|
||||
if (entry.column === 'newColumn') {
|
||||
const columnName = entry.columnName as string;
|
||||
|
||||
|
@ -262,9 +264,7 @@ export async function execute(
|
|||
acc[entry.column as string] = entry.fieldValue as string;
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{} as IDataObject,
|
||||
);
|
||||
}, {} as IDataObject);
|
||||
|
||||
fields[columnToMatchOn] = valueToMatchOn;
|
||||
|
||||
|
@ -300,6 +300,7 @@ export async function execute(
|
|||
await sheet.batchUpdate(updateData, valueInputMode);
|
||||
}
|
||||
if (appendData.length) {
|
||||
await sheet.appendEmptyRowsOrColumns(sheetId, 1, 0);
|
||||
const lastRow = sheetData.length + 1;
|
||||
await sheet.appendSheetData(
|
||||
appendData,
|
||||
|
|
|
@ -247,8 +247,9 @@ export async function execute(
|
|||
} else {
|
||||
const valueToMatchOn = this.getNodeParameter('valueToMatchOn', i) as string;
|
||||
|
||||
const fields = (this.getNodeParameter('fieldsUi.values', i, {}) as IDataObject[]).reduce(
|
||||
(acc, entry) => {
|
||||
const fields = (
|
||||
(this.getNodeParameter('fieldsUi.values', i, {}) as IDataObject[]) || []
|
||||
).reduce((acc, entry) => {
|
||||
if (entry.column === 'newColumn') {
|
||||
const columnName = entry.columnName as string;
|
||||
|
||||
|
@ -261,9 +262,7 @@ export async function execute(
|
|||
acc[entry.column as string] = entry.fieldValue as string;
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{} as IDataObject,
|
||||
);
|
||||
}, {} as IDataObject);
|
||||
|
||||
fields[columnToMatchOn] = valueToMatchOn;
|
||||
|
||||
|
|
|
@ -187,6 +187,43 @@ export class GoogleSheet {
|
|||
return response;
|
||||
}
|
||||
|
||||
async appendEmptyRowsOrColumns(sheetId: string, rowsToAdd = 1, columnsToAdd = 1) {
|
||||
const requests: IDataObject[] = [];
|
||||
|
||||
if (rowsToAdd > 0) {
|
||||
requests.push({
|
||||
appendDimension: {
|
||||
sheetId,
|
||||
dimension: 'ROWS',
|
||||
length: rowsToAdd,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (columnsToAdd > 0) {
|
||||
requests.push({
|
||||
appendDimension: {
|
||||
sheetId,
|
||||
dimension: 'COLUMNS',
|
||||
length: columnsToAdd,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (requests.length === 0) {
|
||||
throw new Error('Must specify at least one column or row to add');
|
||||
}
|
||||
|
||||
const response = await apiRequest.call(
|
||||
this.executeFunctions,
|
||||
'POST',
|
||||
`/v4/spreadsheets/${this.id}:batchUpdate`,
|
||||
{ requests },
|
||||
);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the cell values
|
||||
*/
|
||||
|
|
|
@ -6,56 +6,51 @@ import {
|
|||
NodeOperationError,
|
||||
} from 'n8n-workflow';
|
||||
import { ResourceLocator } from '../helpers/GoogleSheets.types';
|
||||
import { getSpreadsheetId, sortLoadOptions } from '../helpers/GoogleSheets.utils';
|
||||
import { apiRequest, apiRequestAllItems } from '../transport';
|
||||
import { getSpreadsheetId } from '../helpers/GoogleSheets.utils';
|
||||
import { apiRequest } from '../transport';
|
||||
|
||||
export async function spreadSheetsSearch(
|
||||
this: ILoadOptionsFunctions,
|
||||
filter?: string,
|
||||
paginationToken?: string,
|
||||
): Promise<INodeListSearchResult> {
|
||||
try {
|
||||
const returnData: INodeListSearchItems[] = [];
|
||||
const query: string[] = [];
|
||||
if (filter) {
|
||||
query.push(`name contains '${filter.replace("'", "\\'")}'`);
|
||||
}
|
||||
query.push("mimeType = 'application/vnd.google-apps.spreadsheet'");
|
||||
|
||||
const qs = {
|
||||
pageSize: 50,
|
||||
orderBy: 'modifiedTime desc',
|
||||
fields: 'nextPageToken, files(id, name, webViewLink)',
|
||||
q: query.join(' and '),
|
||||
pageToken: (paginationToken as string) || undefined,
|
||||
fields: 'nextPageToken, files(id, name, webViewLink)',
|
||||
orderBy: 'name_natural',
|
||||
includeItemsFromAllDrives: true,
|
||||
supportsAllDrives: true,
|
||||
};
|
||||
|
||||
const sheets = await apiRequestAllItems.call(
|
||||
const res = await apiRequest.call(
|
||||
this,
|
||||
'files',
|
||||
'GET',
|
||||
'',
|
||||
{},
|
||||
qs,
|
||||
'https://www.googleapis.com/drive/v3/files',
|
||||
);
|
||||
for (const sheet of sheets) {
|
||||
returnData.push({
|
||||
return {
|
||||
results: res.files.map((sheet: IDataObject) => ({
|
||||
name: sheet.name as string,
|
||||
value: sheet.id as string,
|
||||
url: sheet.webViewLink as string,
|
||||
});
|
||||
}
|
||||
return { results: sortLoadOptions(returnData) };
|
||||
} catch (error) {
|
||||
return { results: [] };
|
||||
}
|
||||
})),
|
||||
paginationToken: res.nextPageToken,
|
||||
};
|
||||
}
|
||||
|
||||
export async function sheetsSearch(
|
||||
this: ILoadOptionsFunctions,
|
||||
_filter?: string,
|
||||
): Promise<INodeListSearchResult> {
|
||||
try {
|
||||
const { mode, value } = this.getNodeParameter('documentId', 0) as IDataObject;
|
||||
const spreadsheetId = getSpreadsheetId(mode as ResourceLocator, value as string);
|
||||
|
||||
|
@ -90,7 +85,4 @@ export async function sheetsSearch(
|
|||
}
|
||||
|
||||
return { results: returnData };
|
||||
} catch (error) {
|
||||
return { results: [] };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import { getSpreadsheetId } from '../helpers/GoogleSheets.utils';
|
|||
import { ResourceLocator } from '../helpers/GoogleSheets.types';
|
||||
|
||||
export async function getSheets(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
try {
|
||||
const { mode, value } = this.getNodeParameter('documentId', 0) as IDataObject;
|
||||
const spreadsheetId = getSpreadsheetId(mode as ResourceLocator, value as string);
|
||||
|
||||
|
@ -33,15 +32,11 @@ export async function getSheets(this: ILoadOptionsFunctions): Promise<INodePrope
|
|||
}
|
||||
|
||||
return returnData;
|
||||
} catch (error) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export async function getSheetHeaderRow(
|
||||
this: ILoadOptionsFunctions,
|
||||
): Promise<INodePropertyOptions[]> {
|
||||
try {
|
||||
const { mode, value } = this.getNodeParameter('documentId', 0) as IDataObject;
|
||||
const spreadsheetId = getSpreadsheetId(mode as ResourceLocator, value as string);
|
||||
|
||||
|
@ -73,9 +68,6 @@ export async function getSheetHeaderRow(
|
|||
}
|
||||
|
||||
return returnData;
|
||||
} catch (error) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export async function getSheetHeaderRowAndAddColumn(
|
||||
|
|
|
@ -52,11 +52,10 @@ export async function apiRequest(
|
|||
);
|
||||
|
||||
options.headers!.Authorization = `Bearer ${access_token}`;
|
||||
//@ts-ignore
|
||||
return await this.helpers.request(options);
|
||||
|
||||
return await this.helpers.request!(options);
|
||||
} else {
|
||||
//@ts-ignore
|
||||
return await this.helpers.requestOAuth2.call(this, 'googleSheetsOAuth2Api', options);
|
||||
return await this.helpers.requestOAuth2!.call(this, 'googleSheetsOAuth2Api', options);
|
||||
}
|
||||
} catch (error) {
|
||||
if (error.code === 'ERR_OSSL_PEM_NO_START_LINE') {
|
||||
|
@ -151,6 +150,5 @@ export function getAccessToken(
|
|||
json: true,
|
||||
};
|
||||
|
||||
//@ts-ignore
|
||||
return this.helpers.request(options);
|
||||
return this.helpers.request!(options);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue