如何在表格单元格内插入内容控件

input文件:
input.docx (10.0 KB)

这是我的原代码:

public static void main(String[] args) throws Exception {
    String filename1 = "D:\\input.docx";
    String filename2 = "D:\\output.docx";
    String bookmarkName = "bookmark";
    Document document = new Document(filename1);
    DocumentBuilder documentBuilder = new DocumentBuilder(document);
    BookmarkCollection bookmarkList = document.getRange().getBookmarks();
    List<Bookmark> bookmarks = new ArrayList<>();
    for (Bookmark bookmark : bookmarkList) {
        bookmarks.add(bookmark);
    }
    // 获取书签
    Bookmark bookmark = bookmarks.stream()
            .filter(item -> item.getName().equals(bookmarkName))
            .findFirst().orElse(null);
    if (bookmark == null) {
        log.warn("未扫描到书签", bookmarkName);
        return;
    }
    // 置为空值
    bookmark.setText("");
    // 文档指针移动到书签位置
    documentBuilder.moveToBookmark("bookmark", true, true);
    documentBuilder.write(" ");
    // 新建表格
    documentBuilder.startTable();
    documentBuilder.insertCell();
    documentBuilder.write("姓名1");
    documentBuilder.insertCell();
    documentBuilder.write("年龄1");
    documentBuilder.endRow();
    documentBuilder.insertCell();
    documentBuilder.write("姓名2");
    documentBuilder.insertCell();
    documentBuilder.write("年龄2");
    documentBuilder.endRow();
    // 结束表格
    documentBuilder.endTable();
    document.save(filename2);
}

但是我希望插入每个单元格内容时插入内容控件,比如test文件:
test.docx (14.8 KB)

文档结构是这样:

@whitemeen 您可以使用以下代码对表格进行后处理来实现此目的:

for(Row r : t.getRows())
{
    for(Cell c : r.getCells())
    {
        // Create SDT for cell
        StructuredDocumentTag tag = new StructuredDocumentTag(document, SdtType.RICH_TEXT, MarkupLevel.CELL);
        tag.removeAllChildren();
        tag.isShowingPlaceholderText(false);
        // Put the tag before the cell and move cell inside the inserted SDT.
        c.getParentNode().insertBefore(tag, c);
        tag.appendChild(c);
    }
}

以下是我这边生成的输出结果:out.docx (13.9 KB)

我们会存在非常复杂的场景,比如以下仅在非加粗的数据位置插入内容控件,甚至更复杂,所以我希望在写入数据的同时插入StructuredDocumentTag内容控件

public static void main(String[] args) throws Exception {
    String filename1 = "D:\\input.docx";
    String filename2 = "D:\\output.docx";
    String bookmarkName = "bookmark";
    String[] headers = new String[]{"合同名称", "合同编号"};
    List<String[]> tableData = new ArrayList<>();
    String[] tableData1 = new String[]{"数据-合同名称1", "数据-合同编号1"};
    String[] tableData2 = new String[]{"数据-合同名称2", "数据-合同编号2"};
    tableData.add(tableData1);
    tableData.add(tableData2);
    Document document = new Document(filename1);
    DocumentBuilder documentBuilder = new DocumentBuilder(document);
    BookmarkCollection bookmarkList = document.getRange().getBookmarks();
    List<Bookmark> bookmarks = new ArrayList<>();
    for (Bookmark bookmark : bookmarkList) {
        bookmarks.add(bookmark);
    }
    // 获取书签
    Bookmark bookmark = bookmarks.stream()
            .filter(item -> item.getName().equals(bookmarkName))
            .findFirst().orElse(null);
    if (bookmark == null) {
        log.warn("未扫描到书签", bookmarkName);
        return;
    }
    // 置为空值
    bookmark.setText("");
    // 文档指针移动到书签位置
    documentBuilder.moveToBookmark("bookmark", true, true);
    documentBuilder.write(" ");
    // 新建表格
    documentBuilder.startTable();
    documentBuilder.insertCell();
    documentBuilder.setBold(true);
    documentBuilder.write("项目名称");
    documentBuilder.setBold(false);
    documentBuilder.insertCell();
    documentBuilder.write("数据-xx项目");
    documentBuilder.endRow();
    documentBuilder.setBold(true);
    // 输出表头
    for (String header : headers) {
        documentBuilder.insertCell();
        documentBuilder.write(header);
    }
    documentBuilder.setBold(false);
    documentBuilder.endRow();
    // 输出数据
    for (String[] rowDate : tableData) {
        for (int i = 0; i < rowDate.length; i++) {
            documentBuilder.insertCell();
            documentBuilder.write(rowDate[i]);
        }
        // 结束当前行
        documentBuilder.endRow();
    }
    // 结束表格
    documentBuilder.endTable();
    document.save(filename2);
}

@whitemeen 在这种情况下,我建议收集需要用SDT封装的单元格,然后按照上述方法进行后处理。恐怕没有更简单的方法可以实现您的需求。