【问题标题】:Excel User Defined Function Locks Invoking SpreadsheetExcel 用户定义功能锁调用电子表格
【发布时间】:2015-03-04 16:50:13
【问题描述】:

我正在使用 NetOffice 编辑 Excel 电子表格。如果我从 Excel 用户定义函数调用代码,它不会让我编辑调用电子表格。

Excel.Application excelApplication = Excel.Application.GetActiveInstance();
Excel.Worksheet workSheet = (Excel.Worksheet) excelApplication.ActiveSheet;
Excel.Range cell = workSheet.Cells[2, 2];

object value = cell.Value; //works
cell.Value = 3; //Throws Exception

是否有解决方法可以让我做到这一点?

例外是

“System.Runtime.InteropServices.COMException (0x80004005):有关详细信息,请参阅内部异常。---> System.Reflection.TargetInvocationException:调用目标已引发异常。---> 系统.Runtime.InteropServices.COMException:来自 HRESULT 的异常:0x800A03EC --- 内部异常堆栈跟踪结束 --- 在 System.RuntimeType.InvokeDispMethod(字符串名称,BindingFlags invokeAttr,对象目标,对象 [] 参数,布尔 [] byrefModifiers,Int32 文化,字符串 [] 命名参数) 在 System.RuntimeType.InvokeMember(字符串名称、BindingFlags bindingFlags、Binder binder、Object 目标、Object[] providedArgs、ParameterModifier[] 修饰符、CultureInfo 文化、String[] namedParams) 在 System.Type.InvokeMember(字符串名称、BindingFlags invokeAttr、Binder binder、Object target、Object[] args、CultureInfo 文化) 在 NetOffice.Invoker.PropertySet(COMObject comObject,字符串名称,对象 [] 值) 在 NetOffice.Invoker.PropertySet(COMObject comObject,字符串名称,对象 [] 值) 在 NetOffice.ExcelApi.Range.set_Value(对象值) 在 ExcelExamplesCS45.Example01.RunExample() 在 \psf\home\Documents\Visual Studio 2013\Projects\Excel-REPL\Excel-REPL\Example01.cs:line 29 在 ClojureExcel.MainClass.Test() in \psf\home\Documents\Visual Studio 2013\Projects\Excel-REPL\Excel-REPL\MainClass.cs:line 310"

【问题讨论】:

  • 一般来说,工作表单元格中的 UDF 只能向该单元格返回一个值。它不能改变其他单元格。
  • 我想知道 Excel 实例在评估 UDF 时是否放置了一些锁,或者是否有办法绕过所述锁。
  • 是的,只需在单独的线程中运行上述代码即可。像魅力一样工作!
  • 在尝试使用另一个线程解决此 Excel 限制时存在许多问题:您的代码可能无法获得正确的 Excel 实例或正确的工作表(因为您不知道何时另一个线程上的代码运行),并且可能由于悬空的 COM 引用而使 Excel 进程继续运行。有一些解决方法,但 Excel 有充分的理由阻止此类调用...
  • 传统上我使用 Apache POI 创建电子表格,但最近我想要一种更像 repl 的方式,所以我创建了github.com/whamtet/Excel-REPL。它有点滥用 Excel,但总的来说效果很好!

标签: c# excel netoffice


【解决方案1】:
    Exception from HRESULT: 0x800A03EC

我将仅描述此类问题的一般故障排除策略,对于此错误已经有许多个答案。可能太多了。

HRESULT 是一个错误代码,可以帮助您查明错误的根本原因。它分为 3 个部分,错误的严重性、“设施”代码和错误代码。您机器上的 WinError.h SDK 文件可以准确地向您显示代码中的哪些位与信息的哪些部分相对应。 “设施”是一个令人讨厌的词,意思是“错误源”。

设施代码是 0x0A = 10。这意味着“应用程序定义错误”。或者换句话说,错误代码高度特定于生成错误的应用程序。错误代码是0x03EC = 1004。所以你可以把它写成:“Excel error 1004”。

你可以用谷歌搜索一下,你会得到 356,000 次点击。花一些时间阅读热门歌曲,了解它的全部内容。忽略吸血鬼网站的点击,只要您从运行注册表清理程序开始,就可以修复您机器上的任何错误。事实是,这个错误非常很常见,它也会在宏和 VBA 代码中生成。通常使用稍微好一点的错误消息,在 Excel 中,您可以获得超过 1004 错误代码的错误的简要说明。但是,当您使用自动化时,您必须不使用它,这当然会更难。

您可以通过查看堆栈跟踪获得另一个数据点,您可以看到 NetOffice 做了什么。它使用后期绑定 (InvokeDispMethod),因此您不能 100% 确定哪种特定互操作方法失败。 NetOffice 的一个广告功能,它实际上使故障排除更加困难。但一个非常值得注意的互操作点是“Range.set_Value”。这是您可以对高度特定的 Excel 自动化属性进行逆向工程的东西,Excel 对象模型有一个 Range 接口,它有一个 Value 属性。它正在分配失败的属性。与您要执行的操作完全匹配,设置单元格的值。

因此,您可以将 Google 查询改进为“Excel 错误 1004 Range.Value”。这使得点击更加具体,前 4 个点击都是 SO 问题,并且所有吸血鬼网站点击都被过滤掉了。总结错误的主要解释:

  • 您无法写入电子表格,因为它受到保护
  • 您写入的值与单元格格式不兼容,如无效日期
  • 您尝试更新的范围无效,例如行号或列号
  • 代码运行是由于在单元格中输入了一个函数,并且它正在尝试更新另一个单元格。

您可以很容易地消除第一个项目符号,只需确保电子表格不受保护和/或使用 Unprotect()。第二个项目符号也一样,只需写回您阅读的内容。第三个子弹不可能,你可以很好地阅读单元格。第 4 个项目符号与您的问题标题“用户定义函数”完全匹配。换句话说,问题是

   Excel.Range cell = workSheet.Cells[2, 2];

问题在于这不是包含用户定义函数的单元格。所以分配它是非法的。如果不知道 [2, 2] 有什么特别之处,我无法提出解决方法。尝试将其更改为实际包含 UDF 的单元格。

UDF应该要做的是返回一个值,然后该值将成为显示的单元格值。 This KB article 记录了 UDF 的限制。 This SO question 有关于在 .NET 代码中实现 UDF 的答案,它提到了 Excel-DNA。

【讨论】:

    【解决方案2】:

    有一个非常简单的解决方法:只需在单独的线程中编辑工作表。为什么我一开始就没有想到!!???

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-14
      • 1970-01-01
      • 2012-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多