xml - Apache POI 设置单元格格式,包括表总行的结果

标签 xml apache-poi

可以在包含总行的行表上设置单元格公式吗?

例如:我有一个总行,如下所示:

enter image description here

Col[B] 有小计,Col[C] 也有小计

我需要 Col[D] 为 Col[B] 的总计 + Col[C] 的总计或/它们!

我尝试了这段代码:

import java.io.FileOutputStream;
import org.apache.poi.xssf.usermodel.*;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellReference;

class CreateExcelTable {

    public static void main(String[] args) throws Exception {

        try ( XSSFWorkbook workbook = new XSSFWorkbook();  FileOutputStream fileout = new FileOutputStream("Excel.xlsx")) {

            //prepairing the sheet
            XSSFSheet sheet = workbook.createSheet();

            String[] tableHeadings = new String[]{"Heading1", "Heading2", "Heading3", "Heading4"};
            String tableName = "Table1";
            int firstRow = 0; //start table in row 1
            int firstCol = 0; //start table in column A
            int rows = 6; //we have to populate headings row, 4 data rows and 1 totals row
            int cols = 4; //three columns in each row

            for (int r = 0; r < rows; r++) {
                XSSFRow row = sheet.createRow(firstRow + r);
                for (int c = 0; c < cols; c++) {
                    XSSFCell localXSSFCell = row.createCell(firstCol + c);
                    if (r == 0) {
                        localXSSFCell.setCellValue(tableHeadings[c]);
                    } else if (r == 5) {
                        //totals row content will be set later
                    } else {
                        localXSSFCell.setCellValue(r + c);
                    }
                }
            }

            //create the table
            CellReference topLeft = new CellReference(sheet.getRow(firstRow).getCell(firstCol));
            CellReference bottomRight = new CellReference(sheet.getRow(firstRow + rows - 1).getCell(firstCol + cols - 1));
            AreaReference tableArea = workbook.getCreationHelper().createAreaReference(topLeft, bottomRight);
            XSSFTable dataTable = sheet.createTable(tableArea);
            dataTable.setName(tableName);
            dataTable.setDisplayName(tableName);

            //this styles the table as Excel would do per default
            dataTable.getCTTable().addNewTableStyleInfo();
            XSSFTableStyleInfo style = (XSSFTableStyleInfo) dataTable.getStyle();
            style.setName("TableStyleMedium9");
            style.setShowColumnStripes(false);
            style.setShowRowStripes(true);
            style.setFirstColumn(false);
            style.setLastColumn(false);

            //this sets auto filters
            dataTable.getCTTable().addNewAutoFilter().setRef(tableArea.formatAsString());

            //this sets totals properties to table and totals formulas to sheet
            XSSFRow totalsRow = dataTable.getXSSFSheet().getRow(tableArea.getLastCell().getRow());
            for (int c = 0; c < dataTable.getCTTable().getTableColumns().getTableColumnList().size(); c++) {
                switch (c) {
                    case 0:
                        dataTable.getCTTable().getTableColumns().getTableColumnList().get(c).setTotalsRowLabel("Totals: ");
                        totalsRow.getCell(tableArea.getFirstCell().getCol() + c).setCellValue("Totals: ");
                        break;
                    case 1:
                        dataTable.getCTTable().getTableColumns().getTableColumnList().get(c).setTotalsRowFunction(org.openxmlformats.schemas.spreadsheetml.x2006.main.STTotalsRowFunction.SUM);
                        totalsRow.getCell(tableArea.getFirstCell().getCol() + c).setCellFormula("SUBTOTAL(109," + tableName + "[" + tableHeadings[c] + "])");
                        break;
                    case 2:
                        dataTable.getCTTable().getTableColumns().getTableColumnList().get(c).setTotalsRowFunction(org.openxmlformats.schemas.spreadsheetml.x2006.main.STTotalsRowFunction.SUM);
                        totalsRow.getCell(tableArea.getFirstCell().getCol() + c).setCellFormula("SUBTOTAL(109," + tableName + "[" + tableHeadings[c] + "])");
                        break;
                    case 3:
                        /// Formila on a totil row ??
                        totalsRow.getCell(tableArea.getFirstCell().getCol() + c).setCellFormula("Table1[[#Totals],[Heading2]]+Table1[[#Totals],[Heading3]]");
                        break;
                    default:
                        break;
                }
            }
            //this shows the totals row
            dataTable.getCTTable().setTotalsRowCount(1);

            workbook.write(fileout);
        }

    }
}

但它不起作用,最终会自动删除整行!

我还尝试了另一种方法,将单元格公式设置为循环,但最终出现相同的错误!

enter image description here

有什么帮助吗?

最佳答案

使用 Excel 的 GUI 来完成此操作。然后保存*.xlsx 文件。然后解压缩该 *.xlsx 文件并查看 /xl/tables/table1.xml。在那里你会发现:

...
<tableColumn name="Heading4" id="4" totalsRowFunction="custom">
 <totalsRowFormula>Table1[[#Totals],[Heading2]]+Table1[[#Totals],[Heading3]]</totalsRowFormula>
...

因此,第四个表列需要一个 custom 类型的 totalsRowFunction 和一个存储该自定义公式的 totalsRowFormula

但是工作表还需要在适当的单元格中添加该公式。

所以翻译成Java代码:

...
dataTable.getCTTable().getTableColumns().getTableColumnList().get(c).setTotalsRowFunction(
 org.openxmlformats.schemas.spreadsheetml.x2006.main.STTotalsRowFunction.CUSTOM); 
dataTable.getCTTable().getTableColumns().getTableColumnList().get(c).addNewTotalsRowFormula().setStringValue(
 tableName+"[[#Totals],["+tableHeadings[c-2]+"]]+"+tableName+"[[#Totals],["+tableHeadings[c-1]+"]]");
totalsRow.getCell(tableArea.getFirstCell().getCol()+c).setCellFormula(
 tableName+"[[#Totals],["+tableHeadings[c-2]+"]]+"+tableName+"[[#Totals],["+tableHeadings[c-1]+"]]");
...

关于xml - Apache POI 设置单元格格式,包括表总行的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68783226/

相关文章:

java - 使用DOM将一个xml文档复制到另一个

c++ - 从 XML 解析字符串时向 n 添加额外的反斜杠

java - 我的按钮在 MainActivity.java 文件中找不到方法

java - 如何确保 clojure 变量是正确的 Java 类型

使用 apache POI 导出 Excel 让我抓狂

java - Apache POI 和文件删除类

javascript - Google map 中的动态矩形

c# - 将 XML 转换为 PDF 时 itextsharp 5.4 出现问题

grails - 如何使用Grails Excel导入插件读取列值?

java - 如何通过apache poi在excel中设置字体颜色rgb