如何使用 apache poi 在 docx 中计算 =SUM(Above) 函数
How to compute =SUM(Above) function in docx using apache poi
我正在尝试使用 apache poi 处理 docx 格式文件,但我一直坚持使用 table 中的公式。例如看图片:
我曾尝试将文本设置为“=SUM(ABOVE)”,但这种方式不起作用。
我想我可能需要在此处设置自定义 xml 数据,但我不确定如何进行。我尝试了以下代码:
XWPFTable table = document.createTable();
//create first row
XWPFTableRow tableRowOne = table.getRow(0);
table.getRow(0).createCell();
table.getRow(0).getCell(0).setText("10");
table.getRow(0).createCell();
table.getRow(0).getCell(1).setText("=SUM(ABOVE)");
遇到这样的需求我是这样处理的:
首先,使用 Word
GUI
创建包含所需内容的最简单的 Word
文档。然后查看 Word
创建的内容,了解需要使用 apache poi
.
创建的内容
具体来说:
在 Word
中创建尽可能简单的 table,其中有一个字段 {=SUM(ABOVE)}
。将其保存为 *.docx
。现在解压缩 *.docx
(Office Open XML 文件,如 *.docx
只是 ZIP
存档)。查看该存档中的 /word/document.xml
。在那里你会发现类似的东西:
<w:tc>
<w:p>
<w:fldSimple w:instr="=SUM(ABOVE)"/>
...
</w:p>
</w:tc>
这是 XML
的 table 单元格,其段落中有一个 fldSimple
元素,其中 instr
属性包含公式。
现在我们知道了,我们需要 table 单元格 XWPFTableCell
和其中的 XWPFParagraph
。然后我们需要在此段落中设置一个 fldSimple
元素,其中 instr
属性包含公式。
这就像
一样简单
paragraphInCell.getCTP().addNewFldSimple().setInstr("=SUM(ABOVE)");
但当然必须告诉 Word
打开文档时需要计算公式。最简单的解决方案是设置字段 "dirty"。这导致需要在 Word
中打开文档时更新字段。它还会导致关于需要更新的确认消息对话框。
使用 apache poi 4.1.0
的完整示例:
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 {
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) table.getRow(row).getCell(col).setText("row " + row + ", col " + col);
else table.getRow(row).getCell(col).setText("" + ((row + 1) * 1234));
}
}
//set Sum row
table.getRow(3).getCell(0).setText("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)");
//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();
}
}
这一切只有在使用 Microsoft Word
打开文档时才能正常工作。 LibreOffice Writer
无法将此类公式字段存储为 Office Open XML
(*.docx
) 格式,也无法正确读取此类 Office Open XML
公式字段。
我正在尝试使用 apache poi 处理 docx 格式文件,但我一直坚持使用 table 中的公式。例如看图片:
我曾尝试将文本设置为“=SUM(ABOVE)”,但这种方式不起作用。 我想我可能需要在此处设置自定义 xml 数据,但我不确定如何进行。我尝试了以下代码:
XWPFTable table = document.createTable();
//create first row
XWPFTableRow tableRowOne = table.getRow(0);
table.getRow(0).createCell();
table.getRow(0).getCell(0).setText("10");
table.getRow(0).createCell();
table.getRow(0).getCell(1).setText("=SUM(ABOVE)");
遇到这样的需求我是这样处理的:
首先,使用 Word
GUI
创建包含所需内容的最简单的 Word
文档。然后查看 Word
创建的内容,了解需要使用 apache poi
.
具体来说:
在 Word
中创建尽可能简单的 table,其中有一个字段 {=SUM(ABOVE)}
。将其保存为 *.docx
。现在解压缩 *.docx
(Office Open XML 文件,如 *.docx
只是 ZIP
存档)。查看该存档中的 /word/document.xml
。在那里你会发现类似的东西:
<w:tc>
<w:p>
<w:fldSimple w:instr="=SUM(ABOVE)"/>
...
</w:p>
</w:tc>
这是 XML
的 table 单元格,其段落中有一个 fldSimple
元素,其中 instr
属性包含公式。
现在我们知道了,我们需要 table 单元格 XWPFTableCell
和其中的 XWPFParagraph
。然后我们需要在此段落中设置一个 fldSimple
元素,其中 instr
属性包含公式。
这就像
一样简单paragraphInCell.getCTP().addNewFldSimple().setInstr("=SUM(ABOVE)");
但当然必须告诉 Word
打开文档时需要计算公式。最简单的解决方案是设置字段 "dirty"。这导致需要在 Word
中打开文档时更新字段。它还会导致关于需要更新的确认消息对话框。
使用 apache poi 4.1.0
的完整示例:
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 {
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) table.getRow(row).getCell(col).setText("row " + row + ", col " + col);
else table.getRow(row).getCell(col).setText("" + ((row + 1) * 1234));
}
}
//set Sum row
table.getRow(3).getCell(0).setText("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)");
//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();
}
}
这一切只有在使用 Microsoft Word
打开文档时才能正常工作。 LibreOffice Writer
无法将此类公式字段存储为 Office Open XML
(*.docx
) 格式,也无法正确读取此类 Office Open XML
公式字段。