如何用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
相关产品推荐
相关产品推荐

