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
text/typescript
/**
* 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);
}
};