Как изменить поля при конвертации с помощью Apache Poi - PullRequest
0 голосов
/ 23 сентября 2018

Мне нужно изменить поле файла PDF при преобразовании из документа Microsoft Word.

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();
        }
    }
}

Это не работает.Поле не изменяется в pdf


Но когда я делаю это:

        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();

Без преобразования в PDF это работает.

1 Ответ

0 голосов
/ 24 сентября 2018

Решение:

Настройте часть кода, связанную с sectPr и pgMar, чтобы не добавлять новые разделы, а использовать их повторно:

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));

Объяснение:

Причина проблемы в том, что конвертер XDocReport (который является отдельным проектом от Apache POI ) обрабатывает только первую запись sectPr документа.

Ваш образец сгенерирует WordprocessingML >> ниже:

<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>

, который при преобразовании в PDF будет обрабатываться так, как секунда pgmar (<w:pgMar w:bottom="620" w:left="620" w:right="620" w:top="620"/>) будет игнорироваться, посколькуэто часть второго sectPr.

То же самое время в случае сохранения скорректированного документа в новый Word документ pgMar s будет объединен, и вы увидите нужный результат (скорректированныйmargin), новый WordprocessingML будет выглядеть так:

<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>

Пример кода из раздела Solution сгенерирует один sectPr с одним pgMarпоэтому PDFConverter будет работать по мере необходимости.


Дополнительная информация:

Также neСледует упомянуть, что XDocReport предоставляет возможность конфигурации >> :

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

Но, к сожалению, невозможно обрабатывать поля таким образом (также значения полей из docx документ перезапишет их после того, как конфигурация будет выполнена в любом случае).


Дополнительно ниже pom.xml используются зависимости:

<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>
...