aardio 文档

NPOI 导出对象到 Excel 格式数据

简介

本文将介绍如何使用 aardio 结合 NPOI 库实现通用的 Excel 导出功能。

准备工作

本方案的核心思想是通过 NPOI 库实现通用 Excel 导出功能。在 aardio 中,我们只需导入 NPOI 扩展库即可开始使用。

代码实现

我们创建了一个通用的 Excel 导出工具类,主要包含两个核心功能模块:

  1. ExcelExport 类 - 包含基础导出逻辑
  2. 数据转换桥接器 - 将 aardio 表对象转换为 NPOI Excel 对象

基础导出类 (ExcelExport)

import NPOI;
import System.IO;
namespace ExcelExport {

    // 基础导出类
    class ExcelExport {

        // 导出方法
        export = function(exportData, fileName, sheetName = "Sheet1") {
            this.fields = {}; 

            this.fileName = fileName;
            this.sheetName = sheetName;

            // 创建新工作簿和工作表
            this.workbook = ..NPOI.XSSF.UserModel.XSSFWorkbook();
            this.sheet = this.workbook.CreateSheet(this.sheetName);

            // 设置表头样式
            var headerStyle = this.workbook.CreateCellStyle();
            var headerFont = this.workbook.CreateFont();
            headerFont.IsBold = true;
            headerStyle.SetFont(headerFont);

            // 写入数据
            this.writeData(exportData);

            // 创建表头行
            var header = this.sheet.CreateRow(0);
            for(i=1; #this.fields; 1) {
                var cell = header.CreateCell(i-1);
                cell.SetCellValue(this.fields[i]);
                cell.CellStyle = headerStyle;
                // 大数据量时自动列宽会影响性能
                // this.sheet.AutoSizeColumn(i-1);
            }

            // 创建内存流并返回
            var memoryStream = ..System.IO.MemoryStream();
            this.workbook.Write(memoryStream);
            return memoryStream;
        }

        // 抽象方法 - 由子类实现具体数据写入逻辑
        writeData = function(exportData) {
            error("请在子类中实现此方法");
        }
    }
}

数据转换桥接器

namespace ExcelExport {

    // 数据转换桥接器
    class ExcelExportBridge {

        ctor() {
            this = ..ExcelExport.ExcelExport();
            this.fields = {}; 
        }

        // 实现数据写入方法
        writeData = function(exportData) {
            // 获取第一个对象的属性列表
            var firstItem = exportData[1];
            var properties = {};

            if(exportData.fields){
                this.fields = exportData.fields;
            }   
            else{
                for k,v in ..table.eachName(firstItem){
                    ..table.push(this.fields,k); // 属性名转为标题格式 
                }
            }

            // 创建数据行
            for(i=1; #exportData; 1) {
                var row = this.sheet.CreateRow(i);
                var item = exportData[i];

                for(j=1; #this.fields; 1) {
                    var cell = row.CreateCell(j-1);
                    var value = item[this.fields[j]];
                    cell.SetCellValue(tostring(value));
                }
            }
        }
    }
}

使用示例


// 准备测试数据
var testData = [
    fields:["Name","Age","Salary","JoinDate"],//指定列
    { Name = "张三", Age = 25, Salary = 5000.50, JoinDate = time() },
    { Name = "李四", Age = 30, Salary = 6000.75, JoinDate = time() },
    { Name = "王五", Age = 28, Salary = 5500.25, JoinDate = time() }
];

// 创建导出器实例
var exporter = ExcelExport.ExcelExportBridge();

// 导出数据到内存流
var stream = exporter.export(testData, "员工数据");

// 将流保存为文件
System.IO.File.WriteAllBytes("/员工数据.xlsx", stream.ToArray());

// 或者直接返回给 HTTP 响应(Web 应用场景)
/*
response.contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
response.headers["Content-Disposition"] = 'attachment; filename="员工数据_'++time.format(time(),"yyyyMMddHHmmss")++'.xlsx"';
response.write( stream.ToArray() )
*/

技术背景

我们使用 NPOI 库来实现 Excel 导出功能,这是一个免费开源的 .NET 库。相比传统的字符串拼接或 Interop 方式,NPOI 提供了更高效、更稳定的 Excel 操作能力。

实现要点

  1. 通用性:可以处理任意类型的对象列表
  2. 灵活性:自动识别属性名作为列标题
  3. 类型安全:根据属性类型正确处理单元格格式
  4. 性能优化:避免大数据量时的自动列宽计算

改进方向

  1. 移除对 DataTable 的依赖(aardio 中直接使用表对象)
  2. 增加更多数据类型支持
  3. 优化大文件导出性能
  4. 添加样式自定义选项

实际应用

当我们需要为多个数据表提供导出功能时,这种通用方案可以大幅减少重复代码。相比为每个表单独实现导出逻辑,此方案只需准备数据并调用统一接口即可。

注意事项

  1. 大数据量导出时建议分页处理
  2. 复杂格式需求可能需要扩展样式设置
  3. 日期时间格式可根据需求调整

这个方案已在生产环境中验证,能够稳定处理各种数据导出需求。您可以根据实际项目需要进行进一步定制和优化。

Markdown 格式