Create table with docx4j

user1335772 picture user1335772 · Nov 13, 2013 · Viewed 12.6k times · Source

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.

Answer

user1335772 picture user1335772 · Nov 15, 2013

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