excel_read
Convert Excel files to structured JSON format to extract and process spreadsheet data programmatically.
Instructions
Read Excel file and convert to JSON format while preserving structure
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| inputPath | Yes | Path to the input Excel file | |
| includeHeaders | No | Whether to include headers in the output |
Implementation Reference
- src/tools/excelTools.ts:107-166 (handler)The async handler function that implements the core logic for reading Excel files, parsing sheets into JSON structure, handling headers, and returning success/error responses.
export async function readExcelFile(inputPath: string, includeHeaders: boolean = true) { try { // 驗證檔案存在 if (!fs.existsSync(inputPath)) { return { success: false, error: `File not found: ${inputPath}`, }; } // 驗證檔案副檔名 const ext = path.extname(inputPath).toLowerCase(); if (ext !== ".xlsx" && ext !== ".xls") { return { success: false, error: `Unsupported file format: ${ext}`, }; } console.log(`Reading Excel file: ${inputPath}`); const workbook = new ExcelJS.Workbook(); await workbook.xlsx.readFile(inputPath); const result: Record<string, any[]> = {}; workbook.worksheets.forEach((worksheet) => { const sheetName = worksheet.name; const rows: any[] = []; worksheet.eachRow((row, rowNumber) => { const rowData: Record<number, any> = {}; row.eachCell((cell, colNumber) => { if (includeHeaders && rowNumber === 1) { rows.push(cell.value); } else { rowData[colNumber] = cell.value; } }); if (rowNumber > 1 || !includeHeaders) { rows.push(rowData); } }); result[sheetName] = rows; }); console.log(`Successfully parsed Excel file: ${inputPath}`); return { success: true, data: result, }; } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : "Unknown error occurred"; console.error(`Error processing Excel file: ${errorMessage}`); return { success: false, error: errorMessage, }; } } - src/tools/excelTools.ts:15-43 (schema)Tool definition with inputSchema, TypeScript interface for args, and runtime validator function isExcelReadArgs.
export const EXCEL_READ_TOOL: Tool = { name: "excel_read", description: "Read Excel file and convert to JSON format while preserving structure", inputSchema: { type: "object", properties: { inputPath: { type: "string", description: "Path to the input Excel file", }, includeHeaders: { type: "boolean", description: "Whether to include headers in the output", default: true, }, }, required: ["inputPath"], }, }; export interface ExcelReadArgs { inputPath: string; includeHeaders?: boolean; } // 類型檢查函數 export function isExcelReadArgs(args: unknown): args is ExcelReadArgs { return typeof args === "object" && args !== null && "inputPath" in args && typeof (args as ExcelReadArgs).inputPath === "string" && (typeof (args as ExcelReadArgs).includeHeaders === "undefined" || typeof (args as ExcelReadArgs).includeHeaders === "boolean"); } - src/tools/_index.ts:3-9 (registration)Imports EXCEL_READ_TOOL and includes it in the exported tools array used for MCP ListTools response.
import { EXCEL_READ_TOOL } from "./excelTools.js"; import { FORMAT_CONVERTER_TOOL } from "./formatConverterPlus.js"; import { HTML_CLEAN_TOOL, HTML_EXTRACT_RESOURCES_TOOL, HTML_FORMAT_TOOL, HTML_TO_MARKDOWN_TOOL, HTML_TO_TEXT_TOOL } from "./htmlTools.js"; import { PDF_MERGE_TOOL, PDF_SPLIT_TOOL } from "./pdfTools.js"; import { TEXT_DIFF_TOOL, TEXT_ENCODING_CONVERT_TOOL, TEXT_FORMAT_TOOL, TEXT_SPLIT_TOOL } from "./txtTools.js"; export const tools = [DOCUMENT_READER_TOOL, PDF_MERGE_TOOL, PDF_SPLIT_TOOL, DOCX_TO_PDF_TOOL, DOCX_TO_HTML_TOOL, HTML_CLEAN_TOOL, HTML_TO_TEXT_TOOL, HTML_TO_MARKDOWN_TOOL, HTML_EXTRACT_RESOURCES_TOOL, HTML_FORMAT_TOOL, TEXT_DIFF_TOOL, TEXT_SPLIT_TOOL, TEXT_FORMAT_TOOL, TEXT_ENCODING_CONVERT_TOOL, EXCEL_READ_TOOL, FORMAT_CONVERTER_TOOL]; - src/tools/excelTools.ts:15-33 (registration)Exports the partial Tool object for excel_read which is included in the tools list.
export const EXCEL_READ_TOOL: Tool = { name: "excel_read", description: "Read Excel file and convert to JSON format while preserving structure", inputSchema: { type: "object", properties: { inputPath: { type: "string", description: "Path to the input Excel file", }, includeHeaders: { type: "boolean", description: "Whether to include headers in the output", default: true, }, }, required: ["inputPath"], }, }; - src/tools/excelTools.ts:48-104 (helper)Supporting static class method for reading Excel files, similar to the main handler but without the success/error wrapper and with additional options.
export class ExcelTools { /** * Reads an Excel file and returns its content as JSON * @param filePath Path to the Excel file * @param options Processing options * @returns Promise resolving to the parsed Excel data */ public static async readExcelFile(filePath: string, options: ExcelProcessOptions = { includeHeaders: true }): Promise<any> { try { // Verify file exists if (!fs.existsSync(filePath)) { throw new Error(`File not found: ${filePath}`); } // Verify file extension const ext = path.extname(filePath).toLowerCase(); if (ext !== ".xlsx" && ext !== ".xls") { throw new Error(`Unsupported file format: ${ext}`); } console.log(`Reading Excel file: ${filePath}`); const workbook = new ExcelJS.Workbook(); await workbook.xlsx.readFile(filePath); const result: any = {}; workbook.worksheets.forEach((worksheet) => { const sheetName = worksheet.name; const rows: any[] = []; worksheet.eachRow((row, rowNumber) => { const rowData: any = {}; row.eachCell((cell, colNumber) => { if (options.includeHeaders && rowNumber === 1) { // Handle headers rows.push(cell.value); } else { // Handle data rows rowData[colNumber] = cell.value; } }); if (rowNumber > 1 || !options.includeHeaders) { rows.push(rowData); } }); result[sheetName] = rows; }); console.log(`Successfully parsed Excel file: ${filePath}`); return result; } catch (error: any) { console.error(`Error processing Excel file: ${error.message}`); throw error; } } }