资讯详情

资讯详情

C# 实现 Excel 转 JSON 工具与源码:基于 Open XML SDK 的工程化方案

简介这是一份面向C#开发者与数据处理人员的Excel转JSON工具源码包针对需要将结构化表格数据导入Web应用或NoSQL数据库的场景提供可直接运行的转换方案。压缩包共36个文件约193KB包含6个cs源码文件、1个sln解决方案与csproj工程文件、3个exe可执行程序及配套dll、pdb调试文件另有config配置、resx资源与json示例等工程结构完整便于二次开发与调试。资源围绕OleDbConnection读取Excel、DataTable承载数据、JavaScriptSerializer序列化为JSON的完整链路展开并提示了.xls与.xlsx连接字符串差异、异常处理、大数据分批读取及日期格式清洗等实用要点。目前已有936人学习下载适合初、中级C#开发者参考可快速掌握文件I/O与数据序列化技巧也可将代码封装为独立工具类在项目中复用。1. 从 Excel 到 JSON 的 C# 转换工具为什么我建议你手头常备一份源码做后端或工具链开发的人迟早会撞上同一个需求业务方丢来一个 Excel说“把这个表转成 JSON接口要用”。第一次你可能手动复制粘贴第二次写个一次性脚本第三次就会发现——每次字段名不一样、每次合并单元格的坑都要重踩一遍。这份 C# 实现的 Excel 转 JSON 工具加源码解决的正是这个反复出现的脏活。它把读取、映射、序列化三步固化下来适合经常要处理配置表、字典表、测试数据的 .NET 开发者。拿到源码后你能直接改字段映射规则而不是被某个在线转换网站的黑匣子卡住。2. 先搞懂 Excel 转 JSON 在 C# 里到底走哪条路2.1 两条主流技术路线OLE DB 与 Open XML SDK在 C# 里读 Excel绕不开两个选择。第一条是老牌的 OLE DB / ACE 驱动通过Microsoft.ACE.OLEDB把工作表当数据库表查写 SQL 就能拿数据。优点是代码短、上手快缺点是必须装对应版本的 Access Database Engine32 位和 64 位还对不上部署到服务器上经常翻车。第二条是 Open XML SDKDocumentFormat.OpenXml直接解析.xlsx的 XML 结构不依赖 Office 或驱动纯托管代码跨平台也能跑。这份工具的源码走的是 Open XML 路线原因很实际你不可能要求每台部署机器都装一个 ACE 驱动尤其是容器环境。选型上我的判断标准很简单——如果只是本地临时转一次OLE DB 够用如果这个转换要进 CI、要进服务、要给别人用就老老实实上 Open XML。代价是代码量会多但换来的是可控和可移植。2.2 读取工作表与共享字符串表.xlsx本质是个 zip 包里面xl/worksheets/sheet1.xml存单元格xl/sharedStrings.xml存所有文本值。单元格里如果是字符串v存的不是文本本身而是共享字符串表的索引。很多人第一次解析发现拿到的全是数字就是漏了这一步回查。下面这段是读取的核心逻辑using DocumentFormat.OpenXml.Packaging; using DocumentFormat.OpenXml.Spreadsheet; public static ListDictionarystring, string ReadSheet(string filePath, string sheetName) { var rows new ListDictionarystring, string(); using (var doc SpreadsheetDocument.Open(filePath, false)) { var wbPart doc.WorkbookPart; // 按名字找到对应工作表避免默认取第一个 var sheet wbPart.Workbook.DescendantsSheet() .FirstOrDefault(s s.Name sheetName); if (sheet null) throw new ArgumentException($找不到工作表: {sheetName}); var wsPart (WorksheetPart)wbPart.GetPartById(sheet.Id); var sharedStrings wbPart.SharedStringTablePart?.SharedStringTable; var sheetData wsPart.Worksheet.ElementsSheetData().First(); var allRows sheetData.ElementsRow().ToList(); if (allRows.Count 0) return rows; // 第一行当表头 var headers allRows[0].ElementsCell() .Select(c GetCellValue(c, sharedStrings)).ToList(); foreach (var row in allRows.Skip(1)) { var dict new Dictionarystring, string(); var cells row.ElementsCell().ToList(); for (int i 0; i headers.Count; i) { // 单元格可能因空值被跳过需要按列引用对齐 var cell cells.FirstOrDefault(c GetColumnIndex(c.CellReference) i); dict[headers[i]] cell null ? : GetCellValue(cell, sharedStrings); } rows.Add(dict); } } return rows; }逻辑说明先定位工作表再拿共享字符串表备用。表头取第一行数据行逐行映射。这里有个关键点——Excel 里空单元格不会生成c节点所以不能简单按顺序取必须用CellReference比如B3算出列号再对齐否则一旦某行中间有空值后面所有列全部错位。GetColumnIndex就是把B3里的B转成数字 1 的小工具GetCellValue负责判断DataType是否为SharedString并回查。2.3 把行数据序列化成 JSON拿到ListDictionarystring, string之后序列化本身不难难的是类型处理。Excel 里所有东西读出来都是字符串但接口要的 JSON 里数字得是数字、布尔得是布尔。常见做法是加一层类型推断或让调用方传 schema。这份源码用的是显式类型映射稳妥using System.Text.Json; public static string ToJson(ListDictionarystring, string rows, Dictionarystring, string typeMap) { var result new ListDictionarystring, object(); foreach (var row in rows) { var obj new Dictionarystring, object(); foreach (var kv in row) { // 根据 typeMap 决定转换目标类型未声明的按字符串处理 obj[kv.Key] typeMap.TryGetValue(kv.Key, out var t) ? t switch { int long.TryParse(kv.Value, out var l) ? l : 0, double double.TryParse(kv.Value, out var d) ? d : 0.0, bool kv.Value 1 || kv.Value.Equals(true, StringComparison.OrdinalIgnoreCase), _ kv.Value } : kv.Value; } result.Add(obj); } // WriteIndented 方便人工核对生产环境可关掉 return JsonSerializer.Serialize(result, new JsonSerializerOptions { WriteIndented true, Encoder System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping }); }参数说明typeMap是字段名到类型的字典比如{age:int,score:double,enabled:bool}。没在 map 里的字段一律当字符串避免误转。UnsafeRelaxedJsonEscaping是为了让中文不被转成\uXXXX否则导出的 JSON 里全是转义码人工看很痛苦。WriteIndented在调试时开着正式输出可以设 false 省体积。3. 把工具跑起来从命令行到批量转换3.1 项目结构与依赖安装源码包解压后是一个标准的 .NET 控制台项目核心就三个文件Program.cs入口、ExcelReader.cs读取、JsonWriter.cs序列化。依赖只有一个 NuGet 包dotnet add package DocumentFormat.OpenXml --version 3.0.0装完直接dotnet build就能编译。如果你的项目是 .NET Framework 4.xOpen XML SDK 2.5 以上都支持但要注意System.Text.Json需要额外引 NuGet 包或者改用Newtonsoft.Json。我一般在新项目里统一用System.Text.Json少一个依赖是一个。3.2 命令行参数怎么传工具设计成命令行调用方便塞进批处理或 CI 脚本。参数就四个参数含义是否必填示例-i输入 Excel 路径是-i data.xlsx-s工作表名否默认第一个-s Sheet1-o输出 JSON 路径否默认同名 .json-o out.json-t类型映射文件否-t types.json调用示例dotnet run -- -i ./config.xlsx -s 角色表 -o ./role.json -t ./types.jsontypes.json长这样{ id: int, level: int, rate: double, isBoss: bool }这样跑完role.json里id就是数字而不是1001。如果不传-t所有字段都是字符串接口那边可能因为类型不匹配报错这是最常见的对接问题。3.3 批量转换多个工作表实际项目里一个 Excel 往往有十几张表一张张转太慢。源码里留了个-all开关遍历工作簿里所有 sheet每张输出一个同名 JSONif (args.Contains(-all)) { foreach (var sheetName in GetAllSheetNames(inputPath)) { var data ReadSheet(inputPath, sheetName); var json ToJson(data, typeMap); // 输出文件名用工作表名避免覆盖 File.WriteAllText(${outputDir}/{sheetName}.json, json); } }注意工作表名里可能有空格或特殊字符直接当文件名在 Windows 上会出问题稳妥做法是做一次文件名净化把非法字符替换成下划线。这个细节源码里已经处理了但如果你自己改别忘了。4. 避坑指南Excel 转 JSON 最容易翻车的五个地方4.1 合并单元格导致数据只出现在第一格现象表头是合并的比如“用户信息”横跨三列读出来只有第一列有值后面两列是空。原因合并单元格在 XML 里只有左上角那个格子存值其余格子根本不存在。解决要么在读取时根据MergeCells信息向上/向左填充要么在转换前要求业务方取消合并。我一般选后者因为填充逻辑一旦遇到复杂合并很容易出错不如从源头规范。4.2 日期变成一串数字现象Excel 里明明是2024-01-15读出来是45306。原因Excel 内部日期存的是从 1900-01-01 起的天数Open XML 读到的就是原始数字。解决判断单元格StyleIndex对应的数字格式是否为日期是的话用DateTime.FromOADate转换。但FromOADate对 1900 年之前的日期有 bug业务数据一般不会碰到知道边界就行。4.3 大文件内存爆掉现象几十万行的 Excel 一转就 OOM。原因SpreadsheetDocument.Open默认把整个 DOM 加载进内存。解决改用OpenXmlReader流式读取逐行处理内存占用能降一个数量级。代价是代码复杂一些不能随机访问。我的经验是超过 5 万行就上流式以下用 DOM 无所谓。4.4 数字精度丢失现象Excel 里123456789012345678这种长整数转出来末尾几位变 0。原因Excel 本身只保证 15 位有效数字超过就丢精度这是 Excel 的锅不是代码的锅。解决长 ID 类字段在 Excel 里就存成文本格式或者干脆别用 Excel 存这种数据。4.5 空行和尾部空列混进结果现象JSON 里多出一堆空对象。原因Excel 的UsedRange经常比实际数据大尾部有看不见的空行。解决读取后过滤掉所有值都为空的字典源码里加了一行rows.RemoveAll(r r.Values.All(string.IsNullOrWhiteSpace))。这行看着简单但少了它下游解析经常报莫名其妙的错。5. 进阶技巧让转换结果直接对接接口和配置系统5.1 用 JSON Schema 做输出校验转出来的 JSON 对不对别靠肉眼。我习惯在转换后跑一遍 Schema 校验尤其是字段类型和必填项。用NJsonSchema几行就能搞定var schema await NJsonSchema.JsonSchema.FromFileAsync(schema.json); var errors schema.Validate(jsonString); if (errors.Count 0) throw new Exception($JSON 校验失败: {string.Join(, , errors.Select(e e.ToString()))});这样一旦 Excel 里某列类型不对转换阶段就拦住了不会等到接口报 500 才发现。Schema 文件本身可以从接口的 DTO 反向生成保持单一事实来源。5.2 把转换嵌进构建流程如果 JSON 是给前端或客户端当配置用的完全可以把它做成构建的一步。在.csproj里加一个 MSBuild Target每次编译前自动跑转换Target NameExcelToJson BeforeTargetsBeforeBuild Exec Commanddotnet run --project tools/ExcelToJson -- -i config/data.xlsx -all -o wwwroot/config/ / /Target这样策划改完 Excel 提交CI 一跑JSON 自动更新省掉手动转换和忘记转换的麻烦。注意Exec的工作目录路径写错会静默失败建议加ContinueOnErrorfalse让它出错就中断构建。5.3 一个我踩过的教训早期我图省事直接在读取时把表头硬编码成字段名结果业务方改了一次列名整个转换静默产出空字段接口返回一堆 null排查了半天才发现是表头对不上。从那以后我每次改完 Excel 模板都强制走一遍“转换 → Schema 校验 → 抽样比对”三步哪怕只改了一个字。工具是死的流程是活的源码给你的是可控性但用不用好还是看习惯。希望这份工具和源码能帮你少加几次班。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →