如何使用docx4j向表中添加多行

9q78igpj  于 2021-07-03  发布在  Java
关注(0)|答案(2)|浏览(406)

我有一个表,我需要向其中添加多行,而不是您在图像中看到的变量。我用的是docx4j。

我这样改变变量:

HashMap mappings = new HashMap();
VariablePrepare.prepare(template);
mappings.put("example", "example");
template.getMainDocumentPart().variableReplace(mappings);
6uxekuva

6uxekuva1#

这对我很有用,但是我的word模板中没有列标题,所以小心它们可能会破坏这个功能。
只要正确地填充hashmap,如果一切都设置正确,它应该可以开箱即用;)
以下是我用于替换的3个功能:

private void replaceTable(String[] placeholders, List<Map<String, String>> textToAdd, WordprocessingMLPackage template) throws Docx4JException, JAXBException {
    List<Object> tables = doc.getAllElementFromObject(template.getMainDocumentPart(), Tbl.class);
    Tbl tempTable = getTemplateTable(tables, placeholders[0]);
    List<Object> rows = doc.getAllElementFromObject(tempTable, Tr.class);
    if (rows.size() == 1) { //careful only tables with 1 row are considered here
        Tr templateRow = (Tr) rows.get(0);
        for (Map<String, String> replacements : textToAdd) {
            addRowToTable(tempTable, templateRow, replacements);
        }
        assert tempTable != null;
        tempTable.getContent().remove(templateRow);
    }
}

private void addRowToTable(Tbl reviewTable, Tr templateRow, Map<String, String> replacements) {
    Tr workingRow = (Tr) XmlUtils.deepCopy(templateRow);
    List<?> textElements = doc.getAllElementFromObject(workingRow, Text.class);
    for (Object object : textElements) {
        Text text = (Text) object;
        String replacementValue = (String) replacements.get(text.getValue());
        if (replacementValue != null)
            text.setValue(replacementValue);
    }
    reviewTable.getContent().add(workingRow);
}

private Tbl getTemplateTable(List<Object> tables, String templateKey) throws Docx4JException, JAXBException {
    for (Object tbl : tables) {
        List<?> textElements = doc.getAllElementFromObject(tbl, Text.class);
        for (Object text : textElements) {
            Text textElement = (Text) text;
            if (textElement.getValue() != null && textElement.getValue().equals(templateKey))
                return (Tbl) tbl;
        }
    }
    return null;
}

下面是如何用它来举例:

ArrayList<Map<String, String>> list = new ArrayList<>();
//Create a loop here through all entries
Map<String, String> entry = new HashMap<>();
entry.put("${nrCrt}", "1");
list.add(entry);
//...
entry.put("${tva}", "55");
list.add(entry);
entry.put("${nrCrt}", "2");
list.add(entry);
//...

replaceTable(new String[]{"${nrCrt}"}, list, template);

我忘了提: doc 只是一个助手类,这是 getAllElementFromObject :

public List<Object> getAllElementFromObject(Object obj, Class<?> toSearch) {
    List<Object> result = new ArrayList<Object>();
    if (obj instanceof JAXBElement) obj = ((JAXBElement<?>) obj).getValue();

    if (obj.getClass().equals(toSearch))
        result.add(obj);
    else if (obj instanceof ContentAccessor) {
        List<?> children = ((ContentAccessor) obj).getContent();
        for (Object child : children) {
            result.addAll(getAllElementFromObject(child, toSearch));
        }
    }
    return result;
}
vuktfyat

vuktfyat2#

variablereplace不用于重复数据。
可以改用opendope内容控件数据绑定:在表行周围 Package 一个repeat content控件。
https://github.com/plutext/docx4j/blob/master/src/main/java/org/docx4j/model/datastorage/migration/fromvariablereplacement.java 可能有助于从variableplace迁移到opendope。

相关问题