Apache POI 格式 Table 未显示总行数

Apache POI Format Table Not showing Total Row

我有一个 class 可以使用下面的代码创建格式化的 table :

public class formatAsTable {

    public static void main(String[] args)
            throws FileNotFoundException, IOException {

        Workbook wb = new XSSFWorkbook();
        XSSFSheet sheet = (XSSFSheet) wb.createSheet();


        XSSFTable my_table = sheet.createTable();


        CTTable cttable = my_table.getCTTable();

        /* Let us define the required Style for the table */
        CTTableStyleInfo table_style = cttable.addNewTableStyleInfo();
        table_style.setName("TableStyleMedium9");


        table_style.setShowColumnStripes(false); //showColumnStripes=0
        table_style.setShowRowStripes(true); //showRowStripes=1


        AreaReference my_data_range = wb.getCreationHelper().createAreaReference(new CellReference(0, 0), new CellReference(4, 2));

        cttable.setRef(my_data_range.formatAsString());
        cttable.setDisplayName("MYTABLE");

        cttable.addNewAutoFilter();

        cttable.setName("Test");
        cttable.setId(1L);

        CTTableColumns columns = cttable.addNewTableColumns();
        columns.setCount(3L); //define number of columns

        for (int i = 0; i < 3; i++) {
            CTTableColumn column = columns.addNewTableColumn();
            column.setName("Column" + i);
            column.setId(i + 1);
        }

        /* Add And Show TotelRow */
        cttable.setTotalsRowShown(true);

        for (int x = 0; x < 3; x++) {
            cttable.getTableColumns().getTableColumnArray(x).setId(x + 1);

            switch (x) {
                case 0 ->
                    cttable.getTableColumns().getTableColumnArray(x).setTotalsRowLabel("Totales: ");
                default ->
                    cttable.getTableColumns().getTableColumnArray(x).setTotalsRowFunction(org.openxmlformats.schemas.spreadsheetml.x2006.main.STTotalsRowFunction.SUM);
            }
        }

        for (int i = 0; i <= 4; i++) //we have to populate 4 rows
        {
            XSSFRow row = sheet.createRow(i);
            for (int j = 0; j < 3; j++) //Three columns in each row
            {
                XSSFCell localXSSFCell = row.createCell(j);
                if (i == 0) {
                    localXSSFCell.setCellValue("Heading" + j);
                } else {
                    localXSSFCell.setCellValue(i + j);
                }
            }
        }

        FileOutputStream fileOut = new FileOutputStream("Excel_Format_As_Table.xlsx");
        wb.write(fileOut);
        fileOut.close();
    }
}

它工作正常,但即使我设置 cttable.setTotalsRowShown(true);它没有显示总行数!

而且我必须打开文件并在 table 中的 Total Row 上选中要制作的设计可见:

我更改了名称和内容,并尝试添加不同的格式,但没有结果

主要问题是需要设置 CTTable.setTotalsRowCount(1) 以显示一个总计行。您使用的 CTTable.setTotalsRowShown(true) 有其他含义。

根据 ECMA-376 Office Open XML 文件格式属性 totalsRowShown 表示:

A Boolean indicating whether the totals row has ever been shown in the past for this table. True if the totals row has been shown, false otherwise.

但是属性 totalsRowCount 表示:

An integer representing the number of totals rows that shall be shown at the bottom of the table.

0 means that the totals row is not shown. It is up to the spreadsheet application to determine if numbers greater than 1 are allowed. Unless the spreadsheet application has a feature where their might ever be more than one totals row, this number should not be higher than 1.

但在 Excel 中,table 的值和设置始终必须在 table 设置和存在 table 的 sheet 中同步。否则它将无法工作,甚至可能导致工作簿损坏。因此,与 headers 行一样,sheet 也需要有总计行。 sheet 中总计行中的值和公式必须对应于 table 设置。

以下完整示例展示了这一切。在可能的情况下,它使用 apache poi 的高级别 类。它使用 apache poi 5.0.0apache poi 4.1.2 进行了测试和工作。不支持较低版本,因为它们在 table 创建时存在错误。

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"};
   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 = 3; //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++) {
    if (c == 0) {
     dataTable.getCTTable().getTableColumns().getTableColumnList().get(c).setTotalsRowLabel("Totals: ");
     totalsRow.getCell(tableArea.getFirstCell().getCol()+c).setCellValue("Totals: ");
   } else {
     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] + "])");
    }
   }
   //this shows the totals row
   dataTable.getCTTable().setTotalsRowCount(1);

   workbook.write(fileout);
  }

 }
}

所有org.openxmlformats.schemas.spreadsheetml.x2006.main.*的使用类需要ooxml-schemas-1.4.jar用于apache poi 4.1.2poi-ooxml-full-5.0.0.jar用于apache poi 5.0.0ooxml 的精简版不包含所有 类。参见 https://poi.apache.org/help/faq.html#faq-N10025