合同模板、入职登记表、项目立项申请这类文档,往往需要在固定版式中留出若干可编辑的位置。用普通段落加下划线也能做出类似效果,但填写人可能误删说明文字,也无法限制可填写的内容类型。Word 的内容控件(content control)正是为此设计的:它把一段内容包裹成带类型、带属性的独立对象,既能约束填写范围,也便于程序识别与批量处理。
在桌面软件中逐个插入内容控件,适合少量文档;一旦需要在 Web 流程里批量生成,手工操作就难以为继。把文件传到服务端处理,又会让文档离开用户的设备。本文用 Spire.Doc for JavaScript 在浏览器中直接添加内容控件:文档通过虚拟文件系统(VFS)读入内存,处理完成后写回 VFS 再触发下载,整个过程不依赖 Office,也不需要任何后端服务。
本文介绍三个功能点:
三类控件都由 StructureDocumentTagInline 创建,区别在于 SDTProperties.SDTType 的取值与控制属性:
| 控件类型 | SDTType 取值 |
控制属性类 |
|---|---|---|
| 文本内容控件 | SdtType.Text |
SdtText |
| 富文本内容控件 | SdtType.RichText |
SdtText |
| 图片内容控件 | SdtType.Picture |
DocPicture |
有关安装和项目配置,请参考 React 项目中集成 Spire.Doc for JavaScript。下面的示例假定 Spire.Doc 已安装、WebAssembly 模块已初始化。
添加文本内容控件
文本内容控件用来接收纯文本输入,适合项目名称、联系人、部门名称这类不允许复杂格式的字段。用 StructureDocumentTagInline 创建行内控件后,把 SDTType 设为 SdtType.Text,再通过 SdtText 控制是否允许多行输入。
添加文本内容控件涉及以下成员:
| 成员 | 作用 |
|---|---|
StructureDocumentTagInline(document) |
创建行内内容控件对象 |
SDTProperties.SDTType |
指定控件类型,此处为 SdtType.Text |
SDTProperties.ControlProperties |
类型专属属性,文本控件对应 SdtText |
SdtText.IsMultiline |
是否允许多行输入 |
SDTContent.ChildObjects |
存放控件内的文本内容 |
具体操作步骤如下:
- 获取 Spire.Doc 的 WASM 模块,确认已就绪。
- 载入字体,使用
Document类创建文档并添加一节。 - 在段落中创建
StructureDocumentTagInline控件,将SDTType设为SdtType.Text。 - 用
SdtText设置多行属性,向SDTContent写入TextRange内容。 - 使用
SaveToFile()保存结果文件,从 VFS 读出并触发浏览器下载。
添加文本内容控件的代码如下:
function App() {
const addTextControl = async () => {
// 获取 Spire.Doc 的 WASM 模块
const wasmModule = window.wasmModule?.spiredoc;
if (!wasmModule) {
alert('Spire.Doc is not ready yet');
return;
}
// 载入字体
await window.spire.FetchFileToVFS('msyh.ttc', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
await window.spire.FetchFileToVFS('msyhbd.ttc', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
// 创建文档并添加一节
const doc = new wasmModule.Document();
const section = doc.AddSection();
// 添加标题段落
const titleParagraph = section.AddParagraph();
const titleRange = titleParagraph.AppendText('项目立项申请表');
titleRange.CharacterFormat.FontName = '微软雅黑';
titleRange.CharacterFormat.FontSize = 19;
titleRange.CharacterFormat.Bold = true;
titleRange.CharacterFormat.TextColor = wasmModule.Color.FromArgb(255, 15, 110, 90);
titleParagraph.Format.AfterSpacing = 6;
// 添加副标题
const subtitleParagraph = section.AddParagraph();
const subtitleRange = subtitleParagraph.AppendText('技术委员会 2026 年 11 月');
subtitleRange.CharacterFormat.FontName = '微软雅黑';
subtitleRange.CharacterFormat.FontSize = 9;
subtitleRange.CharacterFormat.TextColor = wasmModule.Color.FromArgb(255, 89, 89, 89);
subtitleParagraph.Format.AfterSpacing = 16;
// 添加控件前的说明文字
const paragraph = section.AddParagraph();
paragraph.AppendText('项目名称: ');
// 创建行内内容控件并放入段落
const sdt = new wasmModule.StructureDocumentTagInline(doc);
paragraph.ChildObjects.Add(sdt);
// 指定控件类型为文本
sdt.SDTProperties.SDTType = wasmModule.SdtType.Text;
const textProperties = new wasmModule.SdtText(true);
textProperties.IsMultiline = true;
sdt.SDTProperties.ControlProperties = textProperties;
// 设置别名、标记与显示外观
sdt.SDTProperties.Alias = '项目名称';
sdt.SDTProperties.Tag = 'project-name';
sdt.SDTProperties.Appearance = wasmModule.SdtAppearance.Tags;
// 写入控件内容
const content = new wasmModule.TextRange(doc);
content.Text = '智能文档处理平台(二期)';
sdt.SDTContent.ChildObjects.Add(content);
// 添加填写说明
const noteParagraph = section.AddParagraph();
noteParagraph.Format.BeforeSpacing = 10;
const noteRange = noteParagraph.AppendText('填写说明:项目名称控制在 30 个汉字以内,需与立项批复文件保持一致。');
noteRange.CharacterFormat.FontName = '微软雅黑';
noteRange.CharacterFormat.FontSize = 9;
noteRange.CharacterFormat.TextColor = wasmModule.Color.FromArgb(255, 89, 89, 89);
// 保存结果文件
const outputFileName = 'AddTextContentControl.docx';
doc.SaveToFile({ fileName: outputFileName, fileFormat: wasmModule.FileFormat.Docx2013 });
doc.Dispose();
// 从 VFS 读取生成的文件,触发下载
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>添加文本内容控件</h1>
<button onClick={addTextControl}>生成文档</button>
</div>
);
}
export default App;
添加文本内容控件后的文档:

内容控件的别名、标记与外观
SDTProperties 上还有三组与内容无关、但与后续处理密切相关的属性:
| 属性 | 用途 |
|---|---|
Alias |
控件在 Word 中显示的名称,便于填写人辨认 |
Tag |
程序可读的标记,通常用英文短横线命名,便于按业务字段定位 |
Appearance |
控件在文档中的显示方式,Tags 会在内容两侧显示别名标签 |
示例中把 Appearance 设为 SdtAppearance.Tags,是为了让生成的文档直接显示控件边界与别名,方便核对结果。若不设置,Word 会按默认方式显示,控件看上去与普通文本无异。
添加富文本内容控件
富文本内容控件同样基于 SdtText,但类型为 SdtType.RichText。它允许在控件内部保留字体、字号、颜色、加粗等格式,适合版本要点、批复意见、合同补充条款这类需要强调重点的段落。
与文本内容控件相比,两者的操作步骤基本一致,差别只有一处:SDTType 使用 SdtType.RichText,控件内容可以拆成多个 TextRange,分别设置格式。
具体操作步骤如下:
- 获取 Spire.Doc 的 WASM 模块,确认已就绪。
- 载入字体,使用
Document类创建文档并添加一节。 - 在段落中创建
StructureDocumentTagInline控件,将SDTType设为SdtType.RichText。 - 依次创建多个
TextRange,分别设置颜色与加粗后加入SDTContent。 - 使用
SaveToFile()保存结果文件,从 VFS 读出并触发浏览器下载。
添加富文本内容控件的代码如下:
function App() {
const addRichTextControl = async () => {
// 获取 Spire.Doc 的 WASM 模块
const wasmModule = window.wasmModule?.spiredoc;
if (!wasmModule) {
alert('Spire.Doc is not ready yet');
return;
}
// 载入字体
await window.spire.FetchFileToVFS('msyh.ttc', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
await window.spire.FetchFileToVFS('msyhbd.ttc', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
// 创建文档并添加一节
const doc = new wasmModule.Document();
const section = doc.AddSection();
// 添加标题段落
const titleParagraph = section.AddParagraph();
const titleRange = titleParagraph.AppendText('版本发布说明');
titleRange.CharacterFormat.FontName = '微软雅黑';
titleRange.CharacterFormat.FontSize = 19;
titleRange.CharacterFormat.Bold = true;
titleRange.CharacterFormat.TextColor = wasmModule.Color.FromArgb(255, 15, 110, 90);
titleParagraph.Format.AfterSpacing = 6;
// 添加副标题
const subtitleParagraph = section.AddParagraph();
const subtitleRange = subtitleParagraph.AppendText('北辰文档平台 2026.11');
subtitleRange.CharacterFormat.FontName = '微软雅黑';
subtitleRange.CharacterFormat.FontSize = 9;
subtitleRange.CharacterFormat.TextColor = wasmModule.Color.FromArgb(255, 89, 89, 89);
subtitleParagraph.Format.AfterSpacing = 16;
// 添加控件前的说明文字
const paragraph = section.AddParagraph();
paragraph.AppendText('版本要点: ');
// 创建行内内容控件并放入段落
const sdt = new wasmModule.StructureDocumentTagInline(doc);
paragraph.ChildObjects.Add(sdt);
// 指定控件类型为富文本
sdt.SDTProperties.SDTType = wasmModule.SdtType.RichText;
const textProperties = new wasmModule.SdtText(true);
textProperties.IsMultiline = true;
sdt.SDTProperties.ControlProperties = textProperties;
// 设置别名、标记与显示外观
sdt.SDTProperties.Alias = '版本要点';
sdt.SDTProperties.Tag = 'release-highlights';
sdt.SDTProperties.Appearance = wasmModule.SdtAppearance.Tags;
// 第一个文本片段:绿色正文
const firstRange = new wasmModule.TextRange(doc);
firstRange.Text = '本版本支持';
firstRange.CharacterFormat.FontName = '微软雅黑';
firstRange.CharacterFormat.TextColor = wasmModule.Color.FromArgb(255, 0, 128, 0);
sdt.SDTContent.ChildObjects.Add(firstRange);
// 第二个文本片段:橙色加粗关键词
const secondRange = new wasmModule.TextRange(doc);
secondRange.Text = '内容控件';
secondRange.CharacterFormat.FontName = '微软雅黑';
secondRange.CharacterFormat.Bold = true;
secondRange.CharacterFormat.TextColor = wasmModule.Color.FromArgb(255, 237, 125, 49);
sdt.SDTContent.ChildObjects.Add(secondRange);
// 第三个文本片段:绿色正文
const thirdRange = new wasmModule.TextRange(doc);
thirdRange.Text = '的批量写入与格式校验。';
thirdRange.CharacterFormat.FontName = '微软雅黑';
thirdRange.CharacterFormat.TextColor = wasmModule.Color.FromArgb(255, 0, 128, 0);
sdt.SDTContent.ChildObjects.Add(thirdRange);
// 添加提示说明
const noteParagraph = section.AddParagraph();
noteParagraph.Format.BeforeSpacing = 10;
const noteRange = noteParagraph.AppendText('提示:富文本控件内部可以拆成多个 TextRange,分别设置字体、颜色与加粗。');
noteRange.CharacterFormat.FontName = '微软雅黑';
noteRange.CharacterFormat.FontSize = 9;
noteRange.CharacterFormat.TextColor = wasmModule.Color.FromArgb(255, 89, 89, 89);
// 保存结果文件
const outputFileName = 'AddRichTextContentControl.docx';
doc.SaveToFile({ fileName: outputFileName, fileFormat: wasmModule.FileFormat.Docx2013 });
doc.Dispose();
// 从 VFS 读取生成的文件,触发下载
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>添加富文本内容控件</h1>
<button onClick={addRichTextControl}>生成文档</button>
</div>
);
}
export default App;
添加富文本内容控件后的文档:

在富文本控件中组合多种格式
富文本控件的内容由若干个 TextRange 顺序拼接而成。每加入一个 TextRange,就相当于在控件内追加一段独立格式的文字:可以只给关键词换色,也可以整段加粗。需要注意,TextRange 的 CharacterFormat 只影响该片段本身,不会作用于控件中的其他内容;若希望整段统一格式,逐个设置即可。
添加图片内容控件
图片内容控件用来放置可替换的图片,适合公司标志、产品示意图、签章位等场景。创建方式与前两类相同,SDTType 设为 SdtType.Picture,控件内容改为 DocPicture 对象。
图片内容控件不通过 ControlProperties 设置属性,而是直接把 DocPicture 加入 SDTContent。示例从 public/data 读取 logo.png,运行时请把该图片放入项目的 public/data 目录。图片的尺寸以磅为单位,可在 LoadImage() 之后调整:
| 成员 | 作用 |
|---|---|
DocPicture(document) |
创建图片对象 |
DocPicture.LoadImage(path) |
从 VFS 载入图片 |
DocPicture.Width / Height |
图片显示尺寸,单位为磅 |
具体操作步骤如下:
- 获取 Spire.Doc 的 WASM 模块,确认已就绪。
- 载入字体与示例图片到 VFS,创建文档并添加一节。
- 创建
StructureDocumentTagInline控件,将SDTType设为SdtType.Picture。 - 创建
DocPicture,载入图片并设置宽高,加入SDTContent。 - 使用
SaveToFile()保存结果文件,从 VFS 读出并触发浏览器下载。
添加图片内容控件的代码如下:
function App() {
const addPictureControl = async () => {
// 获取 Spire.Doc 的 WASM 模块
const wasmModule = window.wasmModule?.spiredoc;
if (!wasmModule) {
alert('Spire.Doc is not ready yet');
return;
}
// 载入字体与示例图片
await window.spire.FetchFileToVFS('msyh.ttc', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
await window.spire.FetchFileToVFS('msyhbd.ttc', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
await window.spire.FetchFileToVFS('logo.png', '', `${process.env.PUBLIC_URL}/data/`);
// 创建文档并添加一节
const doc = new wasmModule.Document();
const section = doc.AddSection();
// 添加标题段落
const titleParagraph = section.AddParagraph();
const titleRange = titleParagraph.AppendText('品牌标识');
titleRange.CharacterFormat.FontName = '微软雅黑';
titleRange.CharacterFormat.FontSize = 19;
titleRange.CharacterFormat.Bold = true;
titleRange.CharacterFormat.TextColor = wasmModule.Color.FromArgb(255, 15, 110, 90);
titleParagraph.Format.AfterSpacing = 6;
// 添加副标题
const subtitleParagraph = section.AddParagraph();
const subtitleRange = subtitleParagraph.AppendText('对外文档统一使用以下标志');
subtitleRange.CharacterFormat.FontName = '微软雅黑';
subtitleRange.CharacterFormat.FontSize = 9;
subtitleRange.CharacterFormat.TextColor = wasmModule.Color.FromArgb(255, 89, 89, 89);
subtitleParagraph.Format.AfterSpacing = 16;
// 添加图片前的说明文字
const label = section.AddParagraph();
label.AppendText('公司标志:');
// 创建行内内容控件并放入新段落
const paragraph = section.AddParagraph();
const sdt = new wasmModule.StructureDocumentTagInline(doc);
paragraph.ChildObjects.Add(sdt);
// 指定控件类型为图片
sdt.SDTProperties.SDTType = wasmModule.SdtType.Picture;
sdt.SDTProperties.Alias = '公司标志';
sdt.SDTProperties.Tag = 'brand-logo';
// 载入图片并设置显示尺寸
const picture = new wasmModule.DocPicture(doc);
picture.LoadImage('logo.png');
picture.Width = 160;
picture.Height = 54;
sdt.SDTContent.ChildObjects.Add(picture);
// 添加尺寸说明
const noteParagraph = section.AddParagraph();
noteParagraph.Format.BeforeSpacing = 10;
const noteRange = noteParagraph.AppendText('图片内容控件的尺寸以磅为单位,示例尺寸为 160 × 54 磅。');
noteRange.CharacterFormat.FontName = '微软雅黑';
noteRange.CharacterFormat.FontSize = 9;
noteRange.CharacterFormat.TextColor = wasmModule.Color.FromArgb(255, 89, 89, 89);
// 保存结果文件
const outputFileName = 'AddPictureContentControl.docx';
doc.SaveToFile({ fileName: outputFileName, fileFormat: wasmModule.FileFormat.Docx2013 });
doc.Dispose();
// 从 VFS 读取生成的文件,触发下载
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>添加图片内容控件</h1>
<button onClick={addPictureControl}>生成文档</button>
</div>
);
}
export default App;
添加图片内容控件后的文档:

常见问题
内容控件与普通文本有什么区别
普通文本只是段落里的一段字符,程序只能按位置或文字内容去查找;内容控件是一个带类型、别名、标记和锁定状态的独立对象,可以通过 SDTProperties 直接读取业务含义。在 Word 中,它还会以标签或边框的形式提示填写范围。对于需要回收数据、反复套用的模板,内容控件的可维护性通常更好。
生成的内容控件在 Word 中看不到边框怎么办
默认外观下,控件与普通文字差别不大。可以把 SDTProperties.Appearance 设为 SdtAppearance.Tags,控件两侧会显示别名标签;也可以设为 SdtAppearance.BoundingBox,在 Word 的编辑视图中显示边框。外观只影响显示,不会改变控件类型或内容。
文本内容控件与富文本内容控件应该如何选择
如果字段只接受纯文字,且不希望填写人改变字体和颜色,选文本内容控件;如果需要在控件内部保留加粗、颜色等格式,或者内容本身就是一段带重点的说明,选富文本内容控件。两者在代码上的差别仅在于 SDTType 与内容片段的组织方式。
图片内容控件设置的尺寸为什么与实际略有差异
DocPicture.Width 与 Height 同时设置时,图片会按原始宽高比做等比缩放,最终尺寸可能与设定的数值相差一两个磅。若需要精确尺寸,可以只设置其中一个方向,让另一个方向按比例计算,或先把源图片裁切到目标比例再插入。
获取免费许可证
如果您希望删除结果文档中的评估消息,或者摆脱功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。







