You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何不依赖表格行,通过OpenTBS生成可纳入目录的动态层级DOCX内容

如何不依赖表格行,通过OpenTBS生成可纳入目录的动态层级DOCX内容

我太懂这种用表格硬凑层级内容的憋屈了——既不优雅还容易留格式坑。其实OpenTBS完全可以直接用段落块来实现你的需求,还能完美适配DOCX的目录识别,我给你捋一套更简洁的方案:

第一步:先把数据结构优化成嵌套型(核心!)

你原来的扁平数组重复了大量父级数据,不仅冗余还容易出错。改成嵌套结构后,层级关系一目了然,Merge的时候也更省心:

$docxdata = [
    [
        "id" => 280,
        "title" => "I. Formalien",
        "content" => "",
        "children" => [
            [
                "id" => 281,
                "title" => "I.1. Verantwortliche Stelle",
                "content" => "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
                "children" => []
            ]
        ]
    ],
    [
        "id" => 283,
        "title" => "II. Prüfplanung",
        "content" => "",
        "children" => [
            [
                "id" => 284,
                "title" => "II.1. Zusammenstellung des Teams",
                "content" => "",
                "children" => [
                    [
                        "id" => 285,
                        "title" => "II.1.1. Datenschutzbeauftragter",
                        "content" => "Mr. A",
                        "children" => []
                    ],
                    [
                        "id" => 286,
                        "title" => "II.1.2. Vertretung des betrieblichen Datenschutzbeauftragten",
                        "content" => "Mr. B",
                        "children" => []
                    ]
                ]
            ]
        ]
    ],
    [
        "id" => 287,
        "title" => "III. Angaben zur zu prüfenden Datenverarbeitung",
        "content" => "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
        "children" => []
    ]
];

第二步:调整PHP的Merge逻辑

不用复杂的parentgrp,直接用嵌套块合并就能搞定层级:

$TBS = new clsTinyButStrong;
$TBS->Plugin(TBS_INSTALL, OPENTBS_PLUGIN);
$TBS->LoadTemplate($param["template"], OPENTBS_ALREADY_UTF8);

// 合并主层级(一级标题)
$TBS->MergeBlock('b', $docxdata);
// 合并二级子层级
$TBS->MergeBlock('b.child', $docxdata);
// 合并三级子层级
$TBS->MergeBlock('b.child.child', $docxdata);

$TBS->Show(OPENTBS_DOWNLOAD, "document.docx");

第三步:DOCX模板写法(核心中的核心!)

这部分完全脱离表格,直接用段落+内置标题样式(必须用内置样式,不然DOCX目录识别不了),配合OpenTBS的块控制:

模板内容(直接在DOCX的空白段落里写,不要用表格)

<!-- 一级标题块:提前给这个段落设置「Heading 1」样式 -->
[b.title;block=tbs:p;when [b.id] != '';sub1]
[onshow;block=begin;enlarge=tbs:p;when [b.content] != '']
[b.content;enlarge=tbs:p]
[onshow;block=end]

<!-- 二级标题块:提前给这个段落设置「Heading 2」样式 -->
[b.child.title;block=tbs:p;when [b.child.id] != '';sub2]
[onshow;block=begin;enlarge=tbs:p;when [b.child.content] != '']
[b.child.content;enlarge=tbs:p]
[onshow;block=end]

<!-- 三级标题块:提前给这个段落设置「Heading 3」样式 -->
[b.child.child.title;block=tbs:p;when [b.child.child.id] != '';sub3]
[onshow;block=begin;enlarge=tbs:p;when [b.child.child.content] != '']
[b.child.child.content;enlarge=tbs:p]
[onshow;block=end]

关键细节说明:

  • 标题样式必须提前设置:在Word模板里,选中对应标签的段落,在「开始」选项卡中选择对应的内置标题样式(Heading 1/2/3)。DOCX的目录是基于这些内置样式识别的,这一步是标题能进目录的核心。
  • block=tbs:p的作用:告诉OpenTBS以段落为单位合并,不会破坏原有格式,也不会强制分页。
  • enlarge=tbs:p:确保内容段落可以自动扩展,不会因为内容过长被截断或强制分页。
  • when条件判断:只有当id或内容不为空时才生成对应段落,避免出现空行或空白标题。

最后验证效果

生成DOCX后,右键目录选择「更新域→更新整个目录」,就能看到所有层级标题都完美纳入目录了,整个文档没有任何表格残留,格式干净利落。

如果需要更多层级(比如四级、五级),只需要在数据里继续嵌套children,模板里对应增加b.child.child.child的块就行,逻辑完全一致,扩展性拉满!

这样是不是比用表格清爽多了?有任何细节卡壳随时问我~

火山引擎 最新活动