相关文章推荐
风流的书签  ·  std=train_x.std(axis=0 ...·  7 月前    · 
忐忑的灯泡  ·  Go ...·  8 月前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I need to change the margin of the PDF file when I convert from Microsoft Word document.

public class TestCon {
    public static final String DEST = "./test.pdf";
    public static final String SRC = "./test.docx";
    public static void main(String[] args) {
        try {
            InputStream doc = new FileInputStream(new File(SRC));
            XWPFDocument document = new XWPFDocument(doc );
            CTSectPr addNewSectPr = document.getDocument().getBody().addNewSectPr();
            CTPageMar addNewPgMar = addNewSectPr.addNewPgMar();
            addNewPgMar.setLeft(BigInteger.valueOf(720L));
            addNewPgMar.setTop(BigInteger.valueOf(720L));
            addNewPgMar.setRight(BigInteger.valueOf(720L));
            addNewPgMar.setBottom(BigInteger.valueOf(720L));
            OutputStream out = new FileOutputStream(new File(DEST));
            PdfOptions options = PdfOptions.create();
            PdfConverter.getInstance().convert(document, out, options);
        } catch (Throwable e) {
            e.printStackTrace();

This does not work. The margin does not change in pdf

But when I do this:

        FileOutputStream out = new FileOutputStream(new File(SRC1));
        InputStream doc = new FileInputStream(new File(SRC));
        XWPFDocument document = new XWPFDocument(doc );
        CTSectPr addNewSectPr = document.getDocument().getBody().addNewSectPr();
        CTPageMar addNewPgMar = addNewSectPr.addNewPgMar();
        addNewPgMar.setLeft(BigInteger.valueOf(720L));
        addNewPgMar.setTop(BigInteger.valueOf(720L));
        addNewPgMar.setRight(BigInteger.valueOf(720L));
        addNewPgMar.setBottom(BigInteger.valueOf(720L));
        document.write(out);
        out.close();

Without converting to PDF, it works.

Solution:

Adjust code part related to sectPr and pgMar to not add new sections, but reuse them:

CTSectPr getSectPr = document.getDocument().getBody().getSectPr();
getSectPr.unsetPgMar();
CTPageMar addNewPgMar = getSectPr.addNewPgMar();
addNewPgMar.setLeft(BigInteger.valueOf(720L));
addNewPgMar.setTop(BigInteger.valueOf(720L));
addNewPgMar.setRight(BigInteger.valueOf(720L));
addNewPgMar.setBottom(BigInteger.valueOf(720L));
// Also good to handle footer and header for more expectable result
addNewPgMar.setFooter(BigInteger.valueOf(0L));
addNewPgMar.setHeader(BigInteger.valueOf(0L));

Explanation:

Reason of the issue is that XDocReport converter (which is a separate project from Apache POI) handles only the first sectPr entry of the document.

Your sample will generate WordprocessingML >> below:

<w:sectPr w:rsidR="003F19CD" w:rsidRPr="005E1322">
  <w:pgSz w:h="16838" w:w="11906"/>
  <w:pgMar w:bottom="1134" w:footer="708" w:header="708" w:left="1701" w:right="850" w:top="1134"/>
  <w:cols w:space="708"/>
  <w:docGrid w:linePitch="360"/>
</w:sectPr>
<w:sectPr>
  <w:pgMar w:bottom="620" w:left="620" w:right="620" w:top="620"/>
</w:sectPr>

Which during conversion to PDF will be handled in the way second pgmar (<w:pgMar w:bottom="620" w:left="620" w:right="620" w:top="620"/>) will be ignored, since it is part of the second sectPr.

Same time in case of saving adjusted document to a new Word document pgMars will be merged and you will see needed result (adjusted margin), new WordprocessingML will look so:

<w:sectPr w:rsidR="003F19CD" w:rsidRPr="005E1322">
  <w:pgSz w:h="16838" w:w="11906"/>
  <w:pgMar w:left="620" w:top="620" w:right="620" w:bottom="620" w:footer="0" w:header="0"/>
  <w:cols w:space="708"/>
  <w:docGrid w:linePitch="360"/>
</w:sectPr>
<w:sectPr>
  <w:pgMar w:bottom="620" w:left="620" w:right="620" w:top="620"/>
</w:sectPr>

Additional information:

Also need to mention that XDocReport provides configuration possibility >>:

options.setConfiguration(new IPdfWriterConfiguration() {
    public void configure(PdfWriter writer) {
        writer.setPDFXConformance(PdfWriter.PDFA1A);

But unfortunately it is not possible to handle margins this way (also margin values from the docx document will overwrite them after configuration will be done anyway).

Additionally below is pom.xml dependencies used:

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.15</version>
</dependency>
<dependency>
    <groupId>fr.opensagres.xdocreport</groupId>
    <artifactId>fr.opensagres.poi.xwpf.converter.pdf</artifactId>
    <version>2.0.1</version>
</dependency>
                Thank you so much! At me one more question, and whether it is possible by means of WordprocessingML to make auto hyphenation?
– crazy_deviL
                Sep 25, 2018 at 9:05
                @crazy_deviL, it supports since it is an XML-based document format developed by Microsoft for Excel and Word documents. Please read this question >> for additional details where auto hyphenation configuration is stored. But it doesn't imply that XDocReport's converter will support auto hyphenation (you can test it simply and see that it doesn't).
– marme1ad
                Sep 25, 2018 at 13:33
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.