Some test text!

platform
search
< Windows samples

PDF Interactive Forms (AcroForms) in VB

Sample VB code for using PDFTron SDK with interactive forms (also known as AcroForms). Capabilities include programatically creating new fields and widget annotations, form filling, modifying existing field values, form templating, and flattening form fields. Learn more about our PDF Form Filler SDK.

Step 1: Get your free trial license key, or sign in

Start Trial
Sign in

Step 2: Add the code:

'---------------------------------------------------------------------------------------
' Copyright (c) 2001-2019 by PDFTron Systems Inc. All Rights Reserved.
' Consult legal.txt regarding legal and license information.
'---------------------------------------------------------------------------------------

Imports System

Imports pdftron
Imports pdftron.Common
Imports pdftron.Filters
Imports pdftron.SDF
Imports pdftron.PDF

'---------------------------------------------------------------------------------------
' This sample illustrates basic PDFNet capabilities related to interactive 
' forms (also known as AcroForms). 
'---------------------------------------------------------------------------------------
Module InteractiveFormsTestVB
	Dim pdfNetLoader As PDFNetLoader
	Sub New()
		pdfNetLoader = pdftron.PDFNetLoader.Instance()
	End Sub

	Sub Main()

		PDFNet.Initialize()

		' Relative path to the folder containing test files.
		' Dim input_path As String = "../../../../TestFiles/"
		Dim output_path As String = "../../../../TestFiles/Output/"

		Try
			'----------------------------------------------------------------------------------
			' Example 1: Programatically create new Form Fields and Widget Annotations.
			'----------------------------------------------------------------------------------
			Using doc As PDFDoc = New PDFDoc
				Dim blank_page As Page = doc.PageCreate()		  ' Create a blank page and some new fields (aka "AcroForms").

				' Create new fields.
				Dim emp_first_name As Field = doc.FieldCreate("employee.name.first", _
				 Field.Type.e_text, doc.CreateIndirectString("John"))
				Dim emp_last_name As Field = doc.FieldCreate("employee.name.last", _
				 Field.Type.e_text, doc.CreateIndirectString("Doe"))
				Dim emp_last_check1 As Field = doc.FieldCreate("employee.name.check1", _
				 Field.Type.e_check, doc.CreateIndirectName("Yes"))
				Dim submit As Field = doc.FieldCreate("submit", _
				 Field.Type.e_button)

				' Create page annotations for the above fields.
				Dim sdfdoc As SDFDoc = doc.GetSDFDoc()

				' Create text annotations
				Dim annot1 As pdftron.PDF.Annots.Widget = pdftron.PDF.Annots.Widget.Create(sdfdoc, New Rect(50, 550, 350, 600), emp_first_name)
				Dim annot2 As pdftron.PDF.Annots.Widget = pdftron.PDF.Annots.Widget.Create(sdfdoc, New Rect(50, 450, 350, 500), emp_last_name)

				' Create check-box annotation
				Dim annot3 As pdftron.PDF.Annots.Widget = pdftron.PDF.Annots.Widget.Create(sdfdoc, New Rect(64, 356, 120, 410), emp_last_check1)

				' Set the annotation appearance for the "Yes" state...
				annot3.SetAppearance(CreateCheckmarkAppearance(doc), Annot.AnnotationState.e_normal, "Yes")

				' Create button annotation
				Dim annot4 As pdftron.PDF.Annots.Widget = pdftron.PDF.Annots.Widget.Create(sdfdoc, New Rect(64, 284, 163, 320), submit)
				' Set the annotation appearances for the down and up state...
				annot4.SetAppearance(CreateButtonAppearance(doc, False), Annot.AnnotationState.e_normal)
				annot4.SetAppearance(CreateButtonAppearance(doc, True), Annot.AnnotationState.e_down)

				' Create 'SubmitForm' action. The action will be linked to the button.
				Dim url As FileSpec = FileSpec.CreateURL(sdfdoc, "http://www.pdftron.com")
				Dim button_action As pdftron.PDF.Action = pdftron.PDF.Action.CreateSubmitForm(url)

				' Associate the above action with 'Down' event in annotations action dictionary.
				Dim annot_action As Obj = annot4.GetSDFObj().PutDict("AA")
				annot_action.Put("D", button_action.GetSDFObj())

				blank_page.AnnotPushBack(annot1)			  ' Add annotations to the page
				blank_page.AnnotPushBack(annot2)
				blank_page.AnnotPushBack(annot3)
				blank_page.AnnotPushBack(annot4)

				doc.PagePushBack(blank_page)			 ' Add the page as the last page in the document.

				' If you are not satisfied with the look of default auto-generated appearance 
				' streams you can delete "AP" entry from the Widget annotation and set 
				' "NeedAppearances" flag in AcroForm dictionary:
				'    doc.GetAcroForm().PutBool("NeedAppearances", true)
				'    			
				' This will force the viewer application to auto-generate new appearance streams 
				' every time the document is opened.
				'
				' Alternatively you can generate custom annotation appearance using ElementWriter 
				' and then set the "AP" entry in the widget dictionary to the new appearance
				' stream.
				'
				' Yet another option is to pre-populate field entries with dummy text. When 
				' you edit the field values using PDFNet the new field appearances will match 
				' the old ones.
				doc.RefreshFieldAppearances()

				doc.Save(output_path + "forms_test1.pdf", 0)
			End Using
			Console.WriteLine("Done. Result saved in forms_test1.pdf")

			'----------------------------------------------------------------------------------
			' Example 2: 
			' Fill-in forms / Modify values of existing fields.
			' Traverse all form fields in the document (and print out their names). 
			' Search for specific fields in the document.
			'----------------------------------------------------------------------------------
			Using doc4 As PDFDoc = New PDFDoc(output_path + "forms_test1.pdf")
				doc4.InitSecurityHandler()

				Dim itr As FieldIterator = doc4.GetFieldIterator()
				While itr.HasNext()
					Console.WriteLine("Field name: {0}", itr.Current().GetName())
					Console.WriteLine("Field partial name: {0}", itr.Current().GetPartialName())
					Console.Write("Field type: ")

					Dim field As Field = itr.Current()
					Dim type As Field.Type = field.GetType()

					If type = field.Type.e_button Then
						Console.WriteLine("Button")
					ElseIf type = field.Type.e_radio Then
						Console.WriteLine("Radio button")
					ElseIf type = field.Type.e_check Then
						Console.WriteLine("Check box")
						field.SetValue(True)
					ElseIf type = field.Type.e_text Then
						Console.WriteLine("Text")

						' Edit all variable text in the document
						Dim old_value As String = "none"
						If Not field.GetValue() Is Nothing Then
							old_value = field.GetValueAsString()
						End If
						field.SetValue("This is a new value. The old one was: " + old_value)
					ElseIf type = field.Type.e_choice Then
						Console.WriteLine("Choice")
					ElseIf type = field.Type.e_signature Then
						Console.WriteLine("Signature")
					End If

					Console.WriteLine("------------------------------")
					itr.Next()
				End While

				' Search for a specific field
				Dim fld As Field = doc4.GetField("employee.name.first")
				If Not fld Is Nothing Then
					Console.WriteLine("Field search for {0} was successful: ", fld.GetName(), fld.GetValueAsString())
				Else
					Console.WriteLine("Field search failed.")
				End If

				' Regenerate field appearances.
				doc4.RefreshFieldAppearances()

				doc4.Save(output_path + "forms_test_edit.pdf", 0)
			End Using
			Console.WriteLine("Done. Results saved in forms_test_edit.pdf")

			'----------------------------------------------------------------------------------
			' Sample: Form templating
			' Replicate pages and form data within a document. Then rename field names to make 
			' them unique.
			'----------------------------------------------------------------------------------
			Using doc3 As PDFDoc = New PDFDoc(output_path + "forms_test1.pdf")
				doc3.InitSecurityHandler()

				Dim src_page3 As Page = doc3.GetPage(1)
				doc3.PagePushBack(src_page3)	 ' Append several copies of the second page
				doc3.PagePushBack(src_page3)	 ' Note that forms are successfully copied
				doc3.PagePushBack(src_page3)

				' Now we rename fields in order to make every field unique.
				' You can use this technique for dynamic template filling where you have a 'master'
				' form page that should be replicated, but with unique field names on every page. 
				RenameAllFields(doc3, "employee.name.first")
				RenameAllFields(doc3, "employee.name.last")
				RenameAllFields(doc3, "employee.name.check1")
				RenameAllFields(doc3, "submit")

				doc3.RefreshFieldAppearances()

				doc3.Save(output_path + "forms_test1_cloned.pdf", 0)
			End Using
			Console.WriteLine("Done. Results saved in forms_test1_cloned.pdf")

			'----------------------------------------------------------------------------------
			' Sample: 
			' Flatten all form fields in a document.
			' Note that this sample is intended to show that it is possible to flatten
			' individual fields. PDFNet provides a utility function PDFDoc.FlattenAnnotations()
			' that will automatically flatten all fields.
			'----------------------------------------------------------------------------------
			Using doc5 As PDFDoc = New PDFDoc(output_path + "forms_test1.pdf")
				doc5.InitSecurityHandler()

				Dim autoflat As Boolean = True
				If (autoflat) Then
					doc5.FlattenAnnotations()
				Else	' Manual flattening
					Dim pitr As PageIterator = doc5.GetPageIterator()
					While pitr.HasNext()
						Dim page As Page = pitr.Current()
						Dim annots As Obj = page.GetAnnots()
						If Not annots Is Nothing Then
							' Look for all widget annotations (in reverse order)
							Dim i As Integer = annots.Size() - 1
							While i >= 0
								Dim subtype As String = annots.GetAt(i).Get("Subtype").Value().GetName()
								If subtype.Equals("Widget") Then
									Dim field As Field = New Field(annots.GetAt(i))
									field.Flatten(page)
									' Another way of making a read only field is by modifying 
									' field's e_read_only flag: 
									' field.SetFlag(Field.FieldFlag.e_read_only, true)
								End If
								i = i - 1
							End While
						End If
						pitr.Next()
					End While
				End If


				doc5.Save(output_path + "forms_test1_flattened.pdf", 0)
			End Using
			Console.WriteLine("Done. forms_test1_flattened.pdf")

		Catch ex As PDFNetException
			Console.WriteLine(ex.Message)
		Catch ex As Exception
			MsgBox(ex.Message)
		End Try

	End Sub

	Sub RenameAllFields(ByRef d As PDFDoc, ByVal name As String)
		Dim fld As Field = d.GetField(name)
		Dim counter As Integer = 0
		While Not fld Is Nothing
			fld.Rename(name + counter.ToString())
			fld = d.GetField(name)
			counter = counter + 1
		End While
	End Sub

	Function CreateCheckmarkAppearance(ByRef doc As PDFDoc) As Obj
		' Create a checkmark appearance stream ------------------------------------
		Dim builder As ElementBuilder = New ElementBuilder
		Dim writer As ElementWriter = New ElementWriter

		writer.Begin(doc.GetSDFDoc())
		writer.WriteElement(builder.CreateTextBegin())

		' other options are circle ("l"), diamond ("H"), cross ("\x35")
		' See section D.4 "ZapfDingbats Set and Encoding" in PDF Reference Manual for 
		' the complete graphical map for ZapfDingbats font.
		Dim checkmark As Element = builder.CreateTextRun("4", Font.Create(doc, Font.StandardType1Font.e_zapf_dingbats), 1)
		writer.WriteElement(checkmark)

		writer.WriteElement(builder.CreateTextEnd())

		Dim stm As Obj = writer.End()

		' Calling Dispose() on ElementReader/Writer/Builder can result in increased performance and lower memory consumption.
		writer.Dispose()
		builder.Dispose()

		' Set the bounding box
		stm.PutRect("BBox", -0.2, -0.2, 1, 1)
		stm.PutName("Subtype", "Form")
		Return stm
	End Function

	Function CreateButtonAppearance(ByRef doc As PDFDoc, ByVal button_down As Boolean) As Obj
		' Create a button appearance stream ------------------------------------
		Dim builder As ElementBuilder = New ElementBuilder
		Dim writer As ElementWriter = New ElementWriter

		writer.Begin(doc.GetSDFDoc())

		' Draw background
		Dim element As Element = builder.CreateRect(0, 0, 101, 37)
		element.SetPathFill(True)
		element.SetPathStroke(False)
		element.GetGState().SetFillColorSpace(ColorSpace.CreateDeviceGray())
		element.GetGState().SetFillColor(New ColorPt(0.75, 0, 0))
		writer.WriteElement(element)

		' Draw 'Submit' text
		writer.WriteElement(builder.CreateTextBegin())

		element = builder.CreateTextRun("Submit", Font.Create(doc, Font.StandardType1Font.e_helvetica_bold), 12)
		element.GetGState().SetFillColor(New ColorPt(0, 0, 0))

		If (button_down) Then
			element.SetTextMatrix(1, 0, 0, 1, 33, 10)
		Else
			element.SetTextMatrix(1, 0, 0, 1, 30, 13)
		End If

		writer.WriteElement(element)
		writer.WriteElement(builder.CreateTextEnd())

		Dim stm As Obj = writer.End()

		' Calling Dispose() on ElementReader/Writer/Builder can result in increased performance and lower memory consumption.
		writer.Dispose()
		builder.Dispose()

		' Set the bounding box
		stm.PutRect("BBox", 0, 0, 101, 37)
		stm.PutName("Subtype", "Form")
		Return stm
	End Function

End Module