2
votes

Is it possible to create new header for every different sections using docx4j?

I've seen that MS Word provides functionality to create different headers by creating different sections using section breaks. But I want to implement this functionality using docx4j.

For example: If I've to create a docx files that may contains list of products, some terms and conditions, and some other sections. And I want title for each section to be displayed at top with paging (Like Product Summary: Page 1 of 2, Terms & Conditions: Page 3 of 3).

Also I'm using MainDocumentPart.addAltChunk() method to write html content in the document for creating Document.

Thanks in Advance.

--

Regards,

Sanshey Sachdeva

3
Yes it is possible. Create a docx in Word setup as you'd like it, then run it through the docx4j demo webapp to see the contents of the sectPr elements. You can also use the demo webapp to generate code (but not for creating and adding the header/footer part objects themselves). - JasonPlutext
Sorry. But, I'm new in this so, it is very difficult for me to understand docx file as the collection of xml files to get what I want and then implement it in docx4j. I've searched on net that I can use different headers but with some limitations like setting front page header or even/odd page header. But, I didn't find the solution to set different header for a section in the middle of document. - Sanshey Sachdeva
Did you try my suggestion "Create a docx in Word [with headers] setup as you'd like it, then run it through the docx4j demo webapp"? - JasonPlutext
Hello JasonPlutext, I didn't find any option to generate code through docx4j demo webapp (webapp.docx4java.org/OnlineDemo/demo_landing.html). It only generated xmls when I clicked 1st link and on clicking last link (Merge docx), I got the generated code but it uses Plutext Library which is paid library. So is there any other way to do this, if not possible in docx4j, then in poi, java. - Sanshey Sachdeva
The link that generates xml is the one you want. Click on an XML element (eg sectPr element, or an element in a header part) and it will generate corresponding code. That leaves creating and adding the actual header parts: maindocumentpart.addPart(headerPart) will return the relId you need to use in the header ref in the sectPr. If this doesn't make sense, I may have time to write a blog post walk through tomorrow. - JasonPlutext

3 Answers

1
votes

Finally I got the solution.

Below mentioned method creates as many headers as I want.

private static int countHeader = 0;

public static void createHeaderForSection(WordprocessingMLPackage wordprocessingMLPackage, String headerString) throws Exception {
    MainDocumentPart documentPart = wordprocessingMLPackage.getMainDocumentPart();
    HeaderPart headerPart = new HeaderPart(new PartName("/word/header"+ (++countHeader) +".xml"));
    headerPart.setPackage(wordprocessingMLPackage);
    headerPart.addAltChunk(AltChunkType.Html, headerString.getBytes("UTF-8"));
    headerPart.setRelationshipType(Namespaces.HEADER);
    Relationship relationship = documentPart.addTargetPart(headerPart);
    SectPr sectPr = objectFactory.createSectPr();
    HeaderReference headerReference = factory.createHeaderReference();
    headerReference.setId(relationship.getId());
    headerReference.setType(HdrFtrRef.DEFAULT);
    sectPr.getEGHdrFtrReferences().add(headerReference);
    P p = objectFactory.createP();
    PPr ppr = objectFactory.createPPr();
    p.setPPr(ppr);
    ppr.setSectPr(sectPr);
    wordprocessingMLPackage.getMainDocumentPart().getContent().add(p);
}

But, Still I'm unable to find out how to introduce paging in each section while using headerPart.addAltChunk();

1
votes

Finally I got the solution.

Below piece of code allows me to handle sections:

SectPr sectPr = null;
if(isLastSection){
    List<SectionWrapper> sections = wordprocessingMLPackage.getDocumentModel().getSections();
    sectPr = sections.get(sections.size() - 1).getSectPr();
    if (sectPr==null ) {
        sectPr = objectFactory.createSectPr();
        wordprocessingMLPackage.getMainDocumentPart().addObject(sectPr);
        sections.get(sections.size() - 1).setSectPr(sectPr);
    }
}
else{
    sectPr = objectFactory.createSectPr();
}

This code allows me to create separate header for each section:

HeaderPart headerPart = new HeaderPart(new PartName("/word/header"+ (countHeader++) +".xml"));
headerPart.setPackage(wordprocessingMLPackage);
headerPart.setRelationshipType(Namespaces.HEADER);
headerPart.setJaxbElement(objectFactory.createHdr());
Relationship relationship = documentPart.addTargetPart(headerPart);
HeaderReference headerReference = objectFactory.createHeaderReference();
headerReference.setId(relationship.getId());
headerReference.setType(HdrFtrRef.DEFAULT);
sectPr.getEGHdrFtrReferences().add(headerReference);

This piece of code allows me to create separate paging for each section:

CTPageNumber ctPageNumber = objectFactory.createCTPageNumber();
ctPageNumber.setStart(BigInteger.ONE);
sectPr.setPgNumType(ctPageNumber);
0
votes

I did it for Footer as well

 FooterPart footerPart = new FooterPart(new PartName("/word/footer"+ (countHeader) +".xml"));
 footerPart.setPackage(pkg);
 footerPart.setRelationshipType(Namespaces.FOOTER);
 footerPart.setJaxbElement(objectFactory.createFtr());
 Relationship relationshipF = documentPart.addTargetPart(footerPart);
 FooterReference footerReference = objectFactory.createFooterReference();
 footerReference.setId(relationshipF.getId());
 footerReference.setType(HdrFtrRef.DEFAULT);
 sectPr.getEGHdrFtrReferences().add(footerReference);

Thanks for the direction and it worked fine.