none
possible bug in Word.ContentControl? RRS feed

  • Question

  • it seems to be the Word.ContentControl does something wrong.
    the method SetPlaceholderText is not ready to use in a latebind scenario.
    it works well with a method pointer/delegate(early bind)
    i use c# but anyway, try visual basic

    Dim control as Word.Control = GetControlAnywhere()
    control.SetPlaceholderText(Nothing, Nothing, "text")

    works as well but now change control to Object. the vb auto-dispatch feature does a good job normaly but you got a TypeMissmatchException. it doesnt works also with c# dynamics or GetType().Invoke...
    tested on different machines/vm's.

    not sure but the IDispatch::Invoke implementation is the problem at the end?
    i do a test in c++ and a direct Invoke call with the same result.




    Thursday, February 7, 2013 10:01 AM

Answers

  • i find the problem! its not the dispatch implementation or anyone else.
    its a faulty default parameter in the type library.

    IDL definition:
    [id(0x0000000b), helpcontext(0x0fe3000b)]
    void SetPlaceholderText(
                    [in, optional, defaultvalue(0)] BuildingBlock* BuildingBlock,
                    [in, optional, defaultvalue(0)] Range* Range,
                    [in, optional, defaultvalue("")] BSTR Text);

    the 0 number for Range and BuildingBlock is not valid and a type missmatch occurs. you have to set a valid parameter at hand and it works. few methods in serveral office products has these problem with faulty defaults in the type library and thats the reason for it works early bind but not late bind.

    now its solved :)
    Saturday, July 13, 2013 2:47 PM

All replies

  • Hi Alfred,

    Thanks for posting in the MSDN Forum.

    Would you please show detailed code snippet for further research?

    Have a good day,

    Tom


    Tom Xu [MSFT]
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Friday, February 8, 2013 5:17 AM
    Moderator
  • yes, of course

    // c# Word2007 / PIA's(not embedded) /.NET 4

    Word.Application application = new Word.Application();
    Word.Document = application.Documents.Add();
    dynamic control = document.ContentControls.Add();
    control.SetPlaceholderText(null, null, "sampleText");
    // last line throws an error. change dynamic to Word.ContentControl and it works fine
    // error: 2-argument cannot convert

    ' VB Word2007 / PIA's(not embedded) /.NET 4
    Dim application As Word.Application = new Word.Application()
    Dim document As Word.Document = application.Documents.Add()
    Dim control As Object = document.ContentControls.Add()
    control.SetPlaceholderText(Nothing, Nothing, "sampleText")
    ' last line throws an error. change Object to Word.ContentControl and it works fine
    ' error: typemissmatch exception

    // C# Word2007 and strictly Latebinding (NetOffice in my real Scenario) .NET 4

    object appplication =
    Activator.CreateInstance(Type.GetTypeFromProgID("Word.Application"));
    object documents = application.GetType().InvokeMember("Documents", BindingFlags.GetProperty, null, application, new object[0]);

    object document = documents.GetType().InvokeMember("Add", BindingFlags.InvokeMethod, null, documents, new object[0]);
    object controls = document.GetType().InvokeMember("ContentControls",          BindingFlags.GetProperty, null, document, new object[0]);
    object control = documents.GetType().InvokeMember("Add", BindingFlags.InvokeMethod, null, controls, new object[0]);
    control.GetType().InvokeMember("SetPlaceholderText", BindingFlags.InvokeMethod, null, control, new object[]{
    Type.Missing, Type.Missing, "sampleText"};
    // last line throws an error
    // error: typemissmatch exception


    as far i know all these techniques use Invoke from the IDispatch interface at the end

    // C++ Word2007 unmanaged InvokeCall

    VARIANT par1, par2, par3;
    
    VariantInit(&par1); VariantInit(&par2); VariantInit(&par3);
    par1.vt = VT_DISPATCH; par1.pdispVal = NULL;
    par2.vt = VT_DISPATCH; par2.pdispVal = NULL;
    par3.vt = VT_BSTR; par3.bstrVal = L"sampleText";
    VARIANT result; VariantInit(&result); m_hr=OLEMethod(DISPATCH_METHOD, &result, m_pControl, L"SetPlaceholderText",
    3, par1, par2, par3); // last line throws an error. typemissmatch again

    now i do a different thing (in C#) and write a small method to call SetPlaceholdertext with a methodpointer from the VTable. this works great because i dont need Invoke
    public static void SetPlaceholderText2(object control, object buildingBlock = null,
     object range = null, string text = "")
    {
       IntPtr comPtr = Marshal.GetComInterfaceForObject(control,
             typeof(Word.ContentControl)); // from the interop assembly
       IntPtr vTable = Marshal.ReadIntPtr(comPtr);
       IntPtr methodPointer = Marshal.ReadIntPtr(vTable, 23 * IntPtr.Size);
                                               // 23 is the VTable position
       SetPlaceHolderTextCallback invoker = 
       Marshal.GetDelegateForFunctionPointer(methodPointer, 
             typeof(SetPlaceHolderTextCallback)) as SetPlaceHolderTextCallback;
       invoker(comPtr,buildingBlock, range, text);
       // some release code...
    }

    may not important, typical is GetType() for a com proxy give me all the methods and so on.
    in this case i got no additional informations for the ContentControl proxy but anyway, the interop runtime throws a specific unkown member exception in this situation.(call a unkown/ non existing method)

    okay, long post. you still reading this, thanks ;)

    Friday, February 8, 2013 9:13 PM
  • Hi Alfred

    I don't know an answer, either, but this is interesting and I'll be watching to learn what Tom can find out.

    To add to the information you provide, I did corresponding tests (in 2010) using Word's "native" VBA and with the following results.

    All parameters are optional. If I provide only the last parameter, leaving out the first two, as follows, I see the same error (type mismatch):

    Sub CCwithLateBinding()
        Dim cc As Variant 'also Object
        
        Set cc = ActiveDocument.Contentcontrols(1)
        Debug.Print cc.PlaceholderText
        cc.SetPlaceholderText "Clicking is good" 'error
     End Sub
    

    If, however, I include all three parameters, it works (corresponds to your VB.NET example):

    Sub CCwithLateBinding()
        Dim cc As Variant 'also Object
        
        Set cc = ActiveDocument.Contentcontrols(1)
        Debug.Print cc.PlaceholderText
        cc.SetPlaceholderText Nothing, Nothing, "Clicking is good"
    End Sub
    

    It also does not work with a single, named parameter, but does work with three named parameters:

    Sub CCwithLateBinding()
        Dim cc As Variant 'also Object
        
        Set cc = ActiveDocument.Contentcontrols(1)
        Debug.Print cc.PlaceholderText
        cc.SetPlaceholderText Text:="Clicking is always good" 'error!
     End Sub


    Cindy Meister, VSTO/Word MVP, my blog

    Saturday, February 9, 2013 8:48 AM
    Moderator
  • hello cindy,

    thanks for your reply.
    oh yes, its true, it works like a charme in vba (i do the the tests also in vba)
    i'm not sure vba for applications is optimized to use the host application just as early bind without type informations or not. if not then i surrender.
    please checkout the documentation for the SetPlaceholderText method(http://msdn.microsoft.com/en-us/library/office/bb256831%28v=office.12%29.aspx)

    Remarks

    Only one of the parameters is used when specifying placeholder text. If more than one parameter is used, Microsoft Office Word uses the text specified in the first parameter. If all parameters are omitted, the placeholder text is blank.

    hmmm.... word use only the first parameter at all ???

    still for me : it looks like the implementation in IDispatch::Invoke is confused and does something wrong.

    BTW:
    i take a look into the common infrastructure code for .NET and see why Word.ContentControl give me no informations trough GetType()
    GetType() checks for the Component/ModuleName for the instance and try to load the registered PIA assembly now(not available on my system) if it fails GetType() returns just new Object.GetType()

    WM_REGARDS
    Sebastian

    Saturday, February 9, 2013 9:25 AM
  • Hi Alfred

    My point was that it does NOT always work with VBA; only the one scenario works. But with VBA I'd expect all three scenarios to work.

    <<Only one of the parameters is used when specifying placeholder text. If more than one parameter is used, Microsoft Office Word uses the text specified in the first parameter. If all parameters are omitted, the placeholder text is blank.

    hmmm.... word use only the first parameter at all ???>>

    That's really the question, isn't it: How this method is actually constructed? In the VBA environment with three optional parameters, I'd expect the method to act like an overload and use the matching method signature. After all, according to the Help the three parameters are typed differently: BuildingBlock, Range and String. And it does work if Word knows it's dealing with an object typed as ContentControl. But why it should behave differently when Word receives an untyped object is the mystery...

    And then, I agree, it appears to be trying to compare using only the first parameter. So I did a quick test, assigning a Building Block instead of a string. Here, again, that only works if I provided all three parameters. Then I tried only assigning a Range. Same thing: I need to provide all three parameters in order to avoid the Type Mismatch error.

    So, as far as VBA is concerned, when working with an object to which a ContentControl that is assigned, but not strongly typed, all three parameters are required, not optional. Apparently this is NOT carrying over to the PIA, otherwise your first two tests would work. So something must be wacky with how the method is constructed in the Word API, I'm thinking.

    Additional Note: It also appears to make no difference whether the parameter values are passed as objects, or as strongly typed values matching the parameter data type.


    Cindy Meister, VSTO/Word MVP, my blog

    Saturday, February 9, 2013 9:47 AM
    Moderator
  • hello tom,

    why you mark this posting as answer? (for your job?)
    BTW: i do some new 2 tests with VB6 and Excel VBA -> failed.

    i try do mark this problem as bug to connect.microsoft but no chance at the moment to clearify the situation because ms mark office(classic) as 'closed'

    its okay for me to to say we have a critical situation or an untested scenario(whatever) but i need an answer for my customers. i'm not qualified to handle the situation or the problem is much bigger?
    thats all what i want.
    Sunday, February 17, 2013 11:25 AM
  • Hi Alfred,

    I tried to close it due to I feel Cindy's reply is so good to explain it. And I waiting for a long time for your response for it. I thought might you are satisfied with it. I think it's not problem to reopen it. We are welcome community members discuss every issue which exists problem.

    Have a good day,

    Tom 


    Tom Xu [MSFT]
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.


    Wednesday, February 20, 2013 4:54 AM
    Moderator
  • Hi Tom

    I wasn't explaining, it, only providing additional observations. Fact is, it appears to be a bug...


    Cindy Meister, VSTO/Word MVP, my blog

    Wednesday, February 20, 2013 7:53 AM
    Moderator
  • Not work under Word 2010, Word crash when invoke , maybe vTable changed.

    XBRL Expert

    Saturday, July 13, 2013 3:34 AM
  • i find the problem! its not the dispatch implementation or anyone else.
    its a faulty default parameter in the type library.

    IDL definition:
    [id(0x0000000b), helpcontext(0x0fe3000b)]
    void SetPlaceholderText(
                    [in, optional, defaultvalue(0)] BuildingBlock* BuildingBlock,
                    [in, optional, defaultvalue(0)] Range* Range,
                    [in, optional, defaultvalue("")] BSTR Text);

    the 0 number for Range and BuildingBlock is not valid and a type missmatch occurs. you have to set a valid parameter at hand and it works. few methods in serveral office products has these problem with faulty defaults in the type library and thats the reason for it works early bind but not late bind.

    now its solved :)
    Saturday, July 13, 2013 2:47 PM
  • Wonderful! Thank you for tracking this down and taking the time to come back and report your findings. I'll pass this along to someone I know who can, I hope, put it on a list to be fixed - at least for a future version of the product.

    Cindy Meister, VSTO/Word MVP, my blog

    Saturday, July 13, 2013 3:20 PM
    Moderator
  • Could you please tell me how exactly you solved the problem with late binding. Unfortunatly i am not able to set valid parameters at hand. I simple don't know how to do this!!! Example would be fine.

    Thank you very much!

    • Proposed as answer by BCVolkert Saturday, September 15, 2018 9:55 PM
    • Unproposed as answer by BCVolkert Saturday, September 15, 2018 9:56 PM
    Tuesday, January 7, 2014 1:20 PM
  • I've been struggling with this too; but, using VBA. Based on the clues in this thread I tried a few things and this is what I learned. 

            ' The following two statements work when Early Binding but fail _
              with Error 13 - Type mismatch when Late Binding.
            .SetPlaceholderText Text:=sPlaceHolderText
            .SetPlaceholderText , , sPlaceHolderText
            ' The following two statements work when Early or Late Binding.
            .SetPlaceholderText BuildingBLock:=Nothing, Range:=Nothing, Text:=sPlaceHolderText
            .SetPlaceholderText Nothing, Nothing, sPlaceHolderText

    Saturday, September 15, 2018 10:01 PM
    • Edited by macropodMVP Monday, September 17, 2018 6:09 AM
    Monday, September 17, 2018 6:08 AM