Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion apps/docs/content/docs/en/tools/microsoft_excel.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ In Sim, the Microsoft Excel integration provides seamless access to spreadsheet

## Usage Instructions

Integrate Microsoft Excel into the workflow. Can read, write, update, and add to table.
Integrate Microsoft Excel into the workflow. Can read, write, update, add to table, and create new worksheets.



Expand Down Expand Up @@ -94,6 +94,23 @@ Add new rows to a Microsoft Excel table
| `values` | array | Array of rows that were added to the table |
| `metadata` | object | Spreadsheet metadata |

### `microsoft_excel_worksheet_add`

Create a new worksheet (sheet) in a Microsoft Excel workbook

#### Input

| Parameter | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `spreadsheetId` | string | Yes | The ID of the Excel workbook to add the worksheet to |
| `worksheetName` | string | Yes | The name of the new worksheet. Must be unique within the workbook and cannot exceed 31 characters |

#### Output

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `worksheet` | object | Details of the newly created worksheet |



## Notes
Expand Down
47 changes: 43 additions & 4 deletions apps/sim/blocks/blocks/microsoft_excel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const MicrosoftExcelBlock: BlockConfig<MicrosoftExcelResponse> = {
description: 'Read, write, and update data',
authMode: AuthMode.OAuth,
longDescription:
'Integrate Microsoft Excel into the workflow. Can read, write, update, and add to table.',
'Integrate Microsoft Excel into the workflow. Can read, write, update, add to table, and create new worksheets.',
docsLink: 'https://docs.sim.ai/tools/microsoft_excel',
category: 'tools',
bgColor: '#E0E0E0',
Expand All @@ -23,6 +23,7 @@ export const MicrosoftExcelBlock: BlockConfig<MicrosoftExcelResponse> = {
{ label: 'Read Data', id: 'read' },
{ label: 'Write/Update Data', id: 'write' },
{ label: 'Add to Table', id: 'table_add' },
{ label: 'Add Worksheet', id: 'worksheet_add' },
],
value: () => 'read',
},
Expand Down Expand Up @@ -80,6 +81,14 @@ export const MicrosoftExcelBlock: BlockConfig<MicrosoftExcelResponse> = {
condition: { field: 'operation', value: ['table_add'] },
required: true,
},
{
id: 'worksheetName',
title: 'Worksheet Name',
type: 'short-input',
placeholder: 'Name of the new worksheet (max 31 characters)',
condition: { field: 'operation', value: ['worksheet_add'] },
required: true,
},
{
id: 'values',
title: 'Values',
Expand Down Expand Up @@ -129,7 +138,12 @@ export const MicrosoftExcelBlock: BlockConfig<MicrosoftExcelResponse> = {
},
],
tools: {
access: ['microsoft_excel_read', 'microsoft_excel_write', 'microsoft_excel_table_add'],
access: [
'microsoft_excel_read',
'microsoft_excel_write',
'microsoft_excel_table_add',
'microsoft_excel_worksheet_add',
],
config: {
tool: (params) => {
switch (params.operation) {
Expand All @@ -139,13 +153,22 @@ export const MicrosoftExcelBlock: BlockConfig<MicrosoftExcelResponse> = {
return 'microsoft_excel_write'
case 'table_add':
return 'microsoft_excel_table_add'
case 'worksheet_add':
return 'microsoft_excel_worksheet_add'
default:
throw new Error(`Invalid Microsoft Excel operation: ${params.operation}`)
}
},
params: (params) => {
const { credential, values, spreadsheetId, manualSpreadsheetId, tableName, ...rest } =
params
const {
credential,
values,
spreadsheetId,
manualSpreadsheetId,
tableName,
worksheetName,
...rest
} = params

const effectiveSpreadsheetId = (spreadsheetId || manualSpreadsheetId || '').trim()

Expand All @@ -164,6 +187,10 @@ export const MicrosoftExcelBlock: BlockConfig<MicrosoftExcelResponse> = {
throw new Error('Table name is required for table operations.')
}

if (params.operation === 'worksheet_add' && !worksheetName) {
throw new Error('Worksheet name is required for worksheet operations.')
}

const baseParams = {
...rest,
spreadsheetId: effectiveSpreadsheetId,
Expand All @@ -178,6 +205,13 @@ export const MicrosoftExcelBlock: BlockConfig<MicrosoftExcelResponse> = {
}
}

if (params.operation === 'worksheet_add') {
return {
...baseParams,
worksheetName,
}
}

return baseParams
},
},
Expand All @@ -189,6 +223,7 @@ export const MicrosoftExcelBlock: BlockConfig<MicrosoftExcelResponse> = {
manualSpreadsheetId: { type: 'string', description: 'Manual spreadsheet identifier' },
range: { type: 'string', description: 'Cell range' },
tableName: { type: 'string', description: 'Table name' },
worksheetName: { type: 'string', description: 'Worksheet name' },
values: { type: 'string', description: 'Cell values data' },
valueInputOption: { type: 'string', description: 'Value input option' },
},
Expand All @@ -207,5 +242,9 @@ export const MicrosoftExcelBlock: BlockConfig<MicrosoftExcelResponse> = {
},
index: { type: 'number', description: 'Row index for table add operations' },
values: { type: 'json', description: 'Cell values array for table add operations' },
worksheet: {
type: 'json',
description: 'Details of the newly created worksheet (worksheet_add operations)',
},
},
}
2 changes: 2 additions & 0 deletions apps/sim/tools/microsoft_excel/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { readTool } from '@/tools/microsoft_excel/read'
import { tableAddTool } from '@/tools/microsoft_excel/table_add'
import { worksheetAddTool } from '@/tools/microsoft_excel/worksheet_add'
import { writeTool } from '@/tools/microsoft_excel/write'

export const microsoftExcelReadTool = readTool
export const microsoftExcelTableAddTool = tableAddTool
export const microsoftExcelWorksheetAddTool = worksheetAddTool
export const microsoftExcelWriteTool = writeTool
19 changes: 19 additions & 0 deletions apps/sim/tools/microsoft_excel/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@ export interface MicrosoftExcelTableAddResponse extends ToolResponse {
}
}

export interface MicrosoftExcelWorksheetAddResponse extends ToolResponse {
output: {
worksheet: {
id: string
name: string
position: number
visibility: string
}
metadata: MicrosoftExcelMetadata
}
}

export interface MicrosoftExcelToolParams {
accessToken: string
spreadsheetId: string
Expand All @@ -68,7 +80,14 @@ export interface MicrosoftExcelTableToolParams {
rowIndex?: number
}

export interface MicrosoftExcelWorksheetToolParams {
accessToken: string
spreadsheetId: string
worksheetName: string
}

export type MicrosoftExcelResponse =
| MicrosoftExcelReadResponse
| MicrosoftExcelWriteResponse
| MicrosoftExcelTableAddResponse
| MicrosoftExcelWorksheetAddResponse
161 changes: 161 additions & 0 deletions apps/sim/tools/microsoft_excel/worksheet_add.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import type {
MicrosoftExcelWorksheetAddResponse,
MicrosoftExcelWorksheetToolParams,
} from '@/tools/microsoft_excel/types'
import { getSpreadsheetWebUrl } from '@/tools/microsoft_excel/utils'
import type { ToolConfig } from '@/tools/types'

/**
* Tool for adding a new worksheet to a Microsoft Excel workbook
* Uses Microsoft Graph API endpoint: POST /me/drive/items/{id}/workbook/worksheets/add
*/
export const worksheetAddTool: ToolConfig<
MicrosoftExcelWorksheetToolParams,
MicrosoftExcelWorksheetAddResponse
> = {
id: 'microsoft_excel_worksheet_add',
name: 'Add Worksheet to Microsoft Excel',
description: 'Create a new worksheet (sheet) in a Microsoft Excel workbook',
version: '1.0',

oauth: {
required: true,
provider: 'microsoft-excel',
},

params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'The access token for the Microsoft Excel API',
},
spreadsheetId: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'The ID of the Excel workbook to add the worksheet to',
},
worksheetName: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description:
'The name of the new worksheet. Must be unique within the workbook and cannot exceed 31 characters',
},
},

request: {
url: (params) => {
const spreadsheetId = params.spreadsheetId?.trim()
if (!spreadsheetId) {
throw new Error('Spreadsheet ID is required')
}
return `https://graph.microsoft.com/v1.0/me/drive/items/${spreadsheetId}/workbook/worksheets/add`
},
method: 'POST',
headers: (params) => {
if (!params.accessToken) {
throw new Error('Access token is required')
}

return {
Authorization: `Bearer ${params.accessToken}`,
'Content-Type': 'application/json',
}
},
body: (params) => {
const worksheetName = params.worksheetName?.trim()

if (!worksheetName) {
throw new Error('Worksheet name is required')
}

// Validate worksheet name length (Excel limitation)
if (worksheetName.length > 31) {
throw new Error('Worksheet name cannot exceed 31 characters. Please provide a shorter name')
}

// Validate worksheet name doesn't contain invalid characters
const invalidChars = ['\\', '/', '?', '*', '[', ']', ':']
for (const char of invalidChars) {
if (worksheetName.includes(char)) {
throw new Error(`Worksheet name cannot contain the following characters: \\ / ? * [ ] :`)
}
}

return {
name: worksheetName,
}
},
},

transformResponse: async (response: Response, params?: MicrosoftExcelWorksheetToolParams) => {
if (!response.ok) {
const errorData = await response.json().catch(() => ({}))
const errorMessage =
errorData?.error?.message || `Failed to create worksheet: ${response.statusText}`

// Handle specific error cases
if (response.status === 409) {
throw new Error('A worksheet with this name already exists. Please choose a different name')
}

throw new Error(errorMessage)
}

const data = await response.json()

const urlParts = response.url.split('/drive/items/')
const spreadsheetId = urlParts[1]?.split('/')[0] || ''

// Fetch the browser-accessible web URL
const accessToken = params?.accessToken
if (!accessToken) {
throw new Error('Access token is required')
}
const webUrl = await getSpreadsheetWebUrl(spreadsheetId, accessToken)

const result: MicrosoftExcelWorksheetAddResponse = {
success: true,
output: {
worksheet: {
id: data.id || '',
name: data.name || '',
position: data.position ?? 0,
visibility: data.visibility || 'Visible',
},
metadata: {
spreadsheetId,
spreadsheetUrl: webUrl,
},
},
}

return result
},

outputs: {
worksheet: {
type: 'object',
description: 'Details of the newly created worksheet',
properties: {
id: { type: 'string', description: 'The unique ID of the worksheet' },
name: { type: 'string', description: 'The name of the worksheet' },
position: { type: 'number', description: 'The zero-based position of the worksheet' },
visibility: {
type: 'string',
description: 'The visibility state of the worksheet (Visible/Hidden/VeryHidden)',
},
},
},
metadata: {
type: 'object',
description: 'Spreadsheet metadata',
properties: {
spreadsheetId: { type: 'string', description: 'The ID of the spreadsheet' },
spreadsheetUrl: { type: 'string', description: 'URL to access the spreadsheet' },
},
},
},
}
2 changes: 2 additions & 0 deletions apps/sim/tools/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ import { memoryAddTool, memoryDeleteTool, memoryGetAllTool, memoryGetTool } from
import {
microsoftExcelReadTool,
microsoftExcelTableAddTool,
microsoftExcelWorksheetAddTool,
microsoftExcelWriteTool,
} from '@/tools/microsoft_excel'
import {
Expand Down Expand Up @@ -1172,6 +1173,7 @@ export const tools: Record<string, ToolConfig> = {
microsoft_excel_read: microsoftExcelReadTool,
microsoft_excel_write: microsoftExcelWriteTool,
microsoft_excel_table_add: microsoftExcelTableAddTool,
microsoft_excel_worksheet_add: microsoftExcelWorksheetAddTool,
microsoft_planner_create_task: microsoftPlannerCreateTaskTool,
microsoft_planner_read_task: microsoftPlannerReadTaskTool,
microsoft_planner_update_task: microsoftPlannerUpdateTaskTool,
Expand Down