ColdFusion, DDX, and PDFs Part 2: Styling a Table of Contents

As promised, experiences from working with Brian Hall on the ECU printable telephone directory.  We knew we want Adobe Acrobat (aka PDF) files to provide a reasonable platform-agnostic method of producing quality printed output.  One of the features that we wanted is a table of contents.  That’s reasonably easy using DDX, and you can see the DDX-101 version mentioned by Adobe and by the ever-popular ColdFusion Jedi .  Beyond the ability to create a table of contents, there’s not much out there about modifying the look and feel.  Hence the excitement when Brian was able to dig up the DDX reference manual.  It turns out that you actually do have control over the style of the table of contents even with the modified LiveCycle support within ColdFusion 9.0.1.

<cfsavecontent variable="myDDX">
<DDX xmlns="http://ns.adobe.com/DDX/1.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://ns.adobe.com/DDX/1.0/ coldfusion_ddx.xsd">
	<PDF result="Out1">
	<TableOfContents includeInTOC="false" bookmarkTitle="Table of Contents">
		<TableOfContentsEntryPattern applicableLevel="all" >
				<p font-family="Times New Roman" font-size="12pt">
					<leader leader-pattern="dotted"/>
		<PDF source="Doc1" />
		<PDF source="Doc2" />
<cfif IsDDX(#myDDX#)>
	<cfset inputStruct = StructNew()>
	<cfset inputStruct.Doc1 = "FirstDocument.pdf">
	<cfset inputStruct.Doc2 = "SecondDocument.pdf">
	<cfset outputStruct = StructNew()>
	<cfset outputStruct.Out1 = "CombinedDocument.pdf">
	<cfpdf action="processddx" ddxfile="#myddx#" inputfiles="#inputStruct#" outputfiles="#outputStruct#" name="ddxVar">
	<cfdump var="#ddxVar#">
	<cfoutput><p>NO, DDX IS NOT OK</p></cfoutput>

Above is a complete snippet, suitable for saving to a CFM file that will run completely. For it to function on your own ColdFusion instance, you’ll need the following:

Given these two files and the above code saved to a ColdFusion cfm file, you’ll get a new file generated called CombinedFile.pdf.  If you open this file with a PDF reader, you’ll see a table of contents page followed by the contents of your two PDFs.  You’ll also see a bookmark called “Table of Contents”.  The table of contents will have entries for your two PDFs; these entries can be clicked and you’ll go directly to that sub-document.

The reason for this blog post is not the part that takes individual PDFs and combines them (you can find that in the Adobe documentation), but the fact that you can actually style the ToC, not just accept the defaults (which for us was a plain-jane Courier font).  The key is discovering the TableOfContentsEntryPattern, leader, _BookmarkTitle, and _BookmarkPageCitation elements.  The TableOfContentsEntryPattern defines how each line in your ToC will look.  Within that is a StyledText element, which is necessary whenever you are using styled text within DDX.  Further, since you’re defining a single instance of an element that gets repeated by the LiveCycle engine, you need markers for the title and page number.  The title is the _BookmarkTitle and the page number is _BookmarkPageCitation.

The leader element is used for producing the stream of periods between the title and page number.  The leader element has a leader-pattern attribute, which can be:

  • space (default)
  • dashed
  • double-dashed
  • triple-dashed
  • solid
  • double
  • triple
  • dotted
  • double-dotted
  • triple-dotted

This valuable information exists only in the DDX reference, without which you’re not going to be able to produce complex formats.

With the font size we were using, we needed a little space after the document title and before the page number.  The oh-so-useful Space element fit the bill exactly.  Finally, we added a couple of optional attributes to the TableOfContents: includeInToc (which means that the table of contents page itself is not included in the ToC) and bookmarkTitle (which is the text used for the bookmark that references the ToC).

Oh, and one final thing: almost all of the DDX examples I found used a file system file containing the DDX.  Big thanks to Raymond Camden for providing examples where cfsavecontext is used to have an inline version.  Make sure that you use the trim function on your context saved variable, or you’ll have (yet another!) instance of where IsDDX() will return false.

In Part 3, there will be additional formatting options we discovered through a combination of trial and error and combing the DDX documentation.  Until then, get some PDFs and have fun playing with these options.