Spire.XLS for Java 15.10.5 现已正式发布。该版本优化了加载 Excel 文档时的内存消耗。同时,还修复了在获取复选框、加载大文件、复制工作表格式及保存文件等场景中出现的多个问题。更多详情如下:
优化:
问题修复:
Spire.XLS 15.10.3 现已发布。本次更新新增了默认支持读取 Office 缓存的云字体的功能,使其在支持系统字体目录和内存字体的基础上,能够自动识别和加载云字体。同时,本版本调整了 AddDigitalSignature() 和 IDigitalSignatures.Add() 方法的参数定义,并修复了多个已知问题,从而提升了整体的稳定性和兼容性。详细信息如下:
新功能:
调整:
原方法:
AddDigitalSignature(X509Certificate2 certificate, string comments, DateTime signTime)
新方法:
AddDigitalSignature(string certificatePath, string certificatePassword, string comments, DateTime signTime)
问题修复:
Spire.Doc 13.10.3 现已发布,该版本支持从 Word 文件中提取指定范围的页面并保存为另一个文档。同时,修复了一系列与 Word 到 PDF 转换相关的问题。更多详情如下。
新功能:
Document doc = new Document();
doc.LoadFromFile("http://cdn.e-iceblue.cn/sample.docx");
Document extractPage = doc.ExtractPages(0, 1);
extractPage.SaveToFile("result.docx");
问题修复:
Spire.PDF 11.10.4 现已正式发布。该版本支持验证时间戳服务 URL 地址的有效性,并成功修复了一些在转换和比较PDF文档时出现的问题。详情请查阅以下内容。
新功能:
TSAHttpService timestampService = new TSAHttpService("http://time2.certum.pl");
TSAResponse response = timestampService.Check();
//if it is success to receive tsa token
if (response.Success)
{ formatter.TimestampService = timestampService; }
问题修复:

CSV 因其简洁和跨平台的广泛支持,是最常见的表格数据交换格式之一。然而,当需要处理结构化应用程序、配置文件或层次化数据时,XML 通常成为首选格式,因为它能够表示嵌套关系并提供更严格的数据验证。
在本指南中,我们将探讨如何使用 Spire.XLS for Python 将 CSV 文件转换为 XML。你将学习如何将 CSV 转换为 Excel XML 格式以及 标准 XML 。同时,我们还将介绍如何清理和预处理真实世界中的 CSV 文件——处理无效表头、缺失值、特殊字符和嵌套字段等问题,以确保生成的 XML 输出始终有效且结构正确。
文章目录
为什么开发者需要将 CSV 转 XML 呢?以下是一些实际应用场景:
CSV 以简洁取胜,XML 以结构见长。通过两者的互相转换,你可以兼得两种格式的优势。
在开始编写代码之前,请确保准备好以下环境:
通过 pip 安装 Spire.XLS(假设系统中已安装 Python 和 pip):
pip install spire.xls
此外,请准备一个测试用 CSV 文件,例如:
员工ID,姓名,部门,职位,入职日期,薪资
1001,张三,技术部,软件工程师,2021-03-15,15000
1002,李四,市场部,市场专员,2022-07-01,12000
1003,王五,技术部,产品经理,2020-11-10,18000
1004,赵六,人力资源部,招聘经理,2019-05-22,14000
第一种方法是将 CSV 转换为 Excel 兼容的 XML 格式,也称为 SpreadsheetML (Excel 2003 引入)。这种格式可以被 Excel 直接打开。
使用 Spire.XLS,这一过程非常简单:
from spire.xls import *
# 创建 Workbook
workbook = Workbook()
# 加载 CSV 文件
workbook.LoadFromFile("input.csv", ",", 1, 1)
# 保存为 Excel XML格式
workbook.SaveAsXml("output.xml")
# 释放资源
workbook.Dispose()
工作原理
效果图 :

你可能喜欢:使用 Python 将CSV 转为 Excel
更多时候,你可能需要如下所示标准的XML 结构,而不是 Excel 兼容格式:
<Employee>
<employee_id>1001</employee_id>
<name>张三</name>
<department>技术部</department>
<position>软件工程师</position>
<hire_date>2021-03-15</hire_date>
<salary>15000</salary>
</Employee>
实现方式如下:
from spire.xls import *
import xml.etree.ElementTree as ET
from xml.dom import minidom
def chinese_to_english_tag(chinese_header):
"""
将特定的中文列名转换为英文XML标签
"""
mapping = {
'员工ID': 'employee_id',
'姓名': 'name',
'部门': 'department',
'职位': 'position',
'入职日期': 'hire_date',
'薪资': 'salary'
}
# 去除前后空格后查找映射
cleaned_header = chinese_header.strip()
return mapping.get(cleaned_header, cleaned_header)
# Step 1: 加载 CSV 文件
workbook = Workbook()
workbook.LoadFromFile(r"C:\Users\Administrator\Desktop\input.csv", ",", 1, 1)
sheet = workbook.Worksheets[0]
# Step 2: 创建根节点
root = ET.Element("Employees")
# Step 3: 处理表头 - 中文列名转英文
headers = []
for col in range(1, sheet.Columns.Count + 1):
cell_value = sheet.Range[1, col].Value
if not cell_value:
break
english_tag = chinese_to_english_tag(str(cell_value))
headers.append(english_tag)
# Step 4: 添加数据行
for row in range(2, sheet.Rows.Count + 1):
if not sheet.Range[row, 1].Value:
break
employee = ET.SubElement(root, "Employee")
for col, english_header in enumerate(headers, start=1):
cell_value = sheet.Range[row, col].Value
field = ET.SubElement(employee, english_header)
field.text = str(cell_value) if cell_value is not None else ""
# Step 5: 保存为格式化的 XML 文件
xml_str = ET.tostring(root, encoding='utf-8')
pretty_xml = minidom.parseString(xml_str).toprettyxml(indent=" ")
with open("output/standard.xml", 'w', encoding='utf-8') as f:
f.write(pretty_xml)
# 释放资源
workbook.Dispose()
工作原理
效果图 :

你可能喜欢:如何在 Python 中将 CSV 转换为 JSON
将“完美”的 CSV 转换为 XML 很容易,但实际 CSV 往往并不理想。以下是常见问题及对应解决方案:
OrderID,Customer,Products
1001,张三,"电脑;鼠标;键盘"
若直接转换,将丢失层次结构。
<Products>
<Product>电脑</Product>
<Product>鼠标</Product>
<Product>键盘</Product>
</Products>
可使用以下辅助函数自动预处理 CSV (不包含中文列名转换为英文):
import csv
import re
def clean_csv(input_file, output_file, nested_columns=None, nested_delimiter=";"):
if nested_columns is None:
nested_columns = []
cleaned_rows = []
# 转义 XML 特殊字符
def escape_xml(text):
return (text.replace("&", "&")
.replace("<", "<")
.replace(">", ">")
.replace('"', """)
.replace("'", "'"))
with open(input_file, "r", encoding="utf-8") as infile:
reader = csv.reader(infile)
headers = next(reader)
# 清理表头
cleaned_headers = []
for h in headers:
h = h.strip() # 去除首尾空格
h = re.sub(r"\s+", "_", h) # 将空格替换为下划线
h = re.sub(r"[^a-zA-Z0-9_]", "", h) # 移除非法字符
if re.match(r"^\d", h): # 若表头以数字开头,则加前缀
h = "Field_" + h
cleaned_headers.append(h)
cleaned_rows.append(cleaned_headers)
# 读取所有行数据
raw_rows = []
for row in reader:
# 将空单元格替换为 "NULL"
row = [cell if cell.strip() != "" else "NULL" for cell in row]
raw_rows.append(row)
# 处理嵌套列(如多值列)
if nested_columns:
expanded_rows = [cleaned_headers] # 保留表头
for row in raw_rows:
row_variants = [row]
for col_name in nested_columns:
if col_name not in cleaned_headers:
continue
col_index = cleaned_headers.index(col_name)
temp = []
for variant in row_variants:
cell_value = variant[col_index]
# 仅按嵌套分隔符拆分,不影响 XML 特殊字符
if nested_delimiter in cell_value:
items = [item.strip() for item in cell_value.split(nested_delimiter)]
for item in items:
new_variant = variant.copy()
new_variant[col_index] = item
temp.append(new_variant)
else:
temp.append(variant)
row_variants = temp
expanded_rows.extend(row_variants)
cleaned_rows = expanded_rows
else:
cleaned_rows.extend(raw_rows)
# 展开后再转义特殊字符
final_rows = [cleaned_rows[0]] # 保留表头
for row in cleaned_rows[1:]:
final_row = [escape_xml(cell) for cell in row]
final_rows.append(final_row)
# 写入清理后的 CSV 文件
with open(output_file, "w", newline="", encoding="utf-8") as outfile:
writer = csv.writer(outfile)
writer.writerows(final_rows)
print(f"清理后的 CSV 已保存至 {output_file}")
你可以通过传入输入和输出 CSV 文件路径来调用 clean_csv 函数,并可选地指定需要展开嵌套值的列。
# 文件路径
input_file = r"C:\Users\Administrator\Desktop\input.csv"
output_file = r"C:\Users\Administrator\Desktop\cleaned_output.csv"
# 指定可能包含嵌套值的列
nested_columns = ["Products"] # 你也可以添加更多,例如 ["Products", "Reviews"]
# 调用 clean_csv 函数
clean_csv(input_file, output_file, nested_columns=nested_columns, nested_delimiter=";")
该函数可确保 CSV 在转换为 XML 前干净、有效,功能包括:
使用 Spire.XLS for Python 将 CSV 转换为 XML,不仅高效,而且具备极强的灵活性。无论是快速导出、结构化集成,还是复杂的业务数据转换,都能轻松应对。
从企业系统集成、报表归档,到旧系统的数据迁移,这一流程充分结合了 CSV 的简洁性 与 XML 的结构化优势 ,为数据交换与自动化处理提供了稳健、高可维护的解决方案。
可以,但建议采用流式处理(逐行处理)以避免内存问题。
支持。保存为 Excel XML 是内置功能,但自定义 XML 仍需代码实现。
可使用 escape_xml 辅助函数或 Python 内置的 xml.sax.saxutils.escape()。
调用 clean_csv 时,可在 nested_columns 参数中传入多个列名。
可以。生成 XML 后,可根据 XSD 模式进行验证。
如果您需要去除生成文档中的评估提示或解除功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。
Spire.PDF for C++ 11.10.0 现已正式发布。最新版本修复了提取 PDF 页面文本抛异常的问题。详情请查阅下方的内容。
问题修复:
Spire.Presentation for Java 10.10.2 现已发布。本次更新新增支持将 Markdown 转换为 PPTX 文件,以及将 SVG 转换为 Shape,同时增强了 PPT 转 PDF 的转换功能。此外,本次更新还修复了一些已知问题,例如添加的 LaTeX 公式渲染不正确的问题。详情如下:
新功能:
Presentation pt = new Presentation();
pt.loadFromFile("input.md", FileFormat.Markdown);
pt.saveToFile("output.pptx", FileFormat.PPTX_2013);
pt.dispose();
Presentation ppt = new Presentation();
ppt.loadFromFile("input.pptx");
for (int i = 0; i < ppt.getSlides().getCount(); i++)
{
ppt.getSlides().get(i).getShapes().addFromSVGAsShapes("in.svg");
}
ppt.saveToFile("output.pptx", FileFormat.PPTX_2013);
ppt.dispose();
问题修复:
https://www.e-iceblue.cn/Downloads/Spire-Presentation-JAVA.html
Spire.Presentation 10.10.1 现已发布,此更新引入了设置音频淡入和淡出持续时间的功能,以及裁剪音频的能力。以下是详细信息:
新功能:
// New Append Audio
Presentation pres = new Presentation();
FileStream from_stream = File.OpenRead(inputFile);
RectangleF audioRect = new RectangleF(50, 50, 100, 100);
IAudio audio = pres.Slides[0].Shapes.AppendAudioMedia(from_stream, audioRect);
// Set the duration of the starting fade for 13s
audio.FadeInDuration = 13000f;
// Set the duration of the ending fade for 40s
audio.FadeOutDuration = 10000f;
pres.SaveToFile(outputFile, FileFormat.Pptx2013);
// Retrieve existing documents
FileStream from_stream = File.OpenRead(inputFile);
Presentation presentation = new Presentation();
presentation.LoadFromStream(from_stream, FileFormat.Auto);
foreach (IShape shape in presentation.Slides[0].Shapes)
{
if (shape is IAudio)
{
IAudio audio = shape as IAudio;
// Set the duration of the starting fade for 13s
audio.FadeInDuration = 13000f;
// Set the duration of the ending fade for 20s
audio.FadeOutDuration = 20000f;
}
}
presentation.SaveToFile(outputFile, FileFormat.Pptx2013);
// New Append Audio
Presentation pres = new Presentation();
FileStream from_stream = File.OpenRead(inputFile);
RectangleF audioRect = new RectangleF(50, 50, 100, 100);
IAudio audio = pres.Slides[0].Shapes.AppendAudioMedia(from_stream, audioRect);
// Set the start trimming time 8 seconds
audio.TrimFromStart = 8000f;
// Set the end trimming time 13 seconds
audio.TrimFromEnd = 13000f;
pres.SaveToFile(outputFile, FileFormat.Pptx2013);
// Retrieve existing documents
FileStream from_stream = File.OpenRead(inputFile);
Presentation presentation = new Presentation();
presentation.LoadFromStream(from_stream, FileFormat.Auto);
foreach (IShape shape in presentation.Slides[0].Shapes)
{
if (shape is IAudio)
{
IAudio audio = shape as IAudio;
// Set the start trimming time 8 seconds
audio.TrimFromStart = 8000f;
// Set the end trimming time 13 seconds
audio.TrimFromEnd = 13000f;
}
}
presentation.SaveToFile(outputFile, FileFormat.Pptx2013);
https://www.e-iceblue.cn/Downloads/Spire-Presentation-NET.html

在 Python 中处理数据时,将 TXT 文本文件转换为 CSV 是数据分析、报表生成或跨应用共享数据的常见需求。TXT 文件通常存储非结构化的纯文本,直接处理较为繁琐,而 CSV 文件能将数据组织成行和列,更便于分析和处理。本文将详细介绍如何使用 Python 实现 TXT 文件转 CSV,包括单文件转换、批量转换以及处理不同分隔符的技巧。
CSV(逗号分隔值)文件是一种基于文本的简单文件格式,用于存储表格数据。每一行表示一条记录,行内的值用逗号、制表符或自定义分隔符分隔。
CSV 文件具有以下优势:
在实际应用中,CSV 文件可用来存储联系人信息、销售数据、日志数据等结构化数据,便于后续处理和分析。
Spire.XLS for Python是一个功能强大的库,不仅支持创建和编辑 Excel 文件,还能高效操作 CSV 文件,且无需安装 Microsoft Excel。借助 Spire.XLS,开发者可以轻松实现 TXT 转 CSV、数据写入、表格格式处理、公式计算以及批量文件操作等任务。

你可以运行以下命令直接从 PyPI 安装该库:
pip install Spire.XLS
如果需要安装指导,请参考如何安装 Spire.XLS for Python。
将单个TXT文本文件转换为 CSV 非常简单,只需以下几个步骤即可完成:
示例代码:
下面的代码示例展示如何使用 Python 导出 TXT 文本文件为 CSV:
from spire.xls import *
# 读取 TXT 文件
with open("data.txt", "r", encoding="utf-8") as file:
lines = file.readlines()
# 处理每行数据(按空格分割,可根据需要更改分隔符)
processed_data = [line.strip().split() for line in lines]
# 创建 Excel 工作簿
workbook = Workbook()
# 获取第一个工作表
sheet = workbook.Worksheets[0]
# 将处理后的数据写入工作表
for row_num, row_data in enumerate(processed_data):
for col_num, cell_data in enumerate(row_data):
sheet.Range[row_num + 1, col_num + 1].Value = cell_data
# 将工作表保存为 CSV 文件(UTF-8 编码)
sheet.SaveToFile("Txt转Csv.csv", ",", Encoding.get_UTF8())
# 释放工作簿资源
workbook.Dispose()
TXT 转 CSV 输出结果:

如果你还希望将 TXT 文件转换为 Excel 文件,可参考教程如何使用 Python 将 TXT 转 Excel。
如果你有多个文本文件需要自动转换为 CSV,可以遍历文件夹中的所有 .txt 文件,并逐一转换。
以下代码演示如何在 Python 中批量将多个 TXT 文件转换为 CSV:
import os
from spire.xls import *
# TXT 文件所在文件夹
input_folder = "txt_files"
output_folder = "csv_files"
# 如果输出文件夹不存在,则创建
os.makedirs(output_folder, exist_ok=True)
# 单个 TXT 文件转换函数
def convert_txt_to_csv(file_path, output_path):
with open(file_path, "r", encoding="utf-8") as f:
lines = f.readlines()
processed_data = [line.strip().split() for line in lines if line.strip()]
workbook = Workbook()
sheet = workbook.Worksheets[0]
for row_num, row_data in enumerate(processed_data):
for col_num, cell_data in enumerate(row_data):
sheet.Range[row_num + 1, col_num + 1].Value = cell_data
sheet.SaveToFile(output_path, ",", Encoding.get_UTF8())
workbook.Dispose()
print(f"已转换 '{file_path}' -> '{output_path}'")
# 遍历文件夹中所有 TXT 文件并转换
for filename in os.listdir(input_folder):
if filename.lower().endswith(".txt"):
input_path = os.path.join(input_folder, filename)
output_name = os.path.splitext(filename)[0] + ".csv"
output_path = os.path.join(output_folder, output_name)
convert_txt_to_csv(input_path, output_path)
在将文本文件转换为 CSV 时,不同文本文件可能存在格式差异或潜在错误,以下技巧可帮助你更高效地处理各种场景。
并非所有文本文件都使用空格分隔值。如果 TXT 文件使用制表符、逗号或其他字符,可调整 split() 函数以匹配分隔符:
processed_data = [line.strip().split('\t') for line in lines]
processed_data = [line.strip().split(',') for line in lines]
processed_data = [line.strip().split('|') for line in lines]
这样可以确保数据在写入 CSV 前正确拆分为列。
读取或写入文件时,使用 try-except 捕获潜在错误,可增强脚本稳健性,避免意外崩溃:
try:
# 你的代码
except Exception as e:
print("错误:", e)
提示:使用清晰的错误信息提示便于理解问题所在。
有些 TXT 文件可能包含空行,可在处理时过滤空行,避免在 CSV 中生成空行:
processed_data = [line.strip().split() for line in lines if line.strip()]
本文介绍了如何使用 Spire.XLS for Python 在 Python 中将 TXT 文本文件转换为 CSV。通过这些方法,你可以轻松处理文本数据,使其适合分析、报表和共享。Spire.XLS 不仅支持单文件转换,还能实现批量处理,并可灵活应对不同分隔符和文本格式。
如果你在 Python TXT 转 CSV 转换过程中遇到问题或需要技术支持,可访问我们的支持论坛获取帮助。
A1: 可以。Spire.XLS for Python 独立于 Excel,可直接创建和导出 CSV 文件。
A2: 使用循环读取文件夹中的所有 TXT 文件,并对每个文件应用转换逻辑。教程中提供了可直接使用的 Python 批量转换示例。
A3: 在处理过程中过滤空行,并检查列数一致性,以避免输出 CSV 中出现错误或空行。
A4: 可根据 TXT 文件中的分隔符调整 split() 函数--制表符 (\t)、逗号或其他自定义字符,然后再写入 CSV。

在企业应用、报表系统或财务工具的开发中,生成规范、专业的 PDF 文档是常见需求。与其在代码中硬编码布局,不如使用模板来提高开发效率。模板不仅能加快开发进程,还能确保品牌视觉与文档格式的一致性。
本文将介绍如何使用 Spire.PDF for .NET 在 C# 中通过 HTML 模板 或 预设 PDF 模板 生成 PDF 文档,无论是需要动态布局还是快速替换占位符,都能灵活应对。
本文目录
Spire.PDF for .NET 是一款功能强大的 PDF 操作库,允许 .NET 开发者无需依赖 Adobe Acrobat 即可创建、读取、编辑和转换 PDF 文档。该库提供全面的 API 接口,适用于生成报表、发票、证书及其他 PDF 格式文件,非常适合在 C# 应用中进行自动化文档处理。
与本教程相关的主要功能包括:
要在 C# 项目中通过模板生成 PDF,首先需将 Spire.PDF 引入项目中。对于 HTML 转 PDF 的场景,Spire.PDF 依赖外部渲染引擎(Qt WebEngine 或 Google Chrome)。本文以 Qt WebEngine为例。
步骤 1:安装 Spire.PDF
在 Visual Studio 的 NuGet 包管理器中运行以下命令:
Install-Package Spire.PDF
或从官方网站下载 Spire.PDF 安装包,并将 DLL 文件手动导入项目。
步骤 2:下载并配置 Qt 插件
根据系统下载对应的 Qt WebEngine 插件:
解压文件后可获得插件目录,例如:C:\plugins-windows-x64\plugins
在 C# 代码中注册插件路径:
HtmlConverter.PluginPath = @"C:\plugins-windows-x64\plugins";
HTML 模板非常适合需要表格、页眉页脚或复杂样式布局(如发票、报表)的文档。
步骤 1:构建带占位符的 HTML 模板
可在 HTML 中添加双花括号包裹的动态字段,例如:
<h1>发票</h1>
<p>发票编号: {{INVOICE_NUMBER}}</p>
<p>日期: {{INVOICE_DATE}}</p>
<p><strong>姓名: </strong> {{CUSTOMER_NAME}}</p>
步骤 2:使用运行时数据替换占位符
以下是一个生成发票 PDF 的完整示例代码:
using Spire.Additions.Qt;
using System.Drawing;
using Spire.Pdf.Graphics;
namespace CreatePdfFromHtmlTemplate
{
class Program
{
static void Main(string[] args)
{
// 带有占位符变量的HTML模板
string htmlTemplate = @"
<!DOCTYPE html>
<html lang=""zh"">
<head>
<meta charset=""UTF-8"">
<meta name=""viewport"" content=""width=device-width, initial-scale=1.0"">
<title>发票</title>
<style>
body {
font-family: ""SimHei"", ""黑体"", Tahoma, sans-serif;
margin: 40px auto;
padding: 20px;
max-width: 800px;
font-size: 20px;
}
h1 {
text-align: right;
font-size: 40px;
letter-spacing: 2px;
color: #222;
margin: 0 0 30px 0;
}
.invoice-header, .invoice-footer {
margin-bottom: 50px;
}
.invoice-header {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 3px solid #444;
padding-bottom: 10px;
}
.invoice-details {
margin: 20px 0;
padding: 15px;
background: #f5f5f5;
border-radius: 6px;
}
.invoice-details h2 {
font-size: 20px;
margin-bottom: 10px;
color: #444;
}
.info p {
margin: 2px 0;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 15px;
}
th, td {
padding: 10px;
border: 1px solid #ddd;
text-align: left;
}
th {
background-color: #efefef;
font-weight: 600;
}
tbody tr:nth-child(even) {
background: #f9f9f9;
}
.total {
margin-top: 20px;
text-align: right;
font-size: 15px;
}
.total p {
margin: 5px 0;
}
.total p span {
display: inline-block;
width: 120px;
}
.grand-total {
font-size: 18px;
font-weight: bold;
border-top: 2px solid #444;
margin-top: 10px;
padding-top: 10px;
}
.invoice-footer {
text-align: center;
font-size: 18px;
color: #666;
margin-top: 50px;
padding-top: 10px;
}
</style>
</head>
<body>
<div class=""invoice-header"">
<div>
<h2>公司名称</h2>
<p>123 商业街<br>重庆, 中国</p>
</div>
<div>
<h1>发票</h1>
<p>发票编号: {{INVOICE_NUMBER}}<br>日期: {{INVOICE_DATE}}</p>
</div>
</div>
<div class=""invoice-details"">
<h2>账单寄送至</h2>
<div class=""info"">
<p><strong>姓名:</strong> {{BILLER_NAME}}</p>
<p><strong>地址:</strong> {{BILLER_ADDRESS}}</p>
<p><strong>邮箱:</strong> {{BILLER_EMAIL}}</p>
</div>
</div>
<table>
<thead>
<tr>
<th>描述</th>
<th>数量</th>
<th>单价</th>
<th>行总计</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ITEM_DESCRIPTION}}</td>
<td>{{ITEM_QUANTITY}}</td>
<td>{{ITEM_UNIT_PRICE}}</td>
<td>{{ITEM_TOTAL}}</td>
</tr>
<!-- 这里可以添加更多行 -->
</tbody>
</table>
<div class=""total"">
<p><span>小计:</span> {{SUBTOTAL}}</p>
<p><span>税 ({{TAX_RATE}}%):</span> {{TAX}}</p>
<p class=""grand-total""><span>总计:</span> {{TOTAL}}</p>
</div>
<div class=""invoice-footer"">
<p>感谢您的惠顾!</p>
<p>如有任何疑问,请联系我们 该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。</p>
</div>
</body>
</html>
";
// 发票的样本数据 - 与模板占位符匹配的键值对
Dictionary<string, string> invoiceData = new Dictionary<string, string>()
{
{ "INVOICE_NUMBER", "12345" },
{ "INVOICE_DATE", "2025-08-25" },
{ "BILLER_NAME", "张三" },
{ "BILLER_ADDRESS", "重庆市新北街123号" },
{ "BILLER_EMAIL", "zhangsan@ example.com" },
{ "ITEM_DESCRIPTION", "咨询服务" },
{ "ITEM_QUANTITY", "10" },
{ "ITEM_UNIT_PRICE", "$100" },
{ "ITEM_TOTAL", "$1000" },
{ "SUBTOTAL", "$1000" },
{ "TAX_RATE", "5" },
{ "TAX", "$50" },
{ "TOTAL", "$1050" }
};
// 用实际数据值填充HTML模板
string populatedInvoice = PopulateInvoice(htmlTemplate, invoiceData);
// 指定生成的PDF输出文件路径
string outputFile = "HtmlToPdf.pdf";
// 指定HTML转换器的插件路径(QT插件)
string pluginPath = @"C:\plugins-windows-x64\plugins";
// 设置HTML到PDF转换所需的插件路径
HtmlConverter.PluginPath = pluginPath;
// 使用指定设置将HTML字符串转换为PDF
HtmlConverter.Convert(
populatedInvoice,
outputFile,
true, // 启用JavaScript
100000, // 超时(毫秒)
new SizeF(595, 842), // A4纸大小(595x842点)
new PdfMargins(20), // 四周20点边距
LoadHtmlType.SourceCode // 从源代码字符串加载HTML
);
}
// 辅助方法: 用数据字典中的实际值替换模板占位符
private static string PopulateInvoice(string template, Dictionary<string, string> data)
{
string result = template;
foreach (var entry in data)
{
result = result.Replace("{{" + entry.Key + "}}", entry.Value);
}
return result;
}
}
}
实现原理
输出结果:

有时设计团队会提供带有占位符(如 {PROJECT_NAME})的静态 PDF 模板。通过简单的文本替换即可将这些模板快速填充成正式文档。
示例:填充项目报告模板
using Spire.Pdf;
using Spire.Pdf.Texts;
using static Spire.Pdf.Texts.PdfTextReplaceOptions;
namespace GeneratePdfFromPdfTemplate
{
class Program
{
static void Main(string[] args)
{
// 创建一个PdfDocument对象
PdfDocument doc = new PdfDocument();
// 加载一个PDF文件
doc.LoadFromFile(@"C:\Users\Administrator\Desktop\Template.pdf");
// 创建一个PdfTextReplaceOptions对象并指定选项
PdfTextReplaceOptions textReplaceOptions = new PdfTextReplaceOptions();
textReplaceOptions.ReplaceType = ReplaceActionType.WholeWord; // 替换类型设置为整词替换
// 获取特定页面
PdfPageBase page = doc.Pages[0];
// 基于页面创建一个PdfTextReplacer对象
PdfTextReplacer textReplacer = new PdfTextReplacer(page);
textReplacer.Options = textReplaceOptions;
// 旧字符串和新字符串的字典
Dictionary<string, string> replacements = new Dictionary<string, string>()
{
{ "{PROJECT_NAME}", "新网站开发" },
{ "{PROJECT_NO}", "2023-001" },
{ "{PROJECT MANAGER}", "爱丽丝·约翰逊" },
{ "{PERIOD}", "2023年第三季度" },
{ "{START_DATE}", "2023年7月1日" },
{ "{END_DATE}", "2023年9月30日" }
};
// 遍历字典进行文本替换
foreach (var pair in replacements)
{
textReplacer.ReplaceText(pair.Key, pair.Value);
}
// 将文档保存为另一个PDF文件
doc.SaveToFile("FromPdfTemplate.pdf");
doc.Close();
}
}
}
实现原理
限制说明: 此方法仅适用于短文本(如姓名、编号、日期等)的替换。对于多行文本或动态扩展的内容,它的效果不佳,因为PDF不会自动重新排版文本。对于较大的内容块,请使用HTML或Word模板。
输出结果:

Spire.PDF 支持更多文本替换设置,请参考:在 C# 中替换 PDF 文档中的文本
选择合适的模板类型
占位符设计
测试与验证
模板管理
可以。对于复杂 HTML、CSS 或现代 JavaScript,建议使用 ChromeHtmlConverter 类,它能生成更精确的 PDF。
?详见教程:使用 ChromeHtmlConverter 将 HTML 转换为 PDF
PDF 布局固定,替换文本不会自动重排。当新文本过长可能溢出,过短则留白。适用于可预测的字段内容(如姓名、日期等)。对于多行文本或动态内容,可使用 HTML 或 Word 模板,或借助 Spire.PDF 的绘图 API 直接绘制新文本块。
Spire.PDF 主要用于 PDF 操作,如需根据 Word 模板生成PDF,可使用 Spire.Doc for .NET 替换 Word 模板内容,然后再保存为 PDF。
这样即可轻松添加公司 Logo、水印或电子签名。
使用 Spire.PDF 在 C# 中基于模板生成 PDF,是提升文档自动化效率的理想方式。无论选择 HTML 模板还是现有 PDF 模板,开发者都能轻松创建内容准确、版面统一、外观专业的文件。通过在开发流程中引入模板机制,不仅能显著减少重复性工作,还能确保品牌风格与格式的一致性。
在实施过程中,合理选择模板类型、规范占位符设计,并在部署前充分测试真实数据,能够帮助你获得更稳定的输出效果。随着项目的深入,还可以结合 Spire.PDF 的高级功能,如数字签名、加密与批注等,实现更安全、更智能的文档处理方案。
通过这一方法,你的团队将能够在保证质量与一致性的同时,大幅提升 PDF 文档的生成速度与管理效率,从而让自动化办公与报告生成更加高效、可控。
如果您需要去除生成文档中的评估提示或解除功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。