2009-07-16 5 views
12

Я пытаюсь добавить пользовательские свойства в книгу, которую я создал программно. У меня есть метод для получения и настройки свойств, но проблема заключается в том, что рабочая книга возвращает null для свойства CustomDocumentProperties. Я не могу понять, как инициализировать это свойство, чтобы я мог добавлять и извлекать свойства из книги. Microsoft.Office.Core.DocumentProperties является интерфейсом, так что я не могу пойти и сделать следующийПрограммный доступ к свойствам пользовательского документа Excel

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)

ответ

10

Я посмотрел на мой собственный код и может видеть, что доступ I свойства с использованием позднего связывания. Я не могу вспомнить, почему, но я отправлю код на случай, если это поможет.

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); 

EDIT: ах, теперь я помню why. :-)

EDIT 2: ответ Jimbojones' - использовать динамический ключевое слово - это лучшее решение (если вы цените простоту использования над издержками, используя dynamic).

+0

Именно ссылки я нашел, и я отправил свой код в то время как вы отправляете это. +1 и принята для вас :-) –

+0

Обновить ссылку на "почему": https://support.microsoft.com/en-us/kb/303296 –

7

Я нашел решение 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; 
    } 

Некоторые обработки исключений необходимо передать, если свойство оленья кожа существовать при извлечении

3

Поздний ответ на этот вопрос, но я разработал более простой метод добавления пользовательских DocumentProperties, которые могут быть полезны кому-то в будущем.

Моя проблема заключалась в том, что вызов метода Add() с помощью типа System, предоставленного System.String.GetType(), вызвал COMException: тип несоответствия. Ссылаясь на ссылку в предыдущих ответах, ясно, что этот метод ожидает типа Ведомственного, поэтому код, который в конечном итоге работает для меня:

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

Потому что это CustomDocumentProperty бюро будет добавить настраиваемое свойство без труда , но если вам нужно проверить наличие или подтвердить значение, если CustomDocumentProperty может не существовать, вам придется поймать System.ArgumentException.

EDIT

Как было отмечено в комментарии Оливера Бока, это Office 2007 и выше единственное решение, насколько я знаю.

+1

Я нахожу (с Excel 2000), что я не могу использовать workbook.CustomDocumentProperties к Office.DocumentProperties. Однако код отражений в других ответах работает. –

+0

А, да, я должен был отметить (и сделал это сейчас), что считаю, что это Office 2007 и только функция (хотя она может работать в 2003 году - у меня больше нет доступа к этому для тестирования). В моей защите это то, что использовал оригинальный плакат. – cori

12

Если вы используете .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); 
    } 
}