js使用exceljs组件读excel文件单元格的实际值而非显示值

最近要写一个页面,上传 excel 文档,读一些固定栏位存入 DB,并做一些简单的计算,计算均值、标准差等。原本很简单的需求,计算的结果却和 excel 中公式计算结果对不上,并且相差不少,绝不是简单的 2.0 变成 2.0000000001 的问题。仔细检查发现原来 excel 中有些单元格中是小数点后4位小数,结果显示为3位小数,最终导致计算结果的差异。

因此最终的需求就变成读取文档的数字的存储数值,而非显示显示数值。

有下面一个的简单测试表格,A-J列为3位或者4位小数,N列为公式计算结果。

首先测试了xlsx.js这个组件,看是否满足需求

xlsx.js

<script src="./plugins/jquery/jquery-1.12.4.min.js"></script>
<script src="./plugins/xlsx.full.min.js"></script>
<input type="file" id="uploadFile" accept=".xls,.xlsx,.xlsm" />
<button onclick="uploadExcel(this)">uploadExcel</button>
<script>
  function uploadExcel(elem) {
    const file = $("#uploadFile")[0].files[0];
    const fileTypes = [
      "application/vnd.ms-excel", //xls
      "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", //xlsx
      "application/vnd.ms-excel.sheet.macroEnabled.12", //xlsm
    ];
    if (!file || file.size < 1 || fileTypes.indexOf(file.type) === -1) {
      alert("請選擇EXCEL文檔");
      return;
    }

    const reader = new FileReader();
    const data = [];
    reader.onload = function (e) {
      const workbook = XLSX.read(e.target.result, {
        type: "binary",
        cellDates: true,
      });
      const sheetNames = workbook.SheetNames;
      const worksheet = workbook.Sheets[sheetNames[0]];
      const csv_data = XLSX.utils.sheet_to_csv(worksheet).split("\n");

      console.log(sheetNames);
      for (let row of csv_data) {
        console.log(row);
      }
    };
    reader.readAsBinaryString(file);
  }
</script>

结果,读取的数值为文档的显示数字,而非实际数字。
<

PhpSpreadsheet

require '../libs/phpoffice/vendor/autoload.php';

use PhpOffice\PhpSpreadsheet\IOFactory;

ini_set("memory_limit", -1);
ini_set('max_execution_time', 0);

#读文件
$file_name = '../files/Book1.xlsx';
$spreadSheet = IOFactory::load($file_name); //载入xlsx文件

$sheet = $spreadSheet-&gt;getSheetByName('Sheet1'); //根据表名获取工作表
//最大行数
$row_num = $sheet-&gt;getHighestRow();
//最大列数
$col_num = $sheet-&gt;getHighestColumn();

//获取当前工作表所有有数据
$data = $sheet-&gt;toArray(); //二位数组

echo '&lt;pre&gt;';
var_dump($row_num, $col_num);
var_dump($data);

结果,读取的数值为文档的显示数字,而非实际数字

exceljs

<script src="./plugins/jquery/jquery-1.12.4.min.js"></script>
<script src="./plugins/exceljs/exceljs.js"></script>
<input type="file" id="uploadFile" accept=".xls,.xlsx,.xlsm" />
<button onclick="uploadExcel(this)">uploadExcel</button>
<script>
  function uploadExcel(elem) {
    const file = $("#uploadFile")[0].files[0];
    const fileTypes = [
      "application/vnd.ms-excel", //xls
      "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", //xlsx
      "application/vnd.ms-excel.sheet.macroEnabled.12", //xlsm
    ];
    if (!file || file.size < 1 || fileTypes.indexOf(file.type) === -1) {
      alert("請選擇EXCEL文檔");
      return;
    }

    const reader = new FileReader();

    reader.onload = function (e) {
      const workbook = new ExcelJS.Workbook();

      const data_res = {};
      let rowCount, row, rows;
      workbook.xlsx
        .load(e.target.result, {
          ignoreNodes: ["autoFilter", "headerFooter", "hyperlinks", "pageMargins", "dataValidations", "mergeCells", "printOptions", "picture", "drawing", "conditionalFormatting"],
        })
        .then((res) => {
          for (let worksheet of workbook.worksheets) {
            console.log(worksheet.name);
            row = worksheet.getRow(1);
            console.log(row.values);

            rowCount = worksheet.rowCount;
            console.log(rowCount);
            rows = worksheet.getRows(2, rowCount - 1);
            for (row of rows) {
              console.log(row.values);
            }
          }

          //遍历每张工作表
          // workbook.eachSheet(function (worksheet, sheetId) {
          //   //遍历每行
          //   worksheet.eachRow({ includeEmpty: true }, function (row, rowNumber) {
          //     console.log(row, rowNumber);
          //   });
          // });
        });
    };
    reader.readAsBinaryString(file);
  }

  function getDate(str) {
    const date = new Date(str);
    return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${date.getDate()}`;
  }
</script>

结果:读取的数值为文档的实际存储数值。并且各单元格依照存储的格式解析为对应的值,公式单元格中包括公式和结果。

exceljs 可以满足需求。

posted @ 2025-04-30 10:36  carol2014  阅读(115)  评论(0)    收藏  举报