在 Java 中使用 Apache POI XWPF 在 Word 文档中的横向/纵向之间切换
Posted
技术标签:
【中文标题】在 Java 中使用 Apache POI XWPF 在 Word 文档中的横向/纵向之间切换【英文标题】:Switching between Landscape/portrait in word document using Apache POI XWPF in Java 【发布时间】:2015-04-02 08:19:54 【问题描述】:我试图在here 的帮助下在单个页面上设置页面方向,但没有成功。此代码 sn -p 生成一个文档,但它只将最后一页设置为横向。我不知道出了什么问题...任何帮助或指导将不胜感激!
public static void main(String[] args) throws Exception
XWPFDocument document = new XWPFDocument();
XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
run.setText("FIRST PAGE");
changeOrientation(document, "landscape");
paragraph = document.createParagraph();
run = paragraph.createRun();
run.setText("SECOND PAGE");
changeOrientation(document, "portrait");
paragraph = document.createParagraph();
run = paragraph.createRun();
run.setText("THIRD PAGE");
changeOrientation(document, "landscape");
paragraph = document.createParagraph();
run = paragraph.createRun();
run.setText("FOURTH PAGE");
FileOutputStream fos = new FileOutputStream(new File("C:/test.docx"));
document.write(fos);
fos.close();
private static void changeOrientation(XWPFDocument document, String orientation)
CTDocument1 doc = document.getDocument();
CTBody body = doc.getBody();
CTSectPr section = body.addNewSectPr();
XWPFParagraph para = document.createParagraph();
CTP ctp = para.getCTP();
CTPPr br = ctp.addNewPPr();
br.setSectPr(section);
CTPageSz pageSize = section.isSetPgSz() ? section.getPgSz() : section.addNewPgSz();
if(orientation.equals("landscape"))
pageSize.setOrient(STPageOrientation.LANDSCAPE);
pageSize.setW(BigInteger.valueOf(842 * 20));
pageSize.setH(BigInteger.valueOf(595 * 20));
else
pageSize.setOrient(STPageOrientation.PORTRAIT);
pageSize.setH(BigInteger.valueOf(842 * 20));
pageSize.setW(BigInteger.valueOf(595 * 20));
编辑: 这给了我 document.xml(看起来不正确):
<?xml version="1.0" encoding="UTF-8"?>
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"><w:body>
<w:p><w:r><w:t>FIRST PAGE</w:t></w:r></w:p>
<w:p><w:pPr><w:sectPr/></w:pPr></w:p>
<w:p><w:r><w:t>SECOND PAGE</w:t></w:r></w:p>
<w:p><w:pPr><w:sectPr/></w:pPr></w:p>
<w:p><w:r><w:t>THIRD PAGE</w:t></w:r></w:p>
<w:p><w:pPr><w:sectPr/></w:pPr></w:p>
<w:p><w:r><w:t>FOURTH PAGE</w:t></w:r></w:p>
<w:sectPr><w:pgSz w:orient="landscape" w:w="16840" w:h="11900"/></w:sectPr>
<w:sectPr><w:pgSz w:orient="portrait" w:h="16840" w:w="11900"/></w:sectPr>
<w:sectPr><w:pgSz w:orient="landscape" w:w="16840" w:h="11900"/></w:sectPr>
</w:body></w:document>
编辑 2:这就是使用 Word 创建时 document.xml 的样子(删除了一些不相关的东西......)。恐怕我在 POI 方面还不够好,无法弄清楚如何使它生成这样的 xml:
<w:p w:rsidR="004E2FF4" w:rsidRDefault="004E2FF4"><w:pPr><w:sectPr w:rsidR="004E2FF4"><w:pgSz w:w="11906" w:h="16838"/></w:sectPr></w:pPr><w:r><w:t>FIRST PAGE</w:t></w:r></w:p>
<w:p w:rsidR="004E2FF4" w:rsidRDefault="004E2FF4"><w:pPr><w:sectPr w:rsidR="004E2FF4" w:rsidSect="004E2FF4"><w:pgSz w:w="16838" w:h="11906" w:orient="landscape"/></w:sectPr></w:pPr>
<w:r><w:lastRenderedPageBreak/><w:t>SECOND PAGE</w:t></w:r></w:p><w:p w:rsidR="004E2FF4" w:rsidRDefault="004E2FF4"><w:pPr><w:sectPr w:rsidR="004E2FF4"><w:pgSz w:w="11906" w:h="16838"/></w:sectPr></w:pPr>
<w:r><w:lastRenderedPageBreak/><w:t>THIRD PAGE</w:t></w:r></w:p><w:p w:rsidR="00D70BD0" w:rsidRDefault="004E2FF4">
<w:r><w:lastRenderedPageBreak/><w:t>FOURTH PAGE</w:t></w:r></w:p><w:sectPr w:rsidR="00D70BD0" w:rsidSect="004E2FF4"><w:pgSz w:w="16838" w:h="11906" w:orient="landscape"/></w:sectPr>
编辑 3: 感谢您的指导,但我仍然无法使其 100% 正常工作。我现在已将代码更改为以下内容。但这导致设置上一页方向而不是所需的方向。其余的都不正确。 Image that shows the resulting pages
private static void changeOrientation(XWPFDocument document, String orientation, boolean pFinalSection)
CTSectPr section;
if (pFinalSection)
CTDocument1 doc = document.getDocument();
CTBody body = doc.getBody();
section = body.getSectPr() != null ? body.getSectPr() : body.addNewSectPr();
XWPFParagraph para = document.createParagraph();
CTP ctp = para.getCTP();
CTPPr br = ctp.addNewPPr();
br.setSectPr(section);
else
XWPFParagraph para = document.createParagraph();
CTP ctp = para.getCTP();
CTPPr br = ctp.addNewPPr();
section = br.addNewSectPr();
br.setSectPr(section);
CTPageSz pageSize = section.isSetPgSz() ? section.getPgSz() : section.addNewPgSz();
if(orientation.equals("landscape"))
pageSize.setOrient(STPageOrientation.LANDSCAPE);
pageSize.setW(BigInteger.valueOf(842 * 20));
pageSize.setH(BigInteger.valueOf(595 * 20));
else
pageSize.setOrient(STPageOrientation.PORTRAIT);
pageSize.setH(BigInteger.valueOf(842 * 20));
pageSize.setW(BigInteger.valueOf(595 * 20));
【问题讨论】:
您似乎没有将页面文本添加到您正在创建的部分中。如果您针对横向/纵向部分创建段落/运行会发生什么? 怎么做? CTSectPr 没有创建段落/运行的方法...不是 br.setSectPr(section); 行吗?应该将此段设置为本节? 我不确定。如果您在 word 中创建一个包含几个不同部分的简单 .docx,然后解压缩 .docx 文件(它是 xml 的 zip),这些段落是如何绑定到它们的部分的? 在帖子中编辑以包含生成的 document.xml。不知何故,我需要将段落绑定到正确的部分。试图将文本添加到在方法 changeOrientation 中创建的段落中,但没有成功... 尝试在 Word 中创建相同的示例文档,解压缩 word 生成的版本,然后发布其中的(关键)部分,展示 Word 是如何执行这些部分的 【参考方案1】:请在Landscape and portrait pages in the same word document using Apache POI XWPF in Java 的帖子中查看我对同一问题的回答。
根据OOXML规范ECMA-376, Fourth Edition, Part 1 - Fundamentals And Markup Language Reference - 17.6.18 sectPr(Section Properties),在具有多个section的文档中,section属性(sectPr元素)存储为:的子元素:
该部分的最后一段,适用于除最后一段之外的所有部分 部分, body 元素,用于最后一节。您可以使用CTPPr
的addNewSectPr
方法为其添加CTSectPr
。
CTBody
的末尾有一个 CTSectPr
。您可以使用getSectPr
方法获取它。
【讨论】:
根据 OOXML 规范,CTSectPr
应该出现在节的末尾。所以你应该在创建节段落之后而不是之前设置CTSectPr
。
现在(几乎)可以工作了。感谢你的帮助!声望不足,无法投票,抱歉...以上是关于在 Java 中使用 Apache POI XWPF 在 Word 文档中的横向/纵向之间切换的主要内容,如果未能解决你的问题,请参考以下文章
缺少Java org.apache.poi.unsupportedfileformatexception
求解!JAVA 使用Apache POI将PPTX转图片出错。见下图