简体   繁体   English

如何使用 Excel Interop 获取 CustomDocumentProperties?

[英]How to get CustomDocumentProperties using Excel Interop?

The below code is used to get the custom document properties for Excel workbook.以下代码用于获取 Excel 工作簿的自定义文档属性。

var xlApp = Globals.ThisAddIn.Application; // This works in VSTO Excel Add-in
var xlApp = new global::Microsoft.Office.Interop.Excel.Application(); // This doesn't work anywhere
xlApp.Visible = true;
global::Microsoft.Office.Interop.Excel.Workbook workbook = xlApp.Workbooks.Open(file, false, true, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, false, Type.Missing, Type.Missing);

global::Microsoft.Office.Core.DocumentProperties properties = workbook.CustomDocumentProperties; // Exception occurs here
global::Microsoft.Office.Core.DocumentProperty property = properties["propertyname"];

The first 2 lines are references to the Excel Application .前两行是对 Excel Application引用。 One obtain the reference from VSTO add-in internals, the other is a regular new Application() .一个从 VSTO 插件内部获取引用,另一个是常规的new Application()

When using the Application from VSTO internals, the code run fines without any problems.从 VSTO 内部使用Application ,代码运行良好,没有任何问题。 But when using new Application() , the workbook.CustomDocumentProperties line throws InvalidCastException :但是当使用new Application()workbook.CustomDocumentProperties行会抛出InvalidCastException

Unable to cast COM object of type 'System.__ComObject' to interface type 'Microsoft.Office.Core.DocumentProperties'.无法将类型为“System.__ComObject”的 COM 对象转换为接口类型“Microsoft.Office.Core.DocumentProperties”。 This operation failed because the QueryInterface call on the COM component for the interface with IID '{2DF8D04D-5BFA-101B-BDE5-00AA0044DE52}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).此操作失败,因为 IID 为“{2DF8D04D-5BFA-101B-BDE5-00AA0044DE52}”的接口的 COM 组件上的 QueryInterface 调用因以下错误而失败:不支持此类接口(来自 HRESULT 的异常:0x80004002 (E_NOINTERFACE)) .

I am trying to make it to work on a C# winforms project without VSTO.我试图让它在没有 VSTO 的 C# winforms 项目上工作。 A lot of examples and tutorials use new Application() for Excel interop, but I noticed that Microsoft.Office.Interop.Excel.Application is an interface, so using new on interface is actually strange to me.很多示例和教程使用new Application()进行 Excel 互操作,但我注意到Microsoft.Office.Interop.Excel.Application是一个接口,因此在接口上使用new对我来说实际上很陌生。 How can I create a proper Application that can get the CustomDocumentProperties ?如何创建可以获取CustomDocumentProperties的正确应用程序?

Reference Assemblies I am using:我正在使用的参考程序集:

  • Microsoft.Office.Interop.Excel v2.0.50727 Version 14.0.0.0 Microsoft.Office.Interop.Excel v2.0.50727 版本 14.0.0.0
  • Microsoft.CSharp v4.0.30319 Version 4.0.0.0 Microsoft.CSharp v4.0.30319 版本 4.0.0.0

I noticed that Microsoft.Office.Interop.Excel.Application is an interface, so using new on interface is actually strange to me.我注意到 Microsoft.Office.Interop.Excel.Application 是一个接口,所以在接口上使用 new 对我来说实际上很陌生。

That is strange indeed, but by design.这确实很奇怪,但有意为之。 The Excel.Application interface is decorated with the CoClass attribute telling the actual class to instantiate on 'instantiating' the interface. Excel.Application接口用CoClass属性装饰,告诉实际类在“实例化”接口时实例化。 More about it here .更多关于它在这里

But when using new Application() , the workbook.CustomDocumentProperties line throws InvalidCastException :但是当使用new Application()workbook.CustomDocumentProperties行会抛出InvalidCastException

Strange indeed again.果然又奇怪了。 I have experienced some issues myself using document properties.我自己在使用文档属性时遇到了一些问题。 It seems that the actual class returned differs from the spec, so I moved to use dynamic in order to prevent type casting issues.返回的实际类似乎与规范不同,因此我改为使用dynamic以防止类型转换问题。

So instead of this:所以而不是这个:

Microsoft.Office.Core.DocumentProperties properties = workbook.CustomDocumentProperties;

Use:用:

dynamic properties = workbook.CustomDocumentProperties;

How can I create a proper Application that can get the CustomDocumentProperties?如何创建可以获取 CustomDocumentProperties 的正确应用程序?

There is no need to create a new Excel Application instance if you develop an add-in.如果您开发加载项,则无需创建新的 Excel 应用程序实例。 You should use the Application property provided by the VSTO runtime:您应该使用 VSTO 运行时提供的 Application 属性:

var xlApp = Globals.ThisAddIn.Application; // This works in VSTO Excel Add-in

But if you develop a standalone application which automates Excel, in that case you need to create a new Application instance by using the new operator:但是,如果您开发了一个自动化 Excel 的独立应用程序,在这种情况下,您需要使用 new 运算符创建一个新的 Application 实例:

var xlApp = new global::Microsoft.Office.Interop.Excel.Application(); 

Use the late binding technology (Type.InvokeMember) for getting or setting document property as the How To Use Automation to Get and to Set Office Document Properties with Visual C# .NET article suggests.使用后期绑定技术 (Type.InvokeMember) 获取或设置文档属性,如如何使用自动化获取和设置 Office 文档属性与 Visual C# .NET文章所建议的那样。

I've had a same problem.我遇到了同样的问题。 Today it has been resolved.今天已经解决了。 There is a different approach to derive the results.有一种不同的方法来得出结果。 The question and its' answer is at问题及其答案在

How can I read excel custom document property using c# excel interop 如何使用 c# excel interop 读取 excel 自定义文档属性

Here is my implementation.这是我的实现。

public string CheckDocProp(string propName, object props)
        {
            Excel.Workbook workBk = Globals.ThisAddIn.Application.ActiveWorkbook;

            object customProperties = workBk.CustomDocumentProperties;
            Type docPropsType = customProperties.GetType();
            object nrProps;
            object itemProp = null;
            object oPropName;
            object oPropVal = null;

            nrProps = docPropsType.InvokeMember("Count",
                BindingFlags.GetProperty | BindingFlags.Default,
                null, props, new object[] { });
            int iProps = (int)nrProps;

            for (int counter = 1; counter <= ((int)nrProps); counter++)
            {
                itemProp = docPropsType.InvokeMember("Item",
                    BindingFlags.GetProperty | BindingFlags.Default,
                    null, props, new object[] { counter });

                oPropName = docPropsType.InvokeMember("Name",
                    BindingFlags.GetProperty | BindingFlags.Default,
                    null, itemProp, new object[] { });

                if (propName == oPropName.ToString())
                {
                    oPropVal = docPropsType.InvokeMember("Value",
                        BindingFlags.GetProperty | BindingFlags.Default,
                        null, itemProp, new object[] { });
                    return oPropVal.ToString();
                    break;
                }
                else
                {
                    return "Not Found.";
                }
            }
            return "Not Found.";
        }

Usage:用法:

object docProps = wb.CustomDocumentProperties;
            string prop1 = ExistsDocProp("<CustomProperty>", docProps);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM