Print Page | Close Window

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. Unhappy


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
Email sent, thank you.


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, "&#160;", "") & "</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
 
Big smile


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.
 
Big smile


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.



Print Page | Close Window

Forum Software by Web Wiz Forums® version 11.01 - http://www.webwizforums.com
Copyright ©2001-2014 Web Wiz Ltd. - http://www.webwiz.co.uk