apache poi 或 docx4j 中的 SUM(ABOVE) 功能 [英] SUM(ABOVE) functionality in apache poi or docx4j
问题描述
我正在尝试在 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屋!