0

I have tried to set page orientation on single pages with help from here with no luck. This code snippet generates a document, but it only sets the last page to landscape. I can't figure out what is wrong... Any help or guidance would be appreciated!

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

EDIT: This give me the document.xml (which don't look right):

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

EDIT 2: This is how the document.xml looks like when created with Word (with some irrelevant stuff removed...). I'm afraid that I'm noot good enough at POI to figure out what to do to make it generate the xml like this instead:

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

Edit 3: Thanks for the nice guiding, but I can still not get it to work 100%. I have now changed the code to the following. But this resulting in setting the previous page orientation instead of the desired one. And the rest is not getting correct. 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));
    }
}
Community
  • 1
  • 1
Tobias Sjöbeck
  • 151
  • 2
  • 8
  • You don't appear to be adding the page text into the sections you're creating. What happens if you create the paragraphs/runs against the landscape/portrait sections? – Gagravarr Apr 02 '15 at 11:34
  • How to do that? The CTSectPr has no method to create paragraphs/runs... Isn't the line br.setSectPr(section); supposed to set this paragraph to this section? – Tobias Sjöbeck Apr 07 '15 at 07:22
  • Not sure off the top of my head. If you create a simple .docx in word with a few different sections, then unzip the .docx file (it's a zip of xml), how were the paragraphs tied back to their sections? – Gagravarr Apr 07 '15 at 17:17
  • Edit in the post to include the generated document.xml. Somehow I need to bind the paragraphs to the correct sections. Tried to add the text to the paragraph created in the method changeOrientation instead with no luck... – Tobias Sjöbeck Apr 08 '15 at 12:49
  • Try creating the same sample document in Word, unzip the word generated version, and post the (key) part of that showing how Word did the sections – Gagravarr Apr 08 '15 at 12:53
  • Added the relevant part of the xml of the document generated by Word in the post. – Tobias Sjöbeck Apr 09 '15 at 11:39

1 Answers1

4

Please check my answer to the same problem in the post Landscape and portrait pages in the same word document using Apache POI XWPF in Java.

According to OOXML Specification ECMA-376, Fourth Edition, Part 1 - Fundamentals And Markup Language Reference - 17.6.18 sectPr (Section Properties), in a document with multiple sections, section properties (the sectPr element) are stored as the child element of :

  • the last paragraph in the section, for all sections except the final section,
  • the body element, for the final section.

You can use addNewSectPr method of CTPPr to add a CTSectPr to it. CTBody has a CTSectPr at end of it. You can get it using getSectPr method.

Community
  • 1
  • 1
bbhar
  • 599
  • 5
  • 8
  • According to OOXML specification a `CTSectPr` should come at the end of a section. So you should set `CTSectPr` after creating the section paragraphs not before. – bbhar Apr 17 '15 at 06:58
  • Got it to (almost) work now. Thanks for all your help! Not enough reputation to vote up, sorry... – Tobias Sjöbeck Apr 21 '15 at 09:31