apache poi 或 docx4j 中的 SUM(ABOVE) 功能 [英] SUM(ABOVE) functionality in apache poi or docx4j

查看:51
本文介绍了apache poi 或 docx4j 中的 SUM(ABOVE) 功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am trying to implement =SUM(ABOVE) function in docx which is used to sum all elements above to tht column. I was able to implement this with apache poi using :

    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 的情况下将其转换为 pdf,则此功能不会运行.Aspose 有函数调用:

This is ok when someone opens the document and it calculates it. But if I need to convert the document without opening it to pdf then this function doesnt run. Aspose has function called :

Document.UpdateFields

它具有所需的功能,但这是付费应用程序.

which does the required functionality but this is paid application.

我们可以使用 apche poi 或 docx4j 来实现相同的功能吗

Can we implement the same functionality using apche poi or docx4j

推荐答案

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

If you don't want set the field dirty, then you need calculating the sum your own. Following is a working draft for a method to calculate the sum of table cell values of a special column of a 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 一样为字段设置缓存值.

If you have the sum, then CTSimpleField needs to get a text run having the sum set as text value. Then this the same as Word does to set cached value for the field.

完整示例:

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-to-PDF 转换器没有读取该值,则它是不完整的.当然,您可以停止使用该字段并将计算出的总和直接放入表格单元格中.但是,由于不再有字段,因此无法使用 Word 更新总和.

If the Word-to-PDF converter don't read the value, then it is incomplete. Of course you could stop using the field and put the calculated sum directly into the table cell. But then updating the sum using Word is not possible since there is not a field anymore.

这篇关于apache poi 或 docx4j 中的 SUM(ABOVE) 功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆