Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | 2x 2x 2x 2x 2x 2x 2x 2x 8x 8x 8x 8x 8x 91x 91x 8x 8x 8x 2x 4x 4x 4x 7x 7x 7x 7x 2x 2x 5x 5x 4x 4x 2x 2x 2x 2x 2x 2x | import * as vscode from 'vscode';
import * as XLSX from 'xlsx';
import { RuleConverter } from './converter';
import { convertContentWithAI } from '../import-service';
import { buildSystemPrompt } from './prompt-builder';
import type { CustomRule } from '../../types';
import { t } from '../../i18n/messages';
export function buildMarkdownTable(rows: Record<string, unknown>[], sheetName: string): string {
const keys = [...new Set(rows.flatMap(row => Object.keys(row)))];
const header = `| ${keys.join(' | ')} |`;
const separator = `| ${keys.map(() => '---').join(' | ')} |`;
const dataLines = rows.map(row => {
const cells = keys.map(k => String(row[k] ?? ''));
return `| ${cells.join(' | ')} |`;
});
return [`## ${sheetName}`, header, separator, ...dataLines].join('\n');
}
export function renderWorkbookToMarkdown(workbook: XLSX.WorkBook): string | null {
const parts: string[] = [];
for (const sheetName of workbook.SheetNames) {
const sheet = workbook.Sheets[sheetName];
if (!sheet) { continue; }
const rows = XLSX.utils.sheet_to_json<Record<string, string>>(sheet);
if (rows.length === 0) {
continue;
}
parts.push(buildMarkdownTable(rows, sheetName));
}
return parts.length === 0 ? null : parts.join('\n\n');
}
export class ExcelConverter implements RuleConverter {
supportedExtensions = ['.xlsx', '.xls'];
async convert(srcPath: string, context: vscode.ExtensionContext, existingRules?: CustomRule[]): Promise<string | null> {
let workbook: XLSX.WorkBook;
try {
workbook = XLSX.readFile(srcPath);
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
vscode.window.showErrorMessage(t('import.excelReadFail', { 0: msg }));
return null;
}
if (workbook.SheetNames.length === 0) {
vscode.window.showErrorMessage(t('import.excelEmpty'));
return null;
}
let combined: string | null;
try {
combined = renderWorkbookToMarkdown(workbook);
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
vscode.window.showErrorMessage(t('import.excelReadFail', { 0: msg }));
return null;
}
if (combined === null) {
vscode.window.showErrorMessage(t('import.excelNoData'));
return null;
}
return convertContentWithAI(combined, context, buildSystemPrompt('spreadsheet', existingRules));
}
}
|