apache poi 或 docx4j 中的 SUM(ABOVE) 功能
SUM(ABOVE) functionality in apache poi or docx4j
我正在尝试在 docx 中实现 =SUM(ABOVE) 函数,该函数用于将上面的所有元素求和到该列。我能够使用 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 实现相同的功能
如果你不想设置脏字段,那么你需要自己计算总和。以下是计算 XWPFTable
的特殊列的 table 单元格值之和的方法的工作草案:
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 转换器不读取该值,则它是不完整的。当然,您可以停止使用该字段并将计算出的总和直接放入 table 单元格中。但是由于不再有字段,因此无法使用 Word
更新总和。
我正在尝试在 docx 中实现 =SUM(ABOVE) 函数,该函数用于将上面的所有元素求和到该列。我能够使用 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 实现相同的功能
如果你不想设置脏字段,那么你需要自己计算总和。以下是计算 XWPFTable
的特殊列的 table 单元格值之和的方法的工作草案:
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 转换器不读取该值,则它是不完整的。当然,您可以停止使用该字段并将计算出的总和直接放入 table 单元格中。但是由于不再有字段,因此无法使用 Word
更新总和。