【问题标题】:SUM(ABOVE) functionality in apache poi or docx4japache poi 或 docx4j 中的 SUM(ABOVE) 功能
【发布时间】:2020-05-13 14:36:49
【问题描述】:

我正在尝试在 docx 中实现 =SUM(ABOVE) 函数,该函数用于将上面的所有元素汇总到第 tht 列。我能够使用 apache poi 来实现这一点:

    CTSimpleField sumAbove = paragraphInCell.getCTP().addNewFldSimple();
  sumAbove.setInstr("=SUM(ABOVE)");
  //set sum field dirty, so it must be calculated while opening the document
  sumAbove.setDirty(STOnOff.TRUE);

当有人打开文档并计算它时,这是可以的。但是,如果我需要在不打开文档的情况下将其转换为 pdf,则此功能不会运行。 Aspose 有一个函数叫做:

Document.UpdateFields

它执行所需的功能,但这是付费应用程序。

我们能否使用 apche poi 或 docx4j 实现相同的功能

【问题讨论】:

    标签: java apache-poi docx docx4j


    【解决方案1】:

    如果您不想将字段设置为脏,那么您需要自己计算总和。以下是计算XWPFTable 的特殊列的表格单元格值总和的方法的工作草案:

     Double calculateSum(XWPFTable table, int col) {
      Double result = null;
      for (XWPFTableRow row : table.getRows()) {
       if (row.getTableCells().size() > col) {
        XWPFTableCell cell = row.getCell(col);
        String cellContent = cell.getText();
        try {
         Number cellValue = java.text.NumberFormat.getInstance().parse(cellContent);
         if (result == null) result = 0d;
         result += cellValue.doubleValue();
        } catch(Exception ex) {
         //could not parse text to number
         //ex.printStackTrace();
        }
       }
      }
      return result;
     }
    

    如果您有总和,那么CTSimpleField 需要获取一个将总和设置为文本值的文本运行。然后这与Word 为字段设置缓存值相同。

    完整示例:

    import java.io.FileOutputStream;
    
    import org.apache.poi.xwpf.usermodel.*;
    
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSimpleField;
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.STOnOff;
    
    public class CreateWordTableSumAbove {
    
     static Double calculateSum(XWPFTable table, int col) {
      Double result = null;
      for (XWPFTableRow row : table.getRows()) {
       if (row.getTableCells().size() > col) {
        XWPFTableCell cell = row.getCell(col);
        String cellContent = cell.getText();
        try {
         Number cellValue = java.text.NumberFormat.getInstance().parse(cellContent);
         if (result == null) result = 0d;
         result += cellValue.doubleValue();
        } catch(Exception ex) {
         //could not parse text to number
         //ex.printStackTrace();
        }
       }
      }
      return result;
     }
    
     static void setText(XWPFTableCell cell, String text) {
      XWPFParagraph par = null;
      if (cell.getParagraphs().size() == 0) par = cell.addParagraph();
      else par = cell.getParagraphs().get(0);
      par.createRun().setText(text);
     }
    
     public static void main(String[] args) throws Exception {
    
      XWPFDocument document= new XWPFDocument();
    
      XWPFParagraph paragraph = document.createParagraph();
      XWPFRun run=paragraph.createRun();  
      run.setText("The table:");
    
      //create the table
      XWPFTable table = document.createTable(4,3);
      table.setWidth("100%");
      for (int row = 0; row < 3; row++) {
       for (int col = 0; col < 3; col++) {
        if (col < 2) {
         setText(table.getRow(row).getCell(col), "row " + row + ", col " + col);
        } else {
         setText(table.getRow(row).getCell(col), "" + ((row + 1) * 1234));
        }
       }
      }
    
      //set Sum row
      setText(table.getRow(3).getCell(0), "Sum:");
    
      //get paragraph from cell where the sum field shall be contained
      XWPFParagraph paragraphInCell = null;
      if (table.getRow(3).getCell(2).getParagraphs().size() == 0) paragraphInCell = table.getRow(3).getCell(2).addParagraph();
      else paragraphInCell = table.getRow(3).getCell(2).getParagraphs().get(0);
    
      //set sum field in
      CTSimpleField sumAbove = paragraphInCell.getCTP().addNewFldSimple();
      sumAbove.setInstr("=SUM(ABOVE)");
      Double sum = calculateSum(table, 2);
    System.out.println(sum);
      if (sum != null) {
       //if there is a sum, set that sum to be the cached result of the field
       sumAbove.addNewR().addNewT().setStringValue(new java.text.DecimalFormat("#.#").format(sum));
      } else {
       //set sum field dirty, so it must be calculated while opening the document
       sumAbove.setDirty(STOnOff.TRUE);
      }
    
      paragraph = document.createParagraph();
    
      FileOutputStream out = new FileOutputStream("create_table.docx"); 
      document.write(out);
      out.close();
      document.close();
     }
    }
    

    如果 Word 到 PDF 转换器没有读取该值,则它不完整。当然,您可以停止使用该字段并将计算的总和直接放入表格单元格中。但随后无法使用Word 更新总和,因为不再存在字段。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-07
    • 1970-01-01
    • 2020-05-08
    • 1970-01-01
    • 1970-01-01
    • 2016-08-12
    • 1970-01-01
    相关资源
    最近更新 更多