如何使用C#读取Excel中合并单元格对应的下方数据?
用C#读取Excel中合并单元格下方的动态列数据
当然可以实现!我之前也处理过类似的Excel合并单元格数据读取需求,用C#结合成熟的Excel操作库就能轻松搞定,下面给你详细的实现思路和代码示例:
核心思路
要解决这个问题,关键是先定位到“周日”“周一”这类合并单元格的位置,再动态确定其下方对应的数据列范围(因为列数不固定),最后读取数据。这里我推荐用EPPlus(易用性强,对合并单元格的支持很友好),如果需要开源免费的方案,也可以用NPOI,思路是类似的。
具体实现步骤(以EPPlus为例)
1. 安装EPPlus包
首先通过NuGet安装EPPlus,注意:EPPlus 5+版本需要商用许可证,非商用场景可以安装4.x版本:
Install-Package EPPlus -Version 4.5.3.3
2. 编写读取代码
下面是完整的示例代码,包含合并单元格定位、动态列范围识别和数据读取:
using OfficeOpenXml; using System; using System.Collections.Generic; using System.IO; class ExcelReader { static void Main(string[] args) { // 设置EPPlus的许可证上下文(4.x版本需要) ExcelPackage.LicenseContext = LicenseContext.NonCommercial; string filePath = @"你的Excel文件路径.xlsx"; using (var package = new ExcelPackage(new FileInfo(filePath))) { var worksheet = package.Workbook.Worksheets[0]; // 获取第一个工作表 var mergeCells = worksheet.MergedCells; // 获取所有合并单元格区域 // 存储每个日期对应的数据 Dictionary<string, List<List<string>>> dateDataMap = new Dictionary<string, List<List<string>>>(); for (int i = 0; i < mergeCells.Count; i++) { var mergeRange = worksheet.Cells[mergeCells[i]]; string cellText = mergeRange.Value?.ToString().Trim(); // 筛选出我们需要的合并标题:周日、周一 if (cellText == "周日" || cellText == "周一") { // 获取合并单元格的位置信息 int startRow = mergeRange.Start.Row; int startCol = mergeRange.Start.Column; int endRow = mergeRange.End.Row; // 数据起始行是合并单元格的下一行 int dataStartRow = endRow + 1; // 动态确定数据的结束列:找到下一个合并单元格的起始列,或者到工作表最后一列 int dataEndCol = worksheet.Dimension.End.Column; if (i < mergeCells.Count - 1) { var nextMergeRange = worksheet.Cells[mergeCells[i + 1]]; dataEndCol = nextMergeRange.Start.Column - 1; } // 读取该日期下的所有数据行 List<List<string>> dataRows = new List<List<string>>(); for (int row = dataStartRow; row <= worksheet.Dimension.End.Row; row++) { // 检查当前行是否有数据,没有则停止(避免读取空行) bool isRowEmpty = true; List<string> rowData = new List<string>(); for (int col = startCol; col <= dataEndCol; col++) { string cellValue = worksheet.Cells[row, col].Value?.ToString().Trim() ?? ""; rowData.Add(cellValue); if (!string.IsNullOrEmpty(cellValue)) { isRowEmpty = false; } } if (isRowEmpty) { break; // 遇到空行就停止读取该日期的数据 } dataRows.Add(rowData); } dateDataMap.Add(cellText, dataRows); } } // 输出读取到的数据 foreach (var kvp in dateDataMap) { Console.WriteLine($"=== {kvp.Key} 对应数据 ==="); foreach (var row in kvp.Value) { Console.WriteLine(string.Join(", ", row)); } } } } }
3. 代码说明
- 合并单元格定位:通过
worksheet.MergedCells获取所有合并区域,然后筛选出包含“周日”“周一”的区域,注意合并单元格的文本只存储在左上角单元格中。 - 动态列范围:通过判断下一个合并单元格的起始列来确定当前数据的结束列,如果是最后一个合并标题,就取工作表的最后一列。
- 空行处理:读取数据时检查每行是否为空,避免读取无效的空行。
替代方案(NPOI)
如果需要完全开源免费的库,可以用NPOI,核心思路和上面一致:
- 先获取所有合并单元格区域,筛选目标标题
- 确定数据行和列范围
- 遍历读取数据
NPOI的合并单元格处理需要通过sheet.GetMergedRegion(int index)来获取,具体代码可以参考EPPlus的逻辑进行调整。
注意事项
- 如果你的Excel是
.xls格式(旧版),EPPlus不支持,建议用NPOI来处理。 - 确保Excel文件没有被其他程序占用,否则会抛出文件访问异常。
内容的提问来源于stack exchange,提问作者barteloma
相关产品推荐
相关产品推荐

