From 1a67bb52d748755406ecf706c80fa57509e517a8 Mon Sep 17 00:00:00 2001 From: joey Date: Thu, 5 Mar 2026 22:08:21 +0800 Subject: [PATCH] =?UTF-8?q?feat:Node=20=E4=B8=8E=20Python=20=E5=A4=84?= =?UTF-8?q?=E7=90=86=20Excel=20=E8=83=BD=E5=8A=9B=E5=AF=B9=E7=85=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/Node与Python处理Excel能力对照.md | 120 ++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 docs/Node与Python处理Excel能力对照.md diff --git a/docs/Node与Python处理Excel能力对照.md b/docs/Node与Python处理Excel能力对照.md new file mode 100644 index 0000000..ef86c4c --- /dev/null +++ b/docs/Node与Python处理Excel能力对照.md @@ -0,0 +1,120 @@ +# Node 与 Python 处理 Excel 能力对照 + +针对当前项目(财报 Excel 解析、按配置重组、转亿、多 Sheet 输出),逐项对照:**你要实现的功能 Node 是否都支持**。 + +--- + +## 一、当前 Python 用到的能力 + +| 能力 | 当前实现(Python) | Node 是否支持 | 说明 | +|------|--------------------|---------------|------| +| 读 .xlsx | pandas + openpyxl | ✅ 支持 | exceljs / xlsx 都支持 | +| 读 .xls | pandas | ⚠️ 部分 | 见下文「.xls」 | +| 读 .csv (UTF-8) | pandas read_csv | ✅ 支持 | fs + 按行解析,或 csv-parse / xlsx 读 csv | +| 按行、按列访问 | df.iloc[i], df.iloc[:, 0] | ✅ 支持 | 工作表 = 二维数组或按行遍历 | +| 按第一列匹配行 | first_col == item_name / str.strip() | ✅ 支持 | 数组 find/filter,字符串 trim | +| 数字解析 | 去 `=`、逗号、空格,科学计数法 | ✅ 支持 | JS 的 Number/parseFloat 完全够用 | +| 转「亿」、保留 2 位小数 | / 1e8, round(_, 2) | ✅ 支持 | 普通算术 + toFixed/round | +| 多 Sheet 写入 | pd.ExcelWriter, sheet_name= | ✅ 支持 | exceljs 多 worksheet,xlsx 多 sheet | +| 无表头写入 | header=False | ✅ 支持 | 按行写入,不写 header 即可 | +| 按配置过滤行/列 | rows_to_delete, columns_to_keep | ✅ 支持 | 数组 filter / 列索引过滤 | + +结论:**除「.xls 老格式」需单独处理外,你要实现的功能 Node 都支持。** + +--- + +## 二、推荐库与用法摘要 + +### 1. Excel 读写:exceljs(推荐) + +- **读**:`workbook.xlsx.readFile(path)` → `workbook.getWorksheet(1)` 或按名称 → `worksheet.eachRow` / `row.getCell(j).value` +- **写**:`workbook.addWorksheet('资产负债表')` → `worksheet.addRow([...])`,可多次 addRow 实现「无表头」、多 Sheet +- **格式**:主要支持 .xlsx;公式会得到计算后的值(与你当前用 pandas 读到的行为一致) +- **中文/UTF-8**:无问题 + +```bash +npm i exceljs +``` + +### 2. 备选:xlsx(SheetJS) + +- **读**:`XLSX.readFile(path)` → `workbook.Sheets[sheetName]` → `XLSX.utils.sheet_to_json(sheet, { header: 1 })` 得到「二维数组」,和你现在按 iloc 按行按列访问等价 +- **写**:`XLSX.utils.aoa_to_sheet(rows)`,再 `XLSX.utils.book_append_sheet(workbook, sheet, '资产负债表')`,最后 `XLSX.writeFile(workbook, path)` +- 社区版对 .xls 有一定支持(视构建而定);若主要用 .xlsx,exceljs 更易做「按行按格」的细粒度控制 + +### 3. CSV + +- 用 `fs.readFileSync(path, 'utf-8')` + 按行 split + 按逗号/分隔符解析即可 +- 或 `csv-parse`、或直接用 xlsx 读 csv 得到二维数组 + +### 4. 数据处理(替代 pandas) + +- 不需要 DataFrame:当前脚本本质是「按第一列找行、按列做汇总、按配置过滤、组装新行」 +- 用普通数组即可:`rows.find(r => String(r[0]).trim() === itemName)`、`rows.filter(...)`、`colValues.reduce((a, b) => a + safeFloat(b), 0)`、`resultRows.push([...])` +- 不需要额外「数据分析」库 + +--- + +## 三、你关心的几个点 + +### 1. 「按第一列找行」在 Node 里怎么写? + +和 Python 逻辑一致:把当前 Sheet 读成「行的数组」,每行是「单元格值数组」,用第一列匹配。 + +```js +// 读成二维数组后 +function findRowByItemName(rows, itemName) { + const t = itemName.trim(); + return rows.find(r => String(r[0] || '').trim() === t); +} +``` + +### 2. 数字格式:等号、逗号、科学计数法 + +你现在的 `safe_float_convert` / `convert_to_yi` 在 Node 里用一段小函数即可等价实现: + +```js +function safeFloat(value) { + if (value == null || value === '') return 0; + let s = String(value).trim(); + if (s.startsWith('=')) s = s.slice(1); + s = s.replace(/,|,|\s/g, ''); + if (!s || s.toLowerCase() === 'nan') return 0; + const n = parseFloat(s); + return Number.isFinite(n) ? n : 0; +} +``` + +科学计数法(如 `2.07327E+12`)`parseFloat` 直接支持。 + +### 3. 多 Sheet 合并输出(main.py 的 merge_to_excel) + +exceljs 示例: + +```js +const ExcelJS = require('exceljs'); +const wb = new ExcelJS.Workbook(); +const ws1 = wb.addWorksheet('资产负债表'); +const ws2 = wb.addWorksheet('利润表'); +balanceSheetRows.forEach(row => ws1.addRow(row)); // 无表头就连续 addRow +incomeStatementRows.forEach(row => ws2.addRow(row)); +await wb.xlsx.writeFile(outputPath); +``` + +### 4. .xls(老格式) + +- **exceljs**:只支持 .xlsx,不直接支持 .xls。 +- **xlsx (SheetJS)**:部分版本/配置可读 .xls,但不如 .xlsx 稳定。 +- 建议:若数据源仍会提供 .xls,要么在 Node 里用专门库(如 `xls` 等)只做「读成二维数组」再交给现有逻辑,要么在上传前用 Excel/脚本统一转成 .xlsx 再处理。对你当前「下载后上传到 Web」的流程,要求用户上传 .xlsx 或在后端用工具转一次,通常可接受。 + +--- + +## 四、小结 + +| 问题 | 结论 | +|------|------| +| Node 能否完成你现在的 Excel 处理? | **能**。读 xlsx/csv、按行按列查找、数字清洗、转亿、多 Sheet 写出,都有对应库和写法。 | +| 是否不如 Python 稳? | 对**这类**场景(报表级数据、几千行以内):Node + exceljs 足够稳;Python 优势在「超大数据、复杂统计、科学计算」,你当前用到的只是基础读写与简单运算。 | +| 推荐方案 | **exceljs** 做主读写;数据处理用普通 JS 数组;CSV 用 fs + 解析或 csv-parse;.xls 单独处理或要求 .xlsx。 | + +你更熟 Node 的话,用 Node 实现当前功能没有问题;若后面遇到具体文件解析异常(例如某个下载站的 xlsx 格式略怪),再针对该格式微调即可。