none
Cast ActiveDocument to Interface RRS feed

  • Question

  • Hello

    I have these two projects:

    Word 2007 Document - Contains .DOCX and ThisDocument.cs (class)

    Word 2007 AddIn - Contains WinForm, RibbonMenu, etc...

    Now inside AddIn project I have a simple WinForm with just one button, upon clicking this button I want to cast the ActiveDocument to an Interface. The interface is used (inherited) by ThisDocument.cs in the Word 2007 document-project.

    Some example code:

    class ThisDocument : MyInterface
    {
      public void InterfaceFunction()
    {
    MessageBox.Show("Hello world");
    }
    }

    And the WinForm:

    using Template; //A .dll file, of the Word 2007 Document project, imports it... private void button1_Click(object sender, EventArgs e) {

    //Tried various casts... last few hours... Template.ThisDocument temp = (Template.ThisDocument)Globals.ThisAddIn.Application.ActiveDocument;

    Template.MyInterface tempInt = (Template.MyInterface)Globals.ThisAddIn.Application.ActiveDocument;

    }

    Ive tried multiple things for the last few hours...but I am now at the edge of giving up....

    Converting to MyInterface gives runtime-error:

    "Unable to cast COM object of type Word.DocumentClass to Interface type Template.MyInterface. This operation failed becuase the QueryInterface call on the COM component for the interface with ID... Failed due to following error: No such interface supported.

    Any suggestions?

    Friday, September 21, 2012 1:36 PM

Answers

  • HI colaohye

    This question relates to the other discussion, I think? Is the question covered by that other discussion, which appears to be resolved? Or would you like more information about working with content controls?

    <<I want to reach one of the object within the "ThisDocument.cs" (in a Word 2007 template project), for instance a PlainTextContentControl with the tag "TestControl" and change its text.>>

    When using VSTO there are a number of ways to "talk" to a content control. One of them is through VSTO's extended object model, where you'd use the technique described on this page:
    http://msdn.microsoft.com/en-us/library/cc442981(VS.90).aspx

    This would allow you to address the content control directly, by its name, and I get the impression that may be your problem, given the architecture of your solution?

    Another way is to use Word's object model, directly. In that case, you'd need the Document.SelectContentControlsByName or Document.SelectContentControlsByTag method. This method returns an IEnumerable collection (array) of content controls meeting the criterium (name or tag). You can foreach the returned collection to work with the control(s). This would certainly work with the workarounds discussed in the other thread.

    The third possibility is to make sure the content controls are mapped to a Custom XML Part in the document. Then the data can be written directly to the Custom XML Part and it will appear in the content control. This can be done either using the object model and the Document.CustomXMLParts property (collection) or it can be done outside the Word application, on the closed document file, by leveraging the Open XML SDK.


    Cindy Meister, VSTO/Word MVP, my blog

    Tuesday, September 25, 2012 7:59 AM
    Moderator
  • Hi colaohye

    The information in the link would be a possible approach from within ThisAddin.cs and any other class within the Add-in Namespace (so that it can access Globals.ThisAddin). I don't know how you could make it work with the design architecture you'd like to have as the approach does require the "Tools". Basically, the "Tools" wrap up the second approach (SelectContentControlsByName) for you so that it's more like using strongly-typed classes. But in the background it's the same object model provided by Word.

    I only provided the link to the article because I wasn't sure what you were trying, already and in order to provide complete background information.

    What most people do when they have multiple "things" that should share components is to provide the components as separate DLLs referenced by the main VSTO project. In this case, the VSTO Add-in is the "consumer", rather than the reverse, which seems to be what you'd like to do. There may be other ways, but that's the one with which I'm familiar.


    Cindy Meister, VSTO/Word MVP, my blog

    Tuesday, September 25, 2012 12:12 PM
    Moderator

All replies

  • Hi cola

    It's necessary to understand that the VSTO ThisDocument class is a proprietary VSTO "thingy" and I believe it's sealed. You can't just repurpose it get it to inherit some other interface. Same goes for Word objects, such as the Word.Document class.

    What is it you want to accomplish with all of this?


    Cindy Meister, VSTO/Word MVP, my blog

    Friday, September 21, 2012 3:17 PM
    Moderator
  • I want to reach one of the object within the "ThisDocument.cs" (in a Word 2007 template project), for instance a PlainTextContentControl with the tag "TestControl" and change its text. 

    I have a scenario where our customers wants lots of templates and all templates have a lot in common. Logo, title, footer, header, datetime, styles, etc, shall all be equal, just some few PlainTextContentControls that needs to be changed based on various stuff.

    Hence: I am trying to make it all happen in the "Word 2007 Add In"-project...

    Or any other suggestions?

    Edit: I have a "solution", but its ugly... I've created a function that searches the Document for a specific tag, and if it exists, it changes the placeholder.Text to the string-parameter:

    public void SetPlaceholderText(Word.Document document, string Tag, string NewText);

    PS: For the record, I am not just casting the interface because I feel like it. I did get an error message when trying to cast the ActiveDocument to "<Template2007Namespace>.ThisDocument" that said I could cast it to an Interface instead, if the interface was under COM or something... I cannot get back to the same error again though, accidentally removed a line or two, so... :)




    • Edited by colaohye Monday, September 24, 2012 7:07 AM
    Monday, September 24, 2012 6:19 AM
  • HI colaohye

    This question relates to the other discussion, I think? Is the question covered by that other discussion, which appears to be resolved? Or would you like more information about working with content controls?

    <<I want to reach one of the object within the "ThisDocument.cs" (in a Word 2007 template project), for instance a PlainTextContentControl with the tag "TestControl" and change its text.>>

    When using VSTO there are a number of ways to "talk" to a content control. One of them is through VSTO's extended object model, where you'd use the technique described on this page:
    http://msdn.microsoft.com/en-us/library/cc442981(VS.90).aspx

    This would allow you to address the content control directly, by its name, and I get the impression that may be your problem, given the architecture of your solution?

    Another way is to use Word's object model, directly. In that case, you'd need the Document.SelectContentControlsByName or Document.SelectContentControlsByTag method. This method returns an IEnumerable collection (array) of content controls meeting the criterium (name or tag). You can foreach the returned collection to work with the control(s). This would certainly work with the workarounds discussed in the other thread.

    The third possibility is to make sure the content controls are mapped to a Custom XML Part in the document. Then the data can be written directly to the Custom XML Part and it will appear in the content control. This can be done either using the object model and the Document.CustomXMLParts property (collection) or it can be done outside the Word application, on the closed document file, by leveraging the Open XML SDK.


    Cindy Meister, VSTO/Word MVP, my blog

    Tuesday, September 25, 2012 7:59 AM
    Moderator
  • You're right, it is somewhat covered by the other thread, both turned out to have the same solution, not really satisfied with the structure

    "This would allow you to address the content control directly, by its name, and I get the impression that may be your problem, given the architecture of your solution?"

    Is the architecture of my solution bad/wrong, which results in my problem of not addressing the content controls directly (if it is bad, are there any examples that can be downloaded that contains a good architecture for Word Addin/Document...)? Or are you saying that the article in the link would help me, due to the architecture I have? 

    The article you gave, it uses "GetVstoObject()" on the ACtiveDocument. This function does not exist, how do I get it? 

    Running VS 2010 Premium, .NET 4.030319 SP1

    Although: it is more or less resolved, if you answer these two simple questions.


    • Edited by colaohye Tuesday, September 25, 2012 10:52 AM
    Tuesday, September 25, 2012 10:50 AM
  • Hi colaohye

    The information in the link would be a possible approach from within ThisAddin.cs and any other class within the Add-in Namespace (so that it can access Globals.ThisAddin). I don't know how you could make it work with the design architecture you'd like to have as the approach does require the "Tools". Basically, the "Tools" wrap up the second approach (SelectContentControlsByName) for you so that it's more like using strongly-typed classes. But in the background it's the same object model provided by Word.

    I only provided the link to the article because I wasn't sure what you were trying, already and in order to provide complete background information.

    What most people do when they have multiple "things" that should share components is to provide the components as separate DLLs referenced by the main VSTO project. In this case, the VSTO Add-in is the "consumer", rather than the reverse, which seems to be what you'd like to do. There may be other ways, but that's the one with which I'm familiar.


    Cindy Meister, VSTO/Word MVP, my blog

    Tuesday, September 25, 2012 12:12 PM
    Moderator