UNPKG

aspose.cells.mcp

Version:

Excel MCP - AI-powered Excel automation server for Excel AI, Excel Formula MCP, spreadsheets MCP, and Excel automation using Aspose.Cells for Node.js

297 lines (268 loc) 10.4 kB
/** * Row Column Operations Services - Refactored into three focused services */ import { getAbsolutePath, handleExcelFileError } from '../core/utils.js'; // Shared interfaces and utilities interface ServiceResponse { content: Array<{ type: 'text'; text: string; }>; [key: string]: unknown; } /** * Parse row range string to array of row indices */ function parseRowRange(rowRange: string): number[] { if (rowRange.includes(':')) { const [start, end] = rowRange.split(':').map(r => parseInt(r) - 1); return Array.from({ length: end - start + 1 }, (_, i) => start + i); } return [parseInt(rowRange) - 1]; } /** * Parse column range string to array of column indices */ function parseColumnRange(columnRange: string): number[] { const columnToIndex = (col: string): number => { let result = 0; for (let i = 0; i < col.length; i++) { result = result * 26 + (col.charCodeAt(i) - 'A'.charCodeAt(0) + 1); } return result - 1; }; if (columnRange.includes(':')) { const [start, end] = columnRange.split(':'); const startIndex = columnToIndex(start); const endIndex = columnToIndex(end); return Array.from({ length: endIndex - startIndex + 1 }, (_, i) => startIndex + i); } return [columnToIndex(columnRange)]; } /** * Shared handler for all row/column operations */ async function handleRowColumnOperation( filepath: string, sheet_name: string, operation: string, target: string, count?: number, size?: number ): Promise<ServiceResponse> { let fullPath: string = ''; try { const AsposeCells = await import('aspose.cells.node').then(m => m.default); fullPath = getAbsolutePath(filepath); const workbook = new AsposeCells.Workbook(fullPath); const worksheet = workbook.getWorksheets().get(sheet_name); if (!worksheet) { throw new Error(`Sheet "${sheet_name}" not found`); } const cells = worksheet.getCells(); let result: string; switch (operation) { // Insert/Delete operations case 'insert_rows': const insertRowIndex = parseInt(target.split(':')[0]) - 1; const insertRowCount = count || 1; cells.insertRows(insertRowIndex, insertRowCount); result = `Inserted ${insertRowCount} row(s) at row ${target}`; break; case 'delete_rows': const deleteRowIndexes = parseRowRange(target); deleteRowIndexes.reverse().forEach(rowIndex => { cells.deleteRows(rowIndex, 1); }); result = `Deleted row(s) ${target}`; break; case 'insert_columns': const insertColIndex = parseColumnRange(target.split(':')[0])[0]; const insertColCount = count || 1; cells.insertColumns(insertColIndex, insertColCount); result = `Inserted ${insertColCount} column(s) at column ${target}`; break; case 'delete_columns': const deleteColIndexes = parseColumnRange(target); deleteColIndexes.reverse().forEach(colIndex => { cells.deleteColumns(colIndex, 1, false); }); result = `Deleted column(s) ${target}`; break; // Resize operations case 'set_row_height': if (size === undefined) throw new Error('size parameter required for set_row_height'); const rowIndexes = parseRowRange(target); rowIndexes.forEach(rowIndex => { cells.setRowHeight(rowIndex, size); }); result = `Set row height to ${size}pt for rows ${target}`; break; case 'set_column_width': if (size === undefined) throw new Error('size parameter required for set_column_width'); const columnIndexes = parseColumnRange(target); columnIndexes.forEach(colIndex => { cells.setColumnWidth(colIndex, size); }); result = `Set column width to ${size} for columns ${target}`; break; case 'auto_fit_rows': const autoFitRowIndexes = parseRowRange(target); autoFitRowIndexes.forEach(rowIndex => { worksheet.autoFitRow(rowIndex); }); result = `Auto-fitted row height for rows ${target}`; break; case 'auto_fit_columns': const autoFitColIndexes = parseColumnRange(target); autoFitColIndexes.forEach(colIndex => { worksheet.autoFitColumn(colIndex); }); result = `Auto-fitted column width for columns ${target}`; break; // Visibility operations case 'hide_rows': const hideRowIndexes = parseRowRange(target); hideRowIndexes.forEach(rowIndex => { cells.setRowHeight(rowIndex, 0); }); result = `Hidden rows ${target}`; break; case 'unhide_rows': const unhideRowIndexes = parseRowRange(target); unhideRowIndexes.forEach(rowIndex => { cells.setRowHeight(rowIndex, 15); }); result = `Unhidden rows ${target}`; break; case 'hide_columns': const hideColIndexes = parseColumnRange(target); hideColIndexes.forEach(colIndex => { cells.setColumnWidth(colIndex, 0); }); result = `Hidden columns ${target}`; break; case 'unhide_columns': const unhideColIndexes = parseColumnRange(target); unhideColIndexes.forEach(colIndex => { cells.setColumnWidth(colIndex, 8.5); }); result = `Unhidden columns ${target}`; break; default: throw new Error(`Unknown operation: ${operation}`); } workbook.save(fullPath); return { content: [{ type: 'text', text: result }] }; } catch (error) { const err = error instanceof Error ? error : new Error(String(error)); handleExcelFileError(err, fullPath || filepath, filepath, `performing ${operation} operation`); } } // 1. Insert/Delete Rows and Columns Service export const insertDeleteService = { definition: { name: 'insert_delete_rows_columns', description: 'Insert or delete rows and columns', inputSchema: { type: 'object', properties: { filepath: { type: 'string', description: 'Path to the Excel file' }, sheet_name: { type: 'string', description: 'Name of the worksheet' }, operation: { type: 'string', enum: ['insert_rows', 'delete_rows', 'insert_columns', 'delete_columns'], description: `Insert/Delete operation type: - insert_rows: Insert new rows at specified position - delete_rows: Delete specified rows - insert_columns: Insert new columns at specified position - delete_columns: Delete specified columns` }, target: { type: 'string', description: 'Target rows (e.g., "1" or "1:3") or columns (e.g., "A" or "A:C")' }, count: { type: 'number', description: 'Number of rows/columns to insert (for insert operations)', default: 1 } }, required: ['filepath', 'sheet_name', 'operation', 'target'] } }, async handler(args: { filepath: string; sheet_name: string; operation: string; target: string; count?: number }): Promise<ServiceResponse> { return handleRowColumnOperation(args.filepath, args.sheet_name, args.operation, args.target, args.count); } }; // 2. Resize Rows and Columns Service export const resizeService = { definition: { name: 'resize_rows_columns', description: 'Set row height, column width, or auto-fit rows/columns', inputSchema: { type: 'object', properties: { filepath: { type: 'string', description: 'Path to the Excel file' }, sheet_name: { type: 'string', description: 'Name of the worksheet' }, operation: { type: 'string', enum: ['set_row_height', 'set_column_width', 'auto_fit_rows', 'auto_fit_columns'], description: `Resize operation type: - set_row_height: Set specific row height in points - set_column_width: Set specific column width in characters - auto_fit_rows: Auto-fit row height to content - auto_fit_columns: Auto-fit column width to content` }, target: { type: 'string', description: 'Target rows (e.g., "1" or "1:3") or columns (e.g., "A" or "A:C")' }, size: { type: 'number', description: 'Height in points (for rows) or width in characters (for columns)' } }, required: ['filepath', 'sheet_name', 'operation', 'target'] } }, async handler(args: { filepath: string; sheet_name: string; operation: string; target: string; size?: number }): Promise<ServiceResponse> { return handleRowColumnOperation(args.filepath, args.sheet_name, args.operation, args.target, undefined, args.size); } }; // 3. Hide/Unhide Rows and Columns Service export const visibilityService = { definition: { name: 'hide_unhide_rows_columns', description: 'Hide or unhide rows and columns', inputSchema: { type: 'object', properties: { filepath: { type: 'string', description: 'Path to the Excel file' }, sheet_name: { type: 'string', description: 'Name of the worksheet' }, operation: { type: 'string', enum: ['hide_rows', 'unhide_rows', 'hide_columns', 'unhide_columns'], description: `Visibility operation type: - hide_rows: Hide specified rows - unhide_rows: Show previously hidden rows - hide_columns: Hide specified columns - unhide_columns: Show previously hidden columns` }, target: { type: 'string', description: 'Target rows (e.g., "1" or "1:3") or columns (e.g., "A" or "A:C")' } }, required: ['filepath', 'sheet_name', 'operation', 'target'] } }, async handler(args: { filepath: string; sheet_name: string; operation: string; target: string }): Promise<ServiceResponse> { return handleRowColumnOperation(args.filepath, args.sheet_name, args.operation, args.target); } };