
在 C# 开发中,处理 PDF 的字节数组是一种常见需求。开发者常常需要将 PDF 文档存储到数据库、通过 API 传输,或者完全在内存中进行处理而不依赖文件系统。在这些场景下,在 C# 中实现 PDF 与字节数组的互转 就显得尤为重要。
本文将通过 Spire.PDF for .NET 演示具体实现步骤。你将学习如何将字节数组转换为 PDF,如何将 PDF 转换为字节数组,以及如何直接在内存中使用 C# 代码编辑 PDF。
快速导航
使用 byte[] 作为传输格式,可以避免生成临时文件,使代码更适配云环境和容器环境。
准备工作: 在运行示例前,请先在项目中安装 Spire.PDF for .NET 的 NuGet 包。
Install-Package Spire.PDF
安装完成后,即可通过 byte[] 或 Stream 加载 PDF,编辑页面,并将结果写回内存或磁盘,无需额外转换器。
当上游服务(如 API 或消息队列)传递一个代表 PDF 的 byte[] 时,通常需要将其还原为文档,便于进一步处理或保存到磁盘。使用 Spire.PDF for .NET,这个过程可以直接在内存中完成,无需中间临时文件。
应用场景与方法: 从数据库或 API 获取一个 byte[],在内存中构建 PdfDocument,可选地验证一些基础信息,然后保存为 PDF。
using Spire.Pdf;
using System.IO;
class Program
{
static void Main()
{
// 示例来源:从数据库或 API 获取的字节数组
byte[] pdfBytes = File.ReadAllBytes("Sample.pdf"); // 请替换为实际数据来源
// 1) 从字节数组加载 PDF(内存中完成)
PdfDocument doc = new PdfDocument();
doc.LoadFromBytes(pdfBytes);
// 2) (可选)在保存或处理前查看文档信息
// int pageCount = doc.Pages.Count;
// 3) 保存为文件
doc.SaveToFile("Output.pdf");
doc.Close();
}
}
下图展示了字节数组到 PDF 的转换流程:

代码解析:
反向转换时,将 PDF 转换为 byte[] 便于写入数据库、缓存,或通过 HTTP 响应返回文件。Spire.PDF for .NET 支持将 PDF 保存到 MemoryStream,再通过 ToArray() 转换为字节数组。
应用场景与方法: 加载现有 PDF,将其保存到 MemoryStream,再提取 byte[]。这种方式特别适用于 API 返回 PDF 或持久化存储。
using Spire.Pdf;
using System.IO;
class Program
{
static void Main()
{
// 1) 从磁盘、网络或资源文件加载 PDF
PdfDocument doc = new PdfDocument();
doc.LoadFromFile("Input.pdf");
// 2) 保存到内存流,避免生成临时文件
byte[] pdfBytes;
using (var ms = new MemoryStream())
{
doc.SaveToStream(ms);
pdfBytes = ms.ToArray();
}
doc.Close();
// pdfBytes 现在包含完整文档(可直接写入数据库或 API 返回)
// 示例:return File(pdfBytes, "application/pdf");
}
}
下图展示了 PDF 转换为字节数组的流程:

关键点总结:
更强大的场景是直接在内存中编辑 PDF。你可以从 byte[] 加载 PDF,添加文字或图片、加水印、填写表单,再将结果保存为新的 byte[]。这种无文件管道非常适合微服务。
应用场景与方法: 从字节数组加载 PDF,在第一页添加文字标记,最后输出新的字节数组。
using Spire.Pdf;
using Spire.Pdf.Graphics;
using System.Drawing;
using System.IO;
class Program
{
static void Main()
{
// 来源可以是数据库、API 或文件,这里用 byte[] 表示
byte[] inputBytes = File.ReadAllBytes("Input.pdf");
// 1) 内存加载 PDF
var doc = new PdfDocument();
doc.LoadFromBytes(inputBytes);
// 2) 编辑:在第一页写入一个小标记
PdfPageBase page = doc.Pages[0];
page.Canvas.DrawString(
"编辑后的PDF文档",
new PdfTrueTypeFont(new Font("HarmonyOS Sans SC", 26f), true),
PdfBrushes.DarkBlue,
new PointF(100, page.Size.Height - 100)
);
// 3) 保存为新的字节数组
byte[] editedBytes;
using (var ms = new MemoryStream())
{
doc.SaveToStream(ms);
editedBytes = ms.ToArray();
}
doc.Close();
// editedBytes 可持久化存储或由 API 返回
}
}
下图展示了编辑后的 PDF 页面:

要点说明:
如果你想学习如何从零创建 PDF,可以参考我们的文章:在 C# 中创建 PDF 文档。
下表总结了该 API 在字节数组处理中的优势:
| 需求点 | Spire.PDF for .NET 的优势 |
|---|---|
| I/O 灵活性 | 同一个 PdfDocument API 支持从文件路径、Stream 或 byte[] 加载与保存 |
| 内存编辑 | 可绘制文本/图片、管理批注/表单、添加水印等,无需临时文件 |
| 服务友好 | 轻松集成到 ASP.NET 接口和后台任务 |
| 处理真实文档 | 支持多页 PDF,可通过流控制内存消耗 |
| 代码简洁 | 避免手动字节操作和复杂互操作,简化实现 |
本文演示了如何在 C# 中 将字节数组转换为 PDF、如何 将 PDF 转换为字节数组,以及如何 直接在内存中编辑 PDF。通过流和字节数组操作,可以让 API 设计更简洁、响应更高效,同时兼顾数据库和云环境的适配性。Spire.PDF for .NET 提供了一套一致的无文件化工作流,既适合快速转换,也能扩展为完整的内存文档处理。
如果你想在无功能限制的情况下体验这些特性,可以申请 30 天免费临时授权。或者,你也可以试用 Free Spire.PDF for .NET,适合轻量级 PDF 任务。
可以。使用 LoadFromBytes 从 byte[] 加载 PDF,然后保存到 MemoryStream 或直接在 API 中返回,无需落盘。
使用 PdfDocument.SaveToStream 方法,并调用 MemoryStream.ToArray() 获取字节数组,再存储为 BLOB 或传递给其他服务。
完全可以。先通过字节数组加载 PDF,再进行文字、图片、水印、批注或表单填写等编辑,最后保存为新的 byte[]。
及时释放流、在合适的场景重用缓冲区、每个操作/线程单独创建 PdfDocument。对于大文件,建议使用流式 I/O 控制内存使用,保证可预测性。
Spire.Presentation for .NET 10.8.2 现已发布, 该版本更新了 .NET 6.0 和 .NET Core 2.0 框架下的依赖项,并修复了在将 PPTX 转换为 PDF 时出现的一系列问题。更多详细信息如下所示。
更新依赖项::
Microsoft.Win32.Registry >= 4.5.0
System.Drawing.Common >= 4.7.2
System.Security.Permissions >= 4.7.0
System.Text.Encoding.CodePages >= 4.5.0
System.Security.Cryptography.Pkcs >= 4.7.0
System.Security.Cryptography.Xml >=4.7.1
HarfBuzzSharp >=8.3.0.1
Microsoft.Win32.Registry >= 5.0.0
System.Drawing.Common >= 6.0.0
System.Security.Permissions >= 6.0.0
System.Text.Encoding.CodePages >= 6.0.0
System.Security.Cryptography.Pkcs >= 6.0.5
System.Security.Cryptography.Xml >= 6.0.2
HarfBuzzSharp >=8.3.0.1
问题修复:
https://www.e-iceblue.cn/Downloads/Spire-Presentation-NET.html
Spire.PDF for Java 11.8.3 现已正式发布。该版本优化了 PDF 转 OFD 的内存消耗,并且还修复了一个在转换 SVG 到 PDF 文件时遇到的问题。详情请查阅以下内容。
优化:
问题修复:

水印技术是保护文档安全、声明所有权及防止未经授权复制的关键手段。无论是分发草稿还是为最终交付成果添加品牌标识,使用水印都能有效保护您的内容。本教程将指导您如何使用 Spire.PDF for Python 在 Python 中为 PDF 文件添加水印 。
我们将逐步演示如何插入文字水印与图片水印、调整透明度与定位,并解决常见问题——所有步骤均配有清晰且注释完善的代码示例。
Spire.PDF for Python 是一款功能强大的 PDF 处理库,特别针对水印功能提供以下特性:
开始前请确保已通过以下命令安装库:
pip install spire.pdf
以下代码演示如何为 PDF 每页添加倾斜的"禁止复制"文字水印,包含字号、颜色、位置、旋转角度及透明度的专业级设置:
from spire.pdf import *
from spire.pdf.common import *
import math
# 创建PdfDocument类的对象
doc = PdfDocument()
# 从指定路径加载PDF文档
doc.LoadFromFile("C:\\Users\\Administrator\\Desktop\\Input.pdf")
# 为水印字体创建PdfTrueTypeFont类的对象
font = PdfTrueTypeFont("黑体", 48.0, 0, True)
# 指定水印文本
text = "禁 止 复 制"
# 测量文本的尺寸以确保正确定位
text_width = font.MeasureString(text).Width
text_height = font.MeasureString(text).Height
# 循环遍历文档中的每一页
for i in range(doc.Pages.Count):
# 获取当前页面
page = doc.Pages.get_Item(i)
# 保存当前画布状态
state = page.Canvas.Save()
# 计算页面的中心坐标
x = page.Canvas.Size.Width / 2
y = page.Canvas.Size.Height / 2
# 将坐标系平移到中心,使页面的中心成为原点(0, 0)
page.Canvas.TranslateTransform(x, y)
# 将画布逆时针旋转45度以显示水印
page.Canvas.RotateTransform(-45.0)
# 设置水印的透明度
page.Canvas.SetTransparency(0.4)
# 使用负偏移量在中心位置绘制水印文本
page.Canvas.DrawString(text, font, PdfBrushes.get_Blue(), PointF(-text_width / 2, -text_height / 2))
# 恢复画布状态,以防止变换影响后续绘图
page.Canvas.Restore(state)
# 将修改后的文档保存到新的PDF文件
doc.SaveToFile("output/TextWatermark.pdf")
# 释放资源
doc.Dispose()
代码解析:
效果图:

以下代码演示如何为PDF每一页添加半透明图片水印,确保精准定位并呈现专业视觉效果。
from spire.pdf import *
from spire.pdf.common import *
# 创建PdfDocument类的对象
doc = PdfDocument()
# 从指定路径加载PDF文档
doc.LoadFromFile("C:\\Users\\Administrator\\Desktop\\Input.pdf")
# 从指定路径加载水印图像
image = PdfImage.FromFile("C:\\Users\\Administrator\\Desktop\\logo.png")
# 获取加载的图像的宽度和高度以进行定位
imageWidth = float(image.Width)
imageHeight = float(image.Height)
# 循环遍历文档中的每一页以应用水印
for i in range(doc.Pages.Count):
# 获取当前页面
page = doc.Pages.get_Item(i)
# 将水印的透明度设置为50%
page.Canvas.SetTransparency(0.5)
# 获取当前页面的尺寸
pageWidth = page.ActualSize.Width
pageHeight = page.ActualSize.Height
# 计算x和y坐标以将图像居中放置在页面上
x = (pageWidth - imageWidth) / 2
y = (pageHeight - imageHeight) / 2
# 在计算出的中心位置绘制图像
page.Canvas.DrawImage(image, x, y, imageWidth, imageHeight)
# 将修改后的文档保存到新的PDF文件
doc.SaveToFile("output/ImageWatermark.pdf")
# 释放资源
doc.Dispose()
代码解析:
效果图:

除了水印之外,您还可以为 PDF 添加图章。与水印固定位置不同,图章可以自由移动或删除,为文档批注提供了更大的灵活性。
借助 Spire.PDF for Python 库,为 PDF 文档添加水印既简单便捷又功能强大。您既可以批量添加醒目的"机密"警示水印,也能嵌入品牌 Logo 作为优雅的背景标识。该库支持灵活的坐标定位、透明度调节、旋转等高级功能,让您能够根据文档类型和使用场景,轻松打造专业级的水印解决方案。
可以,您只需在遍历PDF页面的循环中结合使用两种水印添加方法即可。
与文字水印示例类似,在绘制图片前使用 Canvas.RotateTransform( 角度) 方法即可实现旋转。
支持。当使用PNG图片作为水印时,Spire.PDF会保留其原有的透明度。
完全可以。您可以在页面循环中添加条件判断逻辑,根据页码或其他标准为不同页面应用不同的水印。
如果您需要去除生成文档中的评估提示或解除功能限制,请该Email地址已收到反垃圾邮件插件保护。要显示它您需要在浏览器中启用JavaScript。获取有效期 30 天的临时许可证。

在现代业务应用中,在 ASP.NET 环境下扫描条码和二维码的需求非常常见。无论是票务验证、支付处理,还是库存管理,集成一个ASP.NET 二维码扫描器或条码读取功能,都能显著提升系统的效率和准确性。
本教程将演示如何使用 Spire.Barcode for .NET 和 C#,在 ASP.NET 中实现完整的条码扫描解决方案。我们将创建一个 ASP.NET Core Web 应用,能够从上传的图片中读取二维码和多种条码格式,识别准确,并可方便地集成到现有项目中。
教程概览
步骤 1:创建项目
创建一个新的 ASP.NET Core Razor Pages 项目,作为扫描功能的基础。可通过以下命令创建新项目,也可在 Visual Studio 中手动配置:
dotnet new webapp -n QrBarcodeScanner
cd QrBarcodeScanner
步骤 2:安装 Spire.Barcode for .NET
安装 Spire.Barcode for .NET NuGet 包。该组件支持解码多种条码类型,并提供简单易用的 API。可在 NuGet 包管理器中搜索或使用以下命令安装:
dotnet add package Spire.Barcode
Spire.Barcode for .NET 内置支持二维码和多种条码格式,如 Code128、EAN-13 和 Code39,无需额外的图像处理库即可集成到 ASP.NET 项目。更多支持的条码类型,请参考 BarCodeType API 文档。
对于小型项目,也可使用 Free Spire.Barcode for .NET。
二维码和条码的扫描功能主要包括两部分:
我们先实现后端,确保扫描流程正确,然后再连接一个简洁的 Razor Page 前端,从而构建一个完整的二维码与条码扫描解决方案。
后端代码将上传的文件读入内存,并使用 Spire.Barcode 进行扫描,可通过内存流或文件路径处理。扫描结果会返回给前端。此实现支持二维码及其他条码类型,无需针对格式编写额外逻辑。
Index.cshtml.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Spire.Barcode;
public class IndexModel : PageModel
{
[BindProperty]
public IFormFile Upload { get; set; } // 上传的文件
public string Result { get; set; } // 扫描结果
public string UploadedImageBase64 { get; set; } // 用于预览的 Base64 字符串
public void OnPost()
{
if (Upload != null && Upload.Length > 0)
{
using (var ms = new MemoryStream())
{
// 将上传文件读入内存
Upload.CopyTo(ms);
// 转换为 Base64,用于 HTML <img> 显示
UploadedImageBase64 = "data:" + Upload.ContentType + ";base64," +
Convert.ToBase64String(ms.ToArray());
// 重置流位置以便扫描
ms.Position = 0;
// 扫描二维码或条码
try
{
string[] scanned = BarcodeScanner.Scan(ms);
Result = scanned != null && scanned.Length > 0
? string.Join(", ", scanned)
: "未检测到二维码或条码。";
}
catch (Exception ex)
{
Result = "扫描过程中出错: " + ex.Message;
}
}
}
}
}
关键类和方法说明
根据应用需求,这些方法可灵活使用。
下面的页面提供一个简洁的上传表单,用户上传包含二维码或条码的图片后,可显示图片及识别结果,并可一键复制。页面布局保持简洁,实现了在浏览器中快速识别二维码等条码的能力。
Index.cshtml
@page
@model IndexModel
@{
ViewData["Title"] = "二维码与条码扫描器";
}
<div style="max-width:420px;margin:40px auto;padding:20px;border:1px solid #ccc;border-radius:8px;background:#f9f9f9;">
<h2>二维码与条码扫描器</h2>
<form method="post" enctype="multipart/form-data" id="uploadForm">
<input type="file" name="upload" accept="image/*" required onchange="this.form.submit()" style="margin:10px 0;" />
</form>
@if (!string.IsNullOrEmpty(Model.UploadedImageBase64))
{
<div style="margin-top:15px;text-align:center;">
<img src="@Model.UploadedImageBase64" style="width:300px;height:300px;object-fit:contain;border:1px solid #ddd;background:#fff;" />
</div>
}
@if (!string.IsNullOrEmpty(Model.Result))
{
<div style="margin-top:15px;padding:10px;background:#e8f5e9;border-radius:6px;">
<b>扫描结果:</b>
<p id="scanText">@Model.Result</p>
<button type="button" onclick="navigator.clipboard.writeText(scanText.innerText)" style="background:#28a745;color:#fff;padding:6px 10px;border:none;border-radius:4px;">复制</button>
</div>
}
</div>
下图展示了扫描页面成功识别二维码和 Code128 条码后的效果,结果显示并可一键复制:

该 ASP.NET Core 应用可以从上传图片扫描二维码和条码。如需生成二维码或条码,请参考 在 ASP.NET Core 中生成二维码教程。
运行应用后,可用以下图片测试扫描功能:
若识别失败:
建议维护一个小型二维码和条码样本库,用于修改代码后定期测试。
本教程的条码扫描逻辑在不同 .NET 应用类型中使用方式相同,只需提供图片的方式不同。核心解码方法 BarcodeScanner.Scan() 可在以下环境中复用:
示例:最简 ASP.NET Core Web API 接口 — 接收 HTTP POST 上传的图片,并返回解码结果 JSON:
[ApiController]
[Route("api/[controller]")]
public class ScanController : ControllerBase
{
[HttpPost]
public IActionResult Scan(IFormFile file)
{
if (file == null) return BadRequest("未上传文件");
using var ms = new MemoryStream();
file.CopyTo(ms);
ms.Position = 0;
string[] results = BarcodeScanner.Scan(ms);
return Ok(results);
}
}
示例:控制台应用 — 扫描本地图片文件并打印解码文本:
string[] result = BarcodeScanner.Scan(@"C:\path\to\image.png");
Console.WriteLine(string.Join(", ", result));
这种灵活性方便开发者快速在新项目中集成二维码和条码扫描,或扩展已有 .NET 应用。
本教程展示了如何在 ASP.NET Core 中使用 Spire.Barcode for .NET,实现完整的二维码和条码扫描解决方案。从上传图片到解码显示结果,流程清晰,适用于多种应用类型。借助此方法,开发者可以快速在电商平台、票务系统、文件验证工具及其他关键业务 Web 应用中集成可靠的扫描功能。
对于更高级的场景,Spire.Barcode for .NET 提供了自定义识别流程、支持多种图片格式和条码类型等功能。申请免费试用以解锁所有高级功能。
立即下载 Spire.Barcode for .NET,开始构建自己的 ASP.NET 条码扫描解决方案。
Spire.Doc for Python 13.8.0 现已正式发布。该版本支持设置图表坐标轴间距,同时修复了获取文本框数量、公式显示、文档对比、自定义属性及内容格式等多个问题。更多详情如下。
新功能:
chart.AxisX.Units.Major = 5
chart.AxisX.Units.MajorTimeUnit= AxisTimeUnit.Days
chart.AxisX.Units.BaseTimeUnit= AxisTimeUnit.Days
doc.DefaultSubstitutionFontName = "SimSun";
问题修复:

Excel 常用于数据录入、整理和报表展示,而 JSON 则广泛应用于接口通信、前后端数据交互和系统集成。当数据需要在业务人员使用的 Excel 文件与程序使用的 JSON 格式之间流转时,就需要完成两种格式的相互转换。
本文将详细介绍如何使用 C# 和 Spire.XLS for .NET 库实现 Excel 转 JSON 和 JSON 转 Excel。内容涵盖导出整个工作簿、指定工作表和单元格区域为 JSON,自定义 JSON 输出格式,以及扁平或嵌套 JSON 数据写入 Excel 等常见场景,并提供可直接参考的代码示例。
目录
在 .NET 应用程序中,Excel(.xlsx 或 .xls)与 JSON 之间的转换通常用于以下场景:
开始之前,请确保开发环境满足以下要求:
在 Visual Studio 中打开项目,然后在“程序包管理器控制台”中执行以下命令:
Install-Package Spire.XLS
Install-Package Newtonsoft.Json
在终端环境中进行跨平台开发时,可在项目根目录执行以下命令:
dotnet add package Spire.XLS
dotnet add package Newtonsoft.Json
从 Spire.XLS for .NET 15.11.3 版本开始,开发者可以调用 SaveToFile() 方法,直接将 Excel 文件导出为 JSON 文件。这种方式适合转换整个工作簿,并且不需要自定义 JSON 结构的场景。
Workbook 对象。LoadFromFile() 方法加载 Excel 工作簿。SaveToFile() 方法,并将输出格式指定为 FileFormat.Json。using System;
using Spire.Xls;
namespace ConvertExcelToJSON
{
class Program
{
static void Main(string[] args)
{
string inputFile = @"Sample.xlsx";
string outputFile = @"output.json";
try
{
// 创建 Workbook 对象
using (Workbook workbook = new Workbook())
{
// 加载 Excel 文件
workbook.LoadFromFile(inputFile);
// 将整个工作簿保存为一个 JSON 文件
// 此功能需要 Spire.XLS 15.11.3 或更高版本
workbook.SaveToFile(outputFile, FileFormat.Json);
}
}
catch (Exception ex)
{
Console.WriteLine($"转换过程中发生错误:{ex.Message}");
}
}
}
}
输出的 JSON 文件:
转换后的 JSON 结构与 Excel 的对照关系如下:

直接将整个工作簿保存为 JSON 非常高效,但在一些场景中,需要对转换范围或输出格式进行更精细的控制,例如只转换指定工作表、指定单元格区域,或者自定义 JSON 的输出结构。针对这些需求,Spire.XLS 提供了相应的处理方式。
如果只需要转换工作簿中的某一个工作表,可以先将目标工作表复制到一个新的工作簿中,再将新工作簿保存为 JSON。
LoadFromFile() 加载源工作簿。Workbook 对象。Worksheets.AddCopy(),将目标工作表复制到新工作簿。SaveToFile(),并指定输出格式为 FileFormat.Json。using System;
using Spire.Xls;
namespace ConvertWorksheetToJSON
{
class Program
{
static void Main(string[] args)
{
string inputFile = @"Sample.xlsx";
string outputFile = @"sheet_output.json";
try
{
using (Workbook sourceWorkbook = new Workbook())
{
sourceWorkbook.LoadFromFile(inputFile);
// 通过索引获取第一个工作表
// 也可以按名称获取:sourceWorkbook.Worksheets["sheetName"]
Worksheet targetSheet = sourceWorkbook.Worksheets[0];
using (Workbook newWorkbook = new Workbook())
{
// 删除新工作簿中默认创建的工作表
newWorkbook.Worksheets.Clear();
// 将目标工作表复制到新工作簿
newWorkbook.Worksheets.AddCopy(targetSheet);
// 将新工作簿保存为 JSON 文件
newWorkbook.SaveToFile(outputFile, FileFormat.Json);
}
}
}
catch (Exception ex)
{
Console.WriteLine($"转换过程中发生错误:{ex.Message}");
}
}
}
}
如果只需要导出工作表中的部分数据,例如某个表格或指定区域,可以先将目标区域复制到一个新的工作簿中,再将新工作簿保存为 JSON。
worksheet.Range["A1:D3"]。Workbook 对象。Worksheet.Copy() 将目标区域复制到新工作簿的工作表中。SaveToFile(),并指定 FileFormat.Json,将新工作簿保存为 .json 文件。using System;
using Spire.Xls;
namespace ConvertExcelToJSON
{
class Program
{
static void Main(string[] args)
{
string inputFile = @"Sample.xlsx";
string outputFile = @"range_output.json";
try
{
using (Workbook sourceWorkbook = new Workbook())
{
sourceWorkbook.LoadFromFile(inputFile);
Worksheet sourceWorksheet = sourceWorkbook.Worksheets[0];
// 定义需要导出的区域,例如 A1:D3
CellRange sourceRange = sourceWorksheet.Range["A1:D3"];
using (Workbook targetWorkbook = new Workbook())
{
// 删除默认工作表
targetWorkbook.Worksheets.Clear();
// 新建一个用于保存所选区域的工作表
Worksheet targetWorksheet = targetWorkbook.Worksheets.Add("RangeData");
// 定义与源区域大小一致的目标区域
CellRange destinationRange = targetWorksheet.Range["A1:D3"];
// 将单元格的值和样式复制到新工作簿
sourceWorksheet.Copy(sourceRange, destinationRange, true);
// 将新工作簿保存为 JSON
targetWorkbook.SaveToFile(outputFile, FileFormat.Json);
}
}
}
catch (Exception ex)
{
Console.WriteLine($"导出单元格区域时发生错误:{ex.Message}");
}
}
}
}
SaveToFile() 方法可以快速完成转换,但生成的 JSON 格式是固定的。如果需要更灵活地控制输出样式,可以使用 ExportDataTable() 方法将工作表数据导出为 DataTable,再使用 Newtonsoft.Json 进行序列化。通过这种方式,可以自定义属性名称、空值处理、日期格式和缩进方式等内容。
ExportDataTable() 将数据导出为 DataTable。JsonSerializerSettings,定义 camelCase 命名、空值处理、日期格式等规则。JsonConvert.SerializeObject(),将 DataTable 按指定规则序列化为 JSON。using System;
using System.Data;
using System.IO;
using Spire.Xls;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace ConvertExcelToJSON
{
class Program
{
static void Main(string[] args)
{
string excelFilePath = @"Sample.xlsx";
string jsonOutputPath = "custom_output.json";
try
{
using (Workbook workbook = new Workbook())
{
workbook.LoadFromFile(excelFilePath);
Worksheet worksheet = workbook.Worksheets[0];
// 将表格数据转换为内存中的 DataTable
DataTable dataTable = worksheet.ExportDataTable(worksheet.AllocatedRange, true);
// 定义 JSON 序列化规则
JsonSerializerSettings settings = new JsonSerializerSettings
{
Formatting = Formatting.Indented, // 使用缩进,提高可读性
ContractResolver = new CamelCasePropertyNamesContractResolver(), // 使用 camelCase 命名
NullValueHandling = NullValueHandling.Ignore, // 忽略值为 null 的字段
DateFormatString = "yyyy-MM-dd" // 指定日期输出格式
};
// 根据规则将 DataTable 序列化为 JSON 字符串
string jsonResult = JsonConvert.SerializeObject(dataTable, settings);
// 将 JSON 字符串写入目标文件
File.WriteAllText(jsonOutputPath, jsonResult);
}
}
catch (Exception ex)
{
Console.WriteLine($"自定义 JSON 序列化时发生错误:{ex.Message}");
}
}
}
}
| 设置 | 作用 |
|---|---|
Formatting = Formatting.Indented |
添加换行和缩进,生成便于阅读的 JSON。 |
CamelCasePropertyNamesContractResolver |
对适用的属性名称使用 camelCase,这是 JSON API 中常见的命名方式。 |
NullValueHandling = NullValueHandling.Ignore |
忽略值为 null 或 DBNull.Value 的字段。 |
DateFormatString = "yyyy-MM-dd" |
按指定格式输出 DateTime 或 DateTimeOffset 类型的值。 |
注:CamelCasePropertyNamesContractResolver 主要针对英文属性名进行首字母小写转换,若 Excel 列名为中文则保持原样。
此外,还可以通过自定义 JsonConverter、调整日期处理规则或使用其他 ContractResolver,进一步控制 JSON 输出结果。更多信息可参阅 Newtonsoft.Json 文档。
将 JSON 转换为 Excel 时,可以先把 JSON 数据反序列化为 DataTable,再将该表格插入 Excel 工作表。
Newtonsoft.Json.JsonConvert.DeserializeObject<DataTable>(),将 JSON 转换为 DataTable。Workbook 对象。InsertDataTable() 将 DataTable 写入新工作簿的工作表中。using System;
using System.Data;
using System.Drawing;
using Spire.Xls;
using Newtonsoft.Json;
namespace ConvertJSONToExcel
{
class Program
{
static void Main(string[] args)
{
// 示例 JSON 数组
string jsonInput = @"
[
{""姓名"":""张三"",""年龄"":30,""部门"":""销售部"",""入职日期"":""2020-05-12"",""全职"":true},
{""姓名"":""李四"",""年龄"":25,""部门"":""市场部"",""入职日期"":""2021-09-01"",""全职"":false},
{""姓名"":""王五"",""年龄"":40,""部门"":""技术部"",""入职日期"":""2018-03-15"",""全职"":true},
{""姓名"":""赵六"",""年龄"":35,""部门"":""财务部"",""入职日期"":""2019-07-20"",""全职"":true}
]";
string excelOutputPath = "output.xlsx";
try
{
// 将 JSON 数组反序列化为 DataTable
DataTable dataTable = JsonConvert.DeserializeObject<DataTable>(jsonInput);
using (Workbook workbook = new Workbook())
{
Worksheet worksheet = workbook.Worksheets[0];
// 将 DataTable 插入工作表(包含列头)
worksheet.InsertDataTable(dataTable, true, 1, 1);
// 定义表头样式
CellStyle headerStyle = workbook.Styles.Add("HeaderStyle");
headerStyle.Font.IsBold = true;
headerStyle.Font.Size = 12;
headerStyle.Font.Color = Color.White;
headerStyle.Color = Color.DarkBlue;
headerStyle.HorizontalAlignment = HorizontalAlignType.Center;
headerStyle.VerticalAlignment = VerticalAlignType.Center;
// 将样式应用到表头行
int colCount = dataTable.Columns.Count;
worksheet.Range[1, 1, 1, colCount].CellStyleName = "HeaderStyle";
// 定义数据行样式
CellStyle dataStyle = workbook.Styles.Add("DataStyle");
dataStyle.HorizontalAlignment = HorizontalAlignType.Center;
dataStyle.VerticalAlignment = VerticalAlignType.Center;
dataStyle.Borders[BordersLineType.EdgeLeft].LineStyle = LineStyleType.Thin;
dataStyle.Borders[BordersLineType.EdgeRight].LineStyle = LineStyleType.Thin;
dataStyle.Borders[BordersLineType.EdgeTop].LineStyle = LineStyleType.Thin;
dataStyle.Borders[BordersLineType.EdgeBottom].LineStyle = LineStyleType.Thin;
// 将样式应用到数据行
int rowCount = dataTable.Rows.Count;
worksheet.Range[2, 1, rowCount + 1, colCount].CellStyleName = "DataStyle";
// 自动调整列宽
worksheet.AllocatedRange.AutoFitColumns();
// 将工作簿保存为 XLSX 文件
workbook.SaveToFile(excelOutputPath, ExcelVersion.Version2016);
}
}
catch (Exception ex)
{
Console.WriteLine($"转换过程中发生异常:{ex.Message}");
}
}
}
}

直接反序列化为 DataTable 的方式更适合结构扁平的 JSON 数组。如果记录被包含在根对象中,或者数据中包含嵌套对象和数组,则需要先提取目标记录并将嵌套结构扁平化,再转换为 DataTable。
例如,下面的 JSON 字符串同时包含根对象和嵌套数据:
string jsonInput = @"
{
""状态"": ""成功"",
""数据"": [
{
""订单编号"": ""DD20260001"",
""客户"": {
""编号"": 1001,
""姓名"": ""王芳"",
""会员等级"": ""黄金""
},
""商品"": [
{
""名称"": ""无线蓝牙耳机"",
""数量"": 2,
""单价"": 299.00
},
{
""名称"": ""手机保护壳"",
""数量"": 1,
""单价"": 39.90
}
],
""下单时间"": ""2026-07-10"",
""已付款"": true
},
{
""订单编号"": ""DD20260002"",
""客户"": {
""编号"": 1002,
""姓名"": ""陈明"",
""会员等级"": ""普通""
},
""商品"": [
{
""名称"": ""机械键盘"",
""数量"": 1,
""单价"": 459.00
}
],
""下单时间"": ""2026-07-12"",
""已付款"": false
}
]
}";
可以通过以下方法提取 数据 数组,将嵌套字段转换为适合表格展示的扁平字段,并返回 DataTable:
using System;
using System.Data;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
private static DataTable ConvertNestedJsonToDataTable(string jsonInput)
{
// JSON 根节点既可以是对象,也可以是数组
JToken rootToken = JToken.Parse(jsonInput);
// 支持根节点直接为数组,或数组位于根对象的 "数据" 属性中
JArray records = rootToken as JArray
?? ((rootToken as JObject)?["数据"] as JArray)
?? throw new ArgumentException("JSON 中未找到有效的记录数组。", nameof(jsonInput));
// 将嵌套对象和数组转换为适合表格展示的字段
var flattenedRecords = records.Select(record => new
{
订单编号 = (string)record["订单编号"] ?? string.Empty,
// 将 客户 对象拆分为独立列
客户编号 = (int?)record["客户"]?["编号"],
客户姓名 = (string)record["客户"]?["姓名"] ?? string.Empty,
会员等级 = (string)record["客户"]?["会员等级"] ?? string.Empty,
// 商品 是"数组套对象",先把每个商品格式化成 "名称×数量" 的字符串,
// 再用分号拼接成一列,同时把小计金额累加成 商品总额 列
商品明细 = string.Join(
"; ",
(record["商品"] as JArray)?.Select(item =>
$"{(string)item["名称"]}×{(int?)item["数量"]}")
?? Enumerable.Empty<string>()),
商品总额 = (record["商品"] as JArray)?
.Sum(item => ((decimal?)item["数量"] ?? 0) * ((decimal?)item["单价"] ?? 0)) ?? 0,
下单时间 = (string)record["下单时间"] ?? string.Empty,
已付款 = (bool?)record["已付款"] ?? false
});
// 将扁平化后的记录转换为 DataTable
string flattenedJson =
JsonConvert.SerializeObject(flattenedRecords);
DataTable dataTable =
JsonConvert.DeserializeObject<DataTable>(flattenedJson);
if (dataTable == null || dataTable.Columns.Count == 0)
throw new ArgumentException("JSON 中不包含可转换为表格的记录。", nameof(jsonInput));
return dataTable;
}
上述字段映射是根据示例 JSON 的结构编写的。处理其他 JSON 结构时,需要根据实际的数据层级调整所选属性和输出列。
在 Excel 与 JSON 之间转换数据时,建议注意以下事项,以提高转换结果的准确性和可用性:
null、空字符串、默认值,还是省略对应字段,并在整个转换过程中保持处理规则一致。00125 被转换为 125。不需要。Spire.XLS 是一个独立的 .NET 类库,可以读取、写入和转换 Excel 文件,不依赖 Microsoft Office 或 Excel Interop。
可以。LoadFromFile() 会自动识别文件格式,因此同一套代码既可以处理 .xls,也可以处理 .xlsx 文件。
可以,但 JsonConvert.DeserializeObject<DataTable>() 更适合处理扁平的 JSON 数组。对于嵌套 JSON,应先将数据整理为简单的对象列表,再调用 InsertDataTable() 写入 Excel。
适用。Spire.XLS 支持 .NET Framework、.NET Core 以及 .NET 5–10,因此这些代码可以运行在控制台应用、ASP.NET Core 服务,以及 Linux、macOS 等跨平台环境中。
本文介绍了如何使用 C# 将整个 Excel 工作簿、指定工作表和单元格区域转换为 JSON,以及如何将 JSON 数据导入 Excel。结合 Spire.XLS 与 Newtonsoft.Json 库,开发者既可以处理简单的格式转换,也可以应对自定义 JSON 格式和嵌套数据处理等进阶场景。
如需完整体验 Spire.XLS for .NET 的功能,可以申请有效期为 30 天的免费临时许可证。
Spire.PDF 11.8.0 现已正式发布。该版本优化了转换 PDF 到 PDFA 的耗时,同时修复了多个与 PDF 转换、文本提取以及表格内容显示相关的问题。更多详情如下。
优化:
调整:
问题修复:
Spire.PDF for Java 11.8.0 现已正式发布。该版本修复了内存溢出、透明度丢失及无法生成输出文档等问题,进一步提升了 PDF 转换过程的稳定性和正确性。详细更新内容如下:
问题修复:
Spire.PDF for C++ 11.8.1 已发布。本次更新修复了特定场景下,多产品同时使用的兼容性问题。详情请阅读以下内容。
问题修复: