TimeSheetForm.vb
  1. ''
  2. '' This code is part of Document Solutions for PDF demos.
  3. '' Copyright (c) MESCIUS inc. All rights reserved.
  4. ''
  5. Imports System.IO
  6. Imports System.Drawing
  7. Imports GrapeCity.Documents.Pdf
  8. Imports GrapeCity.Documents.Pdf.AcroForms
  9. Imports GrapeCity.Documents.Text
  10. Imports GrapeCity.Documents.Common
  11. Imports GrapeCity.Documents.Drawing
  12. Imports GCTEXT = GrapeCity.Documents.Text
  13. Imports GCDRAW = GrapeCity.Documents.Drawing
  14.  
  15. '' This sample generates a PDF AcroForm representing a time sheet.
  16. '' The same code Is used to generated the time sheet in the TimeSheet use case sample.
  17. Public Class TimeSheetForm
  18. '' Font collection to hold the fonts we need:
  19. Private _fc As FontCollection = New FontCollection()
  20. '' The text layout used to render input fields when flattening the document:
  21. Private _inputTl As TextLayout = New TextLayout(72)
  22. '' The text format used for input fields:
  23. Private _inputFont As GCTEXT.Font = FontCollection.SystemFonts.FindFamilyName("Segoe UI", True)
  24. Private _inputFontSize As Single = 12
  25. '' Input fields margin:
  26. Private _inputMargin As Single = 5
  27. '' Space for employee's signature:
  28. Private _empSignRect As RectangleF
  29. '' Logo (we should dispose it after saving the document):
  30. Private _logo As GCDRAW.Image
  31.  
  32. '' Main entry point of this sample:
  33. Function CreatePDF(ByVal stream As Stream) As Integer
  34. '' Set up a font collection with the fonts we need:
  35. _fc.RegisterDirectory(Path.Combine("Resources", "Fonts"))
  36. '' Set that font collection on input fields' text layout
  37. '' (we will also set it on all text layouts that we'll use):
  38. _inputTl.FontCollection = _fc
  39. '' Set up layout And formatting for input fields:
  40. _inputTl.ParagraphAlignment = ParagraphAlignment.Center
  41. '' Create the time sheet input form
  42. '' (in a real-life scenario, we probably would only create it once,
  43. '' And then re-use the form PDF):
  44. Dim doc = MakeTimeSheetForm()
  45. '' Save the PDF:
  46. doc.Save(stream)
  47. '' Images used in a document can be disposed only after saving the PDF:
  48. _logo.Dispose()
  49. '' Done:
  50. Return doc.Pages.Count
  51. End Function
  52.  
  53. '' Data field names:
  54. Private Structure _Names
  55. Shared ReadOnly Dows As String() = {
  56. "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
  57. }
  58. Const EmpName = "empName"
  59. Const EmpTitle = "empTitle"
  60. Const EmpNum = "empNum"
  61. Const EmpStatus = "empStatus"
  62. Const EmpDep = "empDep"
  63. Const EmpSuper = "empSuper"
  64. Shared ReadOnly DtNames = New Dictionary(Of String, String()) From {
  65. {"Sun", New String() {"dtSun", "tSunStart", "tSunEnd", "tSunReg", "tSunOvr", "tSunTotal"}},
  66. {"Mon", New String() {"dtMon", "tMonStart", "tMonEnd", "tMonReg", "tMonOvr", "tMonTotal"}},
  67. {"Tue", New String() {"dtTue", "tTueStart", "tTueEnd", "tTueReg", "tTueOvr", "tTueTotal"}},
  68. {"Wed", New String() {"dtWed", "tWedStart", "tWedEnd", "tWedReg", "tWedOvr", "tWedTotal"}},
  69. {"Thu", New String() {"dtThu", "tThuStart", "tThuEnd", "tThuReg", "tThuOvr", "tThuTotal"}},
  70. {"Fri", New String() {"dtFri", "tFriStart", "tFriEnd", "tFriReg", "tFriOvr", "tFriTotal"}},
  71. {"Sat", New String() {"dtSat", "tSatStart", "tSatEnd", "tSatReg", "tSatOvr", "tSatTotal"}}
  72. }
  73. Const TotalReg = "totReg"
  74. Const TotalOvr = "totOvr"
  75. Const TotalHours = "totHours"
  76. Const EmpSign = "empSign"
  77. Const EmpSignDate = "empSignDate"
  78. Const SupSign = "supSign"
  79. Const SupSignDate = "supSignDate"
  80. End Structure
  81.  
  82. '' Creates the Time Sheet form:
  83. Private Function MakeTimeSheetForm() As GcPdfDocument
  84.  
  85. Const marginH = 72.0F, marginV = 48.0F
  86. Dim doc = New GcPdfDocument()
  87. Dim page = doc.NewPage()
  88. Dim g = page.Graphics
  89. Dim ip = New PointF(marginH, marginV)
  90.  
  91. Dim tl = New TextLayout(g.Resolution) With {.FontCollection = _fc}
  92.  
  93. tl.Append("TIME SHEET", New TextFormat() With {.FontName = "Segoe UI", .FontSize = 18})
  94. tl.PerformLayout(True)
  95. g.DrawTextLayout(tl, ip)
  96. ip.Y += tl.ContentHeight + 15
  97.  
  98. _logo = GCDRAW.Image.FromFile(Path.Combine("Resources", "ImagesBis", "AcmeLogo-vertical-250px.png"))
  99. Dim s = New SizeF(250.0F * 0.75F, 64.0F * 0.75F)
  100. g.DrawImage(_logo, New RectangleF(ip, s), Nothing, ImageAlign.Default)
  101. ip.Y += s.Height + 5
  102.  
  103. tl.Clear()
  104. tl.Append("Where Business meets Technology",
  105. New TextFormat() With {.FontName = "Segoe UI", .FontItalic = True, .FontSize = 10})
  106. tl.PerformLayout(True)
  107. g.DrawTextLayout(tl, ip)
  108. ip.Y += tl.ContentHeight + 15
  109.  
  110. tl.Clear()
  111. tl.Append($"1901, Halford Avenue,{vbCrLf}Santa Clara, California – 95051-2553,{vbCrLf}United States",
  112. New TextFormat() With {.FontName = "Segoe UI", .FontSize = 9})
  113. tl.MaxWidth = page.Size.Width - marginH * 2
  114. tl.TextAlignment = TextAlignment.Trailing
  115. tl.PerformLayout(True)
  116. g.DrawTextLayout(tl, ip)
  117. ip.Y += tl.ContentHeight + 25
  118.  
  119. Dim pen = New GCDRAW.Pen(Color.Gray, 0.5F)
  120.  
  121. Dim colw = (page.Size.Width - marginH * 2) / 2
  122. Dim fields1 = DrawTable(ip,
  123. New Single() {colw, colw},
  124. New Single() {30, 30, 30},
  125. g, pen)
  126.  
  127. Dim tf = New TextFormat() With {.FontName = "Segoe UI", .FontSize = 9}
  128. With tl
  129. .ParagraphAlignment = ParagraphAlignment.Center
  130. .TextAlignment = TextAlignment.Leading
  131. .MarginLeft = 4
  132. .MarginRight = 4
  133. .MarginTop = 4
  134. .MarginBottom = 4
  135. End With
  136. '' t_ - caption
  137. '' b_ - bounds
  138. '' f_ - field name, null means no field
  139. Dim drawField As Action(Of String, RectangleF, String) =
  140. Sub(t_, b_, f_)
  141. Dim tWidth As Single
  142. If Not String.IsNullOrEmpty(t_) Then
  143. tl.Clear()
  144. tl.MaxHeight = b_.Height
  145. tl.MaxWidth = b_.Width
  146. tl.Append(t_, tf)
  147. tl.PerformLayout(True)
  148. g.DrawTextLayout(tl, b_.Location)
  149. tWidth = tl.ContentRectangle.Right
  150. Else
  151. tWidth = 0
  152. End If
  153. If Not String.IsNullOrEmpty(f_) Then
  154. Dim fld = New TextField() With {.Name = f_}
  155. fld.Widget.Page = page
  156. fld.Widget.Rect = New RectangleF(
  157. b_.X + tWidth + _inputMargin, b_.Y + _inputMargin,
  158. b_.Width - tWidth - _inputMargin * 2, b_.Height - _inputMargin * 2)
  159. fld.Widget.DefaultAppearance.Font = _inputFont
  160. fld.Widget.DefaultAppearance.FontSize = _inputFontSize
  161. fld.Widget.Border.Color = Color.LightSlateGray
  162. fld.Widget.Border.Width = 0.5F
  163. doc.AcroForm.Fields.Add(fld)
  164. End If
  165. End Sub
  166.  
  167. drawField("EMPLOYEE NAME: ", fields1(0, 0), _Names.EmpName)
  168. drawField("TITLE: ", fields1(1, 0), _Names.EmpTitle)
  169. drawField("EMPLOYEE NUMBER: ", fields1(0, 1), _Names.EmpNum)
  170. drawField("STATUS: ", fields1(1, 1), _Names.EmpStatus)
  171. drawField("DEPARTMENT: ", fields1(0, 2), _Names.EmpDep)
  172. drawField("SUPERVISOR: ", fields1(1, 2), _Names.EmpSuper)
  173.  
  174. ip.Y = fields1(0, 2).Bottom
  175.  
  176. Dim col0 = 100.0F
  177. colw = (page.Size.Width - marginH * 2 - col0) / 5
  178. Dim rowh = 25.0F
  179. Dim fields2 = DrawTable(ip,
  180. New Single() {col0, colw, colw, colw, colw, colw},
  181. New Single() {50, rowh, rowh, rowh, rowh, rowh, rowh, rowh, rowh},
  182. g, pen)
  183.  
  184. tl.ParagraphAlignment = ParagraphAlignment.Far
  185. drawField("DATE", fields2(0, 0), Nothing)
  186. drawField("START TIME", fields2(1, 0), Nothing)
  187. drawField("END TIME", fields2(2, 0), Nothing)
  188. drawField("REGULAR HOURS", fields2(3, 0), Nothing)
  189. drawField("OVERTIME HOURS", fields2(4, 0), Nothing)
  190. tf.FontBold = True
  191. drawField("TOTAL HOURS", fields2(5, 0), Nothing)
  192. tf.FontBold = False
  193. tl.ParagraphAlignment = ParagraphAlignment.Center
  194. tf.ForeColor = Color.Gray
  195. For i = 0 To 6
  196. drawField(_Names.Dows(i), fields2(0, i + 1), _Names.DtNames(_Names.Dows(i))(0))
  197. Next
  198. '' Vertically align date fields (compensate for different DOW widths):
  199. Dim dowFields = doc.AcroForm.Fields.TakeLast(7)
  200. Dim minW = dowFields.Min(Function(f_) CType(f_, TextField).Widget.Rect.Width)
  201. dowFields.ToList().ForEach(
  202. Sub(f_)
  203. Dim r_ = CType(f_, TextField).Widget.Rect
  204. r_.Offset(r_.Width - minW, 0)
  205. r_.Width = minW
  206. CType(f_, TextField).Widget.Rect = r_
  207. End Sub
  208. )
  209.  
  210. tf.ForeColor = Color.Black
  211. For row = 1 To 7
  212. For col = 1 To 5
  213. drawField(Nothing, fields2(col, row), _Names.DtNames(_Names.Dows(row - 1))(col))
  214. Next
  215. Next
  216.  
  217. tf.FontBold = True
  218. drawField("WEEKLY TOTALS", fields2(0, 8), Nothing)
  219. tf.FontBold = False
  220.  
  221. drawField(Nothing, fields2(3, 8), _Names.TotalReg)
  222. drawField(Nothing, fields2(4, 8), _Names.TotalOvr)
  223. drawField(Nothing, fields2(5, 8), _Names.TotalHours)
  224.  
  225. ip.Y = fields2(0, 8).Bottom
  226.  
  227. col0 = 72 * 4
  228. colw = page.Size.Width - marginH * 2 - col0
  229. Dim fields3 = DrawTable(ip,
  230. New Single() {col0, colw},
  231. New Single() {rowh + 10, rowh, rowh},
  232. g, pen)
  233.  
  234. drawField("EMPLOYEE SIGNATURE: ", fields3(0, 1), Nothing)
  235. Dim r = fields3(0, 1)
  236. _empSignRect = New RectangleF(r.X + r.Width / 2, r.Y, r.Width / 2 - _inputMargin * 2, r.Height)
  237. Dim sfEmp = New SignatureField()
  238. sfEmp.Name = _Names.EmpSign
  239. sfEmp.Widget.Rect = New RectangleF(r.X + r.Width / 2, r.Y + _inputMargin, r.Width / 2 - _inputMargin * 2, r.Height - _inputMargin * 2)
  240. sfEmp.Widget.Page = page
  241. sfEmp.Widget.BackColor = Color.LightSeaGreen
  242. doc.AcroForm.Fields.Add(sfEmp)
  243. drawField("DATE: ", fields3(1, 1), _Names.EmpSignDate)
  244.  
  245. drawField("SUPERVISOR SIGNATURE: ", fields3(0, 2), Nothing)
  246. r = fields3(0, 2)
  247. Dim sfSup = New SignatureField()
  248. sfSup.Name = _Names.SupSign
  249. sfSup.Widget.Rect = New RectangleF(r.X + r.Width / 2, r.Y + _inputMargin, r.Width / 2 - _inputMargin * 2, r.Height - _inputMargin * 2)
  250. sfSup.Widget.Page = page
  251. sfSup.Widget.BackColor = Color.LightYellow
  252. doc.AcroForm.Fields.Add(sfSup)
  253. drawField("DATE: ", fields3(1, 2), _Names.SupSignDate)
  254.  
  255. '' Done:
  256. Return doc
  257. End Function
  258.  
  259. '' Simple table drawing method. Returns the array of table cell rectangles.
  260. Private Function DrawTable(ByVal loc As PointF, ByVal widths As Single(), ByVal heights As Single(), ByVal g As GcGraphics, ByVal p As GCDRAW.Pen) As RectangleF(,)
  261. If widths.Length = 0 OrElse heights.Length = 0 Then
  262. Throw New Exception("Table must have some columns and rows.")
  263. End If
  264. Dim cells(widths.Length, heights.Length) As RectangleF
  265. Dim r = New RectangleF(loc, New SizeF(widths.Sum(), heights.Sum()))
  266. '' Draw left borders (except for 1st one):
  267. Dim x = loc.X
  268. For i = 0 To widths.Length - 1
  269. For j = 0 To heights.Length - 1
  270. cells(i, j).X = x
  271. cells(i, j).Width = widths(i)
  272. Next
  273. If (i > 0) Then
  274. g.DrawLine(x, r.Top, x, r.Bottom, p)
  275. End If
  276. x += widths(i)
  277. Next
  278. '' Draw top borders (except for 1st one):
  279. Dim y = loc.Y
  280. For j = 0 To heights.Length - 1
  281. For i = 0 To widths.Length - 1
  282. cells(i, j).Y = y
  283. cells(i, j).Height = heights(j)
  284. Next
  285. If (j > 0) Then
  286. g.DrawLine(r.Left, y, r.Right, y, p)
  287. End If
  288. y += heights(j)
  289. Next
  290. '' Draw outer border:
  291. g.DrawRectangle(r, p)
  292. '' Done:
  293. Return cells
  294. End Function
  295. End Class
  296.