Add Activepieces integration for workflow automation
- Add Activepieces fork with SmoothSchedule custom piece - Create integrations app with Activepieces service layer - Add embed token endpoint for iframe integration - Create Automations page with embedded workflow builder - Add sidebar visibility fix for embed mode - Add list inactive customers endpoint to Public API - Include SmoothSchedule triggers: event created/updated/cancelled - Include SmoothSchedule actions: create/update/cancel events, list resources/services/customers 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
HttpRequest,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const addWorksheetAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'add_worksheet',
|
||||
description: 'Add a worksheet to a workbook',
|
||||
displayName: 'Add a Worksheet to a Workbook',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_name: Property.ShortText({
|
||||
displayName: 'Worksheet Name',
|
||||
description: 'The name of the new worksheet',
|
||||
required: false,
|
||||
defaultValue: 'Sheet',
|
||||
}),
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbook_id = propsValue['workbook_id'];
|
||||
const worksheet_name = propsValue['worksheet_name'];
|
||||
|
||||
const request: HttpRequest = {
|
||||
method: HttpMethod.POST,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/worksheets`,
|
||||
body: {
|
||||
name: worksheet_name,
|
||||
},
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
};
|
||||
|
||||
const response = await httpClient.sendRequest(request);
|
||||
|
||||
return response.body;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,66 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
HttpRequest,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon, objectToArray } from '../common/common';
|
||||
|
||||
export const appendRowAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'append_row',
|
||||
description: 'Append row of values to a worksheet',
|
||||
displayName: 'Append Row to Worksheet',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
first_row_headers: Property.Checkbox({
|
||||
displayName: 'Does the first row contain headers?',
|
||||
description: 'If the first row is headers',
|
||||
required: true,
|
||||
defaultValue: false,
|
||||
}),
|
||||
values: excelCommon.values,
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook_id'];
|
||||
const worksheetId = propsValue['worksheet_id'];
|
||||
const values = propsValue.first_row_headers
|
||||
? objectToArray(propsValue['values'])
|
||||
: Object.values(propsValue['values'])[0];
|
||||
|
||||
const lastUsedRow = await excelCommon.getLastUsedRow(
|
||||
workbookId,
|
||||
worksheetId,
|
||||
auth['access_token'],
|
||||
);
|
||||
const lastUsedColumn = excelCommon.numberToColumnName(Object.values(values).length);
|
||||
|
||||
const rangeFrom = `A${lastUsedRow + 1}`;
|
||||
const rangeTo = `${lastUsedColumn}${lastUsedRow + 1}`;
|
||||
|
||||
const url = `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/range(address='${rangeFrom}:${rangeTo}')`;
|
||||
|
||||
const requestBody = {
|
||||
values: [values],
|
||||
};
|
||||
|
||||
const request: HttpRequest = {
|
||||
method: HttpMethod.PATCH,
|
||||
url: url,
|
||||
body: requestBody,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
};
|
||||
|
||||
const response = await httpClient.sendRequest(request);
|
||||
return response.body;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../..';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const appendTableRowsAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'append_table_rows',
|
||||
description: 'Append rows to a table',
|
||||
displayName: 'Append Rows to a Table',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
table_id: excelCommon.table_id,
|
||||
values: excelCommon.table_values,
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook_id'];
|
||||
const worksheetId = propsValue['worksheet_id'];
|
||||
const tableId = propsValue['table_id'];
|
||||
const valuesToAppend = [Object.values(propsValue['values'])];
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/tables/${tableId}/rows`,
|
||||
body: {
|
||||
values: valuesToAppend,
|
||||
},
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
});
|
||||
|
||||
return response.body;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,70 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const clearRangeAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'clear_range',
|
||||
displayName: 'Clear Cells by Range',
|
||||
description: 'Clear a block of cells (range) content or formatting.',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
range: Property.ShortText({
|
||||
displayName: 'Range',
|
||||
description:
|
||||
'The range of cells to clear, in A1 notation (e.g., "A1:C5").',
|
||||
required: true
|
||||
}),
|
||||
applyTo: Property.StaticDropdown({
|
||||
displayName: 'Clear Type',
|
||||
description: 'Specify what to clear from the range.',
|
||||
required: true,
|
||||
defaultValue: 'All',
|
||||
options: {
|
||||
options: [
|
||||
{
|
||||
label: 'All (Contents and Formatting)',
|
||||
value: 'All'
|
||||
},
|
||||
{
|
||||
label: 'Contents Only',
|
||||
value: 'Contents'
|
||||
},
|
||||
{
|
||||
label: 'Formats Only',
|
||||
value: 'Formats'
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
},
|
||||
async run(context) {
|
||||
const { workbook_id, worksheet_id, range, applyTo } = context.propsValue;
|
||||
const { access_token } = context.auth;
|
||||
|
||||
if (!/^[A-Z]+[1-9][0-9]*(:[A-Z]+[1-9][0-9]*)?$/.test(range as string)) {
|
||||
throw new Error('Invalid range format. Please use A1 notation (e.g., "A1" or "A1:C5").');
|
||||
}
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/worksheets/${worksheet_id}/range(address='${range}')/clear`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: access_token
|
||||
},
|
||||
body: {
|
||||
applyTo: applyTo
|
||||
}
|
||||
});
|
||||
|
||||
// A successful request returns a 200 OK with no body.
|
||||
return response.body;
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,81 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const clearColumnAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'clear_column',
|
||||
displayName: 'Clear Column by Index',
|
||||
description: 'Clear contents/formatting of a column by its index.',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
column_index: Property.Number({
|
||||
displayName: 'Column Index',
|
||||
description:
|
||||
'The 1-based index of the column to be cleared (e.g., 1 for column A, 2 for column B).',
|
||||
required: true
|
||||
}),
|
||||
applyTo: Property.StaticDropdown({
|
||||
displayName: 'Clear Type',
|
||||
description: 'Specify what to clear from the column.',
|
||||
required: true,
|
||||
defaultValue: 'All',
|
||||
options: {
|
||||
options: [
|
||||
{
|
||||
label: 'All (Contents and Formatting)',
|
||||
value: 'All'
|
||||
},
|
||||
{
|
||||
label: 'Contents Only',
|
||||
value: 'Contents'
|
||||
},
|
||||
{
|
||||
label: 'Formats Only',
|
||||
value: 'Formats'
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
},
|
||||
async run(context) {
|
||||
const { workbook_id, worksheet_id, column_index, applyTo } =
|
||||
context.propsValue;
|
||||
const { access_token } = context.auth;
|
||||
|
||||
if (
|
||||
typeof column_index !== 'number' ||
|
||||
!Number.isInteger(column_index) ||
|
||||
column_index < 1
|
||||
) {
|
||||
throw new Error('Column index must be a positive integer.');
|
||||
}
|
||||
|
||||
// Convert 1-based index to Excel column letter (e.g., 1 -> 'A')
|
||||
const columnLetter = excelCommon.numberToColumnName(column_index);
|
||||
|
||||
// Construct the range address for the entire column, e.g., 'C:C'
|
||||
const columnAddress = `${columnLetter}:${columnLetter}`;
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/worksheets/${worksheet_id}/range(address='${columnAddress}')/clear`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: access_token
|
||||
},
|
||||
body: {
|
||||
applyTo: applyTo
|
||||
}
|
||||
});
|
||||
|
||||
// A successful request returns a 200 OK with no body.
|
||||
return response.body;
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,69 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { httpClient, HttpMethod, AuthenticationType } from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const clearRowAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'clear_row',
|
||||
displayName: 'Clear Row by ID',
|
||||
description: 'Clear contents/formatting of an entire row by its ID.',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
row_id: Property.Number({
|
||||
displayName: 'Row Number',
|
||||
description: 'The number of the row to be cleared (e.g., 5 for the 5th row).',
|
||||
required: true,
|
||||
}),
|
||||
applyTo: Property.StaticDropdown({
|
||||
displayName: "Clear Type",
|
||||
description: "Specify what to clear from the row.",
|
||||
required: true,
|
||||
defaultValue: 'All',
|
||||
options: {
|
||||
options: [
|
||||
{
|
||||
label: 'All (Contents and Formatting)',
|
||||
value: 'All'
|
||||
},
|
||||
{
|
||||
label: 'Contents Only',
|
||||
value: 'Contents'
|
||||
},
|
||||
{
|
||||
label: 'Formats Only',
|
||||
value: 'Formats'
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
},
|
||||
async run(context) {
|
||||
const { workbook_id, worksheet_id, row_id, applyTo } = context.propsValue;
|
||||
const { access_token } = context.auth;
|
||||
|
||||
if (typeof row_id !== 'number' || !Number.isInteger(row_id) || row_id < 1) {
|
||||
throw new Error('Row index must be a positive integer.');
|
||||
}
|
||||
|
||||
|
||||
// Construct the range address for the entire row, e.g., '5:5'
|
||||
const rowAddress = `${row_id}:${row_id}`;
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/worksheets/${worksheet_id}/range(address='${rowAddress}')/clear`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: access_token,
|
||||
},
|
||||
body: {
|
||||
applyTo: applyTo,
|
||||
},
|
||||
});
|
||||
|
||||
// A successful request returns a 200 OK with no body.
|
||||
return response.body;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,54 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const clearWorksheetAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'clear_worksheet',
|
||||
description: 'Clear a worksheet',
|
||||
displayName: 'Clear Worksheet',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
range: Property.ShortText({
|
||||
displayName: 'Range',
|
||||
description:
|
||||
'The range in A1 notation (e.g., A2:B2) to clear in the worksheet, if not provided, clear the entire worksheet',
|
||||
required: false,
|
||||
}),
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook_id'];
|
||||
const worksheetId = propsValue['worksheet_id'];
|
||||
const range = propsValue['range'];
|
||||
|
||||
let url = `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/`;
|
||||
|
||||
// If range is not provided, clear the entire worksheet
|
||||
if (!range) {
|
||||
url += 'usedRange(valuesOnly=true)/clear';
|
||||
} else {
|
||||
url += `range(address = '${range}')/clear`;
|
||||
}
|
||||
|
||||
const request = {
|
||||
method: HttpMethod.POST,
|
||||
url: url,
|
||||
body: {
|
||||
applyTo: 'contents',
|
||||
},
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN as const,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
};
|
||||
|
||||
const response = await httpClient.sendRequest(request);
|
||||
return response.body;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelCommon } from '../common/common';
|
||||
import { excelAuth } from '../../index';
|
||||
|
||||
export const convertToRangeAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'convert_to_range',
|
||||
description: 'Converts a table to a range',
|
||||
displayName: 'Convert to Range',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
table_id: excelCommon.table_id,
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook_id'];
|
||||
const worksheetId = propsValue['worksheet_id'];
|
||||
const tableId = propsValue['table_id'];
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/tables/${tableId}/convertToRange`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
});
|
||||
|
||||
return response.body;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,94 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const createTableAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'create_table',
|
||||
description: 'Create a table in a worksheet',
|
||||
displayName: 'Create Table',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
selectRange: Property.Dropdown({
|
||||
auth: excelAuth,
|
||||
displayName: 'Select Range',
|
||||
description: 'How to select the range for the table',
|
||||
required: true,
|
||||
options: async () => {
|
||||
return {
|
||||
disabled: false,
|
||||
options: [
|
||||
{
|
||||
label: 'Automatically',
|
||||
value: 'auto',
|
||||
},
|
||||
{
|
||||
label: 'Manually',
|
||||
value: 'manual',
|
||||
},
|
||||
],
|
||||
defaultValue: 'auto',
|
||||
};
|
||||
},
|
||||
refreshers: [],
|
||||
}),
|
||||
range: Property.ShortText({
|
||||
displayName: 'Range',
|
||||
description:
|
||||
'The range of cells in A1 notation (e.g., A2:B2) that will be converted to a table',
|
||||
required: false,
|
||||
defaultValue: 'A1:B2',
|
||||
}),
|
||||
hasHeaders: Property.Checkbox({
|
||||
displayName: 'Has Headers',
|
||||
description: 'Whether the range has column labels',
|
||||
required: true,
|
||||
defaultValue: true,
|
||||
}),
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook_id'];
|
||||
const worksheetId = propsValue['worksheet_id'];
|
||||
const selectRange = propsValue['selectRange'];
|
||||
const hasHeaders = propsValue['hasHeaders'];
|
||||
|
||||
let range: string | undefined;
|
||||
if (selectRange === 'auto') {
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/usedRange`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
queryParams: {
|
||||
select: 'address',
|
||||
},
|
||||
});
|
||||
range = response.body['address'].split('!')[1];
|
||||
} else {
|
||||
range = propsValue['range'];
|
||||
}
|
||||
|
||||
const result = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/tables/add`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
body: {
|
||||
address: range,
|
||||
hasHeaders,
|
||||
},
|
||||
});
|
||||
|
||||
return result.body;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,45 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
} from '@activepieces/pieces-common';
|
||||
|
||||
export const createWorkbook = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'createWorkbook',
|
||||
displayName: 'Create Workbook',
|
||||
description: 'Create a new workbook at the specified location',
|
||||
props: {
|
||||
name: Property.ShortText({
|
||||
displayName: "Name",
|
||||
description: "The name of the new workbook",
|
||||
required: true
|
||||
}),
|
||||
parentFolder: excelCommon.parent_folder
|
||||
},
|
||||
async run(context) {
|
||||
const { name, parentFolder } = context.propsValue
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${excelCommon.baseUrl}/${parentFolder === 'root' ? '' : 'items/'}${parentFolder}/children`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: context.auth['access_token'],
|
||||
},
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: {
|
||||
file: {},
|
||||
name: name.endsWith('.xlsx') ? name : `${name}.xlsx`,
|
||||
'@microsoft.graph.conflictBehavior': 'rename'
|
||||
}
|
||||
})
|
||||
|
||||
return response
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,102 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType
|
||||
} from '@activepieces/pieces-common';
|
||||
|
||||
// Define the response type for creating a worksheet for better type-safety
|
||||
interface CreateWorksheetResponse {
|
||||
id: string;
|
||||
name: string;
|
||||
position: number;
|
||||
visibility: string;
|
||||
}
|
||||
|
||||
export const createWorksheetAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'create_worksheet',
|
||||
displayName: 'Create Worksheet',
|
||||
description:
|
||||
'Add a new worksheet (tab) to an existing workbook with optional default headers.',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
name: Property.ShortText({
|
||||
displayName: 'Worksheet Name',
|
||||
description:
|
||||
"The name for the new worksheet. If not provided, a default name like 'Sheet1' will be assigned.",
|
||||
required: false
|
||||
}),
|
||||
headers: Property.Array({
|
||||
displayName: 'Headers',
|
||||
description:
|
||||
'Optional: A list of headers to add to the first row. A table will be created from these headers.',
|
||||
required: false
|
||||
})
|
||||
},
|
||||
async run(context) {
|
||||
const { workbook_id, name, headers } = context.propsValue;
|
||||
const { access_token } = context.auth;
|
||||
|
||||
// Step 1: Create the new worksheet
|
||||
const createWorksheetResponse =
|
||||
await httpClient.sendRequest<CreateWorksheetResponse>({
|
||||
method: HttpMethod.POST,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/worksheets/add`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: access_token
|
||||
},
|
||||
body: {
|
||||
// Conditionally add the name property to the request body if it exists
|
||||
...(name ? { name } : {})
|
||||
}
|
||||
});
|
||||
|
||||
const newWorksheetName = createWorksheetResponse.body.name;
|
||||
|
||||
// Step 2: If headers are provided, add them and create a table from them
|
||||
if (headers && Array.isArray(headers) && headers.length > 0) {
|
||||
const headersArray = headers as string[];
|
||||
|
||||
// Calculate the table range, e.g., "A1:C1" for 3 headers
|
||||
const endColumn = excelCommon.numberToColumnName(headersArray.length);
|
||||
const address = `A1:${endColumn}1`;
|
||||
|
||||
// Add the header values to the first row of the new worksheet
|
||||
await httpClient.sendRequest({
|
||||
method: HttpMethod.PATCH,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/worksheets/${newWorksheetName}/range(address='${address}')`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: access_token
|
||||
},
|
||||
body: {
|
||||
values: [headersArray] // Values must be a 2D array
|
||||
}
|
||||
});
|
||||
|
||||
// Create a table from the newly added header range
|
||||
const createTableResponse = await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/worksheets/${newWorksheetName}/tables/add`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: access_token
|
||||
},
|
||||
body: {
|
||||
address: address,
|
||||
hasHeaders: true
|
||||
}
|
||||
});
|
||||
|
||||
// Return the result of the table creation
|
||||
return createTableResponse.body;
|
||||
}
|
||||
|
||||
// If no headers were provided, return the result of the worksheet creation
|
||||
return createWorksheetResponse.body;
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const deleteTableAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'delete_table',
|
||||
description: 'Delete a table from a worksheet',
|
||||
displayName: 'Delete Table',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
table_id: excelCommon.table_id,
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook_id'];
|
||||
const worksheetId = propsValue['worksheet_id'];
|
||||
const tableId = propsValue['table_id'];
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.DELETE,
|
||||
url: `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/tables/${tableId}`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
});
|
||||
|
||||
return response.body;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
HttpRequest,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const deleteWorkbookAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'delete_workbook',
|
||||
description: 'Delete a workbook',
|
||||
displayName: 'Delete Workbook',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook_id'];
|
||||
const accessToken = auth['access_token'];
|
||||
|
||||
const request: HttpRequest = {
|
||||
method: HttpMethod.DELETE,
|
||||
url: `${excelCommon.baseUrl}/items/${workbookId}`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: accessToken,
|
||||
},
|
||||
};
|
||||
|
||||
await httpClient.sendRequest(request);
|
||||
return { success: true };
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const deleteWorksheetAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'delete_worksheet',
|
||||
description: 'Delete a worksheet in a workbook',
|
||||
displayName: 'Delete Worksheet',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook_id'];
|
||||
const worksheetId = propsValue['worksheet_id'];
|
||||
|
||||
const request = {
|
||||
method: HttpMethod.DELETE,
|
||||
url: `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN as const,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
};
|
||||
|
||||
const response = await httpClient.sendRequest(request);
|
||||
return response.body;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,121 @@
|
||||
import {
|
||||
createAction,
|
||||
Property,
|
||||
OAuth2PropertyValue
|
||||
} from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const findRowAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'find_row',
|
||||
displayName: 'Find Row',
|
||||
description:
|
||||
'Locate a row by specifying a lookup column and value (e.g. find a row where “ID” = 123).',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
table_id: excelCommon.table_id,
|
||||
lookup_column: Property.Dropdown({
|
||||
auth: excelAuth,
|
||||
displayName: 'Lookup Column',
|
||||
description: 'The column to search in.',
|
||||
required: true,
|
||||
refreshers: ['workbook_id', 'table_id'],
|
||||
options: async ({ auth, workbook_id, table_id }) => {
|
||||
if (!auth || !workbook_id || !table_id) {
|
||||
return {
|
||||
disabled: true,
|
||||
options: [],
|
||||
placeholder: 'Please select a workbook and table first.'
|
||||
};
|
||||
}
|
||||
const authProp = auth as OAuth2PropertyValue;
|
||||
const response = await httpClient.sendRequest<{
|
||||
value: { id: string; name: string }[];
|
||||
}>({
|
||||
method: HttpMethod.GET,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/tables/${table_id}/columns`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: authProp.access_token
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
disabled: false,
|
||||
options: response.body.value.map((column) => ({
|
||||
label: column.name,
|
||||
value: column.id
|
||||
}))
|
||||
};
|
||||
}
|
||||
}),
|
||||
lookup_value: Property.ShortText({
|
||||
displayName: 'Lookup Value',
|
||||
description: 'The value to find in the lookup column.',
|
||||
required: true
|
||||
})
|
||||
},
|
||||
async run(context) {
|
||||
const { workbook_id, table_id, lookup_column, lookup_value } =
|
||||
context.propsValue;
|
||||
const { access_token } = context.auth;
|
||||
const columnId = lookup_column;
|
||||
|
||||
const sanitizedValue = (lookup_value as string).replace(/'/g, "''");
|
||||
|
||||
// Define the URL to clear the filter, which will be used in the 'finally' block
|
||||
const clearFilterUrl = `${excelCommon.baseUrl}/items/${workbook_id}/workbook/tables/${table_id}/columns/${columnId}/filter/clear`;
|
||||
|
||||
try {
|
||||
// Step 1: Apply the filter to the specified column
|
||||
await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/tables/${table_id}/columns/${columnId}/filter/apply`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: access_token
|
||||
},
|
||||
body: {
|
||||
criteria: {
|
||||
criterion1: `=${sanitizedValue}`,
|
||||
filterOn: 'Custom'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Step 2: Get the visible rows (i.e., the filtered results)
|
||||
const foundRowsResponse = await httpClient.sendRequest<{
|
||||
value: unknown[];
|
||||
}>({
|
||||
method: HttpMethod.GET,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/tables/${table_id}/range/visibleView/rows`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: access_token
|
||||
}
|
||||
});
|
||||
|
||||
// The result is the array of rows that matched the filter
|
||||
return foundRowsResponse.body.value;
|
||||
} finally {
|
||||
// Step 3: Clear the filter to restore the table to its original state.
|
||||
// This runs regardless of whether the previous steps succeeded or failed.
|
||||
await httpClient.sendRequest({
|
||||
method: HttpMethod.POST,
|
||||
url: clearFilterUrl,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: access_token
|
||||
},
|
||||
body: {} // Clear action does not require a body
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,48 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const getRangeAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'get_range',
|
||||
displayName: 'Get Cells in Range',
|
||||
description: 'Retrieve the values in a given cell range (e.g., “A1:C10”).',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
range: Property.ShortText({
|
||||
displayName: 'Range',
|
||||
description:
|
||||
'The range of cells to retrieve, in A1 notation (e.g., "A1:C10").',
|
||||
required: true
|
||||
})
|
||||
},
|
||||
async run(context) {
|
||||
const { workbook_id, worksheet_id, range } = context.propsValue;
|
||||
const { access_token } = context.auth;
|
||||
|
||||
if (!/^[A-Z]+[1-9][0-9]*(:[A-Z]+[1-9][0-9]*)?$/.test(range as string)) {
|
||||
throw new Error(
|
||||
'Invalid range format. Please use A1 notation (e.g., "A1" or "A1:C5").'
|
||||
);
|
||||
}
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/worksheets/${worksheet_id}/range(address='${range}')`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: access_token
|
||||
}
|
||||
});
|
||||
|
||||
// The response body contains the workbookRange object with details
|
||||
// like values, text, formulas, rowCount, etc.
|
||||
return response.body;
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,67 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
HttpError
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
|
||||
export const getRowAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'getRowById',
|
||||
displayName: 'Get Row by ID',
|
||||
description: ' Retrieve the entire content of a row by its row ID.',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
table_id: excelCommon.table_id,
|
||||
row_id: Property.Number({
|
||||
displayName: 'Row ID (Index)',
|
||||
description:
|
||||
'The zero-based index of the row to retrieve (e.g., 0 for the first row, 1 for the second).',
|
||||
required: true
|
||||
})
|
||||
},
|
||||
async run(context) {
|
||||
const { workbook_id, table_id, row_id } = context.propsValue;
|
||||
const { access_token } = context.auth;
|
||||
|
||||
const maxRetries = 3;
|
||||
let attempt = 0;
|
||||
|
||||
while (attempt < maxRetries) {
|
||||
try {
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/tables/${table_id}/rows/itemAt(index=${row_id})`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: access_token
|
||||
}
|
||||
});
|
||||
return response.body;
|
||||
} catch (error) {
|
||||
const httpError = error as HttpError;
|
||||
if (httpError.response?.status === 503 && attempt < maxRetries - 1) {
|
||||
const delayMs = 2 ** attempt * 1000;
|
||||
console.warn(
|
||||
`Excel API is unavailable (503). Retrying after ${delayMs}ms... (Attempt ${
|
||||
attempt + 1
|
||||
}/${maxRetries})`
|
||||
);
|
||||
await delay(delayMs);
|
||||
attempt++;
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new Error(
|
||||
'Failed to retrieve row after multiple retries due to API unavailability.'
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { excelCommon } from '../common/common';
|
||||
import { excelAuth } from '../..';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
} from '@activepieces/pieces-common';
|
||||
|
||||
export const getTableColumnsAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'get_table_columns',
|
||||
description: 'List columns of a table in a worksheet',
|
||||
displayName: 'Get Table Columns',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
table: excelCommon.table_id,
|
||||
limit: Property.Number({
|
||||
displayName: 'Limit',
|
||||
description: 'Limit the number of columns retrieved',
|
||||
required: false,
|
||||
}),
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook_id'];
|
||||
const worksheetId = propsValue['worksheet_id'];
|
||||
const tableId = propsValue['table'];
|
||||
const limit = propsValue['limit'];
|
||||
|
||||
let url = `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/tables/${tableId}/columns`;
|
||||
|
||||
if (limit) {
|
||||
url += `?$top=${limit}`;
|
||||
}
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: url,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
});
|
||||
|
||||
const columnNames = response.body['value'].map(
|
||||
(column: { name: any }) => column.name
|
||||
);
|
||||
|
||||
return columnNames;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { excelCommon } from '../common/common';
|
||||
import { excelAuth } from '../..';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
} from '@activepieces/pieces-common';
|
||||
|
||||
export const getTableRowsAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'get_table_rows',
|
||||
description: 'List rows of a table in a worksheet',
|
||||
displayName: 'Get Table Rows',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
table: excelCommon.table_id,
|
||||
limit: Property.Number({
|
||||
displayName: 'Limit',
|
||||
description: 'Limit the number of rows retrieved',
|
||||
required: false,
|
||||
}),
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook_id'];
|
||||
const worksheetId = propsValue['worksheet_id'];
|
||||
const tableId = propsValue['table'];
|
||||
const limit = propsValue['limit'];
|
||||
|
||||
let url = `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/tables/${tableId}/rows`;
|
||||
|
||||
if (limit) {
|
||||
url += `?$top=${limit}`;
|
||||
}
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: url,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
});
|
||||
|
||||
const rowsValues = response.body['value'].map(
|
||||
(row: { values: any[] }) => row.values[0]
|
||||
);
|
||||
|
||||
return rowsValues;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,56 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const getWorkbooksAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'get_workbooks',
|
||||
description: 'Retrieve a list of workbooks',
|
||||
displayName: 'Get Workbooks',
|
||||
props: {
|
||||
limit: Property.Number({
|
||||
displayName: 'Limit',
|
||||
description:
|
||||
'Limits the number of workbooks returned, returns all workbooks if empty',
|
||||
required: false,
|
||||
}),
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const limit = propsValue['limit'];
|
||||
|
||||
const queryParams: any = {
|
||||
$filter:
|
||||
"file ne null and file/mimeType eq 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'",
|
||||
};
|
||||
|
||||
if (limit !== null && limit !== undefined) {
|
||||
queryParams.$top = limit.toString();
|
||||
}
|
||||
|
||||
const request = {
|
||||
method: HttpMethod.GET,
|
||||
url: `${excelCommon.baseUrl}/root/search(q='.xlsx')`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN as const,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
queryParams: queryParams,
|
||||
};
|
||||
|
||||
const response = await httpClient.sendRequest(request);
|
||||
const workbooks = response.body['value'].map(
|
||||
(item: { id: any; name: any; webUrl: any }) => ({
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
webUrl: item.webUrl,
|
||||
})
|
||||
);
|
||||
|
||||
return workbooks;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
import { createAction } from '@activepieces/pieces-framework';
|
||||
import { httpClient, HttpMethod, AuthenticationType } from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const getWorksheetAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'get_worksheet',
|
||||
displayName: 'Get Worksheet by ID',
|
||||
description: 'Retrieve metadata of a worksheet by its ID.',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id, // This dropdown provides the worksheet name as its value
|
||||
},
|
||||
async run(context) {
|
||||
const { workbook_id, worksheet_id } = context.propsValue;
|
||||
const { access_token } = context.auth;
|
||||
|
||||
// The worksheet_id prop from excelCommon returns the worksheet's name,
|
||||
// which can be used to identify it in the API URL as per the documentation ({id|name}).
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/worksheets/${worksheet_id}`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: access_token,
|
||||
},
|
||||
});
|
||||
|
||||
// The response body contains the workbookWorksheet object with its metadata.
|
||||
return response.body;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,73 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelCommon } from '../common/common';
|
||||
import { excelAuth } from '../../index';
|
||||
|
||||
export const getWorksheetRowsAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'get_worksheet_rows',
|
||||
description: 'Retrieve rows from a worksheet',
|
||||
displayName: 'Get Worksheet Rows',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
range: Property.ShortText({
|
||||
displayName: 'Range',
|
||||
description: 'Range of the rows to retrieve (e.g., A2:B2)',
|
||||
required: false,
|
||||
}),
|
||||
headerRow: Property.Number({
|
||||
displayName: 'Header Row',
|
||||
description: 'Row number of the header',
|
||||
required: false,
|
||||
}),
|
||||
firstDataRow: Property.Number({
|
||||
displayName: 'First Data Row',
|
||||
description: 'Row number of the first data row',
|
||||
required: false,
|
||||
}),
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook_id'];
|
||||
const worksheetId = propsValue['worksheet_id'];
|
||||
const range = propsValue['range'];
|
||||
const headerRow = propsValue['headerRow'];
|
||||
const firstDataRow = propsValue['firstDataRow'];
|
||||
|
||||
let url = `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/`;
|
||||
|
||||
if (!range) {
|
||||
url += 'usedRange(valuesOnly=true)';
|
||||
} else {
|
||||
url += `range(address = '${range}')`;
|
||||
}
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: url,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
});
|
||||
|
||||
const rows = response.body['values'];
|
||||
if (headerRow && firstDataRow) {
|
||||
return rows.slice(firstDataRow - 1).map((row: any[]) => {
|
||||
const obj: { [key: string]: any } = {};
|
||||
rows[headerRow - 1].forEach(
|
||||
(header: any, colIndex: string | number) => {
|
||||
obj[String(header)] = row[Number(colIndex)];
|
||||
}
|
||||
);
|
||||
return obj;
|
||||
});
|
||||
}
|
||||
|
||||
return rows;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,59 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { httpClient, HttpMethod } from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const getWorksheetsAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'get_worksheets',
|
||||
description: 'Retrieve worksheets from a workbook',
|
||||
displayName: 'Get Worksheets',
|
||||
props: {
|
||||
workbook: excelCommon.workbook_id,
|
||||
returnAll: Property.Checkbox({
|
||||
displayName: 'Return All',
|
||||
description: 'If checked, all worksheets will be returned',
|
||||
required: false,
|
||||
defaultValue: false,
|
||||
}),
|
||||
limit: Property.Number({
|
||||
displayName: 'Limit',
|
||||
description: 'Limit the number of worksheets returned',
|
||||
required: false,
|
||||
defaultValue: 10,
|
||||
}),
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook'];
|
||||
const returnAll = propsValue['returnAll'];
|
||||
const limit = propsValue['limit'];
|
||||
|
||||
const endpoint = `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets`;
|
||||
const headers = {
|
||||
Authorization: `Bearer ${auth['access_token']}`,
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: endpoint,
|
||||
headers: headers,
|
||||
});
|
||||
|
||||
if (response.status !== 200) {
|
||||
throw new Error(`Failed to retrieve worksheet: ${response.body}`);
|
||||
}
|
||||
|
||||
const worksheets = response.body['value'];
|
||||
|
||||
if (returnAll) {
|
||||
return worksheets;
|
||||
} else {
|
||||
const limitedWorksheets = [];
|
||||
for (let i = 0; i < Math.min(worksheets['length'], limit ?? 0); i++) {
|
||||
limitedWorksheets.push(worksheets[i]);
|
||||
}
|
||||
return limitedWorksheets;
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,88 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType,
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../..';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
export const lookupTableColumnAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'lookup_table_column',
|
||||
description: 'Lookup a value in a table column in a worksheet',
|
||||
displayName: 'Lookup Table Column',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
table_id: excelCommon.table_id,
|
||||
lookup_column: Property.ShortText({
|
||||
displayName: 'Lookup Column',
|
||||
description: 'The column name to lookup the value in',
|
||||
required: true,
|
||||
}),
|
||||
lookup_value: Property.ShortText({
|
||||
displayName: 'Lookup Value',
|
||||
description: 'The value to lookup',
|
||||
required: true,
|
||||
}),
|
||||
return_all_matches: Property.Checkbox({
|
||||
displayName: 'Return All Matches',
|
||||
description: 'If checked, all matching rows will be returned',
|
||||
required: false,
|
||||
defaultValue: false,
|
||||
}),
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook_id'];
|
||||
const worksheetId = propsValue['worksheet_id'];
|
||||
const tableName = propsValue['table_id'];
|
||||
const lookupColumn = propsValue['lookup_column'];
|
||||
const lookupValue = propsValue['lookup_value'];
|
||||
const returnAllMatches = propsValue['return_all_matches'];
|
||||
|
||||
const rowsUrl = `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/tables/${tableName}/rows`;
|
||||
const rowsResponse = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: rowsUrl,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
});
|
||||
|
||||
const columnsUrl = `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/tables/${tableName}/columns`;
|
||||
const columnsResponse = await httpClient.sendRequest({
|
||||
method: HttpMethod.GET,
|
||||
url: columnsUrl,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
});
|
||||
|
||||
const columns = columnsResponse.body['value'];
|
||||
const columnIndex = columns.findIndex(
|
||||
(column: any) => column.name === lookupColumn
|
||||
);
|
||||
|
||||
if (columnIndex === -1) {
|
||||
throw new Error(`Column "${lookupColumn}" not found in the table.`);
|
||||
}
|
||||
|
||||
const rows = rowsResponse.body['value'];
|
||||
const matchedRows = rows.filter(
|
||||
(row: any) => row.values[0][columnIndex] === lookupValue
|
||||
);
|
||||
|
||||
const matchedValues = matchedRows.map(
|
||||
(row: { values: any[] }) => row.values[0]
|
||||
);
|
||||
|
||||
if (returnAllMatches) {
|
||||
return matchedValues;
|
||||
} else {
|
||||
return matchedValues[0] || null;
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import {
|
||||
httpClient,
|
||||
HttpMethod,
|
||||
AuthenticationType
|
||||
} from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon } from '../common/common';
|
||||
|
||||
const namingRules = `
|
||||
The new name for the worksheet. The name must adhere to the following rules:
|
||||
- Cannot be blank.
|
||||
- Cannot exceed 31 characters.
|
||||
- Must not contain any of the following characters: \`/\`, \`\\\`, \`?\`, \`*\`, \`:\`, \`[\`, \`]\`.
|
||||
- The name "History" is reserved by Excel and cannot be used.
|
||||
`;
|
||||
|
||||
export const renameWorksheetAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'rename_worksheet',
|
||||
displayName: 'Rename Worksheet',
|
||||
description: 'Change the name of an existing worksheet.',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
new_name: Property.ShortText({
|
||||
displayName: 'New Worksheet Name',
|
||||
description: namingRules,
|
||||
required: true
|
||||
})
|
||||
},
|
||||
async run(context) {
|
||||
const { workbook_id, worksheet_id, new_name } = context.propsValue;
|
||||
const { access_token } = context.auth;
|
||||
|
||||
// The worksheet_id prop from excelCommon returns the worksheet's current name,
|
||||
// which can be used to identify it in the API URL.
|
||||
const response = await httpClient.sendRequest({
|
||||
method: HttpMethod.PATCH,
|
||||
url: `${excelCommon.baseUrl}/items/${workbook_id}/workbook/worksheets/${worksheet_id}`,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN,
|
||||
token: access_token
|
||||
},
|
||||
body: {
|
||||
name: new_name
|
||||
}
|
||||
});
|
||||
|
||||
return response.body;
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,58 @@
|
||||
import { createAction, Property } from '@activepieces/pieces-framework';
|
||||
import { httpClient, HttpMethod, AuthenticationType } from '@activepieces/pieces-common';
|
||||
import { excelAuth } from '../../index';
|
||||
import { excelCommon, objectToArray } from '../common/common';
|
||||
|
||||
export const updateRowAction = createAction({
|
||||
auth: excelAuth,
|
||||
name: 'update_row',
|
||||
description: 'Update a row in a worksheet',
|
||||
displayName: 'Update Worksheet Rows',
|
||||
props: {
|
||||
workbook_id: excelCommon.workbook_id,
|
||||
worksheet_id: excelCommon.worksheet_id,
|
||||
row_number: Property.Number({
|
||||
displayName: 'Row number',
|
||||
description: 'The row number to update',
|
||||
required: true,
|
||||
}),
|
||||
first_row_headers: Property.Checkbox({
|
||||
displayName: 'Does the first row contain headers?',
|
||||
description: 'If the first row is headers',
|
||||
required: true,
|
||||
defaultValue: false,
|
||||
}),
|
||||
values: excelCommon.values,
|
||||
},
|
||||
async run({ propsValue, auth }) {
|
||||
const workbookId = propsValue['workbook_id'];
|
||||
const worksheetId = propsValue['worksheet_id'];
|
||||
const rowNumber = propsValue['row_number'];
|
||||
const values = propsValue.first_row_headers
|
||||
? objectToArray(propsValue['values'])
|
||||
: Object.values(propsValue['values']);
|
||||
|
||||
const requestBody = {
|
||||
values: [values],
|
||||
};
|
||||
|
||||
const lastUsedColumn = excelCommon.numberToColumnName(Object.values(values).length);
|
||||
|
||||
const rangeFrom = `A${rowNumber}`;
|
||||
const rangeTo = `${lastUsedColumn}${rowNumber}`;
|
||||
|
||||
const request = {
|
||||
method: HttpMethod.PATCH,
|
||||
url: `${excelCommon.baseUrl}/items/${workbookId}/workbook/worksheets/${worksheetId}/range(address='${rangeFrom}:${rangeTo}')`,
|
||||
body: requestBody,
|
||||
authentication: {
|
||||
type: AuthenticationType.BEARER_TOKEN as const,
|
||||
token: auth['access_token'],
|
||||
},
|
||||
};
|
||||
|
||||
const response = await httpClient.sendRequest(request);
|
||||
|
||||
return response.body;
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user