Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用Excel互操作获取CustomDocumentProperties?_C#_Excel_Interop_Vsto - Fatal编程技术网

C# 如何使用Excel互操作获取CustomDocumentProperties?

C# 如何使用Excel互操作获取CustomDocumentProperties?,c#,excel,interop,vsto,C#,Excel,Interop,Vsto,下面的代码用于获取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

下面的代码用于获取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"];
前两行是对Excel
应用程序的引用。一个是从VSTO插件内部获取引用,另一个是常规的
新应用程序()

当从VSTO内部使用
应用程序时,代码运行良好,没有任何问题。但是当使用
newapplication()
时,
workbook.CustomDocumentProperties
行抛出
InvalidCastException

无法将“System.\u ComObject”类型的COM对象强制转换为接口 键入“Microsoft.Office.Core.DocumentProperties”。此操作失败 因为接口的COM组件上的QueryInterface调用 由于以下原因,IID“{2DF8D04D-5BFA-101B-BDE5-00AA0044DE52}”失败: 以下错误:不支持此类接口(HRESULT的异常: 0x80004002(E_NOINTERFACE))

我正试图在没有VSTO的情况下完成一个C#winforms项目。很多示例和教程都使用
new Application()
进行Excel互操作,但我注意到
Microsoft.Office.interop.Excel.Application
是一个界面,所以在界面上使用
new
对我来说其实很陌生。如何创建能够获取
CustomDocumentProperties
的适当应用程序

我正在使用的引用程序集:

  • Microsoft.Office.Interop.Excel v2.0.50727版本14.0.0.0
  • Microsoft.CSharp v4.0.30319版本4.0.0.0
我注意到Microsoft.Office.Interop.Excel.Application是一个界面,所以在界面上使用new实际上对我来说很陌生

这确实很奇怪,但这是故意的。
Excel.Application
接口用
CoClass
属性修饰,告诉实际类在“实例化”接口时实例化。更多关于它

但是当使用
newapplication()
时,
workbook.CustomDocumentProperties
行抛出
InvalidCastException

真奇怪。我自己在使用文档属性时遇到了一些问题。似乎实际返回的类与规范不同,因此我转而使用
dynamic
,以防止类型转换问题

因此,与此相反:

Microsoft.Office.Core.DocumentProperties properties = workbook.CustomDocumentProperties;
使用:

如何创建能够获取CustomDocumentProperties的适当应用程序

如果开发外接程序,则无需创建新的Excel应用程序实例。您应该使用VSTO运行时提供的应用程序属性:

var xlApp = Globals.ThisAddIn.Application; // This works in VSTO Excel Add-in
但是,如果您开发一个自动化Excel的独立应用程序,在这种情况下,您需要使用新操作符创建一个新的应用程序实例:

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

按照文章的建议,使用后期绑定技术(Type.InvokeMember)获取或设置文档属性。

我也遇到了同样的问题。今天已经解决了。有一种不同的方法来推导结果。问题及其答案在

这是我的实现

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.";
        }
public string CheckDocProp(string propName,object props)
{
Excel.Workbook workBk=Globals.ThisAddIn.Application.ActiveWorkbook;
对象customProperties=workBk.CustomDocumentProperties;
类型docPropsType=customProperties.GetType();
对象属性;
objectitemprop=null;
对象名称;
对象oPropVal=null;
nrProps=docPropsType.InvokeMember(“计数”,
BindingFlags.GetProperty | BindingFlags.Default,
null,props,新对象[]{});
int iProps=(int)nrProps;

对于(int counter=1;计数器将
DocumentProperties
DocumentProperty
更改为动态实际上是可行的!但不确定依赖
dynamic
是否是一种好的做法?是否无法确保代码处理的类型正确以防止进一步可能的运行时问题?据我所知不是这样。实际上正是出于这个原因,很多互操作类都在使用
dynamic
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.";
        }
object docProps = wb.CustomDocumentProperties;
            string prop1 = ExistsDocProp("<CustomProperty>", docProps);