none
Pass a message or set a property from Windows Form to Word Document RRS feed

  • Question

  • VS 2013 Update 3. I have Word 2010. I have created a Word 2010 Template that has a custom ribbon with some buttons on it. I have a Windows Forms application. The application uses Microsoft.Office.Interop.Word to create a new document based on my Template. My Windows Forms application needs to hide some of the custom buttons in the template based on the user's role in the application. I have tried this with BuiltInDocumentProperties, where my template creates a new property and then my Forms app attempts to set it. (http://support.microsoft.com/kb/303296) I have been getting errors, and I have read that this method is unreliable.

    I read here:

    http://social.msdn.microsoft.com/Forums/office/en-US/ddf4a3fe-16af-440d-9697-9a3bf53b52c3/customize-microsoft-word-2007-in-cnet-windows-application-using-microsoftofficeinteropword?forum=worddev

    ...that Ribbons cannot be manipulated directly by my application, and Ribbons can only be affected in-process. Well, I don't mind if the template itself does the work of manipulating the Ribbon, but I need to give the template information it needs to make proper decisions. For instance, if the Windows Form could tell the Word Document the User Id, then the Word Document could connect to the database to find out what buttons to show. I understand how to make Word talk to the database, but I can't figure out how to pass Word the User Id, or whatever else it needs to know in order to act correctly.

    Any guidance would be greatly appreciated.



    • Edited by Clay McKinney Friday, September 5, 2014 9:12 PM Wrong link
    Friday, September 5, 2014 8:45 PM

Answers

  • Hi Clay,

    According to How To Use Automation to Get and to Set Office Document Properties with Visual C# .NET, it seems we can't set and get custom properties as the VSTO sample.

    I wrote a sample for your reference:

    private static void OpenCalmsParagraphVersionTemplate()
            {
                object msTemplate = @"D:\1.dotx";
                Word.Application myWordApp = new Word.Application();
                myWordApp.Visible = true;
                var myWordDoc = new Word.Document();
                myWordDoc = myWordApp.Documents.Add(ref msTemplate);
    
                string myMessage = "Burninating the countryside";
                WriteDocumentProperty(myWordDoc, "ArbitraryTextFromOutside", myMessage);
                Console.WriteLine(ReadDocumentProperty(myWordDoc, "ArbitraryTextFromOutside"));
            }
    
            private static void WriteDocumentProperty(Word.Document myWordDoc, string propertyName, string propertyValue)
            {
                object oDocCustomProps = myWordDoc.CustomDocumentProperties;
                Type typeDocCustomProps = oDocCustomProps.GetType();
                if (ReadDocumentProperty(myWordDoc, propertyName) != null)
                {
                    DeleteDocumentProperty(myWordDoc, propertyName);
                }
    
                object[] oArgs = {propertyName,false,
                         MsoDocProperties.msoPropertyTypeString,
                         propertyValue};
    
                typeDocCustomProps.InvokeMember("Add", BindingFlags.Default |
                                           BindingFlags.InvokeMethod, null,
                                           oDocCustomProps, oArgs);
            }
    
            private static string ReadDocumentProperty(Word.Document myWordDoc, string propertyName)
            {
                object properties = myWordDoc.CustomDocumentProperties;
                Type typeDocProps = properties.GetType();
                try
                {
                    object oDocAuthorProp = typeDocProps.InvokeMember("Item",
                                      BindingFlags.Default |
                                      BindingFlags.GetProperty,
                                      null, properties,
                                      new object[] { propertyName });
                    Type typeDocAuthorProp = oDocAuthorProp.GetType();
                    return typeDocAuthorProp.InvokeMember("Value",
                                               BindingFlags.Default |
                                               BindingFlags.GetProperty,
                                               null, oDocAuthorProp,
                                               new object[] { }).ToString();
                }
                catch (Exception ex)
                {
                    return null;
                }
            }
    
            private static void DeleteDocumentProperty(Word.Document myWordDoc, string propertyName)
            {
                object properties = myWordDoc.CustomDocumentProperties;
                Type typeDocProps = properties.GetType();
                object oDocAuthorProp = typeDocProps.InvokeMember("Item",
                                    BindingFlags.Default |
                                    BindingFlags.GetProperty,
                                    null, properties,
                                    new object[] { propertyName });
                Type typeDocAuthorProp = oDocAuthorProp.GetType();
                typeDocAuthorProp.InvokeMember("Delete",
                                            BindingFlags.Default |
                                            BindingFlags.InvokeMethod,
                                            null, oDocAuthorProp,null);
            }

    It works fine in a Windows console application.

    Regards,

    George.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • Marked as answer by Clay McKinney Tuesday, September 9, 2014 9:17 PM
    Tuesday, September 9, 2014 3:41 AM
    Moderator

All replies

  • Hi Clay,

    According to your description, you want to pass user id from the Windows form application to the Word document.

    Where does user id store in? Does it store in a database or a file?

    From my understanding, you can store some specified information through Custom Document Properties. you could refer How to: Create and Modify Custom Document Properties.

    Regards,

    George.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Monday, September 8, 2014 9:41 AM
    Moderator
  • Thank you, George. I appreciate your help.

    UserId of the logged in User is an example of the kind of information I will need to pass to the Word document. The database has a list of all the UserIds, but only the Windows Form (or Console App for testing) would know the UserId of the person logged in at the moment. There is a ton of information in the database, but the Windows Form is responsible for telling the Word document which information to look at. I imagine this could be done by setting a property in the document, like the link you sent.

    The example in the link is for programming within the document. The example is a VSTO document that can create and read its own properties. I'm looking for something slightly different. I'm trying to create a Windows Form that can create (or at least set) properties in a Word document.

    Using the link you sent, I was able to have my Word template set a custom property in itself, and I have a Ribbon button that prints the value to the page. All that works great.

    When I try to read that same value from my Console app, I get this error:

    ______________________

    An unhandled exception of type 'System.InvalidCastException' occurred in System.Core.dll

    Additional information: Unable to cast COM object of type 'System.__ComObject' to interface type 'Microsoft.Office.Core.DocumentProperties'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{2DF8D04D-5BFA-101B-BDE5-00AA0044DE52}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).

    _____________________

    Here is my Console App:

    using System;
    using Microsoft.Office.Tools.Word;
    using Microsoft.VisualStudio.Tools.Applications.Runtime;
    using Word = Microsoft.Office.Interop.Word;
    using Office = Microsoft.Office.Core;
    
    namespace CalmsTestConsole
    {
        class Program
        {
            static void Main(string[] args)
            {
                OpenCalmsParagraphVersionTemplate();            
                Console.ReadLine();
            }
    
            private static void OpenCalmsParagraphVersionTemplate()
            {
                object msTemplate = @"C:\Users\cmckinney\Documents\CalmsParagraphVersionTemplate.dotx";
                Word.Application myWordApp = new Word.Application();
                myWordApp.Visible = true;
                var myWordDoc = new Word.Document();
                myWordDoc = myWordApp.Documents.Add(ref msTemplate);
    
                //string myMessage = "Burninating the countryside";
                //WriteDocumentProperty(myWordDoc, "ArbitraryTextFromOutside", myMessage);
                Console.WriteLine(ReadDocumentProperty(myWordDoc, "ArbitraryTextFromOutside"));
            }
    
            private static void WriteDocumentProperty(Word.Document myWordDoc, string propertyName, string propertyValue)
            {
                Office.DocumentProperties properties;
                properties = (Office.DocumentProperties)myWordDoc.CustomDocumentProperties;
    
                if (ReadDocumentProperty(myWordDoc, propertyName) != null)
                {
                    properties[propertyName].Delete();
                }
    
                properties.Add(
                    propertyName, 
                    false,
                    Microsoft.Office.Core.MsoDocProperties.msoPropertyTypeString,
                    propertyValue
                    );
            }
    
            private static string ReadDocumentProperty(Word.Document myWordDoc, string propertyName)
            {
                Office.DocumentProperties properties;
                properties = myWordDoc.CustomDocumentProperties;
    
                foreach (Office.DocumentProperty prop in properties)
                {
                    if (prop.Name == propertyName)
                    {
                        return prop.Value.ToString();
                    }
                }
                return null;
            }
        }    
    }

    When I try to write to that property (uncommenting those two lines and commenting the Read), I get this error:

    _____________________________

    An unhandled exception of type 'System.InvalidCastException' occurred in System.Core.dll

    Additional information: Unable to cast COM object of type 'System.__ComObject' to interface type 'Microsoft.Office.Core.DocumentProperties'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{2DF8D04D-5BFA-101B-BDE5-00AA0044DE52}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).

    _______________________________

    There has to be some way to to set a document's property programmatically. If Microsoft.Office.Interop.Word can do it I'd prefer to use that. If not, if OpenXML can do it I can learn that. I've just come across a lot of dead ends in my searching, and I need some direction.

    Monday, September 8, 2014 2:43 PM
  • The OpenXML way to set a Word document's custom property from WinForms or a Console App is here:

    http://msdn.microsoft.com/en-us/library/office/ff936167(v=office.14).aspx

    I believe this is my answer.

    I'm still interested if there is an Interop or VSTO way.

    Thanks!

    Monday, September 8, 2014 6:52 PM
  • Hi Clay,

    According to How To Use Automation to Get and to Set Office Document Properties with Visual C# .NET, it seems we can't set and get custom properties as the VSTO sample.

    I wrote a sample for your reference:

    private static void OpenCalmsParagraphVersionTemplate()
            {
                object msTemplate = @"D:\1.dotx";
                Word.Application myWordApp = new Word.Application();
                myWordApp.Visible = true;
                var myWordDoc = new Word.Document();
                myWordDoc = myWordApp.Documents.Add(ref msTemplate);
    
                string myMessage = "Burninating the countryside";
                WriteDocumentProperty(myWordDoc, "ArbitraryTextFromOutside", myMessage);
                Console.WriteLine(ReadDocumentProperty(myWordDoc, "ArbitraryTextFromOutside"));
            }
    
            private static void WriteDocumentProperty(Word.Document myWordDoc, string propertyName, string propertyValue)
            {
                object oDocCustomProps = myWordDoc.CustomDocumentProperties;
                Type typeDocCustomProps = oDocCustomProps.GetType();
                if (ReadDocumentProperty(myWordDoc, propertyName) != null)
                {
                    DeleteDocumentProperty(myWordDoc, propertyName);
                }
    
                object[] oArgs = {propertyName,false,
                         MsoDocProperties.msoPropertyTypeString,
                         propertyValue};
    
                typeDocCustomProps.InvokeMember("Add", BindingFlags.Default |
                                           BindingFlags.InvokeMethod, null,
                                           oDocCustomProps, oArgs);
            }
    
            private static string ReadDocumentProperty(Word.Document myWordDoc, string propertyName)
            {
                object properties = myWordDoc.CustomDocumentProperties;
                Type typeDocProps = properties.GetType();
                try
                {
                    object oDocAuthorProp = typeDocProps.InvokeMember("Item",
                                      BindingFlags.Default |
                                      BindingFlags.GetProperty,
                                      null, properties,
                                      new object[] { propertyName });
                    Type typeDocAuthorProp = oDocAuthorProp.GetType();
                    return typeDocAuthorProp.InvokeMember("Value",
                                               BindingFlags.Default |
                                               BindingFlags.GetProperty,
                                               null, oDocAuthorProp,
                                               new object[] { }).ToString();
                }
                catch (Exception ex)
                {
                    return null;
                }
            }
    
            private static void DeleteDocumentProperty(Word.Document myWordDoc, string propertyName)
            {
                object properties = myWordDoc.CustomDocumentProperties;
                Type typeDocProps = properties.GetType();
                object oDocAuthorProp = typeDocProps.InvokeMember("Item",
                                    BindingFlags.Default |
                                    BindingFlags.GetProperty,
                                    null, properties,
                                    new object[] { propertyName });
                Type typeDocAuthorProp = oDocAuthorProp.GetType();
                typeDocAuthorProp.InvokeMember("Delete",
                                            BindingFlags.Default |
                                            BindingFlags.InvokeMethod,
                                            null, oDocAuthorProp,null);
            }

    It works fine in a Windows console application.

    Regards,

    George.


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    • Marked as answer by Clay McKinney Tuesday, September 9, 2014 9:17 PM
    Tuesday, September 9, 2014 3:41 AM
    Moderator
  • Thank you George! This works great!
    Tuesday, September 9, 2014 9:18 PM