Skip to content

Commit

Permalink
feat: write cell values action
Browse files Browse the repository at this point in the history
  • Loading branch information
ogp-weeloong committed Jan 15, 2024
1 parent 1ab7837 commit 00df16d
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 1 deletion.
3 changes: 2 additions & 1 deletion packages/backend/src/apps/m365-excel/actions/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import createTableRow from './create-table-row'
import getCellValues from './get-cell-values'
import writeCellValues from './write-cell-values'

export default [createTableRow, getCellValues]
export default [createTableRow, getCellValues, writeCellValues]
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import type { IRawAction } from '@plumber/types'

import { generateStepError } from '@/helpers/generate-step-error'

import WorkbookSession from '../../common/workbook-session'

import { parametersSchema } from './parameters-schema'

const action: IRawAction = {
name: 'Write cell values',
key: 'writeCellValues',
description: "Write values into a spreadsheet's cells",
arguments: [
{
key: 'fileId',
label: 'Excel File',
required: true,
description: 'File to edit',
type: 'dropdown' as const,
variables: false,
source: {
type: 'query' as const,
name: 'getDynamicData' as const,
arguments: [
{
name: 'key',
value: 'listFiles',
},
],
},
},
{
key: 'worksheetId',
label: 'Worksheet',
required: true,
description: 'Worksheet to edit',
type: 'dropdown' as const,
variables: false,
source: {
type: 'query' as const,
name: 'getDynamicData' as const,
arguments: [
{
name: 'key',
value: 'listWorksheets',
},
{
name: 'parameters.fileId',
value: '{parameters.fileId}',
},
],
},
},
{
label: 'Values',
key: 'cells',
type: 'multirow' as const,
required: true,
// We need to make 1 separate request for each cell, so limit to 3 as a
// balance between convenience and API quota usage.
description: 'Specify cells you want to write values to. (Max 3)',
subFields: [
{
label: 'Cell Address (e.g. A1)',
key: 'address',
type: 'string' as const,
required: true,
variables: true,
},
{
label: 'Value',
key: 'value',
type: 'string' as const,
required: true,
variables: true,
},
],
},
],

async run($) {
const parametersParseResult = parametersSchema.safeParse($.step.parameters)

if (parametersParseResult.success === false) {
throw generateStepError(
'Action is set up incorrectly.',
parametersParseResult.error.issues[0].message,
$.step?.position,
$.app.name,
)
}

const { fileId, worksheetId, cells } = parametersParseResult.data
const session = await WorkbookSession.acquire($, fileId)

await Promise.all(
cells.map(async (cell) =>
session.request(
`/worksheets/${worksheetId}/range(address='${cell.address}')`,
'patch',
{
data: {
values: [[cell.value]],
},
},
),
),
)

$.setActionItem({
raw: {
success: true,
},
})
},
}

export default action
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import z from 'zod'

import { CELL_A1_ADDRESS_REGEX } from '../../common/workbook-helpers'

// TODO: We should probably store zod schemas in app / action / trigger
// definitions.
export const parametersSchema = z.object({
fileId: z
.string()
.trim()
.min(1, { message: 'Please choose a file to edit.' }),
worksheetId: z
.string()
.trim()
.min(1, { message: 'Please select a worksheet to edit.' }),
cells: z
.array(
z.object({
address: z
.string()
.trim()
.min(1, {
message: 'Please make sure there are no empty cell addresses.',
})
.refine(
(input) => CELL_A1_ADDRESS_REGEX.test(input),
(input) => ({
message: `Please input cell address '${input}' in A1 notation.`,
}),
),
// Not trimming value; we should write user's input as-is.
value: z.string().nullish(),
}),
)
.min(1)
.max(3, {
message: 'Please write to no more than 3 cells in a single step.',
}),
})
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const CELL_A1_ADDRESS_REGEX = /^[a-zA-Z]+[1-9][0-9]*$/

0 comments on commit 00df16d

Please sign in to comment.