在编写将结果集导出到Excel的工具时,我遇到了一个问题.我在列标题上成功创建了带格式和过滤器的表,没问题.问题是我无法弄清楚如何使总行"工作".我想使用真正的总行数,以便它们响应所应用的过滤器,但到目前为止,我可以获得一个包含函数但不是表的一部分的小计的行,或者我可以得到一个空白的小计行.
我相信必须有一些魔法,比如公式评估器或类似的东西,但我还没有在javadocs或示例代码中偶然发现它.我正在使用此位置的代码进行以下修改.在设置列标题的循环内:
if(i == 0)
column.setTotalsRowLabel("Totals:");
else
column.setTotalsRowFunction(STTotalsRowFunctionImpl.COUNT);
Run Code Online (Sandbox Code Playgroud)
然后在循环之外:
cttable.setTotalsRowShown(true);
cttable.setTotalsRowCount(1);
Run Code Online (Sandbox Code Playgroud)
没有运气,如果我为总计添加一个空白行,它将被格式化为表格的一部分,但没有值显示.如果我为公式中的任何一个单元格设置公式,但Excel不喜欢该表并删除总行,尽管公式在那里并且有效,而不是作为总行.
当我查看下面的原始XML时,它与表格的Excel表单几乎无法区分,而工作表则大不相同.
更新:我已经离开这个项目很长一段时间了,最近又回到了它.我已经放弃POI自动执行此操作,而是转而试图通过DOM操作来后门.
我很近,我不能放弃.这完全归结为最终工作表中的命名空间问题.这段代码:
Element b = (Element) wb.getSheetAt(0).getCTWorksheet().getSheetData().getRowList().get(4).getCArray()[3].getDomNode();
Element f = b.getOwnerDocument().createElementNS("main", "f");
b.removeAttribute("t");
b.removeChild(b.getElementsByTagName("v").item(0));
f.appendChild(b.getOwnerDocument().createTextNode("SUBTOTAL(103,MYTABLE[Human])"));
b.appendChild(f);
Run Code Online (Sandbox Code Playgroud)
在sheet1.xml文件中生成以下内容:
<c r="D5">
<main:f>SUBTOTAL(103,MYTABLE[Human])</f>
</c>
Run Code Online (Sandbox Code Playgroud)
如果我使用createElement("f"),我得到:
<c r="D5">
<f xmlns="">SUBTOTAL(103,MYTABLE[Human])</f>
</c>
Run Code Online (Sandbox Code Playgroud)
如果我手动编辑存档中的工作表并删除命名空间标记或限定符,它就可以工作!我没有看到如何在不保存工作簿的情况下解决NS问题,然后继续打开它并修复文件IO的问题.有人对此有任何暗示吗?
我遇到了axisRow pivotFields的setDefaultSubtotal方法的问题.当我为RowLabel字段将值设置为false时,Excel不喜欢它.手动设置我在Excel中如何想要它们然后保存会产生截然不同的XML,这与我在幕后进行修复是完全不同的.我不能(到目前为止)操纵XML以使POI电子表格在Excel中干净地打开.
实际的代码有点长而且难以发布,但这里有一个具有相同问题的可运行的代码:
private static void sample() throws IOException{
Workbook wb = new XSSFWorkbook();
String[][] data = new String[][]{{"STATUS","PASSED","VALUE"},{"BLUE","Y","20"},{"RED","N","10"},{"BLUE","N","30"}};
XSSFSheet sheet = (XSSFSheet) wb.createSheet("data");
XSSFSheet pivot = (XSSFSheet) wb.createSheet("summary");
for(String[] dataRow : data){
XSSFRow row = sheet.createRow(sheet.getPhysicalNumberOfRows());
for(String dataCell : dataRow){
XSSFCell cell = row.createCell(row.getPhysicalNumberOfCells());
cell.setCellValue(dataCell);
}
}
XSSFTable table = sheet.createTable();
CTTable cttable = table.getCTTable();
table.setDisplayName("table");
cttable.setRef("A1:C4");
cttable.setId(1);
CTTableColumns columns = cttable.addNewTableColumns();
columns.setCount(3);
int i = 1;
for (String colName : data[0]){
CTTableColumn column = columns.addNewTableColumn();
column.setId(++i);
column.setName(colName);
} …Run Code Online (Sandbox Code Playgroud)