Программный доступ к свойствам пользовательских документов Excel
Я пытаюсь добавить пользовательские свойства в книгу, которую я создал программно. У меня есть метод для получения и установки свойств, но проблема в том, что рабочая книга возвращает ноль для свойства CustomDocumentProperties. Я не могу понять, как инициализировать это свойство, чтобы я мог добавлять и извлекать свойства из книги. 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 as DocumentProperties; всегда устанавливайте свойства в нуль.
Это использует Microsoft.Office.Core v12.0.0.0 и Microsoft.Office.Interop.Excell v12.0.0.0 (Office 2007)
4 ответа
Я посмотрел на свой собственный код и вижу, что я получаю доступ к свойствам с использованием позднего связывания. Я не могу вспомнить почему, но я выложу некоторый код на случай, если это поможет.
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);
РЕДАКТИРОВАТЬ: ах, теперь я помню, почему.:-)
РЕДАКТИРОВАТЬ 2: Ответ Jimbojones - использовать динамическое ключевое слово - является лучшим решением (если вы цените простоту использования над издержками производительности при использовании dynamic
).
Если вы нацелены на.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);
}
}
Я нашел решение здесь.
Вот код, с которым я закончил:
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;
}
Некоторая обработка исключений необходима для передачи, если свойство не существует при получении
Поздний ответ на этот вопрос, но я разработал более простой способ добавления пользовательских свойств DocumentProperties, которые могут пригодиться кому-то в будущем.
Моя проблема заключалась в том, что вызов метода Add() с типом System, предоставленным System.String.GetType(), вызвал исключение COMException: Type mismatch. Ссылаясь на ссылку в предыдущих ответах, становится ясно, что этот метод ожидает специфичный для Office тип, поэтому код, который в итоге работал для меня, был:
var custProps = (Office.DocumentProperties)this.CustomDocumentProperties;
custProps.Add( "AProperty", false, MsoDocProperties.msoPropertyTypeString, "AStringProperty" );
Поскольку это CustomDocumentProperty, Office без труда добавит настраиваемое свойство, но если вам нужно проверить наличие или проверить значение, когда CustomDocumentProperty может не существовать, вам придется перехватывать исключение System.ArgumentException.
РЕДАКТИРОВАТЬ
Как указано в комментарии Оливера Бока, насколько я знаю, это решение Office 2007 и единственное доступное.