CustomXmlParts.vb
  1. ''
  2. '' This code is part of Document Solutions for Word demos.
  3. '' Copyright (c) MESCIUS inc. All rights reserved.
  4. ''
  5. Imports System.IO
  6. Imports System.Drawing
  7. Imports System.Collections.Generic
  8. Imports System.Linq
  9. Imports System.Xml
  10. Imports GrapeCity.Documents.Word
  11.  
  12. '' This example demonstrates how to create a document with multiple ContentControls,
  13. '' whose values are mapped to user-created CustomXmlPart file, standart Xml file
  14. '' which defines various elements And attributes.
  15. '' This document also contain a header And a footer with elements that are also mapped to
  16. '' proper xml elements.
  17. Public Class CustomXmlParts
  18. Function CreateDocx() As GcWordDocument
  19. Dim doc = New GcWordDocument()
  20.  
  21. '' Create custom xml part And keep it in the document
  22. CreateOrderCustomXmlFromString(doc)
  23.  
  24. '' Set custom xml document element value
  25. SetDeliveryOption(doc, True)
  26.  
  27. '' Compose document with Case properties bound to proper CustomControls
  28.  
  29. '' Create And map To text field
  30. CreateOficialBody(doc)
  31.  
  32. '' Create And map Appeal checkbox And AppealDeadline Text control
  33. CreateDeliveryCheckbox(doc)
  34.  
  35. '' Create Header And map Department xml element
  36. CreateHeaderWithMappedDepartment(doc)
  37.  
  38. '' Create Header And map document built-in Author xml element
  39. CreateFooterWithMappedAuthor(doc)
  40.  
  41. '' Done
  42. Return doc
  43. End Function
  44.  
  45. '' Retrieve a CustomXmlPart from a document by name
  46. Private Shared Function GetCustomXmlPartByName(ByRef doc As GcWordDocument, ByRef name As String) As CustomXmlPart
  47. For Each xmlPart In doc.CustomXmlParts
  48. If String.Compare(xmlPart.XmlDocument.DocumentElement.Name, name, True) = 0 Then
  49. Return xmlPart
  50. End If
  51. Next
  52. Throw New ArgumentException(String.Format("Could not find custom xml part {0}", name))
  53. End Function
  54.  
  55.  
  56. '' Find 'Order' CustomXmlPart and set its DeliveryAppeal xml element to value provided by method parameter:
  57. Private Shared Sub SetDeliveryOption(ByRef doc As GcWordDocument, ByVal deliveryRequired As Boolean)
  58. Dim xmlPart = GetCustomXmlPartByName(doc, "Order")
  59.  
  60. Dim node = xmlPart.XmlDocument.SelectSingleNode("//*[local-name()='Delivery']")
  61. If deliveryRequired Then
  62. node.InnerText = "true"
  63. Else
  64. node.InnerText = "false"
  65. End If
  66. End Sub
  67.  
  68. '' Compose half of document body, map "To" text custom control to proper CustomXml field
  69. Private Shared Sub CreateOficialBody(ByRef doc As GcWordDocument)
  70. Dim p = doc.Body.Paragraphs.Add("Dear ")
  71. Dim tto = p.GetRange().ContentControls.Add(ContentControlType.Text, False)
  72. tto.XmlMapping.SetMapping("//grapecity:To", "xmlns:grapecity='http://grapecity.com'")
  73.  
  74. p.GetRange().Runs.First.Font.Size = 10
  75. tto.Font.Size = 10
  76. p.GetRange().Runs.Add(",")
  77. doc.Body.Paragraphs.Add()
  78.  
  79. p = doc.Body.Paragraphs.Add(
  80. "The first shipment of equipment from AMA Ltd has arrived. " +
  81. "We are delighted with every piece. Therefore, we decided to make " +
  82. "our initial purchase larger than anticipated. I am attaching our " +
  83. "purchase order No. 8393 for additional goods. Since you already have " +
  84. "a copy of our Procurement Guidelines, I shall not attach them to " +
  85. "this order. Current Shipping date is ")
  86.  
  87. '' Add shipping Date control, bound to proper section of Order CustomXmlPart:
  88. Dim dateControl = p.GetRange().ContentControls.Add(ContentControlType.Date, False)
  89. dateControl.DateFormat = "dd.MM.yyyy"
  90. ''here we demonstrate how to map CustomControl with namespaces usage, it allows us write
  91. ''clean And straight XmlPath. Its the right way of XMlMapping
  92. dateControl.XmlMapping.SetMapping("//grapecity:Delivery/@DeliveryDate",
  93. "xmlns:grapecity='http://grapecity.com'")
  94. p.GetRange().Paragraphs.Add(
  95. "If you want to change it, select checkbox below and change Date, " +
  96. "then send this letter back to me")
  97. dateControl.Font.Italic = True
  98.  
  99. p.GetRange().Runs.First.Font.Size = 12
  100. p.GetRange().Runs.First.Font.Italic = True
  101. End Sub
  102.  
  103. '' Create footer And map Author built-in property to Text content control
  104. Private Shared Sub CreateFooterWithMappedAuthor(ByRef doc As GcWordDocument)
  105. Dim footer = doc.Body.Sections.First.Footers(HeaderFooterType.Primary)
  106. Dim p = footer.Body.Paragraphs.Add("Sincerely yours, ")
  107.  
  108. If p.Document.Settings.BuiltinProperties.Author Is Nothing Then
  109. p.Document.Settings.BuiltinProperties.Author = "Nancy Davolio"
  110. End If
  111.  
  112. '' Create Text ContentControl And bind its value to builtin Author property:
  113. Dim authorTextControl = p.GetRange().ContentControls.Add(ContentControlType.Text, False)
  114.  
  115. '' Use specialized SetMapping overload for document BuiltInProperties.
  116. '' here we bind (map) ContentControl to builtin Author property:
  117. authorTextControl.XmlMapping.SetMapping(Function() p.Document.Settings.BuiltinProperties.Author)
  118. End Sub
  119.  
  120. '' Create header with Text ContentControl mapped to 'Department' node of 'Order' CustomXml:
  121. Private Shared Sub CreateHeaderWithMappedDepartment(ByRef doc As GcWordDocument)
  122. '' Create Header And fill it with data:
  123. Dim header = doc.Body.Sections.First.Headers(HeaderFooterType.Primary)
  124. Dim p = header.Body.Paragraphs.Add()
  125. Dim departmentTextControl = p.GetRange().ContentControls.Add(ContentControlType.Text, False)
  126.  
  127. '' Get our Case CustomXmlPart:
  128. Dim xmlPart = GetCustomXmlPartByName(doc, "Order")
  129.  
  130. Dim departmentNode = xmlPart.XmlDocument.SelectSingleNode("//*[local-name()='Department']")
  131. '' Mapping directly to XmlNode:
  132. departmentTextControl.XmlMapping.SetMapping(departmentNode)
  133. End Sub
  134.  
  135. '' Create Delivery part, Checkbox custom control bound to Delivery node And Date custom control
  136. '' bound to details of (possible) Delivery date.
  137. Private Shared Sub CreateDeliveryCheckbox(ByRef doc As GcWordDocument)
  138. Dim p = doc.Body.Paragraphs.Add()
  139.  
  140. '' Create checkbox And map it to Shipping node of 'Case' CustomXmlPart:
  141. Dim checkBox = p.GetRange().ContentControls.Add(ContentControlType.CheckBox, False)
  142.  
  143. '' Here we demonstrate how to map CustomControl ignoring namespaces used in the xml.
  144. '' This way should be avoided as much as possible as pretty inefficient:
  145. checkBox.XmlMapping.SetMapping("//*[local-name()='Delivery']")
  146.  
  147. p.GetRange().Runs.Add("Delivery should be done before ")
  148.  
  149. '' Add shipping Date control, bound to proper section of Order CustomXmlPart:
  150. Dim dateControl = p.GetRange().ContentControls.Add(ContentControlType.Date, False)
  151. dateControl.DateFormat = "dd.MM.yyyy"
  152. '' Here we demonstrate how to map CustomControl with namespaces usage, it allows us write
  153. '' clean And straight XmlPath. Its the right way of XMlMapping:
  154. dateControl.XmlMapping.SetMapping("//grapecity:Delivery/@DeliveryDate",
  155. "xmlns:grapecity='http://grapecity.com'")
  156. End Sub
  157.  
  158. '' Create XML from a string (see alternative method below)
  159. Private Shared Sub CreateOrderCustomXmlFromString(ByRef doc As GcWordDocument)
  160. Dim sb = New System.Text.StringBuilder(201)
  161. Const ns = "'http://grapecity.com'"
  162.  
  163. sb.AppendLine("<Order xmlns=" + ns + ">")
  164. sb.AppendLine(" <To>Mark Donahue</To>")
  165. sb.AppendLine(" <Department>Shipping department</Department>")
  166. sb.AppendLine(" <Delivery DeliveryDate=""12.04.2019"">true</Delivery>")
  167. sb.AppendLine("</Order>")
  168.  
  169. Dim xml = New XmlDocument()
  170. xml.LoadXml(sb.ToString())
  171. Dim xmlPart = doc.CustomXmlParts.Add(xml, Guid.NewGuid().ToString(), New String() {ns}, "application/xml")
  172. End Sub
  173.  
  174. '' Create XML by adding individual nodes one by one
  175. '' (this method Is Not used in this sample, the previous
  176. '' alternative Is used instead)
  177. Private Shared Sub CreateOrderCustomXml(ByRef doc As GcWordDocument)
  178. '' add a custom xml part with custom settings
  179. Const ns = "http://grapecity.com"
  180. Dim xml = New XmlDocument()
  181.  
  182. xml.AppendChild(xml.CreateXmlDeclaration("1.0", "utf-8", Nothing))
  183. Dim root = xml.CreateElement("Order", ns)
  184. xml.AppendChild(root)
  185.  
  186. Dim tto = root.AppendChild(xml.CreateElement("To", ns))
  187. tto.InnerText = "Mark Donahue"
  188.  
  189. Dim dep = root.AppendChild(xml.CreateElement("Department", ns))
  190. dep.InnerText = "Shipping department"
  191.  
  192. Dim child = xml.CreateElement("Delivery", ns)
  193. child.InnerText = "true"
  194. child.SetAttribute("DeliveryDate", "12.04.2019")
  195.  
  196. root.AppendChild(child)
  197.  
  198. Dim xmlPart = doc.CustomXmlParts.Add(xml, Guid.NewGuid().ToString(), New String() {ns}, "application/xml")
  199.  
  200. '' Sad story: we cannot apply schemas To our custom xml parts.
  201. '' Unlike in Office excel (where a schema can be serialized inside a document),
  202. '' it seems that Word can work with schema URIs only so we cannot place an xsd inside the document.
  203. '' This means that we cannot implement native xml-mapping restrictiong And verifying Like
  204. '' xmlPart.Schemas.Add(CreateCelebrationScheme())
  205. End Sub
  206. End Class
  207.