我试图在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实现同样的功能?
如果你不想设置字段为脏,那么你需要自己计算总和。以下是一个工作草案,用于计算一个特殊列的表格单元格值之和的方法。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
是不可能的,因为现在已经没有场子了。