none
Mailmerge includepicture problem in .NET (picture not working) RRS feed

  • Question

  • Hello,


    I am using the mailmerge with a datasource in SQL Server. The problem is that connecting to the datasource is very slow (between 1-2 sec.). As I must do  30-40 merge at once the customers are complaining that is is very slow.

    I am trying to replace the mailmerge by putting directly the value in the mailmerge field.

    All is working but I can(t make it working for the pictures).

    What I do is to find every mergefield and then use the Field.Code.Text = Value for the variable.
    For a picture it doesn't work.
    Can you please tell me how I can make the pictures work?

    Thank you

    Marc

    Here is how I replace the variables.

    The function GetValForPos will read from multiples datasets to find the correct table where the variable is stored. Il will probably change in the future but it is made to do some tests before changing the program.

    Dim MailMerge As Object = TempDoc.MailMerge()

    For Each f As Object In MailMerge.Fields
        Dim str_FieldMergeName As String = f.Code.Text
        Dim i_Pos As Integer = str_FieldMergeName.IndexOf("MERGEFIELD")
        If i_Pos >= 0 Then
            'Mergefield
            Dim i_PosEnd As Integer = str_FieldMergeName.IndexOf("\*", i_Pos)

            Dim str_DatabaseFieldName As String
            If i_PosEnd >= 0 Then
                ' Text field
                str_DatabaseFieldName = str_FieldMergeName.Substring(i_Pos + 10, i_PosEnd - i_Pos - 10).Trim
                f.Select()
                ' Replace selected field with supplied value.
                aWord.Selection.TypeText(GetValForPos(str_DatabaseFieldName, DSet.Tables("tb_CustCorrespPrj").Rows.Find(si_PrjID), DSet.Tables("tb_CustCorrespPos").Rows(0)))
            Else


    'Image Field
                str_DatabaseFieldName = str_FieldMergeName.Substring(i_Pos + 10).Trim
                f.Select()
                'Doesn't work
                'aWord.Selection.TypeText(GetValForPos(str_DatabaseFieldName, DSet.Tables("tb_CustCorrespPrj").Rows.Find(si_PrjID), DSet.Tables("tb_CustCorrespPos").Rows(0)))
                ' Doesn't work too
                f.code.text = GetValForPos(str_DatabaseFieldName, DSet.Tables("tb_CustCorrespPrj").Rows.Find(si_PrjID), DSet.Tables("tb_CustCorrespPos").Rows(0))
            End If
            
        Else
            Stop
        End If
    Next

    Thank you

    Marc

    Tuesday, February 19, 2013 6:36 AM

Answers

  • Hi Marc

    For the IncludePicture field it would probably make sense to look for that field, delete it, then recreate it. Using the loop structure you already have in your code, build this in for the field that contains the file path to the picture:

        Dim rng As word.Range
       
        Set rng = f.code
        f.Delete
        rng = Chr(34) & filePathWithDoubleBackslashes & Chr(34)

    Example for valid file path: """C:\\Pictures\\Bag_VSS.png"""

    Open XML: I'm afraid we're hitting a language barrier with your description; it's just not clear to me what needs to be done. However, with Open XML you can work with the entire document - headers, footers, body of the text, etc. - no problem. And you can generate one document at a time, also no problem.

    You can handle the data source any way you wish, including changing data sources. Put very simply: You generate each item you want to place in the document in memory, then assign it to the appropriate Node in the Open XML.

    I don't have any sample code at hand and my time is limited for the next month. You should probably be able to turn something up at OpenXMLDeveloper.org or in the Open XML SDK forum. Basically, anything that writes data to bookmarks, merge fields or content controls will give you the general steps.


    Cindy Meister, VSTO/Word MVP, my blog

    • Marked as answer by Marc Allard Thursday, February 21, 2013 5:52 AM
    Wednesday, February 20, 2013 3:38 PM
    Moderator

All replies

  • Hi Marc

    It's impossible to tell you without understanding how the "merge field" for the document has been constructed. One assumes this is an IncludePicture field with an embedded merge field, but we can't be certain that's the case...

    As a Word API "purist" I'm also really not happy with your code, although if  it works, it works...

    If speed continues to be an issue the most efficient solution would be to do integrate the data with the Word document using Open XML, rather than the APIs.


    Cindy Meister, VSTO/Word MVP, my blog

    Wednesday, February 20, 2013 7:33 AM
    Moderator
  • Hello,

    You are right, it is a IncludePicture with a merge field (that contains the path to the picture).
    The link to SQL Server takes a little more than one second. If I must open 40 differents documents it is 40 seconds (without doing the merge). With the current method does it in less then 10 seconds for 40 documents.

    With some requirements (from customers) I can't have a page jump between multiple documents and I need to fill headers and footers, so I can't fill all the records in SQL Server and do one mail merge with all the records. (If I want to do it I have to choose either the label output that will not fill headers), either the normal output that will put a page jump between all records).

    That is the reason I need to do that.

    Do you have an example I could use with the OpenXML?
    Also I need to merge differents documents (with differents datasource). Is it possible with OpenXML?

    For example I make a project. In this project there are 40 positions (generally from 10 to 80).
    I need to do a mailmerge with the header data of the projects (and I copy the result into a new document).
    After that I do the mailmerge with every position one by one (and I append the result to the new document).
    When It is done I do the same for the footer of the project and I append the result to the new document.

    I didn't think it was possible with the openXML.

    Thanks for your time

    Marc

    Wednesday, February 20, 2013 7:44 AM
  • Hi Marc

    For the IncludePicture field it would probably make sense to look for that field, delete it, then recreate it. Using the loop structure you already have in your code, build this in for the field that contains the file path to the picture:

        Dim rng As word.Range
       
        Set rng = f.code
        f.Delete
        rng = Chr(34) & filePathWithDoubleBackslashes & Chr(34)

    Example for valid file path: """C:\\Pictures\\Bag_VSS.png"""

    Open XML: I'm afraid we're hitting a language barrier with your description; it's just not clear to me what needs to be done. However, with Open XML you can work with the entire document - headers, footers, body of the text, etc. - no problem. And you can generate one document at a time, also no problem.

    You can handle the data source any way you wish, including changing data sources. Put very simply: You generate each item you want to place in the document in memory, then assign it to the appropriate Node in the Open XML.

    I don't have any sample code at hand and my time is limited for the next month. You should probably be able to turn something up at OpenXMLDeveloper.org or in the Open XML SDK forum. Basically, anything that writes data to bookmarks, merge fields or content controls will give you the general steps.


    Cindy Meister, VSTO/Word MVP, my blog

    • Marked as answer by Marc Allard Thursday, February 21, 2013 5:52 AM
    Wednesday, February 20, 2013 3:38 PM
    Moderator
  • Hello,

    thank you for your time.

    I have seen another way to do it with your ideas : instead of looking at the mergefields I have decided to look at all the fields  and when I do it I see the includepicure. After that I use the same method as before but I replace the includepicture.... by a new includepicture with the correct path.

    For OpenXML I will give it a look because it seems that everything I need is possible. Even if I can only use it for the first part (make all the temporary documents) it seems interesting.

    Thanks again
    Marc

    Thursday, February 21, 2013 5:51 AM