Подтвердить что ты не робот

Программный доступ к свойствам пользовательского документа Excel

Я пытаюсь добавить пользовательские свойства в книгу, которую я создал программно. У меня есть метод для получения и настройки свойств, но проблема заключается в том, что рабочая книга возвращает null для свойства 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);

    }

Линия   properties = workBk.CustomDocumentProperties как DocumentProperties; всегда задает свойства null.

Это использует Microsoft.Office.Core v12.0.0.0 и Microsoft.Office.Interop.Excell v12.0.0.0 (Office 2007)

4b9b3361

Ответ 1

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

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: ах, теперь я помню почему.: -)

РЕДАКТИРОВАТЬ 2: ответ Jimbojones - использование динамического ключевого слова - лучшее решение (если вы цените простоту использования над служебными данными с использованием dynamic).

Ответ 2

Если вы нацеливаете .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);
     }
 }

Ответ 3

Я нашел решение здесь.

Вот код, в котором я закончил:

    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, которые могут быть полезны кому-то в будущем.

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

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

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

ИЗМЕНИТЬ

Как отмечалось в комментарии Оливера Бока, это, по-моему, решение Office 2007 и только вверх.