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

如何用Apache POI在NiFI中生成带筛选的Excel智能表格?

在Apache NiFI Groovy脚本中生成Excel智能表格(带筛选功能)

你当前的NiFI Groovy脚本已实现CSV转XLSX,但需要生成Microsoft Excel的智能表格(格式化表格)——即自带筛选功能、结构化样式的表格,而非普通单元格区域。

解决方案

利用Apache POI的底层XML操作能力,为SXSSFSheet创建Excel标准的Table对象,核心是定义表格数据范围并启用筛选功能。修改后的完整代码如下:

@Grab("org.apache.poi:poi:3.16")
@Grab("org.apache.poi:poi-ooxml:3.16")
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.*;
import org.apache.commons.io.IOUtils
import java.nio.charset.StandardCharsets
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTable
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumn
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumns
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableStyleInfo

def flowFile = session.get()
if(!flowFile)
   return

flowFile = session.write(flowFile, { inputStream, outputStream ->
    try {
        SXSSFWorkbook workBook = new SXSSFWorkbook();
        workBook.setCompressTempFiles(true);

        SXSSFSheet sheet = workBook.createSheet("Sheet");
        sheet.setRandomAccessWindowSize(1000);

        String currentLine = null;
        int rowNum = 0;
        int columnCount = 0;
        BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
        
        // 读取CSV内容并写入单元格
        while ((currentLine = br.readLine()) != null) {
            String[] str = currentLine.split(",");
            columnCount = str.length; // 记录列数,以第一行表头为准
            
            Row currentRow = sheet.createRow(rowNum);
            for(int i=0;i<str.length;i++){
                currentRow.createCell(i).setCellValue(str[i]);
            }
            rowNum++;

            if (rowNum % 1000 == 0) {
                println rowNum;
            }
        }
        
        // 创建Excel智能表格(Table)
        if (rowNum > 0 && columnCount > 0) {
            // 获取底层XSSFSheet,SXSSF需通过此方式操作Table
            XSSFSheet xssfSheet = sheet.getSheet();
            // 生成表格范围:A1到对应列的最后一行(如A1:D100)
            String tableRange = "A1:" + getExcelColumnName(columnCount) + rowNum;
            
            // 初始化Table对象
            CTTable ctTable = xssfSheet.getCTWorksheet().addNewTable();
            ctTable.setDisplayName("DataTable");
            ctTable.setName("DataTable");
            ctTable.setRef(tableRange);
            ctTable.setId(1);
            
            // 启用表头筛选功能
            ctTable.addNewAutoFilter().setRef(tableRange);
            
            // 配置表格列定义
            CTTableColumns ctTableColumns = ctTable.addNewTableColumns();
            ctTableColumns.setCount(columnCount);
            for (int i = 0; i < columnCount; i++) {
                CTTableColumn ctTableColumn = ctTableColumns.addNewTableColumn();
                ctTableColumn.setName("Column" + (i+1));
                ctTableColumn.setId(i+1);
            }
            
            // 设置默认表格样式(模拟Excel内置智能表格样式)
            CTTableStyleInfo tableStyleInfo = ctTable.addNewTableStyleInfo();
            tableStyleInfo.setName("TableStyleMedium2");
            tableStyleInfo.setShowRowStripes(true);
            tableStyleInfo.setShowColumnStripes(false);
        }
        
        workBook.write(outputStream);
    } catch (Exception ex) {
        ex.printStackTrace();
    }
} as StreamCallback)

session.transfer(flowFile, REL_SUCCESS)

// 辅助方法:将列数转换为Excel列名(如1→A,26→Z,27→AA)
def getExcelColumnName(int columnNumber) {
    StringBuilder columnName = new StringBuilder();
    while (columnNumber > 0) {
        int remainder = (columnNumber - 1) % 26;
        columnName.insert(0, (char) ('A' + remainder));
        columnNumber = (columnNumber - 1) / 26;
    }
    return columnName.toString();
}

关键说明

  • 表格范围动态计算:通过getExcelColumnName方法将数字列数转换为Excel列名,自动适配不同列数的CSV文件
  • 筛选功能启用:通过CTTable的AutoFilter配置,为表头添加筛选按钮,完全匹配Excel智能表格的交互逻辑
  • SXSSF兼容处理:由于流式SXSSF未直接封装Table API,需通过sheet.getSheet()获取底层XSSFSheet进行XML层级操作
  • 样式配置:使用Excel内置的TableStyleMedium2样式,可根据需求替换为TableStyleLight1、TableStyleDark3等其他内置样式

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 14:15:48