Populate rich text form field with formatted text
Printed From: Debenu Quick PDF Library - PDF SDK Community Forum
Category: For Users of the Library
Forum Name: I need help - I can help
Forum Description: Problems and solutions while programming with the Debenu Quick PDF Library and Debenu PDF Viewer SDK
URL: http://www.quickpdf.org/forum/forum_posts.asp?TID=2834
Printed Date: 22 Nov 24 at 6:07PM Software Version: Web Wiz Forums 11.01 - http://www.webwizforums.com
Topic: Populate rich text form field with formatted text
Posted By: AndyD
Subject: Populate rich text form field with formatted text
Date Posted: 20 Feb 14 at 9:13AM
Morning all. my app allows the user to modify a standard letter including bold and underlined text etc. When I pass this info to the PDF using QP.SetFormFieldValue it only passes plain text and not the formatted rich text. As I have a RichTextBox in VB6 I can use .textRTF rather than just .text but this just then includes the actual RTF code, for example, {\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Times New Roman;}} \viewkind4\uc1\pard\lang1033\f0\fs23 We thank you for your recent enquiry and are pleased to provide our quotation, drawings and job \par specification for the supply and delivery of the FleXaire cooling units and ancillaries described. Can anyone help with this problem? Many Thanks
|
Replies:
Posted By: Ingo
Date Posted: 20 Feb 14 at 12:19PM
Hi! As far as i know form fields in QuickPDF only works with plain text. Sorry. Cheers, Ingo
------------- Cheers, Ingo
|
Posted By: AndyD
Date Posted: 20 Feb 14 at 12:46PM
I was running version 9.14 but found that in 9.15 a new function SetFormFieldRichTextString was added. I have updated to 9.16 now so I can access this new function but after trying it I am getting an empty form field. There is limited documentation about this new function but I found this: The required format of the input string is defined in the PDF Specification under the section titled "Field Dictionaries" I cannot find this though.
|
Posted By: AndyD
Date Posted: 21 Feb 14 at 11:17AM
Does anyone else have any experience of using QP.SetFormFieldRichTextString in VB6 as I have tried everything and am still getting an empty form field in the pdf.
|
Posted By: jpbro
Date Posted: 21 Feb 14 at 12:37PM
Can you post a small code sample that generates a PDF with a form field, and attempts to populate it? I can experiment here to see if I can find a solution for you.
|
Posted By: AndyD
Date Posted: 21 Feb 14 at 12:49PM
Thank you, there is nothing mentioned in the developers guide and little anywhere else. My code doesn't create a new form but uses an existing template PDF with a form field added. I did it this way as I couldn't find how to set the properties of the form field to allow rich text editing. Anyway the snippet that covers the filling of the field is this: Call QP.SetFormFieldRichTextString(1, "RV", LetterContent) The page only has a single form field for test purpose hence the '1' and the LetterContent is the variable that stores the rich text string. If you need the template pdf I could email it. Any help is greatly appreciated as this is the first problem I have not found a solution for.
|
Posted By: jpbro
Date Posted: 21 Feb 14 at 1:17PM
Hi Andy, can you send me the sample PDF at jbrown "at" statslog.com?
|
Posted By: AndyD
Date Posted: 21 Feb 14 at 2:02PM
Posted By: jpbro
Date Posted: 21 Feb 14 at 3:37PM
What we've found so far (for anyone following), is that according to the PDF1.7 spec definition of "RichText", it appears to be different from what we might know as "RichText", or "RTF". PDF seems to be expecting a valid XML document, with support for some specific tags such as <i> and <b>.
I've been trying to get QPDF to take the example XML in the PDF spec as the value parameter for the SetFormFieldRichTextString method, but so far even that sample text taken directly from the spec doesn't show up in the form field. I've tried a bunch of variations too without success.
Perhaps someone who has used the SetFormFieldRichTextString method successfully can provide a working example?
|
Posted By: AndrewC
Date Posted: 22 Feb 14 at 2:16AM
Hello, The easiest way to determine what format is required would be to set up a rich text formfield in Acrobat and then populate it with some text manually and then save the file.
You should then use GetFormFieldRichTextString to retrieve the required XML string that is generated by Adobe.
These two functions were originally added for a customer who needed to use it exactly this way.
Setting up a formfield for RichText editing requires a whole lot of extra code to handle fonts, styles and the xml etc.. and a whole lot of documentation The PDF file format is very complex and there are areas of the PDF that Debenu Quick PDF Library (DQPL) currently doesn't support and this is one of those areas.
Also DQPL doesn't have the functions required to generate the required appearance streams for rich text fields at the moment. ie. We don't have code to parse and render the XML. This may be why you say you cannot get it working. Once you have updated the XML you will currently need to load the file into Acrobat to have it update the appearance streams.
We are continually adding new features to the library but because the specification is so large and complex we can't add everything and we don't have access to the hundreds of developers that Acrobat does.
Andrew.
|
Posted By: AndyD
Date Posted: 22 Feb 14 at 2:51PM
Hi Andrew, I tried what you suggested, getting the xml string from an existing box with text, then firing the exact same string back to a second empty identical field, but unfortunately the bos remains empty. I can only assume there is some addtitional info I need to send to the field to get it to display. If I can get the xml firing back correctly and displaying, then I can work on writing a module to convert the rtf string into the xml version.
|
Posted By: AndyD
Date Posted: 22 Feb 14 at 3:45PM
Update: I have succeeded in populating the pdf field with rich text. I used the GetFormFieldRichTextString to get some sample xml code, then as the SetFormFieldRichTextString wasn't working, I tried just using the SetFormFieldValue to send this code into the form field and it worked!! So now I just need to write a routine to convert RTF to XML.... I keep everyone posted.
|
Posted By: jpbro
Date Posted: 25 Feb 14 at 1:22AM
I too have been unable to get the SetFormFieldRichTextString method to work, but calling SetFormFieldValue with valid PDF XML seems to work.
In case anyone needs a basic RTF to PDF Rich Text XML converter, I've done a bit of work on one in VB6.
It handles paragraph alignment (left, right, center), font colours, font face and size, and bold, italic, and underline styles. Other RTF will just be ignored.
I haven't tested it too extensively, so there may well be bugs, but it seems to be working pretty well so far.
To use it, just pass a RichTextBox control to the RtfToPdfXml function, and pass the results to the SetFormFieldValue method of a QuickPdf object.
Option Explicit
Private Enum e_Style style_Normal = 0 style_Bold = 1 style_Italic = 2 style_Underline = 4 End Enum
Private Declare Function GetSysColor Lib "user32.dll" (ByVal nIndex As Long) As Long
Public Function RtfToPdfXml(po_Rtb As RichTextLib.RichTextBox) As String Const c_ParaStart As String = "<p style=""" Dim l_Xml As String Dim i As Long Dim l_OpenNewSpan As Boolean Dim l_SpanOpen As Boolean Dim l_SpanText As String Dim l_ParaStart As Boolean Dim l_EmptyParagraph As Boolean Dim l_ThisStyle As e_Style ' Current style of the span Dim l_LastStyle As e_Style ' Last style of the span Dim l_Color As Long Dim l_LastColor As Long Dim l_FontName As String Dim l_LastFontName As String Dim l_FontSize As Single Dim l_LastFontSize As Single ' Set up the XML header l_Xml = "<?xml version=""1.0""?><body xfa:APIVersion=""Acroform:2.7.0.0"" xfa:spec=""2.1"" xmlns=""http://www.w3.org/1999/xhtml"" xmlns:xfa=""http://www.xfa.org/schema/xfa-data/1.0/"" >" ' Start first paragraph l_Xml = l_Xml & c_ParaStart l_ParaStart = True l_EmptyParagraph = True For i = 0 To Len(po_Rtb.Text) - 1 With po_Rtb .SelStart = i .SelLength = 1 On Error Resume Next l_Color = 0 l_Color = .SelColor If l_Color < 0 Then l_Color = GetSysColor(l_Color) End If On Error GoTo 0 l_FontName = .SelFontName l_FontSize = .SelFontSize If l_ParaStart Then ' Start of a paragraph l_ParaStart = False ' Handle paragraph alignment Select Case .SelAlignment Case rtfRight l_Xml = l_Xml & "text-align:right;" Case rtfCenter l_Xml = l_Xml & "text-align:center;" Case Else l_Xml = l_Xml & "text-align:left;" End Select ' Handle text color l_Xml = l_Xml & "color: " & ColorToPdfXmlRgb(l_Color) & ";" ' Handle font face and size l_Xml = l_Xml & "font-family: '" & l_FontName & "';" l_Xml = l_Xml & "font-size: " & Format$(l_FontSize, "0.0") & "pt;" l_Xml = l_Xml & """>" ' Reset stored "previous" attributes for new paragraph l_SpanOpen = False l_OpenNewSpan = False l_ThisStyle = style_Normal l_LastStyle = style_Normal l_LastFontName = "" l_LastFontSize = 0 l_LastColor = vbBlack End If If (.SelLength = 0) Or (.SelText = vbCr) Or (.SelText = vbLf) Then ' New Paragraph If .SelLength = 0 Then i = i + 1 End If ' Append any buffered span text and close the span if open l_Xml = l_Xml & l_SpanText l_SpanText = "" l_LastStyle = style_Normal If l_SpanOpen Then l_SpanOpen = False l_Xml = l_Xml & "</span>" End If ' Start new paragraph l_Xml = l_Xml & IIf(l_EmptyParagraph, " ", "") & "</p>" & c_ParaStart l_ParaStart = True l_EmptyParagraph = True Else ' Continuing processing current paragraph l_ThisStyle = style_Normal l_EmptyParagraph = False
' Handle Bold/Italic/Underline ProcessStyle style_Bold, po_Rtb, l_Xml, l_SpanText, l_LastStyle, l_ThisStyle, l_OpenNewSpan, l_SpanOpen ProcessStyle style_Italic, po_Rtb, l_Xml, l_SpanText, l_LastStyle, l_ThisStyle, l_OpenNewSpan, l_SpanOpen ProcessStyle style_Underline, po_Rtb, l_Xml, l_SpanText, l_LastStyle, l_ThisStyle, l_OpenNewSpan, l_SpanOpen If l_Color <> l_LastColor Then l_OpenNewSpan = True End If If l_FontSize <> l_LastFontSize Then l_OpenNewSpan = True End If If l_FontName <> l_LastFontName Then l_OpenNewSpan = True End If If l_OpenNewSpan Then ' Text attribute(s) changed If l_SpanOpen Then ' Append any buffered span text and close the previous span l_Xml = l_Xml & l_SpanText l_SpanText = "" l_Xml = l_Xml & "</span>" l_SpanOpen = False End If ' Open a new span l_Xml = l_Xml & "<span style=""" ' Add font styles If l_ThisStyle And style_Bold Then l_Xml = l_Xml & "font-weight: bold;" End If If l_ThisStyle And style_Italic Then l_Xml = l_Xml & "font-style: italic;" End If If l_ThisStyle And style_Underline Then l_Xml = l_Xml & "text-decoration: underline;" End If ' Add text color, font family, and font size l_Xml = l_Xml & "color: " & ColorToPdfXmlRgb(l_Color) & ";" l_Xml = l_Xml & "font-family: '" & l_FontName & "';" l_Xml = l_Xml & "font-size: " & Format$(l_FontSize, "0.0") & "pt;" l_Xml = l_Xml & """>" l_OpenNewSpan = False l_SpanOpen = True End If ' Cache properties for comparison on next loop l_LastStyle = l_ThisStyle l_LastColor = l_Color l_LastFontName = l_FontName l_LastFontSize = l_FontSize l_SpanText = l_SpanText & .SelText End If End With Next i If l_SpanText <> "" Then ' Append any buffered text l_Xml = l_Xml & l_SpanText End If If l_SpanOpen Then ' Close the open span l_Xml = l_Xml & "</span>" End If If Right$(l_Xml, Len(c_ParaStart)) = c_ParaStart Then ' Clean up any orphan paragraph l_Xml = Left$(l_Xml, Len(l_Xml) - Len(c_ParaStart)) Else If Right$(l_Xml, 4) <> "</p>" Then ' Close an open paragraph l_Xml = l_Xml & "</p>" End If End If ' Close the body and return the result RtfToPdfXml = l_Xml & "</body>" End Function
Private Sub ProcessStyle(ByVal p_Style As e_Style, po_Rtb As RichTextLib.RichTextBox, p_Xml As String, p_PreviousTextSpan As String, p_LastStyle As e_Style, p_ThisStyle As e_Style, p_OpenSpan As Boolean, p_SpanOpen As Boolean) ' Return TRUE if a new spn should be opened Dim l_StyleApplied As Boolean Select Case p_Style Case style_Underline l_StyleApplied = po_Rtb.SelUnderline Case style_Italic l_StyleApplied = po_Rtb.SelItalic Case style_Bold l_StyleApplied = po_Rtb.SelBold Case Else Err.Raise 5 End Select If l_StyleApplied Then If p_SpanOpen Then If Not CBool(p_LastStyle And p_Style) Then p_OpenSpan = True End If Else p_OpenSpan = True End If p_ThisStyle = p_ThisStyle Or p_Style Else If p_SpanOpen Then If p_LastStyle And p_Style Then p_LastStyle = p_LastStyle And Not p_Style p_OpenSpan = True End If Else If p_LastStyle And p_Style Then p_OpenSpan = True End If End If End If End Sub
Private Function ColorToPdfXmlRgb(ByVal p_Color As OLE_COLOR) As String ' Return a Long color value as a string usable in PDF RichText XML ' e.g. Calling ColorToPdfXmlRgb(12624000) returns "rgb(128,160,192)" Dim l_Red As Byte Dim l_Blue As Byte Dim l_Green As Byte If p_Color < 0 Then p_Color = GetSysColor(p_Color) End If l_Red = p_Color And &HFF l_Green = (p_Color And &HFF00&) \ &H100& l_Blue = (p_Color And &HFF0000) \ &H10000 ColorToPdfXmlRgb = "rgb(" & Format$(l_Red, "000") & "," & Format$(l_Green, "000") & "," & Format$(l_Blue, "000") & ")" End Function
|
|
Posted By: AndyD
Date Posted: 25 Feb 14 at 8:58AM
Superb work and thank you. Now as the FlattenFormField removes formatting if we combine this code with making the form fields read only we end up with a secure formatted pdf with rich styling. About to test it but looks like the strength of some members of this community has solved my problem. Many thanks
|
Posted By: jpbro
Date Posted: 25 Feb 14 at 4:11PM
Glad to have been of some help Andy, and hopefully our exploration might help others who need the same functionality in the future!
|
Posted By: AndyD
Date Posted: 25 Feb 14 at 6:29PM
For all those interested, when I have chance I will create a sample VB6 app and supporting pdf using jp's excellent code and the required functions and post it in the sample code section. So, in short, you can programatically populate rich text form fields with formatted text and save those pdf's with read only fields to create professional looking letters etc from within your app.
|
Posted By: jpbro
Date Posted: 25 Feb 14 at 10:34PM
Great Andy, I look forward to your extended example!
|
Posted By: AndyD
Date Posted: 26 Feb 14 at 5:28PM
Final Update: With jpbro's help we have solved this problem and I have put together a sample VB6 app demonstrating how to do it. Full details can be found here: http://www.quickpdf.org/forum/topic2839_post11527.html#11527" rel="nofollow - http://www.quickpdf.org/forum/topic2839_post11527.html#11527 One final change was to restrict the use of the '&' symbol as this prevents the RTF2XML converter from functioning. If anyone has any feedback or suggestions it would be greatly received.
|
|