在apache poi或docx4j中的SUM(ABOVE)功能。

问题描述 投票:0回答:1

我试图在docx中实现=SUM(ABOVE)函数,用于将上面的所有元素加到tht列中。我可以用apache poi的.NET技术实现这个功能。

    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有一个叫做.NET的函数,它可以实现所需的功能,但是这个函数是不运行的。

Document.UpdateFields

的函数,但这是付费的应用程序。

我们能否用apche poi或docx4j实现同样的功能?

java apache-poi docx docx4j
1个回答
2
投票

如果你不想设置字段为脏,那么你需要自己计算总和。以下是一个工作草案,用于计算一个特殊列的表格单元格值之和的方法。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-to-PDF转换器不读取该值,那么它就是不完整的。当然你可以停止使用该字段,直接将计算出的总和放入表格单元格中。但是如果使用 Word 是不可能的,因为现在已经没有场子了。

© www.soinside.com 2019 - 2024. All rights reserved.