C#控制台程序按指定行数拆分大Excel文件的代码问题
解决C#拆分大型Excel文件时行数异常的问题
看起来你在拆分Excel文件时遇到了循环范围和计数逻辑的问题,我帮你拆解下代码里的核心错误,再给出修正后的完整实现。
问题根源分析
你的代码主要有两个关键问题导致行数混乱:
1. 数据范围的结束行未动态计算
循环里你写了:
Excel.Range rng = (Excel.Range)sheet.Range[sheet.Cells[beginrow, 1], sheet.Cells[maxrows, 3]];
这里的maxrows是固定值10,所以每次都只复制到第10行,而不是从beginrow开始往后取10行数据。比如第一次循环beginrow=2,本该取2-11行(10行数据),但实际只取到10行,所以只有9行;后续循环beginrow不断增大,但结束行还是10,Excel会自动反向选择范围,导致行数完全混乱。
2. 循环次数计算逻辑错误
你用int maxloops = iRowCount / maxrows;计算循环次数,这里的iRowCount包含表头行,而且整数除法会忽略余数。比如51行的测试文件(1行表头+50行数据),51/10=5刚好,但如果是52行(1+51数据行),剩下的1行数据就会被直接忽略。正确的做法是基于实际数据行数向上取整计算循环次数。
修正后的完整代码
我标注了关键修改点,同时做了一些效率和资源优化:
string startPath = System.IO.Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName); string filePath_source = Path.Combine(startPath, @"Source_Files\Offers_Source_Temp.xlsx"); string filePath_copiedinto = Path.Combine(startPath, @"Source_Files\ToBeCopiedInto.xlsx"); Excel.Application app = new Excel.Application(); app.DisplayAlerts = false; Excel.Workbook book = app.Workbooks.Open(filePath_source); Excel.Worksheet sheet = (Excel.Worksheet)book.Worksheets.get_Item(1); int totalRows = sheet.UsedRange.Rows.Count; int rowsPerFile = 10; // 每个目标文件的数据行数,后续可改为50000 int dataRows = totalRows - 1; // 减去表头行,得到总数据行数 // 向上取整计算循环次数,确保所有数据都被拆分 int totalLoops = (dataRows + rowsPerFile - 1) / rowsPerFile; int currentStartRow = 2; // 从第2行开始(跳过表头) // 提前创建输出目录,避免保存时出错 string outputDir = Path.Combine(startPath, "Output_Files"); if (!Directory.Exists(outputDir)) { Directory.CreateDirectory(outputDir); } for (int i = 1; i <= totalLoops; i++) { // 计算当前循环的结束行:防止超出总数据行的最后一行 int currentEndRow = Math.Min(currentStartRow + rowsPerFile - 1, totalRows); // 正确选择要复制的范围:从currentStartRow到currentEndRow Excel.Range rng = sheet.Range[sheet.Cells[currentStartRow, 1], sheet.Cells[currentEndRow, 3]]; rng.Copy(Type.Missing); // 打开目标模板文件并粘贴 Excel.Application destxlApp = new Excel.Application(); destxlApp.DisplayAlerts = false; Excel.Workbook destworkBook = destxlApp.Workbooks.Open(filePath_copiedinto, 0, false); Excel.Worksheet destworkSheet = destworkBook.Worksheets.get_Item(1); // 移除不必要的Select操作,直接粘贴更高效 destworkSheet.Cells[1, 1].PasteSpecial(Type.Missing); // 用循环序号命名文件,更直观易管理 string destFileName = Path.Combine(outputDir, $"{i}.xlsx"); destworkBook.SaveAs(destFileName); // 清理资源:必须正确释放COM对象,避免Excel进程残留 destworkBook.Close(true); destxlApp.Quit(); System.Runtime.InteropServices.Marshal.ReleaseComObject(destworkSheet); System.Runtime.InteropServices.Marshal.ReleaseComObject(destworkBook); System.Runtime.InteropServices.Marshal.ReleaseComObject(destxlApp); // 更新下一次循环的起始行 currentStartRow = currentEndRow + 1; } // 清理源文件的Excel对象 book.Close(true); app.Quit(); System.Runtime.InteropServices.Marshal.ReleaseComObject(sheet); System.Runtime.InteropServices.Marshal.ReleaseComObject(book); System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
额外优化说明
- 移除冗余的Select操作:
destrange.Select()会触发UI交互,效率低且没必要,直接用Cells[1,1].PasteSpecial()即可。 - 添加目录检查:确保输出目录存在,避免保存文件时抛出异常。
- 正确释放COM对象:每次使用完Excel对象后手动释放,防止后台残留Excel进程占用资源。
- 优化文件命名:用循环序号命名文件(如1.xlsx、2.xlsx),比起始行命名更直观易管理。
测试验证
针对你51行的测试文件:
总数据行是50行,每个文件10行,刚好生成5个文件,每个文件都包含完整的10行数据(第一个文件2-11行,第二个12-21行,最后一个42-51行),不会再出现行数异常的情况。
内容的提问来源于stack exchange,提问作者IrfanClemson
相关产品推荐
相关产品推荐

