I have a template which I’m attaching for reference. Depending on a value in SQL query, I would like to delete a section of the word document. Is this possible? If not, what I planned to do was to make all the titles merge fields and populate the titles from my query, but when I do so, the table rows where the merge fields are remain. I would like to make the row shrink up in those cases.
In the template there is a section called Transaction Information. In my query there is a field ListingStatus. If this field is equal not equal to available, I want to supress that entire ListingStatus area…
Hi Ryan,
Thanks for your inquiry.
It’s not quite clear exactly what area you want removed from the document as there is no “ListingStatus” fields or rows in the document. You could please clarify this?
Most likely to achieve this you should insert a bookmark into the template which encloses the area you want removed. Then you can check for the appropriate merge field during merging and check it value. If this value does not match you can then remove the content of the bookmark from the document.
Thanks,
The solution posted there works for my use, and could be expanded to remove entire table rather than just row, you could then format your document accordingly.
I basically want to remove the Table under the heading Transaction Information if the merge field ProperyInfo which is at the top of the document is not equal to Available.
I have been playing around with placing a bookmark inside the table but I either get region errors or it deletes to much out of the document.
'Dim bk As Aspose.Words.Bookmark = doc.Range.Bookmarks("RIDERPLANS_BOOKMARK")
'If bk IsNot Nothing Then
' Get table, where bookmark is located.
' Dim table As Node = bk.BookmarkStart.GetAncestor(NodeType.Table)
' If table IsNot Nothing Then
' table.Remove()
' End If
'End If
That code above seemed to work but I cannot get it adapted to work within a document builder…
Also tried
builder.MoveToBookmark("test")
Dim table As Node = builder.CurrentParagraph.GetAncestor(NodeType.Table)
table.Remove()
Hi Ryan,
Thanks for this additional information. I think there may be two methods depending upon if you want the whole Transaction information table removed or just the content below the title (which is contained in sub tables inside this main table).
I have made two sample documents which demonstrate both situations. I have sent them to your inbox.
The code for the first case, removing the entire table:
// Get the bookmark
Bookmark bookmark = doc.Range.Bookmarks["RIDERPLANS_BOOKMARK"];
// Get the table that this bookmark is contained in.
Table tabletest = (Table) bookmark.BookmarkStart.GetAncestor(NodeType.Table);
// Remove the table
tabletest.Remove();
For the second case when removing only the subtables:
// Get the bookmark.
Bookmark bookmark = doc.Range.Bookmarks["RIDERPLANS_BOOKMARK"];
// Get the table which contains this bookmark.
Table parentTable = (Table) bookmark.BookmarkStart.GetAncestor(NodeType.Table);
// Select all table nodes who are descendants of this table.
// Use ToArray so we don't invalidate the enumuator when removing nodes which otherwise will cause the loop to halt
Node[] nodeArray = parentTable.SelectNodes(".//Table").ToArray();
// Remove each sub table.
foreach(Table table in nodeArray)
table.Remove();
There is really no way to remove the content from a bookmark using DocumentBuilder, this is because as the name suggests, its main use is to build and not to remove content
Seph, thank you for suggesting this code as well. This may come in handy for him.
Please feel free to ask if you have any further problems.
Thanks,
How do I implement either solution with my current data structure? Some records in the dataset will meet the criteria to remove the area, some won’t and dont need anything removed. Can that code my placed directly in a mergecallback?
Current Code:
Dim dtTemplate1 As New DataTable()
adapterTemplate1.Fill(dtTemplate1)
Dim recordCount As Integer
recordCount = dtTemplate1.Rows.Count
dtTemplate1.TableName = "Summary"
doc.MailMerge.FieldMergingCallback = New HandleMergeFieldSummary1()
doc.MailMerge.FieldMergingCallback = New HandleMergeFieldProfile1()
doc.MailMerge.ExecuteWithRegions(dtTemplate1)
doc.MailMerge.Execute(New String() {"Name", "RecordCount", "PreparedBy", "PreparedFor"}, New Object() {rcbExportNameTxt.Text, recordCount, rcbPreparedBy.Text, rcbPreparedFor.Text})
doc.MailMerge.DeleteFields()
If qExportTemplateID = "33" Or qExportTemplateID = "35" Or qExportTemplateID = "37" Or qExportTemplateID = "39" Or qExportTemplateID = "43" Or qExportTemplateID = "45" Or qExportTemplateID = "47" Or qExportTemplateID = "49" Or qExportTemplateID = "51" Then
doc.Save(REPLACE(SavePath, "doc", "pdf"))
Else
doc.Save(SavePath)
End If
Private Class HandleMergeFieldSummary1
Implements IFieldMergingCallback
Dim mIsMergeImage As Boolean = False
Private Sub FieldMerging(args As FieldMergingArgs) Implements IFieldMergingCallback.FieldMerging
If args.FieldName = "SaleTypeTxt" Then
If args.FieldValue = "Hart Exclusive Agency" Then
mIsMergeImage = True
Else
mIsMergeImage = False
End If
End If
End Sub
Private Sub ImageFieldMerging(e As ImageFieldMergingArgs) Implements IFieldMergingCallback.ImageFieldMerging
If (mIsMergeImage) Then
e.ImageFileName = System.IO.Path.Combine("d:\hart11\images", "hartlogoxsmall.gif")
End If
End Sub
End Class
Private Class HandleMergeFieldProfile1
Implements IFieldMergingCallback
Private Sub FieldMerging(args As FieldMergingArgs) Implements IFieldMergingCallback.FieldMerging
Dim builder As New DocumentBuilder(args.Document)
If args.FieldName = "P1" Then
Dim P1s As String = args.FieldValue.ToString()
If P1s > "" And System.IO.File.Exists(P1s) Then
Else
P1s = "D:\hart11\filecabinet\property\default.jpg"
End If
Dim img As System.Drawing.Image
builder.MoveToField(args.Field, True)
img = System.Drawing.Image.FromFile(P1s)
Dim shape As Aspose.Words.Drawing.Shape = builder.InsertImage(img, 275, 125)
shape.WrapType = "5"
End If
End Sub
Private Sub ImageFieldMerging(e As ImageFieldMergingArgs) Implements IFieldMergingCallback.ImageFieldMerging
' Do nothing.
End Sub
End Class
Hi Ryan,
Thanks for this additional information. Yes you can simply insert that logic into your existing handlers. Please note, because the handlers are implementing interfaces now instead of delegates, I don’t believe setting more than one handler will work. I’m pretty sure only HandleMergeFieldProfile1 is being called in your code above.
Below is the code that you can use to implement the logic inside your merging handler. Both code examples go inside the FieldMerging method. Method one:
' Get the bookmark
Dim bookmark As Bookmark = args.Document.Range.Bookmarks("RIDERPLANS_BOOKMARK")
' Get the table that this bookmark is contained in.
Dim parentTable As Table = CType(bookmark.BookmarkStart.GetAncestor(NodeType.Table), Table)
' Remove the table
parentTable.Remove()
Method two:
If args.FieldName.Equals("SaleActualPriceInt") Then
' For this situation the bookmark will be duplicated with each growth of the region. Since the whole table isn't
' removed with each merge the original bookmark will remain. We need to look through all bookmarks with the appropriate name
' and pick the last bookmark as that will be the one corresponding to
Dim bookmarks As BookmarkCollection = args.Document.Range.Bookmarks
Dim targetBookmarks As New ArrayList()
For Each bookmark As Bookmark In bookmarks
If bookmark.Name.Equals("RIDERPLANS_BOOKMARK") Then
targetBookmarks.Add(bookmark)
End If
Next bookmark
' Get the bookmark
Dim targetBookmark As Bookmark = CType(targetBookmarks(targetBookmarks.Count - 1), Bookmark)
' Get the table which contains this bookmark.
Dim parentTable As Table = CType(targetBookmark.BookmarkStart.GetAncestor(NodeType.Table), Table)
' Select all table nodes who are descendants of this table.
' Use ToArray so we don't invalidate the enumuator when removing nodes which otherwise will cause the loop to halt
Dim nodeArray() As Node = parentTable.SelectNodes(".//Table").ToArray()
' Remove each sub table.
For Each table As Table In nodeArray
table.Remove()
Next table
End If
I tried method 1:
I do have a bookmark in my template named: SalePriceTitle
Object reference not set to an instance of an object.
Dim bookmark As Aspose.Words.Bookmark = args.Document.Range.Bookmarks("SalePriceTitle")
Dim parentTable As Aspose.Words.Tables.Table = CType(bookmark.BookmarkStart.GetAncestor(NodeType.Table), Aspose.Words.Tables.Table)
parentTable.Remove()
Dim bk As Aspose.Words.Bookmark = args.Document.Range.Bookmarks("TransDate")
If bk IsNot Nothing Then
Dim table As Node = bk.BookmarkStart.GetAncestor(NodeType.Table)
If table IsNot Nothing Then
table.Remove()
End If
End If
Can you alter this to show me how to just remove the row where the bookmark is located?
Dim bk As Aspose.Words.Bookmark = args.Document.Range.Bookmarks("TransDate")
If bk IsNot Nothing Then
Dim row As Node = bk.BookmarkStart.GetAncestor(NodeType.Row)
If row IsNot Nothing Then
row.Remove()
End If
End If
Something isnt right… Maybe its the bookmarks causing the issue. I’m attaching my template and output so you can see. In the code I tell it to locate the bookmark and remove, only if the merge field PropertyInfo which is at the top of the document is LIKE “Available*”. The first property is correct, but the second property is Sold and the row is removed, as is the third property which is leased and it stripped, then after that, the last 2 properties look like they were ignored completely. The bookmark remains.
Dim dtTemplate1 As New DataTable()
adapterTemplate1.Fill(dtTemplate1)
Dim recordCount As Integer
recordCount = dtTemplate1.Rows.Count
dtTemplate1.TableName = "Summary"
doc.MailMerge.FieldMergingCallback = New HandleMergeFieldSummary()
doc.MailMerge.ExecuteWithRegions(dtTemplate1)
doc.MailMerge.Execute(New String() {"Name", "RecordCount", "PreparedBy", "PreparedFor"}, New Object() {rcbExportNameTxt.Text, recordCount, rcbPreparedBy.Text, rcbPreparedFor.Text})
doc.MailMerge.DeleteFields()
doc.Save(SavePath)
Private Class HandleMergeFieldSummary
Implements IFieldMergingCallback
Dim mIsMergeImage As Boolean = False
Private Sub FieldMerging(args As FieldMergingArgs) Implements IFieldMergingCallback.FieldMerging
If args.FieldName = "SaleTypeTxt" Then
If args.FieldValue = "Hart Exclusive Agency" Then
mIsMergeImage = True
Else
mIsMergeImage = False
End If
End If
Dim builder As New DocumentBuilder(args.Document)
If args.FieldName = "P1" Then
Dim P1s As String = args.FieldValue.ToString()
If P1s > "" And System.IO.File.Exists(P1s) Then
Else
P1s = "D:\hart11\filecabinet\property\default.gif"
End If
Dim img As System.Drawing.Image
builder.MoveToField(args.Field, True)
img = System.Drawing.Image.FromFile(P1s)
Dim shape As Aspose.Words.Drawing.Shape = builder.InsertImage(img, 275, 125)
shape.WrapType = "5"
End If
If args.FieldName = "PropertyInfo" Then
If args.FieldValue Like "Available*" Then
Dim bk3 As Aspose.Words.Bookmark = args.Document.Range.Bookmarks("bkTransactionInformation")
If bk3 IsNot Nothing Then
Dim row As Node = bk3.BookmarkStart.GetAncestor(NodeType.Row)
If row IsNot Nothing Then
row.Remove()
End If
End If
End If
End If
End Sub
Private Sub ImageFieldMerging(e As ImageFieldMergingArgs) Implements IFieldMergingCallback.ImageFieldMerging
If (mIsMergeImage) Then
e.ImageFileName = System.IO.Path.Combine("d:\hart11\images", "hartlogoxsmall.gif")
End If
End Sub
End Class
In the output file, you will see the red bar titled Transaction Information should be missing on any properties that have Available in the PropertyInfo field (the text in small caps in the upper right hand corner of the page).
Hi Ryan,
Thanks for the additonal information.
I’m afraid it appears that you have attached the wrong template, as it does not look anything like the output and does not have the appropriate bookmark or field in it.
Please post your template and I will be glad to assist further.
Thanks,
Hi Ryan,
Thanks for posting your template here.
This is happening because if the row is not removed (PropertyInfo is “Sold”) then the bookmark remains and is then retrieved as the bookmark for the next merge which causes the wrong row to be removed.
Please use the code below:
If args.FieldName.Equals("PropertyInfo") Then
Dim bk3 As Bookmark = args.Document.Range.Bookmarks("bkTransactionInformation")
Dim row As Row = CType(bk3.BookmarkStart.GetAncestor(NodeType.Row), Row)
If args.FieldValue Like "Available*" Then
If row IsNot Nothing Then
row.Remove()
End If
Else
row.Range.Bookmarks(0).Remove()
End If
End If
End If