Spire.Doc is a professional Word .NET library specifically designed for developers to create, read, write, convert and print Word document files. Get free and professional technical support for Spire.Doc for .NET, Java, Android, C++, Python.

Tue Feb 05, 2019 11:01 pm

hello
i try since 3 day to use mail merge group function :
il read all i find
https://www.e-iceblue.com/Tutorials/Spi ... -in-C.html

the code :
Code: Select all
Imports Spire.Doc
Imports Spire.Doc.Documents
Imports Spire.Doc.Fields
Imports Spire.Doc.Reporting
Imports System.IO

Class sommaire
    Dim NUMRANG As String
    Dim TITRE As String
    Dim ARTICLE As String
    Sub New(a, b, c)
        NUMRANG = a
        TITRE = b
        ARTICLE = c
    End Sub
End Class


Module Module1

    Sub Main()
        'data
        Dim s1 As sommaire = New sommaire("1", "azerty", "article 14")
        Dim s2 As sommaire = New sommaire("2", "Qwerty", "article 15")
        Dim li As List(Of sommaire) = New List(Of sommaire)
        li.Add(s1)
        li.Add(s2)
        Dim Table As MailMergeDataTable = New MailMergeDataTable("sommaire", li)

        Dim doctest As Document = New Document("C:\tmp\groupesommaire.docx")
        Dim sect As Section = doctest.Sections(0)



        'group start
        Dim MergefielddebutGr As MergeField = New MergeField(doctest)
        MergefielddebutGr.Type = FieldType.FieldMergeField
        MergefielddebutGr.FieldName = "GroupStart:sommaire"

        'group end
        Dim MergefieldfinGr As MergeField = New MergeField(doctest)
        MergefieldfinGr.Type = FieldType.FieldMergeField
        MergefieldfinGr.FieldName = "GroupEnd:sommaire"

        ' add  champgroup at begin and end of pargraph content (3 mailmerges)
        Dim PardernierNonvide As Paragraph = sect.Paragraphs(0) 'just for init
        Dim _unefois As Boolean = True
        For Each par As Paragraph In sect.Paragraphs
            'delete empty line
            If String.IsNullOrEmpty(par.Text.Trim()) Then
                sect.Paragraphs.Remove(par)
            Else
                If _unefois Then
                    'add group before pargraph content
                    par.Items.Insert(0, MergefielddebutGr)
                    _unefois = False
                    'record last pargraph with text
                    PardernierNonvide = par
                End If
            End If
        Next
        PardernierNonvide.Items.Add(MergefieldfinGr)
        doctest.SaveToFile("C:\tmp\mergegroup.docx", FileFormat.Auto)
        doctest.MailMerge.ExecuteGroup(Table)
        doctest.SaveToFile("C:\tmp\mergegroupafter.docx", FileFormat.Auto)

    End Sub


End Module


the result file before merge look like good but i never merge corectly the data on it .
(before write on forum i try create a new doc with all fields , create group field with word , executegroupe never give a good result)
can you help me .
escuse my poor english ;-)
thank's
FH
ps i attached the file to modify and fill.

labaffagaston
 
Posts: 42
Joined: Sun Dec 24, 2017 7:38 pm

Wed Feb 06, 2019 6:27 am

Hello,

Thanks for your inquiry.
I did noticed the issue and will post it to our Dev team for further investigating and fixing, we will share with you about any progress. Sorry for the inconvenience caused. At present, we are on New Year Holiday (from 04/02/2019 to 10/02/2019). Once our Dev team are back to work, they will look into your issue. Thanks for your understanding.

Sincerely,
Lisa
E-iceblue support team
User avatar

Lisa.Li
 
Posts: 1261
Joined: Wed Apr 25, 2018 3:20 am

Tue Feb 12, 2019 7:21 am

hello ,
i have you some answer ?
or may be an example of code who work i dont find it.
my project need the function mail merge group.
thank you for your help.
FH

labaffagaston
 
Posts: 42
Joined: Sun Dec 24, 2017 7:38 pm

Tue Feb 12, 2019 8:03 am

Hello,

Thank you for following up.
Sorry there is no answer till now. Our dev team are speeding up to investigate the issue and I have given a higher priority to it, please spare us more time, we will keep you informed once there is any progress. Thanks for your patience again.

Sincerely,
Lisa
E-iceblue support team
User avatar

Lisa.Li
 
Posts: 1261
Joined: Wed Apr 25, 2018 3:20 am

Wed Feb 13, 2019 8:08 am

Hello Labaffe,

After our Dev team's investigation, based on our internal merging mechanism, the "sommaire" Class and its attributes have to be public, please refer to the following modified code to try again. Any question, just feel free to contact us.
Code: Select all
Friend Class sommaire
    Public Property NUMRANG() As String
    Public Property TITRE() As String
    Public Property ARTICLE() As String
    Public Sub New(ByVal a As String, ByVal b As String, ByVal c As String)
        Me.NUMRANG = a
        Me.TITRE = b
        Me.ARTICLE = c
    End Sub
End Class
Friend Class Program
   Shared Sub Main(ByVal args() As String)
        'data
        Dim s1 As sommaire = New sommaire("1", "azerty", "article 14")
        Dim s2 As sommaire = New sommaire("2", "Qwerty", "article 15")
        Dim li As List(Of sommaire) = New List(Of sommaire)
        li.Add(s1)
        li.Add(s2)
        Dim Table As MailMergeDataTable = New MailMergeDataTable("sommaire", li)
        Dim doctest As Document = New Document("mergegroup.docx")
        Dim sect As Section = doctest.Sections(0)
        'group start
        Dim MergefielddebutGr As MergeField = New MergeField(doctest)
        MergefielddebutGr.Type = FieldType.FieldMergeField
        MergefielddebutGr.FieldName = "GroupStart:sommaire"
        'group end
        Dim MergefieldfinGr As MergeField = New MergeField(doctest)
        MergefieldfinGr.Type = FieldType.FieldMergeField
        MergefieldfinGr.FieldName = "GroupEnd:sommaire"
        ' add  champgroup at begin and end of pargraph content (3 mailmerges)
        Dim PardernierNonvide As Paragraph = sect.Paragraphs(0) 'just for init
        Dim _unefois As Boolean = True
        For Each par As Paragraph In sect.Paragraphs
            'delete empty line
            If String.IsNullOrEmpty(par.Text.Trim()) Then
                sect.Paragraphs.Remove(par)
            Else
                If _unefois Then
                    'add group before pargraph content
                    par.Items.Insert(0, MergefielddebutGr)
                    _unefois = False
                    'record last pargraph with text
                    PardernierNonvide = par
                End If
            End If
        Next
        PardernierNonvide.Items.Add(MergefieldfinGr)
        doctest.SaveToFile("temp.docx", Spire.Doc.FileFormat.Auto)
        doctest.MailMerge.ExecuteGroup(Table)
        doctest.SaveToFile("result.docx", Spire.Doc.FileFormat.Auto)
    End Sub

Sincerely,
Lisa
E-iceblue support team
User avatar

Lisa.Li
 
Posts: 1261
Joined: Wed Apr 25, 2018 3:20 am

Thu Feb 14, 2019 9:30 am

hello
your code work , but i need more details to use mail merge group
il need use merge groupe with a variable number of field mail merge in group.
i am looking for set data dynamically the number of field mail merge .

i try to also to set data directly in mergetable with MailMergeDataSet() but i dont find documentation

i try with list of string (i can dynamically set the quantity of data to be synch with teh docx file) ,
this code dont work.
Code: Select all
 

 'dataset  this code dont work
        Dim ll As List(Of List(Of String)) = New List(Of List(Of String))
        Dim s1a As List(Of String) = New List(Of String)({"1", "azerty", "article 14"})
        Dim s2a As List(Of String) = New List(Of String)({"2", "Qwerty", "article 15"})

        'but may be if the file model file doc content 4 mailmerge (the number of mail merge can be variable)

        Dim s1a As List(Of String) = New List(Of String)({"1", "azerty", "article 14", "One more"})
        Dim s2a As List(Of String) = New List(Of String)({"2", "Qwerty", "article 15", "One more"})

        ll.Add(s1a)
        ll.Add(s2a)

        Dim table As MailMergeDataTable = New MailMergeDataTable("sommaire", ll)


i try also (this code dont work)
Code: Select all

 Dim table1 As DataTable = New DataTable("sommaire")
        table1.Columns.Add("NUMRANG")
        table1.Columns.Add("TITRE")
        table1.Columns.Add("ARTICLE")
        table1.Rows.Add("1", "azerty", "article 14")
        table1.Rows.Add("1", "azerty", "article 14")

        Dim ta As MailMergeDataTable = New MailMergeDataTable("sommaire", table1.Rows)
...
Dim table As MailMergeDataTable = New MailMergeDataTable("sommaire", ta)

...




i continue to search and try ...

Thank's
FH

labaffagaston
 
Posts: 42
Joined: Sun Dec 24, 2017 7:38 pm

Fri Feb 15, 2019 10:59 am

Hello Labaffe,

Thanks for your feedback.
Case one: as per my understanding, what you want is to mail merge different Word templates (each of them contains different numbers of mail merge fields), right? If so, I would suggest that you create a database file to save your data, and then use document.MailMerge.Execute(DataTable dt) to mail merge fields, here, I made a sample demo for your reference.

Case two: I guess that maybe your template document has no mail merge fields (or has some mail merge fields) but you want to create other different mail merge fields dynamically on it as needed using code, if so, I think it could be achieved by creating mail merge fields. You could provide your original templete and desired template for our reference, and we will then look into it and provide a demo accordingly.

Sincerely,
Lisa
E-iceblue support team
User avatar

Lisa.Li
 
Posts: 1261
Joined: Wed Apr 25, 2018 3:20 am

Fri Feb 15, 2019 7:58 pm

case 1 : i use already the document.MailMerge.Execute.
case 2 : the template include a lot of mailmerge "single" AND group Mail merge (a lot of field mail merge to merge in XXX recurence eaxctely the definition of document.MailMerge.ExecuteGroup())

i try to explain my problem

the size of MMgroup is not constant, our customers can personalize and change the number of fields in each group
and they put in xml data file the good rows, and columns for fill merge grouped fields for each group.

for information the complete process for ours document template :
1 / execute mail merge group on all groups in the template (file docx)
2/ execute DocWordFile.MailMerge.Execute() in the same template (file docx) to merge the simple fields mail merge
3/ execute with bookmarks localisations replace text with picture and/or rtf in same template


i have a lot of contraint for keep the retro compatibilité with word automation and i cannot replace all clients templates .
my project need to set dynamically the size of struct source data to fill tuned MMgroup (client can set more or less field in group ).

i have some ideas :

1/detect MMgroup
2/ in for X-next loop create single pargrah with mailmerge.exexcute on fields in group detected and copy the result single to list of paragraph.
result -> list(of parrgraph).count = X contain the filled group

3/ copy the list of paragraph items result to template original after «GroupStart:>> field
but i prefere avoid to re create the group mailmerge function ,
i already have a lot of work to finish. :D

or

define staticaly the source group class(like "sommaire" in my first post) with 256 public property and set with string empty the property who the fields are not present in MMgroup .
(256 is ours number of all differents fields mail merge possible in one group).

i test this solution with 20 fields in group and i put 3, 5, 15 strings source and the other is set to string empty
class sommaire
public property FMM1
...
public property FMM20
end class

exemple for the first traitement : group sommaire

client set template : <<STDFMM1>>text<<STDFMM1>> «GroupStart:sommaire» <<FMM1>> <<FMM2>> <<FMM3>> «GroupEnd:sommaire» <<STDFMM3>>
and give me X rows with 3 values in xml source for this group
i can create X for instance of "sommaire" class with first 3 property data set with values and the other set to string.empty (17)

with the same code

client set template : <<STDFMM1>>text<<STDFMM1>> «GroupStart:sommaire» <<FMM1>> <<FMM2>> <<FMM3>> <<FMM4>> «GroupEnd:sommaire» <<STDFMM3>>
and give me X rows with 4 values in xml source for this group
i can create X for instance of classe with first 4 property data set with values and the other set to string.empty (16)

its work ! but i dont like this cheap solution

the solution i m looking for :
to fill MailMergeDataTable , or use for data struct for document.MailMerge.ExecuteGroup()
with a structure like list , or array or datatable who i can define size, and/or resize and fill dynamically.

thank's for you help

labaffagaston
 
Posts: 42
Joined: Sun Dec 24, 2017 7:38 pm

Mon Feb 18, 2019 10:49 am

Hello Labaffe,

Thanks for your feedback.
In your previous way, you put the values in a List, please note that there is no relationship between the list values and the MailMerge fields, hence our Spire.Doc has no way to judge which value should be merged to the corresponding field, that led to the failure of the MailMerge. As for your situation, we suggest that you customize different datatable structures based on MailMerge fields name in your templates, and then directly use document.MailMerge.Execute(datatable) to merge data from datatables like the following sample code.
Code: Select all
'customize datatable structures based on MailMerge fields name
Dim dataTable As New DataTable()
dataTable.Columns.Add("NUMRANG")
dataTable.Columns.Add("TITRE")
dataTable.Columns.Add("ARTICLE")
dataTable.Rows.Add(New String() { "1", "azerty", "article 14" })
dataTable.Rows.Add(New String() {"2", "Qwerty", "article 15"})
'load word document
Dim document As New Document()
document.LoadFromFile("mergegroup.docx")
'merge
document.MailMerge.Execute(dataTable)
'Save as docx file.
document.SaveToFile("result.docx", FileFormat.Docx)


Sincerely,
Lisa
E-iceblue support team
User avatar

Lisa.Li
 
Posts: 1261
Joined: Wed Apr 25, 2018 3:20 am

Wed Feb 20, 2019 11:18 am

hello
i test your code :
scenario one : (mergegroup.docx, result.docx)

file source only contain the field mailmerge group
it 's work but there is a "end section " ???? can you explain ?

Senario two : the situation to resolve ( mergegroup2.docx, reslut2.docx)

file source contain standart mail merge and a group fields to repeat (who the number of fields can evoluate)
it doesnt work , and always end section ???

in mergegroup2.docx : i need to complet the group only and also if its size change (number of fields)

Sincerely,
fh

labaffagaston
 
Posts: 42
Joined: Sun Dec 24, 2017 7:38 pm

Thu Feb 21, 2019 12:01 pm

Hello,

Thanks for your feedback.
As for the "Senario two" issue, the mergegroup2.docx has the single mail merge fields(«tempo»,«tempo2»), and they didn't appear in the result2.docx, do you want to keep the fields after mail merging? If so, sorry to tell there is no way to achieve it. Our product is based on MS Word, if you do mail merge by MS Word directly, the fields which has no value to do mail merge will also disappear. About the "end section", you could try the following code to remove it. BTW, if the number of mail merge fields in your templates are different, please customize the corresponding datatable structures to do mail merge respectively. If there is any misunderstanding, please provide more details and share your expected output for reference.
Code: Select all
Document document = new Document();
document.LoadFromFile("result2.docx");
for (int i = 1; i < document.Sections.Count; i++)
{
    for (int j = 0; j < document.Sections[i].Paragraphs.Count; j++)
    {
        document.Sections[0].Body.ChildObjects.Add(document.Sections[i].Paragraphs[j].Clone());
    }
    document.Sections.RemoveAt(i);
}
//save the document
document.SaveToFile("noEndSection.docx", FileFormat.Docx2013);


Sincerely,
Lisa
E-iceblue support team
User avatar

Lisa.Li
 
Posts: 1261
Joined: Wed Apr 25, 2018 3:20 am

Fri Feb 22, 2019 7:56 am

Hello,

We found a better way to fulfill your demand, but it need to firstly add the TableStart field and TableEnd field for the group fields in your template(mergegroup2.docx). Please refer to the following code to have a try. And I also attached my output file for your reference. If there is any question, just feel free to write back.
Code: Select all
'Create a data table named "sommaire"
Dim dataTable As New DataTable("sommaire")
dataTable.Columns.Add("NUMRANG")
dataTable.Columns.Add("TITRE")
dataTable.Columns.Add("ARTICLE")
dataTable.Rows.Add(New String() { "1", "azerty", "article 14" })
dataTable.Rows.Add(New String() { "2", "azerty", "article 15" })
'Load the document
Dim document As New Document()
document.LoadFromFile("mergegroup2.docx")
Dim sect As Section = document.Sections(0)
'Add TableStart:sommaire field
Dim tableStartField As New MergeField(document)
tableStartField.Type = FieldType.FieldMergeField
tableStartField.FieldName = "TableStart:sommaire"
'Add TableEnd:sommaire field
Dim tableEndField As New MergeField(document)
tableEndField.Type = FieldType.FieldMergeField
tableEndField.FieldName = "TableEnd:sommaire"
'Add group field for your group fields which need to be merged
For Each para As Paragraph In sect.Paragraphs
   For i As Integer = 0 To para.ChildObjects.Count - 1
      Dim obj As DocumentObjectCollection = para.ChildObjects
      If TypeOf obj(i) Is MergeField Then
         Dim mf As MergeField = TryCast(obj(i), MergeField)
            If mf.FieldName = "NUMRANG" Then
               Dim currentPara As Paragraph = mf.OwnerParagraph
                currentPara.ChildObjects.Insert(0, tableStartField)
                currentPara.ChildObjects.Add(tableEndField)
            End If
      End If
   Next i
Next para
'Execute merge
document.MailMerge.ExecuteWidthRegion(dataTable)
document.SaveToFile("result.docx", FileFormat.Docx2013)

Sincerely,
Lisa
E-iceblue support team
User avatar

Lisa.Li
 
Posts: 1261
Joined: Wed Apr 25, 2018 3:20 am

Fri Feb 22, 2019 9:06 am

Hello ,
i read your code its look very good solution , :idea:
in my case i have to only replace name of field "Table" insthead of "group"
and
document.MailMerge.ExecuteWidthRegion insthead of doctest.MailMerge.ExecuteGroup
i try this new method , in a few time and i come back write the result

thank you for your perseverance
FH

labaffagaston
 
Posts: 42
Joined: Sun Dec 24, 2017 7:38 pm

Fri Feb 22, 2019 9:43 am

Hello,

Thanks for your quick responce, I am looking forward to your result. Wish everything goes well.

Sincerely,
Lisa
E-iceblue support team
User avatar

Lisa.Li
 
Posts: 1261
Joined: Wed Apr 25, 2018 3:20 am

Tue Feb 26, 2019 5:52 am

Hello,

Greetings from E-iceblue.
How is your issue going? Could you please let us know your testing result at your convenience? Thanks in advance.

Sincerely,
Lisa
E-iceblue support team
User avatar

Lisa.Li
 
Posts: 1261
Joined: Wed Apr 25, 2018 3:20 am

Return to Spire.Doc