关于前端:从服务端生成Excel电子表格GcExcel-SpreadJS

7次阅读

共计 5395 个字符,预计需要花费 14 分钟才能阅读完成。

在服务端生成 Excel 电子表格,除了应用 Node.js + SpreadJS 外,葡萄城官网举荐应用 SpreadJS + GcExcel。该计划不仅可能解决批量绑定数据源并导出 Excel、批量批改大量 Excel 内容及款式、服务端批量打印以及生成 PDF 文档等需要,还提供了远超行业标准的组件性能。

为了验证 SpreadJS + GcExcel 的解决性能,本文将就 GcExcel for Java 和 Node.js 中运行 SpreadJS 的各项数据进行比照。因为 SpreadJS 和 GcExcel 的组件性能十分丰盛,本文仅抉择最为常见的两个性能点做比照,别离是设置区域数据和导出 Excel 文档。

一、本次测试的几个大前提

因为 Node.js 是基于 V8 引擎来执行 JavaScript 的,因而它的 js 也是基于事件机制的非阻塞单线程运行,其文件的 I / O 都是异步执行的,而 Node.js 之所以抉择单线程的形式是因为编码简略、开发难度低、对 ” 码农 ” 码农的心智耗费绝对较小;而且它的文件 I / O 是异步执行的,所以不须要像 Java 那样须要创立、回收线程(Node.js 的 I / O 操作在底层也是线程,这里不做深刻探讨),这方面开销较小。
然而,单线程在做简单运算方面相比多线程则没有任何劣势,也无奈利用多线程来无效调配多核 CPU 进行优化,因而在 Node.js 中运行 SpreadJS 就只能是单线程 JS,这也会影响 SpreadJS 的数据处理性能。

所以,为了取得更加精确的测试后果,本篇中设计的测试用例,在两个环境(Java 和 Node.js)中都采纳单线程执行,并且抉择了与 Node.js 更加匹配的批量 I / O 操作作为测试用例。

二、Node.js 与 SpreadJS 的测试代码和后果:

软件版本 CPU 内存
Node.js 16.10.0 Intel(R) Core(TM) i7-9750HQ CPU @ 2.80 GHz 32G

测试代码:如下所示,用一个 Performance 类执行 1000 次设置数据、导出 Excel 文档的操作。

const fs = require('fs');

// Initialize the mock browser variables
const mockBrowser = require('mock-browser').mocks.MockBrowser;
global.window = mockBrowser.createWindow();
global.document = window.document;
global.navigator = window.navigator;
global.HTMLCollection = window.HTMLCollection;
global.getComputedStyle = window.getComputedStyle;

const fileReader = require('filereader');
global.FileReader = fileReader;

const GC = require('@grapecity/spread-sheets');
const GCExcel = require('@grapecity/spread-excelio');

GC.Spread.Sheets.LicenseKey = GCExcel.LicenseKey = "Your License";

const dataSource = require('./data');

function runPerformance(times) {const timer = `test in ${times} times`;
  console.time(timer);

  for(let t=0; t<times; t++) {// const hostDiv = document.createElement('div');
    // hostDiv.id = 'ss';
    // document.body.appendChild(hostDiv);
    const wb = new GC.Spread.Sheets.Workbook()//global.document.getElementById('ss'));
    const sheet = wb.getSheet(0);
    for(let i=0; i<dataSource.length; i++) {sheet.setValue(i, 0, dataSource[i]["Film"]);
      sheet.setValue(i, 1, dataSource[i]["Genre"]);
      sheet.setValue(i, 2, dataSource[i]["Lead Studio"]);
      sheet.setValue(i, 3, dataSource[i]["Audience Score %"]);
      sheet.setValue(i, 4, dataSource[i]["Profitability"]);
      sheet.setValue(i, 5, dataSource[i]["Rating"]);
      sheet.setValue(i, 6, dataSource[i]["Worldwide Gross"]);
      sheet.setValue(i, 7, dataSource[i]["Year"]);
    }
    exportExcelFile(wb, times, t);
  }
  
}

function exportExcelFile(wb, times, t) {const excelIO = new GCExcel.IO();
    excelIO.save(wb.toJSON(), (data) => {fs.appendFile('results/Invoice' + new Date().valueOf() + '_' + t + '.xlsx', new Buffer(data), function (err) {if (err) {console.log(err);
          }else {if(t === times-1) {console.log('Export success');
              console.timeEnd(`test in ${times} times`);
            }
          }
        });
    }, (err) => {console.log(err);
    }, {useArrayBuffer: true});
}

runPerformance(1000)

残缺的测试工程请参考:https://gitee.com/GrapeCity/Node.js-SpreadJS-two.git

测试工程运行形式:

  • npm install
  • node ./app.js

运行后果:均匀每次破费 18.1 ms

三、GcExcel 的测试代码和后果

软件版本 CPU 内存
GcExcel V5.0 Intel(R) Core(TM) i7-9750HQ CPU @ 2.80 GHz 32G

测试代码如下所示:

public class Performance {public static void main(String[] args) {System.out.println(System.getProperty("user.dir") + "/sources/jsonData");
                String jsonStr = readTxtFileIntoStringArrList(System.getProperty("user.dir") + "/sources/jsonData");
                JSONArray jsonArr = JSON.parseArray(jsonStr);
                //JSONObject jsonObj = (JSONObject) jsonArr.get(0);
                //System.out.println(jsonObj.get("Film"));
                run(1000, jsonArr);
        }

        public static void run(int times, JSONArray dataArr) {String path = System.getProperty("user.dir") + "/results/";
                System.out.println(path + "result.xlsx");
                long start = new Date().getTime();
                for (int i = 0; i < times; i++) {Workbook workbook = new Workbook();
                        IWorksheet worksheet = workbook.getWorksheets().get(0);
                        for (int j = 0; j < dataArr.size(); j++) {JSONObject jsonObj = (JSONObject) dataArr.get(j);
                                worksheet.getRange(j, 0, 1, 8).get(0).setValue(jsonObj.get("Film"));
                                worksheet.getRange(j, 0, 1, 8).get(1).setValue(jsonObj.get("Genre"));
                                worksheet.getRange(j, 0, 1, 8).get(2).setValue(jsonObj.get("Lead Studio"));
                                worksheet.getRange(j, 0, 1, 8).get(3).setValue(jsonObj.get("Audience Score %"));
                                worksheet.getRange(j, 0, 1, 8).get(4).setValue(jsonObj.get("Profitability"));
                                worksheet.getRange(j, 0, 1, 8).get(5).setValue(jsonObj.get("Rating"));
                                worksheet.getRange(j, 0, 1, 8).get(6).setValue(jsonObj.get("Worldwide Gross"));
                                worksheet.getRange(j, 0, 1, 8).get(7).setValue(jsonObj.get("Year"));
                        }
                        workbook.save(path + "result" + i + ".xlsx");
                }
                System.out.println("运行"+times+"次破费时常(ms):" + (new Date().getTime() - start));

        }

        public static String readTxtFileIntoStringArrList(String filePath) {StringBuilder list = new StringBuilder();
                try {
                        String encoding = "GBK";
                        File file = new File(filePath);
                        if (file.isFile() && file.exists()) {InputStreamReader read = new InputStreamReader(new FileInputStream(file), encoding);// 思考到编码格局
                                BufferedReader bufferedReader = new BufferedReader(read);
                                String lineTxt = null;

                                while ((lineTxt = bufferedReader.readLine()) != null) {list.append(lineTxt);
                                }
                                bufferedReader.close();
                                read.close();} else {System.out.println("找不到指定的文件");
                        }
                } catch (Exception e) {System.out.println("读取文件内容出错");
                        e.printStackTrace();}
                return list.toString();}

}

残缺的测试工程 zip 请参考附件:https://gitee.com/GrapeCity/Node.js-SpreadJS-two.git

测试脚本运行形式:导入 Eclipse 后间接 run as Application

运行后果如下所示:均匀每次破费 8.4 ms

四、总结剖析:

1、测试后果剖析:node.js 均匀每次破费 18.1 ms,GcExcel 均匀每次破费 8.4 ms,两者同时执行 1000 次设置数据、导出 Excel 文档的操作,性能相差 2 倍。

2、解决性能的比照剖析:

即使对于单线程的批量 I / O 操作,SpreadJS 在 Node.js 的运行性能仍不如 SpreadJS 在 GcExcel for Java 中运行,一方面是因为 GcExcel 性能确实十分优良,它在 Java 平台上使用了很多优良、成熟的解决方案,做到了同类产品中最一流的性能体现,另一方面是因为 GcExcel 对 Excel 和 SpreadJS 有更加全面的性能反对。目前,GcExcel 曾经作为行业内服务器端解决 Excel 文档的首选计划。

3、技术选型的剖析:

除了性能、编码难度外,对于技术选型而言,有一点也不容忽视,即平台。如果我的项目自身采纳的是 Java Web 或 .Net Web 架构,那么对于提供双平台反对的 GcExcel(GcExcel for java 和 GcExcel for .NET)来说显然更加适合。

以上就是本篇的全部内容,联合本文的测试后果,对于批量解决、批改、导出 Excel,以及服务端批量打印和生成 PDF 文档的需要,SpreadJS + GcExcel 都能提供更加优良的性能和稳定性体现,能够释怀将其作为将来我的项目的首选计划。

正文完
 0