WinBatch Tech Support Home

Database Search

If you can't find the information using the categories below, post a question over in our WinBatch Tech Support Forum.

TechHome

Samples from Users
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus
plus

Can't find the information you are looking for here? Then leave a message over on our WinBatch Tech Support Forum.

Text to PDF UDF


Here is UDF that will convert a text file to a PDF. The code is pure winbatch, using no third-party DLLs.

The output is a very simple PDF report in Courier font - you specify the type size. There is no encryption or password or any other security. When writing the text file, you can force a page break by writing a FORMFEED (Num2Char(12)) character.

To use... "#include" the file in your program, then call...

text2pdf("input.txt","output.pdf",font-size)


;**********************************************************************
;
;   Subroutines to convert a TEXT file into a PDF.  The code is
;   pure winbatch, no 3rd party software needed.
;
;   The result is a very simple PDF file in courier font.  If you need
;   anything more complex, like document security or fancy text formatting,
;   you probably need to look at the 3rd party software.
;
; ----------------------------------------------------------------------
;   To call the function...
;
;      text2pdf ("input.txt", "output.pdf", font-size-in-points)
;
; -----------------------------------------------------------------------
;   The function will inspect the text and adjust the page height and
;   width to fit. (If the text fits on a standard 8.5 x 11 page, then
;   we'll use 8.5 x 11.)
;
;   If the text contains FORMFEED characters ( Num2Char(12) ) to force a
;   page break, we choose a page height big enough for the longest page.
;
;   If there are no specified page breaks the page size will be selected
;   automatically, trying to come as close as we can to a standard
;   8.5 x 11 page.
;
;***************************************************************************

;------------------------------------------------------------------------
;   Subroutine: Write text to a PDF file.  Add bytes written to the
;   "CurrentOffset" (we need the offset becuse the PDF contains a
;   cross-reference with pointers to objects.)   Note: "FileWrite" adds
;   a CRLF to the end of each line, so add 2 extra bytes to the Offset.
;------------------------------------------------------------------------
#DefineSubRoutine text2pdfWriteLine(text2pdfWriteLine_Text)
    FileWrite(hOUT,text2pdfWriteLine_Text)
    CurrentOffset = CurrentOffset + StrLen(text2pdfWriteLine_Text) + 2
    Return
#EndSubRoutine

;------------------------------------------------------------------------
;  Subroutine: Start a new "object" in the PDF file.  Save the offset
;  to the object in a list which we can use later to create the object
;  cross reference.  Note that the objects are not created in numerical
;  order, so the table must include both the object number and offset
;  (number:offset-tab-number:offset-tab-... etc)
;------------------------------------------------------------------------
#DefineSubRoutine text2pdfNewObject(text2pdfNewObjectNumber)
    xrefOffsetList = ItemInsert(StrCat(text2pdfNewObjectNumber,":",CurrentOffset),-1,xrefOffsetList,@TAB)
    text2pdfWriteLine(StrCat(text2pdfNewObjectNumber," 0 obj"))
#EndSubRoutine

;------------------------------------------------------------------------
;
;  Main function
;
;------------------------------------------------------------------------
#DefineFunction text2pdf(InputFile,OutputFile,FontSize)

FORMFEED = Num2Char(12)
CharactersPerInch = 120.0 / (FontSize + 0.0)
FontSizeInches = (FontSize+0.0) / 72.0

;------------------------------------------------------------------------
;  Read the input file.  Get the length of the longest line
;  Compute the page width in inches.
;------------------------------------------------------------------------
InArray = ArrayFileGet(InputFile)
InTop   = ArrInfo(InArray,1) - 1
LongestLine = 0
MaxLines = 0
PageBreaks = @FALSE
PSize = 0
For x = 0 To InTop
   If StrIndex(InArray[x],FORMFEED,1,@FWDSCAN)
       InArray[x] = FORMFEED
       PageBreaks = @TRUE
       If PSize > MaxLines Then MaxLines = PSize
       PSize = 0
   Else
       PSize = PSize + 1
       L = StrLen(InArray[x])
       If L > LongestLine Then LongestLine = L
   EndIf
Next
If PSize > MaxLines Then MaxLines = PSize

;----------------------------------------------------------------------
;  Compute the actual size page required to hold these lines
;----------------------------------------------------------------------
LineWidthInches =  (LongestLine + 0.0) / CharactersPerInch
PageWidthInches = LineWidthInches + 1.0
PageHeightInches = ((MaxLines + 0.0) * FontSizeInches) + 1
PageHeightPoints = Int(PageHeightInches * 72)

;----------------------------------------------------------------------
;  If there were no page breaks to tell us how long a page is,
;  make a guess.
;   (1) If the font is too big for an 8/5 x 11 page,
;       choose a page big enough to hold a line in this font.
;   (2) Otherwise, if the lines fit on an 8.5" wide page,height=11.
;   (3) If the lines are longer than 8.5", choose a "landscape"
;       style page, height=8.5
;----------------------------------------------------------------------
If !PageBreaks
   If FontSizeInches > 7.5
       PageHeightInches = FontSizeInches + 1
   Else
       If PageWidthInches > 8.5
           PageHeightInches = 8.5
       Else
           PageHeightInches = 11.0
       EndIf
   EndIf
EndIf

;----------------------------------------------------------------------
;  If the page fits inside an 8.5 x 11  (portrait or landscape)
;  round up to 8.5 x 11.   If the height or width is > 11
;  try to make the page proportional to 8.5 x 11 so it will scale
;  niecly for printing.
;----------------------------------------------------------------------
If PageWidthInches <= 8.5 && PageHeightInches <= 11.0
    PageWidthInches = 8.5
    PageHeightInches = 11.0
Else
    If PageWidthInches > 8.5 && PageWidthInches <= 11.0 && PageHeightInches <= 8.5
        PageWidthInches = 11.0
        PageHeightInches = 8.5
    Else
       If PageWidthInches < (8.5 * PageHeightInches) / 11
           PageWidthInches = (8.5 * PageHeightInches) / 11
       Else
           If PageHeightInches < ((8.5 * PageWidthInches) / 11)
               PageHeightInches =  ((8.5 * PageWidthInches) / 11)
           EndIf
       EndIf
    EndIf
EndIf

PageWidthPoints  = Int(PageWidthInches * 72.0)
PageHeightPoints = Int(PageHeightInches * 72.0)
If !PageBreaks Then MaxLines = Int((PageHeightPoints - 72) / FontSize)

TopMargin = Int(PageHeightPoints - (MaxLines * FontSize) + (FontSize * .4375)) / 2
If TopMargin > 72 Then TopMargin = 72
TopOffset = PageHeightPoints - TopMargin + (FontSize * .4375)

;------------------------------------------------------------------------
;  Open the PDF file and write the header records
;------------------------------------------------------------------------
hOUT = FileOpen(OutputFile,"WRITE")
CurrentOffset = 0
text2pdfWriteLine("%%PDF-1.2")
text2pdfWriteLine(StrCat("%%",Num2Char(226),Num2Char(227),Num2Char(207),Num2Char(211)))

xrefOffsetList = ""
CurrentObject = 1
text2pdfNewObject(CurrentObject)
objInfo = CurrentObject
text2pdfWriteLine("<<")
text2pdfWriteLine("/Author ()")
text2pdfWriteLine(StrCat("/CreationDate (D:", StrReplace(TimeYmdHms(),":",""), ")"))
text2pdfWriteLine("/Creator (Text2PDF.wbt)")
text2pdfWriteLine("/Producer (Text2PDF.wbt)")
text2pdfWriteLine("/Title ()")
text2pdfWriteLine("/Subject ()")
text2pdfWriteLine("/Keywords ()")
text2pdfWriteLine(">>")
text2pdfWriteLine("endobj")

CurrentObject = CurrentObject + 1
objRoot = CurrentObject

CurrentObject = CurrentObject + 1
objTpages = CurrentObject

CurrentObject = CurrentObject + 1
objEncoding = CurrentObject
text2pdfNewObject(CurrentObject)
text2pdfWriteLine("<<")
text2pdfWriteLine("/Type /Encoding /BaseEncoding /WinAnsiEncoding")
text2pdfWriteLine(">>")
text2pdfWriteLine("endobj")

CurrentObject = CurrentObject + 1
objFont = CurrentObject
text2pdfNewObject(CurrentObject)
text2pdfWriteLine("<<")
text2pdfWriteLine("/Type /Font")
text2pdfWriteLine("/Subtype /Type1")
text2pdfWriteLine("/Name /F1")
text2pdfWriteLine(StrCat("/Encoding ",objEncoding," 0 R"))
text2pdfWriteLine("/BaseFont /Courier")
text2pdfWriteLine(">>")
text2pdfWriteLine("endobj")

CurrentObject = CurrentObject + 1
objResources = CurrentObject
text2pdfNewObject(CurrentObject)
text2pdfWriteLine("<<")
text2pdfWriteLine(StrCat(" /Font << /F1 ",objFont," 0 R >> /ProcSet [ /PDF /Text ]"))
text2pdfWriteLine(">>")
text2pdfWriteLine("endobj")

;-------------------------------------------------------------------------
;  Read the contents of the page and build the PDF "stream" data.
;  (We do this before we create the stream object, because we need
;   to know the length of this data to create the object.)
;-------------------------------------------------------------------------
xIn = 0
PageNo = 0
PageList = ""
While (xIn <= InTop)
  Stream =  StrCat("BT /F1 ",FontSize," Tf ",FontSize ," TL 36 ",TopOffset," Td",@CRLF)
  LineNbr = 0
  While(xIn <= InTop)
     If InArray[xIn] == FORMFEED
         xIn = xIn + 1
         Break
     EndIf
     LineNbr = LineNbr + 1
     If LineNbr > MaxLines Then Break

     Record = StrTrim(InArray[xIn])
     N = StrIndex(InArray[xIn],Record,1,@FWDSCAN)    ; Trim only spaces to right
     If N > 1 Then Record = StrCat(StrFill(" ",N-1), Record)
     Record = StrReplace(Record,"\","\\")
     Record = StrReplace(Record,"(","\(")
     Record = StrReplace(Record,")","\)")
     Stream=StrCat(Stream,"T*(",Record,"\n)Tj",@CRLF)
     xIn = xIn + 1
  EndWhile

  ;-------------------------------------------------------------------------
  ;  Create a stream object
  ;-------------------------------------------------------------------------
  Stream = StrCat(Stream,"ET")
  CurrentObject = CurrentObject + 1
  objStream = CurrentObject
  text2pdfNewObject(CurrentObject)
  text2pdfWriteLine(StrCat("<< /Length ",StrLen(Stream)," >>"))
  text2pdfWriteLine("stream")
  text2pdfWriteLine(Stream)
  text2pdfWriteLine("endstream")
  text2pdfWriteLine("endobj")

  ;-------------------------------------------------------------------------
  ;  Create a page object that points at the stream
  ;-------------------------------------------------------------------------
  CurrentObject = CurrentObject + 1
  text2pdfNewObject(CurrentObject)
  PageList = ItemInsert(CurrentObject,-1,PageList,@TAB)   ; Remember offset of page objects

  PageNo = PageNo + 1
  text2pdfWriteLine("<<")
  text2pdfWriteLine("/Type /Page")
  text2pdfWriteLine(StrCat("/Parent ",objTpages," 0 R"))
  text2pdfWriteLine(StrCat("/Resources ",objResources," 0 R"))
  text2pdfWriteLine(StrCat("/Contents ",objStream," 0 R"))
  text2pdfWriteLine("/Rotate 0")
  text2pdfWriteLine(">>")
  text2pdfWriteLine("endobj")
EndWhile

Drop(InArray)

;-------------------------------------------------------------------------
; Write a "catalog" object
;-------------------------------------------------------------------------
text2pdfNewObject(objRoot)
text2pdfWriteLine("<<")
text2pdfWriteLine("/Type /Catalog")
text2pdfWriteLine(StrCat("/Pages ",objTpages," 0 R"))
text2pdfWriteLine(">>")
text2pdfWriteLine("endobj")

;-------------------------------------------------------------------------
;  Write the "Pages" object
;-------------------------------------------------------------------------
text2pdfNewObject(objTpages)
text2pdfWriteLine("<<")
text2pdfWriteLine("/Type /Pages")
text2pdfWriteLine(StrCat("/Count ",PageNo))
text2pdfWriteLine(StrCat("/MediaBox [ 0 0 ",PageWidthPoints," ",PageHeightPoints," ]"))
text2pdfWriteLine("/Kids [ ")
For x = 1 To PageNo
    text2pdfWriteLine(StrCat(ItemExtract(x,PageList,@TAB)," 0 R"))
Next
text2pdfWriteLine("]")
text2pdfWriteLine(">>")
text2pdfWriteLine("endobj")

;----------------------------------------------------------------
;  Get the object offset values, in order
;----------------------------------------------------------------
Offset = ArrDimension(CurrentObject+1)
For x = 1 To CurrentObject
   Item = ItemExtract(x,xrefOffsetList,@TAB)
   Ix = ItemExtract(1,Item,":")
   Offset[Ix] = ItemExtract(2,Item,":")
Next

;----------------------------------------------------------------
;  Write the cross reference
;----------------------------------------------------------------
whereXref = CurrentOffset
text2pdfWriteLine("xref")
text2pdfWriteLine(StrCat("0 ",CurrentObject+1))
text2pdfWriteLine("0000000000 65535 f")
For x = 1 To CurrentObject
   text2pdfWriteLine(StrCat(StrFixLeft(Offset[x],"0",10)," 00000 n"))
Next

;-----------------------------------------------------------------
;  write the trailer
;-----------------------------------------------------------------
text2pdfWriteLine("trailer")
text2pdfWriteLine("<<")
text2pdfWriteLine(StrCat("/Size ",CurrentObject+1))
text2pdfWriteLine(StrCat("/Root ",objRoot," 0 R"))
text2pdfWriteLine(StrCat("/Info ",objInfo," 0 R"))
text2pdfWriteLine(">>")
text2pdfWriteLine("startxref")
text2pdfWriteLine(whereXref)
text2pdfWriteLine("%%%%EOF")
FileClose(hOUT)
Return
#EndFunction

Article ID:   W17241
File Created: 2007:07:03:14:28:58
Last Updated: 2007:07:03:14:28:58