JAVA APACHE-POI表

有这个下面的类,这将成为一个循环的一部分,这将在Excel表中添加很多表。

我的问题是,我无法弄清楚,如何使格式为formatAsTable风格的表格计算总计行中的值。 我把这2行代码:

cttable.setTotalsRowShown(true); cttable.setTotalsRowCount(1); 

把filter,但公式是不存在的。我知道我有string值,将改变那些后来,但这些都不是问题。下面的完整代码,如果有人知道如何,请详细说明,因为我不知道如何。

 import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Random; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.ss.usermodel.HorizontalAlignment; import org.apache.poi.ss.usermodel.VerticalAlignment; import org.apache.poi.ss.usermodel.WorkbookFactory; import org.apache.poi.ss.util.AreaReference; import org.apache.poi.ss.util.CellRangeAddress; import org.apache.poi.ss.util.CellReference; import org.apache.poi.xssf.usermodel.XSSFCell; import org.apache.poi.xssf.usermodel.XSSFCellStyle; import org.apache.poi.xssf.usermodel.XSSFFont; import org.apache.poi.xssf.usermodel.XSSFRow; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFTable; import org.apache.poi.xssf.usermodel.XSSFWorkbook; 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; public class formatAsTable2 { public static void main(String[] args) throws FileNotFoundException, IOException, InvalidFormatException { String[][] multi = new String[][]{ { "Advisor", "nonContactedUTD", "appointmentsUTD", "totalWorkLoad", "notResponsiveCalls", "successfulCalls", "totalCalls", "totalIncomingEmails", "totalCommunication", "emailsSent","offerLetters","appFees","deposits" }, { "Sharon Brown", "42", "44", "86", "62", "27", "89", "21", "220", "131" , "0", "6", "2", "0" }, { "Elena Soteriou", "40", "44", "NULL", "62", "27", "89", "21", "230", "131" , "0", "7", "2", "0" }, { "Helen Christou","45", "44", "86", "62", "27", "89", "21", "210", "131" , "0", "8", "2", "0" }, { "Maria Georgiou", "48", "44", "86", "NULL", "27", "89", "21", "240", "131" , "0", "45", "2", "0" } }; //(indexes start from 0) areaStart should be added to arenaRow int rowStart = 1; //From which row the table to start +1 int columnStart = 1; // From which column the table to start first column value 0 int len = multi.length; int wid = multi[0].length; int areaRow = len + rowStart; // how many rows the table has int areaColumn = wid + columnStart - 1; //how many columns the table has /* Start with Creating a workbook and worksheet object */ InputStream inp = new FileInputStream("Excel_Format_As_Table.xlsx"); XSSFWorkbook wb = (XSSFWorkbook)WorkbookFactory.create(inp); XSSFSheet sheet = (XSSFSheet)wb.getSheetAt(0); /* Create an object of type XSSFTable */ XSSFTable my_table = sheet.createTable(); XSSFCellStyle my_style_1 = wb.createCellStyle(); XSSFCellStyle my_style_0 = wb.createCellStyle(); my_style_1.setAlignment(HorizontalAlignment.CENTER); my_style_1.setVerticalAlignment(VerticalAlignment.CENTER); XSSFFont my_font = wb.createFont(); my_font.setBold(true); my_style_1.setFont(my_font); my_style_0.setFont(my_font); /* get CTTable object*/ CTTable cttable = my_table.getCTTable(); cttable.setTotalsRowShown(true); cttable.setTotalsRowCount(1); /* Let us define the required Style for the table */ CTTableStyleInfo table_style = cttable.addNewTableStyleInfo(); table_style.setName("TableStyleMedium27"); /* Set Table Style Options */ table_style.setShowColumnStripes(false); //showColumnStripes=0 table_style.setShowRowStripes(true); //showRowStripes=1 /* Define the data range including headers */ AreaReference my_data_range = new AreaReference(new CellReference(rowStart, columnStart), new CellReference(areaRow, areaColumn)); String randomCode = generateRandomChars(); String wantedDisplayName = "MT_" + randomCode; String wantedName = "WN_" + randomCode; long id = 4L; java.util.List<XSSFTable> all_tables = sheet.getTables(); for (XSSFTable a_table : all_tables) { if (wantedDisplayName.equals(a_table.getDisplayName())) wantedDisplayName += "_1"; if (wantedName.equals(a_table.getName())) wantedName += "_1"; if (a_table.getCTTable().getId() > id) id = a_table.getCTTable().getId(); // System.out.println(wantedDisplayName); // System.out.println(wantedName); // System.out.println(id); } id++; cttable.setRef(my_data_range.formatAsString()); cttable.setDisplayName(wantedDisplayName); /* this is the display name of the table */ cttable.setName(wantedName); /* This maps to "displayName" attribute in <table>, OOXML */ cttable.setId(id); //id attribute against table as long value cttable.addNewAutoFilter(); CTTableColumns columns = cttable.addNewTableColumns(); columns.setCount(areaColumn); //define number of columns /* Define Header Information for the Table */ for (int i = columnStart; i <= areaColumn; i++) { CTTableColumn column = columns.addNewTableColumn(); column.setName("Column" + i); column.setId(i + 1); } int x = -1; int y = -1; /* Add remaining Table Data */ XSSFRow rowDate = sheet.createRow(rowStart - 1); XSSFCell dateCell = rowDate.createCell(0); dateCell.setCellValue("Date"); dateCell.setCellStyle(my_style_0); for (int i = rowStart; i<areaRow; i++) //we have to populate 4 rows { ++x; y = -1; /* Create a Row */ XSSFRow row = sheet.createRow(i); for (int j = columnStart; j <= areaColumn; j++) //Three columns in each row { ++y; XSSFCell localXSSFCell = row.createCell(j); if (i == rowStart) { localXSSFCell.setCellValue(multi[x][y]); } else { localXSSFCell.setCellValue(multi[x][y]); } } XSSFRow rowx = sheet.createRow(i + 1); XSSFCell cellx = rowx.createCell(1); cellx.setCellValue("Total"); //cellx = rowx.createCell(2); //cellx.setCellFormula("SUM(C3:C6)"); cttable.setTotalsRowShown(true); cttable.setTotalsRowCount(1); } XSSFRow rowDateValue = sheet.getRow(rowStart); XSSFCell dateCellValue = rowDateValue.createCell(0); dateCellValue.setCellValue("24/02/2017"); dateCellValue.setCellStyle(my_style_1); sheet.addMergedRegion(new CellRangeAddress( rowStart, // mention first row here multi.length + rowStart, //mention last row here, it is 4 as we are doing a row wise merging 0, //mention first column of merging 0 //mention last column to include in merge )); System.out.println("X" + x); System.out.println("y" + y); my_table.updateReferences(); inp.close(); /* Write output as File */ FileOutputStream fileOut = new FileOutputStream("Excel_Format_As_Table.xlsx"); wb.write(fileOut); fileOut.close(); } public static String generateRandomChars() { String candidateChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; int length = 17; StringBuilder sb = new StringBuilder(); Random random = new Random(); for (int i = 0; i < length; i++) { sb.append(candidateChars.charAt(random.nextInt(candidateChars .length()))); } return sb.toString(); } } 

主要的问题是,你必须设置TotalsRowFunction为CTTableColumn以及单元格公式到总计行单元格。 如果未设置,则可以通过单击总计行单元格并从下拉列表中select函数,从而selectExcel中的总计行函数。

但是,在我们可以将单元格公式设置到总计行单元格之前,我们必须修复您的代码中的多个其他问题。

所有代码示例都是您提供的代码的改动或补充:

我们应该有表显示名称和表名相等。 这是因为在Excel中使用显示名称,但是apache poi的公式评估程序使用该名称。

 ... id++; cttable.setRef(my_data_range.formatAsString()); cttable.setDisplayName(wantedDisplayName); /* this is the display name of the table */ cttable.setName(wantedDisplayName); /* This maps to "displayName" attribute in <table>, OOXML */ cttable.setId(id); //id attribute against table as long value cttable.addNewAutoFilter(); ... 

我们应该列出列不是简单的所有“列…”,而是用他们正确的名字命名。 这是因为apache poi公式评估程序需要用于评估结构化参考公式的正确名称。

 ... /* Define Header Information for the Table */ for (int i = columnStart; i <= areaColumn; i++) { CTTableColumn column = columns.addNewTableColumn(); column.setName(multi[0][i-1]); column.setId(i + 1); column.setTotalsRowFunction(org.openxmlformats.schemas.spreadsheetml.x2006.main.STTotalsRowFunction.SUM); } ... 

这里的TotalsRowFunction已经被设置为SUM

对于使用org.openxmlformats.schemas.spreadsheetml.x2006.main.STTotalsRowFunction这个例子需要FAQ-N10025中提到的所有模式ooxml-schemas-1.3.jar的完整jar。

现在我们可以将单元格公式设置为合计行单元格作为结构化参考公式。

 ... XSSFRow rowx = sheet.createRow(i + 1); XSSFCell cellx = rowx.createCell(1); cellx.setCellValue("Total"); for (int j = columnStart+1 ; j <= areaColumn; j++) { cellx = rowx.createCell(j); cellx.setCellFormula("SUBTOTAL(109," + wantedDisplayName + "[" + multi[0][j-1] + "])"); } ... 

这里SUBTOTAL(109,...被设置为SUM