develop1
develop1

Reputation: 767

poi XWPF double space

I am using the apache POI.XWPF library to create word documents. For the last couple of days I have been searching how to do double spaces for the whole document. I have checked the Apache javadocs and just by searching the internet but can't seem to find any answers.

I found the addBreak() method but it won't work because the user will input multiple paragraphs and breaking those paragraphs into single lines seemed unreasonable. If this method is used per paragraph then it won't create the double space between each line but between each paragraph.

Here is a small part of the code I currently have.

public class Paper {
        public static void main(String[] args) throws IOException, XmlException {
ArrayList<String> para = new ArrayList<String>();
        para.add("The first paragraph of a typical business letter is used to state the main point of the letter. Begin with a friendly opening; then quickly transition into the purpose of your letter. Use a couple of sentences to explain the purpose, but do not go in to detail until the next paragraph.");
        para.add("Beginning with the second paragraph, state the supporting details to justify your purpose. These may take the form of background information, statistics or first-hand accounts. A few short paragraphs within the body of the letter should be enough to support your reasoning.");

        XWPFDocument document = new XWPFDocument();

        //Calls on createParagraph() method which creates a single paragraph
        for(int i=0; i< para.size(); i++){
            createParagraph(document, para.get(i));
        }

        FileOutputStream outStream = null;
        try {
            outStream = new FileOutputStream("ResearchPaper.docx");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        try {
            document.write(outStream);
            outStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }


}

//Creates a single paragraph with a one tab indentation
    private static void createParagraph(XWPFDocument document, String para) {
        XWPFParagraph paraOne = document.createParagraph();
        paraOne.setFirstLineIndent(700); // Indents first line of paragraph to the equivalence of one tab
        XWPFRun one = paraOne.createRun();
        one.setFontSize(12);
        one.setFontFamily("Times New Roman");
        one.setText(para);
    }



}

Just to make sure my question is clear, I am trying to find out how to double space a word document (.docx). So between each line there should be one line of space. This is the same thing as pressing ctrl+2 when editing a word document.

Thank you for any help.

Upvotes: 2

Views: 1596

Answers (1)

blagae
blagae

Reputation: 2392

It appears that there isn't a high level method available for what you're trying to achieve. In that case, you'll need to delve into the low-level API of Apache POI. Below is a way of doing that. I'm not saying this is the best way to go about it, I've only found that it works for me when I want to recreate some bizarre feature of MS Word.

1. Find out where the information is stored in the document

If you need to tweak something manually, create 2 documents with as little content as possible: one that contains what you want to do, and one that doesn't. Save both as Office XML documents, because that makes it easy to read. Diff those files - there should only be a handful of changes, and you should have your location in the document structure.

For your case, this is the thing you're looking for.

Unmodified document:

<w:body><w:p> <!-- only included here so you know where to look -->
<w:pPr>
    <w:jc w:val="both" />
    <w:rPr>
        <w:lang w:val="nl-BE" />
    </w:rPr>
</w:pPr>

Modified document:

<w:body><w:p>
<w:pPr>
    <w:spacing w:line="480" w:lineRule="auto" /> <!-- BINGO -->         
    <w:jc w:val="both" />
    <w:rPr>
        <w:lang w:val="nl-BE" />
    </w:rPr>
</w:pPr>

So now you know that you need an object called spacing, that it has some properties, and that it's stored somewhere in the Paragraph object.

2. Get to that location through the low-level API, if at all possible

This part is tricky, because the XML node names are somewhat cryptic and maybe you don't know the terminology very well. Also the API isn't always a 1:1 mapping of the node names, so you have to take some guesses and just try to step through the method calls. Pro tip: download the source code for Apache POI !! You WILL step into some dead ends and you might not get where you want to be by the shortest path, but when you do you feel like an arcane Master of POI. And then you write gloating posts about it on Q&A sites.

For your case in MS Word, this is a path you might take (not necessarily the best, I'm not an expert on the high-level API):

// you probably don't need this first line
// but you'd need it if you were manipulating an existing document
IBody body = doc.getBodyElements().get(0).getBody();
for (XWPFParagraph par : body.getParagraphs()) {
    // work the crazy abbreviated API magic
    CTSpacing spacing = par.getCTP().getPPr().getSpacing();
    if (spacing == null) {
        // it looks hellish to create a CTSpacing object yourself
        // so let POI do it by setting any Spacing parameter
        par.setSpacingLineRule(LineSpacingRule.AUTO);
        // now the Paragraph's spacing shouldn't be null anymore
        spacing = par.getCTP().getPPr().getSpacing();
    }
    // you can set your value, as demonstrated by the XML
    spacing.setAfter(BigInteger.valueOf(480));
    // not sure if this one is necessary
    spacing.setLineRule(STLineSpacingRule.Enum.forString("auto"));
}

3. Bask in your glory !

Upvotes: 2

Related Questions