问题描述
我正在处理一种 ListObject 数据的缓存,并发现了一个可能的错误,即在用户撤消表自动扩展/调整大小后 ListObject 对象引用消失了。
重现步骤:
-
创建 .NET Framework 控制台应用程序(在我的例子中是 4.7.2)
-
添加对 Microsoft.Office.Interop.Excel 的引用(最新版本没问题)
-
将以下代码复制并粘贴到 Program.cs 中(它会打开 Excel,打开示例工作簿,订阅 SheetChange 事件并可选择更改表格而不是您 - 如果您想手动研究问题 - 步骤重现在代码片段中,并在步骤 1 后查看提供的 GIF 以查看导致问题的操作)
-
进一步的复制步骤在代码注释中提到
// Steps to replicate bug: // 1. Change filePath variable to point to the example file and uncomment the "DoAutomaticChanges()" line (50). // 2. Run app,watch the Excel window to view the steps and the SheetChange event handler will report // System.Runtime.InteropServices.COMException: 'Exception from HRESULT: 0x800A01A8' when trying to // access the ListObject after last cell value change in table. // // Manual way to replicate bug: // 1. Change filePath variable to point to the example file. // 2. Comment out the "DoAutomaticChanges()" line (50). // 3. Start the app and let it open the example workbook. // 4. Select a couple of cells in the row beneath the table (example range to select D13:E13) // 5. Enter "test" and press CTRL + Enter // 6. Press CTRL + Z twice (the bug presents itself even if you undo once and try to edit a random table cell) // 7. Edit random cell in table and the SheetChange event handler will report // System.Runtime.InteropServices.COMException: 'Exception from HRESULT: 0x800A01A8' when trying to access the ListObject. static Worksheet sheet; static Application excel; static void Main(string[] args) { var tableName = "ExampleTableName"; var filePath = @"C:\Users\...\ExampleBook.xlsx"; excel = new Application { Visible = true }; var wb = excel.Workbooks.Open(filePath); sheet = wb.Sheets[1] as Worksheet; var listObject = sheet .ListObjects .OfType<ListObject>() .Single(lo => lo.Name == tableName); wb.SheetChange += (s,e) => { var test = listObject.Range; }; //DoAutomaticChanges(); Console.ReadLine(); wb.Close(false); excel.Quit(); } private static void DoAutomaticChanges() { sheet.Range[sheet.Cells[13,4],sheet.Cells[13,5]].Select(); Thread.Sleep(500); excel.SendKeys("test^~"); Thread.Sleep(500); excel.SendKeys("^z"); Thread.Sleep(500); excel.SendKeys("^z"); Thread.Sleep(500); // this approach represents user interaction and makes the ListObject unavailable sheet.Range[sheet.Cells[6,5],sheet.Cells[6,5]].Value2 = "test"; // this approach works from code without losing reference of ListObject,but does not represent actual user interaction //sheet.Range[sheet.Cells[6,5]].Select(); //excel.SendKeys("test"); }
这是预期的行为吗?
在抛出异常并发现存在 ListObject 后,我尝试从工作簿中获取所有表,因此我对问题的理解是在撤消自动扩展/调整大小时以某种方式创建了一个新表而不是旧表。关于这个问题有什么想法吗?
我当前的解决方法 -> 我存储 ListObject 的名称,当异常发生时,我再次从当前工作簿中获取具有相同名称的 ListObject。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)