合并不同工作簿指定工作表至新工作簿时遇COM异常0x800401A8
问题描述
我有三个Excel文件,想从中选择特定工作表创建新工作簿。使用Microsoft.Office.Interop.Excel编写代码时,第一个工作表能成功复制到新工作簿,但复制第二个工作表时抛出异常:System.Runtime.InteropServices.COMException : Exception from HRESULT : 0x800401A8,换了另一种复制写法还是报同样的错。
代码示例:
var App = new Microsoft.Office.Interop.Excel.Application(); Workbook book1 = App.Workbooks.Open(@"path"); Worksheet sheet1 = book1.Worksheets[1]; Workbook book2 = App.Workbooks.Open(@"path"); Worksheet sheet2 = book2.Worksheets[1]; Workbook book3 = App.Workbooks.Open(@"path"); Worksheet sheet3 = book3.Worksheets[1]; var newBook = App.Workbooks.Add(); sheet1.UsedRange.Copy(newBook.Worksheets[1].Range["A1"]); // 第一个sheet1复制正常,但复制第二个sheet2时抛出异常 sheet2.UsedRange.Copy(newBook.Worksheets[2].Range["A1"]); sheet3.UsedRange.Copy(newBook.Worksheets[3].Range["A1"]); newBook.SaveAs(@"path\newWorkbook.xlsx"); newBook.Close(); App.Quit(); // 试过这种写法还是报错 var sourceRange = sheet2.UsedRange; var targetRange = newBook.Worksheets[2].Range["A1"]; sourceRange.Copy(targetRange);
原因分析与解决方法
核心原因
通过App.Workbooks.Add()创建的新工作簿默认只有1个工作表,你尝试访问newBook.Worksheets[2]时,这个工作表根本不存在,所以触发了COM异常。
解决方法1:先添加足够的工作表
在复制数据前,先给新工作簿添加缺失的工作表:
var newBook = App.Workbooks.Add(); // 添加第二个工作表 newBook.Worksheets.Add(After: newBook.Worksheets[newBook.Worksheets.Count]); // 添加第三个工作表 newBook.Worksheets.Add(After: newBook.Worksheets[newBook.Worksheets.Count]); // 再执行复制操作 sheet1.UsedRange.Copy(newBook.Worksheets[1].Range["A1"]); sheet2.UsedRange.Copy(newBook.Worksheets[2].Range["A1"]); sheet3.UsedRange.Copy(newBook.Worksheets[3].Range["A1"]);
解决方法2:直接复制整个工作表(更推荐)
不用复制UsedRange,直接把源工作表复制到新工作簿,这样会自动创建新工作表,还能保留格式、公式等:
var newBook = App.Workbooks.Add(); // 复制sheet1到新工作簿末尾 sheet1.Copy(After: newBook.Worksheets[newBook.Worksheets.Count]); // 复制sheet2到新工作簿末尾 sheet2.Copy(After: newBook.Worksheets[newBook.Worksheets.Count]); // 复制sheet3到新工作簿末尾 sheet3.Copy(After: newBook.Worksheets[newBook.Worksheets.Count]); // 删除新工作簿默认的空白工作表(可选) newBook.Worksheets[1].Delete(); newBook.SaveAs(@"path\newWorkbook.xlsx"); newBook.Close(); App.Quit();
额外注意事项
操作完Excel对象后,务必释放所有COM对象,避免进程残留:
// 释放工作表对象 System.Runtime.InteropServices.Marshal.ReleaseComObject(sheet1); System.Runtime.InteropServices.Marshal.ReleaseComObject(sheet2); System.Runtime.InteropServices.Marshal.ReleaseComObject(sheet3); // 释放工作簿对象 System.Runtime.InteropServices.Marshal.ReleaseComObject(book1); System.Runtime.InteropServices.Marshal.ReleaseComObject(book2); System.Runtime.InteropServices.Marshal.ReleaseComObject(book3); System.Runtime.InteropServices.Marshal.ReleaseComObject(newBook); // 退出并释放应用对象 App.Quit(); System.Runtime.InteropServices.Marshal.ReleaseComObject(App);
内容的提问来源于stack exchange,提问作者Nilesh Patil
相关产品推荐
相关产品推荐

