(workbook: XLSX.WorkBook)
| 69 | } |
| 70 | |
| 71 | private processWorkbook(workbook: XLSX.WorkBook): FileParseResult { |
| 72 | const sheetNames = workbook.SheetNames |
| 73 | let content = '' |
| 74 | let totalRows = 0 |
| 75 | let truncated = false |
| 76 | let contentSize = 0 |
| 77 | const sampledData: any[] = [] |
| 78 | |
| 79 | for (const sheetName of sheetNames) { |
| 80 | const worksheet = workbook.Sheets[sheetName] |
| 81 | |
| 82 | // Get sheet dimensions |
| 83 | const range = XLSX.utils.decode_range(worksheet['!ref'] || 'A1') |
| 84 | const rowCount = range.e.r - range.s.r + 1 |
| 85 | |
| 86 | logger.info(`Processing sheet: ${sheetName} with ${rowCount} rows`) |
| 87 | |
| 88 | // Convert to JSON with header row |
| 89 | const sheetData = XLSX.utils.sheet_to_json(worksheet, { |
| 90 | header: 1, |
| 91 | defval: '', // Default value for empty cells |
| 92 | blankrows: false, // Skip blank rows |
| 93 | }) |
| 94 | |
| 95 | const actualRowCount = sheetData.length |
| 96 | totalRows += actualRowCount |
| 97 | |
| 98 | // Store limited sample for metadata |
| 99 | if (sampledData.length < CONFIG.MAX_SAMPLE_ROWS) { |
| 100 | const sampleSize = Math.min(CONFIG.MAX_SAMPLE_ROWS - sampledData.length, actualRowCount) |
| 101 | sampledData.push(...sheetData.slice(0, sampleSize)) |
| 102 | } |
| 103 | |
| 104 | // Only process limited rows for preview |
| 105 | const rowsToProcess = Math.min(actualRowCount, CONFIG.MAX_PREVIEW_ROWS) |
| 106 | const cleanSheetName = sanitizeTextForUTF8(sheetName) |
| 107 | |
| 108 | // Add sheet header |
| 109 | const sheetHeader = `\n=== Sheet: ${cleanSheetName} ===\n` |
| 110 | content += sheetHeader |
| 111 | contentSize += sheetHeader.length |
| 112 | |
| 113 | if (actualRowCount > 0) { |
| 114 | // Get headers if available |
| 115 | const headers = sheetData[0] as any[] |
| 116 | if (headers && headers.length > 0) { |
| 117 | const headerRow = headers.map((h) => this.truncateCell(h)).join('\t') |
| 118 | content += `${headerRow}\n` |
| 119 | content += `${'-'.repeat(Math.min(80, headerRow.length))}\n` |
| 120 | contentSize += headerRow.length + 82 |
| 121 | } |
| 122 | |
| 123 | // Process data rows in chunks |
| 124 | let chunkContent = '' |
| 125 | let chunkRowCount = 0 |
| 126 | |
| 127 | for (let i = 1; i < rowsToProcess; i++) { |
| 128 | const row = sheetData[i] as any[] |
no test coverage detected