C#编写Excel提取程序 动态定位列首尾数值实现求和
C# 动态定位Excel列数值区间累加实现方案
核心解决逻辑
针对列位置动态变动、列内存在空单元格的场景,不需要写死单元格编号,按三步实现即可:
- 先通过表头文本匹配定位目标列,不受列左右移动影响
- 提取目标列所有有效数值单元格,自动跳过空值,直接拿到列内首个、末尾数值的位置
- 遍历首末数值所在行区间,累加所有有效数值
示例数据结构如下:
| # | 1st column | 2nd column |
|---|---|---|
| 1 | 4 | |
| 2 | 10 | |
| 3 | 8 | |
| 4 | 20 | |
| 5 | 52 |
以上述数据为例:定位1st column列时会自动匹配到对应列,识别首数值4、末数值8,累加结果为22;定位2nd column列时自动匹配对应列,识别首数值20、末数值52,累加结果为72,空单元格完全不影响定位和计算。
完善后的可运行代码
首先需要项目添加Microsoft.Office.Interop.Excel程序集引用,同时引入以下命名空间:
using System; using System.Runtime.InteropServices; using Excel = Microsoft.Office.Interop.Excel;
核心实现代码:
string fileExcel = @"C:\test.xlsx"; Excel.Application xlApplication = null; Excel.Workbook xlWorkbook = null; Excel.Worksheet xlWorksheet = null; Excel.Range headerRange = null; Excel.Range colAllCells = null; Excel.Range colValueCells = null; try { xlApplication = new Excel.Application(); xlApplication.Visible = false; xlWorkbook = xlApplication.Workbooks.Open(fileExcel); xlWorksheet = xlWorkbook.ActiveSheet; // 定位目标列表头,替换表头名即可切换统计列 string targetHeaderName = "1st column"; headerRange = xlWorksheet.Cells.Find( What: targetHeaderName, LookIn: Excel.XlFindLookIn.xlValues, LookAt: Excel.XlLookAt.xlWhole, SearchOrder: Excel.XlSearchOrder.xlByRows, SearchDirection: Excel.XlSearchDirection.xlNext, MatchCase: false ); if (headerRange == null) { throw new Exception($"未找到表头为「{targetHeaderName}」的列,请检查文件内容"); } colAllCells = xlWorksheet.Columns[headerRange.Column]; // 提取列内所有常量数值,自动跳过空单元格、文本单元格 colValueCells = colAllCells.SpecialCells( Excel.XlCellType.xlCellTypeConstants, Excel.XlSpecialCellsValue.xlNumbers ); if (colValueCells == null) { throw new Exception($"目标列「{targetHeaderName}」无有效数值"); } // 定位首、末数值单元格 Excel.Range firstValueCell = colValueCells.Cells[1, 1]; Excel.Range lastValueCell = colValueCells.Cells[colValueCells.Cells.Count, 1]; int startRow = firstValueCell.Row; int endRow = lastValueCell.Row; int targetCol = headerRange.Column; // 区间累加 decimal sumResult = 0; for (int row = startRow; row <= endRow; row++) { Excel.Range currentCell = (Excel.Range)xlWorksheet.Cells[row, targetCol]; if (currentCell.Value != null && decimal.TryParse(currentCell.Value.ToString(), out decimal num)) { sumResult += num; } Marshal.FinalReleaseComObject(currentCell); } Console.WriteLine($"统计结果:首数值{firstValueCell.Value},末数值{lastValueCell.Value},区间累加和{sumResult}"); } catch (Exception ex) { Console.WriteLine($"处理异常:{ex.Message}"); } finally { // 释放所有COM对象,避免Excel进程后台残留锁文件 if (colValueCells != null) Marshal.FinalReleaseComObject(colValueCells); if (colAllCells != null) Marshal.FinalReleaseComObject(colAllCells); if (headerRange != null) Marshal.FinalReleaseComObject(headerRange); xlWorkbook?.Close(false); xlApplication?.Quit(); if (xlWorksheet != null) Marshal.FinalReleaseComObject(xlWorksheet); if (xlWorkbook != null) Marshal.FinalReleaseComObject(xlWorkbook); if (xlApplication != null) Marshal.FinalReleaseComObject(xlApplication); GC.Collect(); GC.WaitForPendingFinalizers(); }
注意事项
- 表头匹配默认使用精确匹配,如果表头存在前后不可见空格,可将
LookAt参数改为Excel.XlLookAt.xlPart,注意避免列名部分重复导致错配 - 如果目标列存在公式生成的数值,将
SpecialCells的第一个参数替换为Excel.XlCellType.xlCellTypeFormulas,或同时传入两种类型即可识别 - 累加逻辑自动跳过区间内的空值、非数值内容,不会抛出转换错误
- 必须在finally块释放COM对象,否则处理完文件后会有Excel进程残留在后台,占用内存且锁定文件无法编辑
内容的提问来源于stack exchange,提问作者m.woods
相关产品推荐
相关产品推荐

