【问题标题】:How to add multiple rows to a table with docx4j如何使用 docx4j 向表中添加多行
【发布时间】:2018-02-12 15:18:06
【问题描述】:

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

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

【问题讨论】:

    标签: java docx4j


    【解决方案1】:

    这对我有用 - 但我的 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;
    }
    

    【讨论】:

    • @ShashankBodkhe 抱歉,我忘记了 doc 对象不是标准的帮助类,如果您对代码有任何疑问,请继续
    【解决方案2】:

    VariableReplace 不适用于重复数据。

    您可以改用 OpenDoPE 内容控件数据绑定:您将重复内容控件包裹在表格行周围。

    https://github.com/plutext/docx4j/blob/master/src/main/java/org/docx4j/model/datastorage/migration/FromVariableReplacement.java 可能有助于从 VariableReplace 迁移到 OpenDoPE。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-02
      • 2013-02-11
      • 2021-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-13
      相关资源
      最近更新 更多