Skip to main content
Glama
ExcelAdapter.ts6.41 kB
import { IDocumentAdapter, ApiResponse, Change } from '../types'; import { HttpClient } from './HttpClient'; export class ExcelAdapter implements IDocumentAdapter { private httpClient: HttpClient; constructor() { this.httpClient = new HttpClient(); } async getContent(): Promise<string> { return Excel.run(async (context) => { const worksheet = context.workbook.worksheets.getActiveWorksheet(); const range = worksheet.getUsedRange(); range.load('values'); await context.sync(); return JSON.stringify(range.values); }); } async setContent(content: string): Promise<void> { const data = JSON.parse(content); await Excel.run(async (context) => { const worksheet = context.workbook.worksheets.getActiveWorksheet(); const range = worksheet.getRange('A1').getResizedRange(data.length - 1, data[0].length - 1); range.values = data; await context.sync(); }); } async getSelection(): Promise<string> { return Excel.run(async (context) => { const range = context.workbook.getSelectedRange(); range.load('values'); await context.sync(); return JSON.stringify(range.values); }); } async insertContent(content: string): Promise<void> { const data = JSON.parse(content); await Excel.run(async (context) => { const range = context.workbook.getSelectedRange(); range.values = data; await context.sync(); }); } async readDocument(): Promise<ApiResponse<{ fileId: string }>> { try { const workbook = await Office.context.document.getFileAsync(Office.FileType.Compressed); const blob = new Blob([workbook.value], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }); const formData = new FormData(); formData.append('file', blob, 'workbook.xlsx'); return await this.httpClient.post<{ fileId: string }>('/files/upload', formData); } catch (error: any) { return { success: false, error: error.message, message: '读取Excel文档失败' }; } } async updateDocument(content: ArrayBuffer | Blob): Promise<void> { const blob = content instanceof ArrayBuffer ? new Blob([content]) : content; const arrayBuffer = await blob.arrayBuffer(); await Office.context.document.setFileAsync(arrayBuffer, { fileType: Office.FileType.Compressed }); } async highlightRange(change: Change): Promise<void> { if (!change.position) return; await Excel.run(async (context) => { const worksheet = context.workbook.worksheets.getActiveWorksheet(); const range = this.parseExcelRange(change.position); const cellRange = worksheet.getRange(range); const color = this.getHighlightColor(change.type); cellRange.format.fill.color = color; if (change.controlId) { cellRange.worksheet.comments.add(range, change.description || '', 'AI Assistant'); } await context.sync(); }); } async removeHighlight(changeId: string): Promise<void> { await Excel.run(async (context) => { const worksheet = context.workbook.worksheets.getActiveWorksheet(); const comments = worksheet.comments.load('items'); await context.sync(); for (const comment of comments.items) { if (comment.content.includes(changeId)) { comment.delete(); } } await context.sync(); }); } async applyChange(change: Change): Promise<void> { if (!change.position) return; await Excel.run(async (context) => { const worksheet = context.workbook.worksheets.getActiveWorksheet(); const range = this.parseExcelRange(change.position); const cellRange = worksheet.getRange(range); switch (change.type) { case 'insert': cellRange.values = [[change.content]]; break; case 'modify': cellRange.values = [[change.content]]; break; case 'delete': cellRange.clear(); break; } // 清除高亮 cellRange.format.fill.clear(); await context.sync(); }); } async getCellValue(address: string): Promise<any> { return Excel.run(async (context) => { const worksheet = context.workbook.worksheets.getActiveWorksheet(); const range = worksheet.getRange(address); range.load('values'); await context.sync(); return range.values[0][0]; }); } async setCellValue(address: string, value: any): Promise<void> { await Excel.run(async (context) => { const worksheet = context.workbook.worksheets.getActiveWorksheet(); const range = worksheet.getRange(address); range.values = [[value]]; await context.sync(); }); } async getWorksheetNames(): Promise<string[]> { return Excel.run(async (context) => { const worksheets = context.workbook.worksheets; worksheets.load('items/name'); await context.sync(); return worksheets.items.map(ws => ws.name); }); } async switchWorksheet(name: string): Promise<void> { await Excel.run(async (context) => { const worksheet = context.workbook.worksheets.getItem(name); worksheet.activate(); await context.sync(); }); } async getUsedRange(): Promise<{ address: string; values: any[][] }> { return Excel.run(async (context) => { const worksheet = context.workbook.worksheets.getActiveWorksheet(); const range = worksheet.getUsedRange(); range.load(['address', 'values']); await context.sync(); return { address: range.address, values: range.values }; }); } private parseExcelRange(position: { start: number; end: number }): string { // 将位置转换为Excel范围格式 (A1:B2) const startCol = String.fromCharCode(65 + (position.start % 26)); const startRow = Math.floor(position.start / 26) + 1; const endCol = String.fromCharCode(65 + (position.end % 26)); const endRow = Math.floor(position.end / 26) + 1; return `${startCol}${startRow}:${endCol}${endRow}`; } private getHighlightColor(type: string): string { switch (type) { case 'insert': return '#E8F5E9'; case 'delete': return '#FFEBEE'; case 'modify': return '#FFF9C4'; default: return '#E3F2FD'; } } } export default ExcelAdapter;

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/walkingzzzy/office-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server