You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中使用XLSX库导出Excel时销售数据未显示问题

销售报表Excel导出无数据问题排查与解决

问题现象

自研React管理后台使用XLSX库导出销售报表为Excel时,导出文件的「Sales Details」工作表无数据显示,但控制台打印原始salesData、处理后的salesTableData、生成的salesWS及工作簿工作表列表均正常。

用户代码

const handleExcelDownload = () => {
    console.log ("Starting Excel export with sales data:", salesData);

    const wb = XLSX.utils.book_new();

    // Summary Sheet
    const summaryData = [
      ['Sales Report', '', '', '', ''],
      ['Generated on:', new Date().toLocaleDateString(), '', '', ''],
      ['', '', '', '', ''],
      ['Summary Statistics', '', '', '', ''],
      ['', '', '', '', ''],
      ['Total Orders', totalSales, '', '', ''],
      ['Total Revenue', formatIndianRupee(totalAmount), '', '', ''],
      ['Total Discounts', formatIndianRupee(totalDiscount), '', '', ''],
      ['', '', '', '', '']
    ];

    const summaryWS = XLSX.utils.aoa_to_sheet(summaryData);
    XLSX.utils.book_append_sheet(wb, summaryWS, 'Summary');

    // Sales data sheet
    const salesHeaders = [
      ['Date', 'Order ID', 'Products', 'User', 'Amount', 'Discount', 'Status']
    ];

    // Convert sales data to rows
    const salesRows = salesData.map(sale => [
      new Date(sale.date).toLocaleDateString(),
      sale.orderId,
      sale.products.map(p => `${p.name} (${p.quantity})`).join(', '),
      sale.userName,
      formatIndianRupee(sale.amount),
      formatIndianRupee(sale.discount),
      sale.status
    ]);

    // Combine headers and rows
    const salesTableData = [...salesHeaders, ...salesRows];
    console.log("Sales Table Data:", salesTableData); // Debugging line

    // Create sales worksheet
    const salesWS = XLSX.utils.aoa_to_sheet(salesTableData);
    console.log("Sales Worksheet:", salesWS); // Debugging line

    // Set column widths
    const salesColWidth = [
      { wch: 15 },  // Date
      { wch: 25 },  // Order ID
      { wch: 40 },  // Products
      { wch: 25 },  // User
      { wch: 15 },  // Amount
      { wch: 15 },  // Discount
      { wch: 15 }   // Status
    ];
    salesWS['!cols'] = salesColWidth;

    // Append sales worksheet to workbook
    XLSX.utils.book_append_sheet(wb, salesWS, 'Sales Details');
    console.log("Workbook Sheets:", wb.SheetNames); // Debugging line

    // Save the file
    try {
      const date = new Date().toISOString().split('T')[0];
      XLSX.writeFile(wb, `sales_report_${date}.xlsx`);
      console.log("Excel file generated successfully");
    } catch (error) {
      console.error("Error generating Excel file:", error);
    }
};

排查方向与解决方案

1. 切换XLSX库版本/导入方式

部分xlsx版本的aoa_to_sheet存在数组转工作表的隐性bug,可替换为xlsx-js-style(保留样式支持):

npm install xlsx-js-style --save

替换导入语句:

import XLSX from 'xlsx-js-style';

2. 改用JSON转工作表替代数组转工作表

放弃数组拼接方式,直接用json_to_sheet处理结构化数据,避免数组格式异常:

// 重构销售数据工作表生成逻辑
const salesWS = XLSX.utils.json_to_sheet(salesData.map(sale => ({
  Date: new Date(sale.date).toLocaleDateString(),
  'Order ID': sale.orderId,
  Products: sale.products.map(p => `${p.name} (${p.quantity})`).join(', '),
  User: sale.userName,
  Amount: formatIndianRupee(sale.amount),
  Discount: formatIndianRupee(sale.discount),
  Status: sale.status
})));

// 保留列宽设置
salesWS['!cols'] = [
  { wch: 15 },
  { wch: 25 },
  { wch: 40 },
  { wch: 25 },
  { wch: 15 },
  { wch: 15 },
  { wch: 15 }
];

3. 清理数据中的特殊字符

检查formatIndianRupee返回值是否包含不可见特殊字符,清理后再生成工作表:

// 格式化函数添加特殊字符清理
const formatIndianRupee = (amount) => {
  return `₹ ${amount.toLocaleString('en-IN')}`.replace(/[\u200B-\u200D\uFEFF]/g, '');
};

4. 强制同步工作表状态

极端情况下,追加工作表后手动更新工作簿引用:

XLSX.utils.book_append_sheet(wb, salesWS, 'Sales Details');
// 强制同步工作表引用
wb.Sheets['Sales Details'] = salesWS;

内容的提问来源于stack exchange,提问作者Abel Tomy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 16:53:14