【问题标题】:Accessing Excel Custom Document Properties programmatically以编程方式访问 Excel 自定义文档属性
【发布时间】:2010-11-11 09:16:39
【问题描述】:

我正在尝试将自定义属性添加到我以编程方式创建的工作簿中。我有一个获取和设置属性的方法,但问题是工作簿为 CustomDocumentProperties 属性返回 null。我无法弄清楚如何初始化此属性,以便我可以从工作簿中添加和检索属性。 Microsoft.Office.Core.DocumentProperties 是一个接口,所以我不能去执行以下操作

if(workbook.CustomDocumentProperties == null)
    workbook.CustomDocumentProperties = new DocumentProperties;

这是我必须获取和设置属性的代码:

     private object GetDocumentProperty(string propertyName, MsoDocProperties type)
    {
        object returnVal = null;

        Microsoft.Office.Core.DocumentProperties properties;
        properties = (Microsoft.Office.Core.DocumentProperties)workBk.CustomDocumentProperties;

        foreach (Microsoft.Office.Core.DocumentProperty property in properties)
        {
            if (property.Name == propertyName && property.Type == type)
            {
                returnVal = property.Value;
            }
            DisposeComObject(property);
        }

        DisposeComObject(properties);

        return returnVal;
    }

    protected void SetDocumentProperty(string propertyName, string propertyValue)
    {
        DocumentProperties properties;
        properties = workBk.CustomDocumentProperties as DocumentProperties;

        bool propertyExists = false;
        foreach (DocumentProperty prop in properties)
        {
            if (prop.Name == propertyName)
            {
                prop.Value = propertyValue;
                propertyExists = true;
            }
            DisposeComObject(prop);

            if(propertyExists) break;
        }

        if (!propertyExists)
        {
            properties.Add(propertyName, false, MsoDocProperties.msoPropertyTypeString, propertyValue, Type.Missing);
        }

        DisposeComObject(propertyExists);

    }

线 属性 = workBk.CustomDocumentProperties 作为 DocumentProperties; 始终将属性设置为 null。

这是使用 Microsoft.Office.Core v12.0.0.0 和 Microsoft.Office.Interop.Excell v12.0.0.0 (Office 2007)

【问题讨论】:

    标签: c# excel automation


    【解决方案1】:

    如果您的目标是 .NET 4.0,则可以使用 dynamic 关键字进行后期绑定

     Document doc = GetActiveDocument();
     if ( doc != null )
     {
         dynamic properties = doc.CustomDocumentProperties;
         foreach (dynamic p in properties)
         {
             Console.WriteLine( p.Name + " " + p.Value);
         }
     }
    

    【讨论】:

      【解决方案2】:

      我查看了自己的代码,可以看到我使用后期绑定访问属性。我不记得为什么了,但我会发布一些代码以防万一。

      object properties = workBk.GetType().InvokeMember("CustomDocumentProperties", BindingFlags.Default | BindingFlags.GetProperty, null, workBk, null);
      
      object property = properties.GetType().InvokeMember("Item", BindingFlags.Default | BindingFlags.GetProperty, null, properties, new object[] { propertyIndex });
      
      object propertyValue = property.GetType().InvokeMember("Value", BindingFlags.Default | BindingFlags.GetProperty, null, propertyWrapper.Object, null);
      

      编辑:啊,现在我记得why。 :-)

      编辑 2:Jimbojones 的回答 - 使用动态关键字 - 是一个更好的解决方案(如果您重视易用性而不是使用 dynamic 的性能开销)。

      【讨论】:

      • 正是我找到的链接,我在您发布此内容时发布了我的代码。 +1 并为您接受:-)
      • @CindyMeister 链接已失效,我无法找到 kb 文章。
      • @Kolky 我也无法打开它。我在四处打听... FWIW 的答案中有关于使用dynamic 启用后期绑定的提示。这些是“后期绑定”到 Office 应用程序中的——并不是它们本机对象模型的真正一部分,即使 VB 开发人员可以像访问它们一样访问它们。但是 C#(dynamic 之前)不能做到这一点。
      • @CindyMeister 奇怪的是 kb 文章不见了。更奇怪的是,为什么使用相同版本的 Office 和 Office.Interop 引用 (15.0.0) 我不能将其转换为正确的类型。 Dynamic 工作,只是不是很漂亮。
      【解决方案3】:

      我找到了解决方案here

      这是我最终得到的代码:

          public void SetDocumentProperty(string propertyName, string propertyValue)
          {
              object oDocCustomProps = workBk.CustomDocumentProperties;
              Type typeDocCustomProps = oDocCustomProps.GetType();
      
              object[] oArgs = {propertyName,false,
                       MsoDocProperties.msoPropertyTypeString,
                       propertyValue};
      
              typeDocCustomProps.InvokeMember("Add", BindingFlags.Default |
                                         BindingFlags.InvokeMethod, null,
                                         oDocCustomProps, oArgs);
      
          }
      
          private object GetDocumentProperty(string propertyName, MsoDocProperties type)
          {
              object returnVal = null;
      
              object oDocCustomProps = workBk.CustomDocumentProperties;
              Type typeDocCustomProps = oDocCustomProps.GetType();
      
      
              object returned = typeDocCustomProps.InvokeMember("Item", 
                                          BindingFlags.Default |
                                         BindingFlags.GetProperty, null,
                                         oDocCustomProps, new object[] { propertyName });
      
              Type typeDocAuthorProp = returned.GetType();
              returnVal = typeDocAuthorProp.InvokeMember("Value",
                                         BindingFlags.Default |
                                         BindingFlags.GetProperty,
                                         null, returned,
                                         new object[] { }).ToString();
      
              return returnVal;
          }
      

      如果在检索时属性不存在,则需要进行一些异常处理

      【讨论】:

        【解决方案4】:

        这个问题的答案较晚,但我想出了一个更简单的方法来添加将来可能对某人有用的自定义 DocumentProperties。

        我的问题是使用 System.String.GetType() 提供的 System 类型调用 Add() 方法触发了 COMException: Type mismatch。参考前面答案中的链接,很明显,此方法需要特定于 Office 的类型,因此最终为我工作的代码是:

        var custProps = (Office.DocumentProperties)this.CustomDocumentProperties;
        custProps.Add( "AProperty", false, MsoDocProperties.msoPropertyTypeString, "AStringProperty" );
        

        因为它是 CustomDocumentProperty Office 将毫无困难地添加自定义属性,但如果您需要在 CustomDocumentProperty 可能不存在时检查是否存在或验证值,则必须捕获 System.ArgumentException。

        编辑

        正如 Oliver Bock 的评论所指出的,据我所知,这是 Office 2007 及更高版本的唯一解决方案。

        【讨论】:

        • 我发现(使用 Excel 2000)我无法将 workbook.CustomDocumentProperties 转换为 Office.DocumentProperties。但是,其他答案中的反射代码确实有效。
        • 啊,是的 - 我应该注意到(并且现在已经这样做了)我相信这是 Office 2007 及更高版本的唯一功能(尽管它可能在 2003 年有效 - 我不再有权使用它为了测试)。在我的辩护中,这就是原始海报所使用的。
        猜你喜欢
        • 2011-02-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-18
        • 1970-01-01
        相关资源
        最近更新 更多