Question

I try to create a new table depending on input data and insert it into an docx-document. Following leads to a corrupted output file:

private Tbl getSampleTable(WordprocessingMLPackage wPMLpackage) {

        ObjectFactory factory = Context.getWmlObjectFactory();
        int writableWidthTwips = wPMLpackage.getDocumentModel().getSections().get(0).getPageDimensions().getWritableWidthTwips();
        List<Map<String, String>> data = getSampleTableData();
        TableDefinition tableDef = getSampleTableDef();
        int cols = tableDef.getColumns().size();
        int cellWidthTwips = new Double(Math.floor((writableWidthTwips / cols))).intValue();

        Tbl table = TblFactory.createTable((data.size() + 1), cols, cellWidthTwips);

        Tr headerRow = (Tr) table.getContent().get(0);

        int f = 0;
        for (Column column : tableDef.getColumns()) {
            Tc column = (Tc) headerRow.getContent().get(f);
            f++;
            Text text = factory.createText();
            text.setValue(column.getName());
            R run = factory.createR();
            run.getContent().add(text);
            column.getContent().add(run);
            headerRow.getContent().add(column);
        }
        int i = 1;

        for (Map<String, String> entry : data) {
            Tr row = (Tr) table.getContent().get(i);
            i++;
            int p = 0;
            for (String key : entry.keySet()) {
                Tc column = (Tc) row.getContent().get(p);
                p++;
                Text tx = factory.createText();
                R run = factory.createR();
                tx.setValue(entry.get(key));
                run.getContent().add(tx);
                column.getContent().add(run);
                row.getContent().add(column);
            }
        }
        return table;
    }

Without inserting the table the docx-document is created how it shall be.

I use the this function by trying to insert this table in an file that I receive as input parameter:

    ByteArrayInputStream bis = new ByteArrayInputStream(file);
    WordprocessingMLPackage wPMLpackage = null;
    wPMLpackage = WordprocessingMLPackage.load(bis);

    // Zip it up
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    SaveToZipFile saver = new SaveToZipFile(wPMLpackage);
    saver.save(baos);
    byte[] template = baos.toByteArray();

    WordprocessingMLPackage target = WordprocessingMLPackage.load(new ByteArrayInputStream(template));
    target.getMainDocumentPart().getContent().clear();

    target.getMainDocumentPart().addObject(getSampleTable(target));
    ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
    SaveToZipFile saver2 = new SaveToZipFile(target);
    saver2.save(baos2);
    return baos2.toByteArray();

Someone has an idea why the generated file can't be interpreted by Microsoft Word? The error message is "The file can't be opened as its contents causes problems". Manipulation of the document works as long as I don't insert this table.

Was it helpful?

Solution

Inserting the runs in paragraphs leads to the desired result:

 private Tbl getSampleTable(WordprocessingMLPackage wPMLpackage) {

    ObjectFactory factory = Context.getWmlObjectFactory();
    int writableWidthTwips = wPMLpackage.getDocumentModel().getSections()
                                        .get(0).getPageDimensions()
                                        .getWritableWidthTwips();
    List<Map<String, String>> data = getSampleTableData();
    TableDefinition tableDef = getSampleTableDef();
    int cols = tableDef.getColumns().size();
    int cellWidthTwips = new Double(
            Math.floor((writableWidthTwips / cols))
        ).intValue();

    Tbl table = TblFactory.createTable((data.size() + 1), cols, cellWidthTwips);

    Tr headerRow = (Tr) table.getContent().get(0);

    int f = 0;
    for (Column column : tableDef.getColumns()) {
        Tc column = (Tc) headerRow.getContent().get(f);
        P columnPara = (P) column.getContent().get(0);
        f++;
        Text text = factory.createText();
        text.setValue(column.getName());
        R run = factory.createR();
        run.getContent().add(text);
        columnPara.getContent().add(run);
    }
    int i = 1;

    for (Map<String, String> entry : data) {
        Tr row = (Tr) table.getContent().get(i);
        i++;
        int d = 0;
        for (String key : entry.keySet()) {
            Tc column = (Tc) row.getContent().get(d);
            P columnPara = (P) column.getContent().get(0);
            d++;
            Text tx = factory.createText();
            R run = factory.createR();
            tx.setValue(entry.get(key));
            run.getContent().add(tx);
            columnPara.getContent().add(run);
        }
    }
    return table;
}

OTHER TIPS

In creating a table (or anything else for that matter), one approach worth bearing in mind is to create what you want in Word, then use one of the docx4j code gen tools to generate corresponding Java code.

The code gen tool is available 2 ways:

The advantage of the Word AddIn is that you avoid the save-upload cycle.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top