All files / src/rules/converters excel-converter.ts

21.87% Statements 14/64
100% Branches 1/1
33.33% Functions 1/3
21.87% Lines 14/64

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 651x 1x 1x 1x 1x 1x 1x 1x                     1x 1x 1x 1x 1x                                                                                 1x  
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';
 
function buildMarkdownTable(rows: Record<string, unknown>[], sheetName: string): string {
  const keys = Object.keys(rows[0]);
  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 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 parts: string[];
    try {
      parts = [];
      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));
      }
    } catch (err) {
      const msg = err instanceof Error ? err.message : String(err);
      vscode.window.showErrorMessage(t('import.excelReadFail', { 0: msg }));
      return null;
    }

    if (parts.length === 0) {
      vscode.window.showErrorMessage(t('import.excelNoData'));
      return null;
    }

    const combined = parts.join('\n\n');
    return convertContentWithAI(combined, context, buildSystemPrompt('spreadsheet', existingRules));
  }
}