<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Karl Heinz Kremer&#039;s Ramblings &#187; JavaScript</title>
	<atom:link href="http://www.khk.net/wordpress/tag/javascript/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.khk.net/wordpress</link>
	<description>Stuff, stuff and more stuff</description>
	<lastBuildDate>Sun, 25 Sep 2011 18:38:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>Reading PDF Form Fields with VBA</title>
		<link>http://www.khk.net/wordpress/2010/09/23/reading-pdf-form-fields-with-vba/</link>
		<comments>http://www.khk.net/wordpress/2010/09/23/reading-pdf-form-fields-with-vba/#comments</comments>
		<pubDate>Thu, 23 Sep 2010 14:04:12 +0000</pubDate>
		<dc:creator>khk</dc:creator>
				<category><![CDATA[Acrobat]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PDF]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Adobe Acrobat]]></category>
		<category><![CDATA[Form]]></category>
		<category><![CDATA[JSO]]></category>
		<category><![CDATA[vba]]></category>

		<guid isPermaLink="false">http://www.khk.net/wordpress/?p=651</guid>
		<description><![CDATA[I&#8217;ve written about VBA and Acrobat JavaScript before, and I&#8217;ve also mentioned that you can combine VBA and JavaScript to access PDF form fields, but I still owe a sample for that. I had to answer another question today about how to exactly do that, so I whipped up a quick sample program that demonstrates [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.khk.net%2Fwordpress%2F2010%2F09%2F23%2Freading-pdf-form-fields-with-vba%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.khk.net%2Fwordpress%2F2010%2F09%2F23%2Freading-pdf-form-fields-with-vba%2F&amp;source=khkremer&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>I&#8217;ve written about VBA and Acrobat JavaScript <a href="http://www.khk.net/wordpress/2009/03/11/acrobat-javascript-and-vb-walk-into-a-bar/">before</a>, and I&#8217;ve also mentioned that you can combine VBA and JavaScript to access PDF form fields, but I still owe a sample for that. I had to answer another question today about how to exactly do that, so I whipped up a quick sample program that demonstrates the use of the JavaScript Object (JSO) to read and write AcroForm fields.</p>
<p>We start the same way as in my <a href="http://www.khk.net/wordpress/2009/03/04/adobe-acrobat-and-vba-an-introduction/">old VBA sample</a> to create a VBA program that references the Acrobat TLB and to add a button to a document. When we now use the following script as the button handler, we can work with form fields:</p>
<p><pre><pre>Private Sub CommandButton1_Click()
&nbsp;&nbsp;&nbsp;&nbsp;Dim AcroApp As Acrobat.CAcroApp
&nbsp;&nbsp;&nbsp;&nbsp;Dim theForm As Acrobat.CAcroPDDoc
&nbsp;&nbsp;&nbsp;&nbsp;Dim jso As Object
&nbsp;&nbsp;&nbsp;&nbsp;Dim text1, text2 As String
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;Set AcroApp = CreateObject(&quot;AcroExch.App&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;Set theForm = CreateObject(&quot;AcroExch.PDDoc&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;theForm.Open (&quot;C:\temp\sampleForm.pdf&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;Set jso = theForm.GetJSObject
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&#039; get the information from the form fields Text1 and Text2
&nbsp;&nbsp;&nbsp;&nbsp;text1 = jso.getField(&quot;Text1&quot;).Value
&nbsp;&nbsp;&nbsp;&nbsp;text2 = jso.getField(&quot;Text2&quot;).Value
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;MsgBox &quot;Values read from PDF: &quot; &amp; text1 &amp; &quot; &quot; &amp; text2

&nbsp;&nbsp;&nbsp;&nbsp;&#039; set a text field
&nbsp;&nbsp;&nbsp;&nbsp;Dim field2 As Object
&nbsp;&nbsp;&nbsp;&nbsp;Set field2 = jso.getField(&quot;Text2&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;field2.Value = 13&nbsp;&nbsp; &#039; assign the number 13 to the fields value
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;&#039; get the information from the form fields Text1 and Text2
&nbsp;&nbsp;&nbsp;&nbsp;text1 = jso.getField(&quot;Text1&quot;).Value
&nbsp;&nbsp;&nbsp;&nbsp;text2 = jso.getField(&quot;Text2&quot;).Value
&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp;&nbsp;MsgBox &quot;Values read from PDF: &quot; &amp; text1 &amp; &quot; &quot; &amp; text2

&nbsp;&nbsp;&nbsp;&nbsp;theForm.Close
&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;AcroApp.Exit
&nbsp;&nbsp;&nbsp;&nbsp;Set AcroApp = Nothing
&nbsp;&nbsp;&nbsp;&nbsp;Set theForm = Nothing
&nbsp;&nbsp;&nbsp;&nbsp; 
&nbsp;&nbsp;&nbsp;&nbsp;MsgBox &quot;Done&quot;
End Sub
</pre></pre></p>
<p>This program requires a PDF file with text fields called &#8220;Text1&#8243; and &#8220;Text2&#8243; to be stored as C:\temp\sampleForm.pdf. With the explanation in the previous two blog posts, it should not be hard to understand what&#8217;s going on here. The only new command introduced is the getField() function, which returns a form field. The form field object has a property &#8220;value&#8221; which contains the actual value that&#8217;s assigned to the field. Give it a try and let me know how it works for you. The updated form field is not saved (because the document does not get saved) &#8211; I&#8217;ll leave that up to the reader to figure out.</p>
<p>Also, this program will not work with XFA forms (the ones you create in Designer). For those, you need to use the XFA DOM to access the form data. For anybody interested in XFA forms, the <a href="http://help.adobe.com/en_US/livecycle/es/lcdesigner_scripting_reference.pdf">LifeCycle Designer ES Scripting Reference</a> is a must read. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.khk.net/wordpress/2010/09/23/reading-pdf-form-fields-with-vba/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Best Way to Learn Acrobat Scripting</title>
		<link>http://www.khk.net/wordpress/2010/08/18/best-way-to-learn-acrobat-scripting/</link>
		<comments>http://www.khk.net/wordpress/2010/08/18/best-way-to-learn-acrobat-scripting/#comments</comments>
		<pubDate>Wed, 18 Aug 2010 15:25:04 +0000</pubDate>
		<dc:creator>khk</dc:creator>
				<category><![CDATA[Acrobat]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PDF]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[adobe pdf]]></category>
		<category><![CDATA[pdfscripting.com]]></category>
		<category><![CDATA[scripting]]></category>

		<guid isPermaLink="false">http://www.khk.net/wordpress/?p=638</guid>
		<description><![CDATA[Every now and then I come across the question &#8220;What is the best way to learn scripting for Adobe Acrobat? Are there any books or other resources averrable?&#8221;. After doing some research, I think I finally found the best resource for beginners and for seasoned Acrobat JavaScript programmers that need a quick tip or a [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.khk.net%2Fwordpress%2F2010%2F08%2F18%2Fbest-way-to-learn-acrobat-scripting%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.khk.net%2Fwordpress%2F2010%2F08%2F18%2Fbest-way-to-learn-acrobat-scripting%2F&amp;source=khkremer&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>Every now and then I come across the question &#8220;What is the best way to learn scripting for Adobe Acrobat? Are there any books or other resources averrable?&#8221;. After doing some research, I think I finally found the best resource for beginners and for seasoned Acrobat JavaScript programmers that need a quick tip or a recipe to copy&amp;paste into a project:</p>
<p><a href="http://www.pdfscripting.com/">PDFScripting.com</a></p>
<p>The site offers content for both paying members and the general public. If you are new to scripting, and you don&#8217;t want to spend the money for a membership (yet), take a look at the free content at ﻿<a href="http://www.pdfscripting.com/public/department40.cfm">http://www.pdfscripting.com/public/department40.cfm</a> &#8211; it walks you through creating your first AcroForm script, but also offers a number of videos that explain more complicated concepts. For the really good stuff however, you have to pay.</p>
<p>Ever wondered how to hook up a PDF form with an Excel spread sheet? Wonder no more! The article series &#8220;<a href="http://www.pdfscripting.com/members/department48.cfm">Acrobat, PDF and Excel Spreadsheets</a>&#8221; teaches you more than you ever wanted to know about that subject.</p>
<p>You may remember my post about <a href="http://www.khk.net/wordpress/2009/05/31/more-interactive-dynamic-stamps-in-seven-easy-steps/">dynamic stamps in Acrobat</a>. The PDFScripting.com site has a lot more information about dynamic forms and provides a number of <a href="http://www.pdfscripting.com/public/images/Video/PDFStampsGoneWild.cfm">very interesting samples</a> (video link).</p>
<p>There is a ton more information available for both AcroForm and LiveCycle Designer scripting. This information comes in form of articles, videos, a copy&amp;paste script library and downloadable sample files that illustrate a subject.</p>
<p>To get familiar with the web site, Thom Parker has recorded a video tour that helps to navigate the site, but also gives a pretty good overview about what&#8217;s available both for free and for paying members at &#8220;﻿<a href="http://www.pdfscripting.com/public/images/video/PDFSTour.cfm">Take a tour of the PDFScripting.com website!</a>&#8221; (video link).</p>
<p>So, no need to ask me for a good Acrobat scripting resource anymore, just go to PDFScripting.com and sign up for a year &#8211; it&#8217;s well worth the membership fee (and as Thom says in his tour video, no surprise at the end of the year, the membership does not automatically renew).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.khk.net/wordpress/2010/08/18/best-way-to-learn-acrobat-scripting/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Developing Acrobat JavaScript on a MacBook</title>
		<link>http://www.khk.net/wordpress/2010/03/23/javascript-console/</link>
		<comments>http://www.khk.net/wordpress/2010/03/23/javascript-console/#comments</comments>
		<pubDate>Tue, 23 Mar 2010 17:58:20 +0000</pubDate>
		<dc:creator>khk</dc:creator>
				<category><![CDATA[Acrobat]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[PDF]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[adobe pdf]]></category>
		<category><![CDATA[development]]></category>

		<guid isPermaLink="false">http://www.khk.net/wordpress/?p=624</guid>
		<description><![CDATA[Acrobat&#8217;s JavaScript is a great tool to extend the application, or to automate reoccurring tasks. There are several ways a JavaScript can be added to the application or a document (e.g. folder level scripts, validation scripts, event handling scripts, &#8230;), but regardless of how a script is written, chances are that the developer wants to [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.khk.net%2Fwordpress%2F2010%2F03%2F23%2Fjavascript-console%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.khk.net%2Fwordpress%2F2010%2F03%2F23%2Fjavascript-console%2F&amp;source=khkremer&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>Acrobat&#8217;s JavaScript is a great tool to extend the application, or to automate reoccurring tasks. There are several ways a JavaScript can be added to the application or a document (e.g. folder level scripts, validation scripts, event handling scripts, &#8230;), but regardless of how a script is written, chances are that the developer wants to test parts of the script in Acrobat&#8217;s Javascript console. This console window can be shown by either using the &#8220;Advanced>Document Processing>JavaScript Debugger&#8230;&#8221; menu item or Ctrl-J on Windows or Cmd-J on a Mac:</p>
<div style="text-align:center;"><img src="http://www.khk.net/wordpress/wp-content/uploads/2010/03/BlogPicsJS_Menu.png" alt="JS_Menu.png" border="0" width="400" /></div>
<p>After the console or debugger window comes up, the user can then enter Javascript and execute it&#8230; </p>
<div style="text-align:center;"><img src="http://www.khk.net/wordpress/wp-content/uploads/2010/03/BlogPicsJS_Debugger.png" alt="JS_Debugger.png" border="0" width="500" /></div>
<p>&#8230; that is, as long as a full keyboard with a numeric keypad is used. In Adobe&#8217;s documentation, we find the following <a href="http://livedocs.adobe.com/acrobat_sdk/9.1/Acrobat9_1_HTMLHelp/JS_Dev_Tools.72.4.html">instructions to execute Javascript typed into the console window</a>:</p>
<p>
The JavaScript console allows you to evaluate single or multiple lines of code. There are three ways to evaluate JavaScript code while using the interactive console:</p>
<ul>
<li>To evaluate a portion of a line of code, highlight the portion and press either the Enter key on the numeric keypad or press Ctrl + Enter.</li>
<li>To evaluate a single line of code, make sure the cursor is positioned on that line and press either the Enter key on the numeric keypad or press Ctrl + Enter.</li>
<li>To evaluate multiple lines of code, highlight those lines and press either the Enter key on the numeric keypad or press Ctrl + Enter.</li>
</ul>
<p>That works fine as long as you have access to the numeric keypad, but on a MacBook or a MacBook Pro without that keypad. No key combination involving fn, ctrl, cmd or option with the Return or Enter key will result in the Javascript getting executed. </p>
<p>The virtual keyboard to the rescue: Mac OS comes with a handy keyboard viewer that allows us to send the correct key code to the application. To bring up the keyboard viewer, bring up the Mac OS System Preferences first and select the &#8220;Keyboard&#8221; category:</p>
<div style="text-align:center;"><img src="http://www.khk.net/wordpress/wp-content/uploads/2010/03/BlogPicsKeyboardViewer_1.png" alt="KeyboardViewer_1.png" border="0" width="500" /></div>
<p>Make sure that the option &#8220;Show Keyboard &#038; Character Viewer in menu bar&#8221; is selected. Once this is done, you can access the keyboard viewer from the menu bar:</p>
<div style="text-align:center;"><img src="http://www.khk.net/wordpress/wp-content/uploads/2010/03/BlogPicsKeyboardViewer_2.png" alt="KeyboardViewer_2.png" border="0" width="244" height="118" /></div>
<p>Now comes the tricky part: Write some Javascript in the console window and place the cursor on the line you want to execute or select the snippet of the Javascript that should be executed. In the following example I&#8217;m using code from <a href="http://livedocs.adobe.com/acrobat_sdk/9.1/Acrobat9_1_HTMLHelp/JS_API_AcroJS.88.151.html">Adobe&#8217;s Javascript API documentation</a>:</p>
<p><pre><pre>
&nbsp;&nbsp;var menuItems = app.listMenuItems()
&nbsp;&nbsp;for( var i in menuItems)
&nbsp;&nbsp;&nbsp;&nbsp;console.println(menuItems[i] + &quot;\n&quot;)
</pre></pre></p>
<p>With the console prepped, bring up the keyboard viewer and start pushing keys &#8211; real keys that is: Hold down the &#8220;fn&#8221; and the &#8220;control&#8221; key, then move the mouse pointer to the &#8220;Enter&#8221; key on the keyboard viewer and click it&#8230;</p>
<div style="text-align:center;"><img src="http://www.khk.net/wordpress/wp-content/uploads/2010/03/BlogPicsJS_Debugger_6.png" alt="JS_Debugger_6.png" border="0" width="500" /></div>
<p>&#8230; and voila, the script gets executed:</p>
<div style="text-align:center;"><img src="http://www.khk.net/wordpress/wp-content/uploads/2010/03/BlogPicsJS_Debugger_7.png" alt="JS_Debugger_7.png" border="0" width="500"/></div>
<p>This is not the most straight forward method, but at least it&#8217;s possible to use the Javascript console to execute code when using a MacBook. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.khk.net/wordpress/2010/03/23/javascript-console/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>More Interactive Dynamic Stamps in Seven Easy Steps</title>
		<link>http://www.khk.net/wordpress/2009/05/31/more-interactive-dynamic-stamps-in-seven-easy-steps/</link>
		<comments>http://www.khk.net/wordpress/2009/05/31/more-interactive-dynamic-stamps-in-seven-easy-steps/#comments</comments>
		<pubDate>Sun, 31 May 2009 23:47:23 +0000</pubDate>
		<dc:creator>khk</dc:creator>
				<category><![CDATA[Acrobat]]></category>
		<category><![CDATA[PDF]]></category>
		<category><![CDATA[dynamic stamp]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://khk.net/wordpress/?p=466</guid>
		<description><![CDATA[A while ago I tried to create an interactive dynamic stamp in Acrobat. These are dynamic stamps (like for example a stamp that automatically puts the current date into a field that is part of the stamp), but with a UI component that pops up and queries the user for some information that also gets [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.khk.net%2Fwordpress%2F2009%2F05%2F31%2Fmore-interactive-dynamic-stamps-in-seven-easy-steps%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.khk.net%2Fwordpress%2F2009%2F05%2F31%2Fmore-interactive-dynamic-stamps-in-seven-easy-steps%2F&amp;source=khkremer&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>A while ago I tried to create an interactive dynamic stamp in Acrobat. These are dynamic stamps (like for example a stamp that automatically puts the current date into a field that is part of the stamp), but with a UI component that pops up and queries the user for some information that also gets embedded as part of the stamp (e.g. a phone number or a name).</p>
<p>I was not very successful. I could not figure out how to make sure that the UI only gets triggered when the stamp gets applied, and not when the stamp file gets loaded by Acrobat.</p>
<p><span id="more-466"></span></p>
<p>Then I came across an article by Rick Borstein titled &#8220;<a href="http://blogs.adobe.com/acrolaw/2009/05/add_dynamic_exhibit_stamps_in_ac.html">Add Dynamic Exhibit Stamps in Acrobat using a free stamp set</a>&#8221; on the <a href="http://blogs.adobe.com/acrolaw/">Acrobat for Legal Professionals blog</a>. It had all the parts that are required, it even came with a couple of sample stamps. It also gave credit to the original source for that information: Acrobat JavaScript Guru <a href="http://www.acrobatusers.com/tutorials/2007/02/dynamic_stamp_secrets">Thom Parker</a></p>
<p>Thom provides all the theory behind why this works &#8211; very interesting to read if you are into that kind of stuff. It&#8217;s however not required to understand all that if you just want to use these stamps. You can just download Rick&#8217;s sample files and modify them until they fit your needs.</p>
<p>However if you want a dynamic stamp that shows more than just one line of interactively provided information, the examples do not work. They only provide one one-line input field and then put that one line on the PDF document. I wanted a stamp that could actually take several lines of user input and use that in a stamp. I had some work to do&#8230;</p>
<p>Acrobat&#8217;s JavaScript does allow to create custom user interfaces by creating a data structure and then calling executeDialog() with that data as parameter. Instead of a simple call to app.response() like in Thom&#8217;s and Rick&#8217;s examples, I needed to create a more complicated UI structure and embed that in the examples.</p>
<p>Here is the original code from the example:<br />
<pre><pre>var cAsk = &quot;Enter Exhibit Number&quot; ;
var cTitle = &quot;Exhibit Number:&nbsp;&nbsp;&quot;;
if(event.source.forReal &amp;amp;&amp;amp; (event.source.stampName == &quot;#UdzyXagRctZoS5p43TZ43C&quot;))
{
&nbsp;&nbsp;var cMsg = app.response(cAsk, cTitle);
&nbsp;&nbsp;event.value = cMsg;
&nbsp;&nbsp;event.source.source.info.exhibit = cMsg;
}</pre></pre><br />
I&#8217;ve replaced that code with the following:<br />
<pre><pre>var dialog = {
&nbsp;&nbsp;retString: &quot;&quot;,

&nbsp;&nbsp;commit:function (dialog) { // called when OK pressed
&nbsp;&nbsp;&nbsp;&nbsp;var results = dialog.store();
&nbsp;&nbsp;&nbsp;&nbsp;this.retString = results[&quot;stxt&quot;];
&nbsp;&nbsp;},

&nbsp;&nbsp;description:
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;name: &quot;Stamp Information&quot;,&nbsp;&nbsp;&nbsp;&nbsp;// Dialog box title
&nbsp;&nbsp;&nbsp;&nbsp;elements:
&nbsp;&nbsp;&nbsp;&nbsp;[
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;type: &quot;view&quot;,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;elements:
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name: &quot;Enter Multi-line Information: &quot;,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;type: &quot;static_text&quot;,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;item_id: &quot;stxt&quot;,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;type: &quot;edit_text&quot;,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;multiline: true,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;width: 300,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;height: 80
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;type: &quot;ok_cancel&quot;,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ok_name: &quot;Ok&quot;,
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cancel_name: &quot;Cancel&quot;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;]
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;},
&nbsp;&nbsp;&nbsp;&nbsp;]
&nbsp;&nbsp;}
}; 

if(event.source.forReal &amp;amp;&amp;amp; (event.source.stampName == &quot;#UdzyXagRctZoS5p43TZ43C&quot;))
{
&nbsp;&nbsp;if (&quot;ok&quot; == app.execDialog(dialog))
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;var cMsg = dialog.retString;
&nbsp;&nbsp;&nbsp;&nbsp;event.value = cMsg;
&nbsp;&nbsp;&nbsp;&nbsp;event.source.source.info.exhibit = cMsg;
&nbsp;&nbsp;}
}</pre></pre><br />
And here are the instructions to change the first stamp in Rick&#8217;s example to the new style:</p>
<ol>
<li>Open the &#8220;Exhibit+Stamp.pdf&#8221; document in Adobe Acrobat Pro</li>
<li>Go to the second page in this document &#8211; that&#8217;s the first stamp</li>
<li>Select the TouchUp Object Tool (e.g. via Tools&gt;Advanced Editing&gt;TouchUp Object Tool)</li>
<li>Right-click on the lower part of the stamp (where the UserData1 field) and select Properties&#8230; from the menu</li>
<li>Select the Options tab and check the &#8220;Multi-line&#8221; checkbox</li>
<li>Select the Calculate tab and click on the Edit button next to the custom calculation script and replace the old script with the one from above</li>
<li>Save the script with the OK button, then close the properties dialog</li>
</ol>
<p>That&#8217;s it &#8211; just install the stamp file as described in Rick&#8217;s document. Done.</p>
<p>Of will of course be hard to see two or more lines in the relatively small stamp, so you may have to change the layout of the stamp to actually make use of the additional lines.f</p>
]]></content:encoded>
			<wfw:commentRss>http://www.khk.net/wordpress/2009/05/31/more-interactive-dynamic-stamps-in-seven-easy-steps/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Splitting PDF Pages</title>
		<link>http://www.khk.net/wordpress/2009/03/30/splitting-pdf-pages/</link>
		<comments>http://www.khk.net/wordpress/2009/03/30/splitting-pdf-pages/#comments</comments>
		<pubDate>Tue, 31 Mar 2009 02:23:49 +0000</pubDate>
		<dc:creator>khk</dc:creator>
				<category><![CDATA[Acrobat]]></category>
		<category><![CDATA[PDF]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Scanned pages]]></category>

		<guid isPermaLink="false">http://khk.net/wordpress/?p=306</guid>
		<description><![CDATA[No, this is not about my patent pending idea of a sheet splitter that turns duplex documents into simplex documents&#8230; This post is about a problem that comes up every now and then: When you scan a book or a magazine, chances are that you end up with two physical pages on your scanned image, [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.khk.net%2Fwordpress%2F2009%2F03%2F30%2Fsplitting-pdf-pages%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.khk.net%2Fwordpress%2F2009%2F03%2F30%2Fsplitting-pdf-pages%2F&amp;source=khkremer&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>No, this is not about my patent pending idea of a sheet splitter that turns  duplex documents into simplex documents&#8230; This post is about a problem that comes up every now and then: When you scan a book or a magazine, chances are that you end up with two physical pages on your scanned image, and your document looks something like this:</p>
<div style="text-align: center;"><img src="http://khk.net/wordpress/wp-content/uploads/2009/03/joinedpages.png" border="0" alt="JoinedPages.png" width="200" /></div>
<p>Pages one and two are on the same scan, three and four are, and five and six and so on.</p>
<p>How can we split such a combined page into it&#8217;s two parts?</p>
<p>There are of course different solutions to this problem, some more complicated than others, some producing better results than others.</p>
<p>The most straight forward approach would be to write an Acrobat plug-in or a standalone application (e.g. using the iText library) that takes the source page, determines what needs to be copied to the new page that should represent the left half of the original page, and then just copy those page elements. With a scanned source document, this would potentially mean that the scanned image needs to be cropped and placed on the target page. Sounds complicated, and it is complicated. Is there an easier way to accomplish the same results?</p>
<p>[More after the jump]</p>
<p><span id="more-306"></span>If we have access the Acrobat, we can use JavaScript to mimic the behavior of the just described application. With Acrobat&#8217;s JavaScript, we do of course not have access to the page content elements, so we need to find a different way to end up with the same results.</p>
<p>JavaScript gives us access to the crop box of a PDF page (if you don&#8217;t know what that is, read up on page boxes in the <a href="http://www.adobe.com/devnet/pdf/pdf_reference.html">PDF Reference</a>), this means we can find out how big a page is, but also set the crop box to configure which part of the page should be displayed in the viewer, or should get printed.</p>
<p>So, if our combined page is 11&#215;17&#8243;, and we want to extract two 8 1/2&#215;11&#8243; pages, we first need to &#8220;select&#8221; the left half of the page, and then the right half of the same page.</p>
<p>Here is the script that will do just that:<br />
<a title="SplitPages.js" href="http://khk.net/wordpress/wp-content/uploads/2009/03/splitpages.js">SplitPages.js</a></p>
<p>Copy that file to the Acrobat JavaScript directory &#8211; for Acrobat 9 on a Windows machine that would be<br />
<pre>c:\Program Files\Adobe\Acrobat 9.0\Acrobat\JavaScript</pre><br />
Now let&#8217;s take a look at the different parts of the script:<br />
<pre><code>ProcessDocument = app.trustedFunction(function()
{
// create a new document
app.beginPriv();
var newDoc = app.newDoc();
app.endPriv();</code></pre><br />
This snippet shows that we are declaring a trusted function. This is necessary because we need to execute the app.newDoc() method, which requires (since Acrobat 7) a privileged context. The first thing we do in this script is to create that new document &#8211; the call is wrapped with the beginPriv() and endPriv() calls. When creating a new document in JavaScript, the document is no only created, Acrobat will also add a page to that document. We don&#8217;t need that page, but every PDF document that is getting displayed in Acrobat, needs at least one PDF page. We will deal with that extra page later.</p>
<p><pre><pre>
var i = 0;
while (i &lt; this.numPages)
{
&nbsp;&nbsp;newDoc.insertPages( {
&nbsp;&nbsp;nPage: newDoc.numPages-1,
&nbsp;&nbsp;cPath: this.path,
&nbsp;&nbsp;nStart: i
});
newDoc.insertPages( {
&nbsp;&nbsp;nPage: newDoc.numPages-1,
&nbsp;&nbsp;cPath: this.path,
&nbsp;&nbsp;nStart: i
});
// we did this twice so that we can then split each copy of the page into a left
// and right half.
i++;
}
</pre></pre></p>
<p>In these few lines we copy every page from the source document (this.path, which is the path to the active document) to our newly created document &#8211; and we are doing that twice. This is necessary because we need to crop out the left half of the page for the first page, and the right half of the page for the second page. After this loop, we will have twice as many pages in our new document than we have in our source document.</p>
<p><pre><pre>
if (newDoc.numPages &gt; 1)
{
&nbsp;&nbsp;newDoc.deletePages(0);&nbsp;&nbsp;// this gets rid of the page that was created with the newDoc call.
}
</pre></pre></p>
<p>Now that we have all the pages in our new document, we no longer need the blank page we got when we created the document. So, we delete it.</p>
<p><pre><code>// at this point we have a documnent with every page from the source document
// copied twice</code></pre></p>
<p><code> </code></p>
<p><pre><pre> for (i=0; i&lt;newDoc.numPages; i++)
{
&nbsp;&nbsp;// determine the crop box of the page
&nbsp;&nbsp;var cropRect = newDoc.getPageBox(&quot;Crop&quot;, i);
&nbsp;&nbsp;var halfWidth = (cropRect[2]-cropRect[0])/2;
</pre></pre><br />
We loop over all pages in our new document (that is twice the number of pages in the original document). And for every page we get the crop box. We also calculate a value that we will need later: The half of the width of that page. That is the location where the page will get split.</p>
<p><pre><code>var cropLeft = new Array();
cropLeft[0] = cropRect[0];
cropLeft[1] = cropRect[1];
cropLeft[2] = cropRect[0] + halfWidth;
cropLeft[3] = cropRect[3];</code></pre></p>
<p>The previous few lines create a new Array. A page box is represented as an array of four values. We can now assign the partially modified values to the new page box. As you can see, three of the four values just are copies of the original crop box. Array element 2 however gets modified. It is the original X value for the lower left point of the crop box, and we add half of our page width to that number. This means, the new right edge of the modified page box is now at the halfway point between the two sides.</p>
<p><pre><code>var cropRight = new Array();
cropRight[0] = cropRect[2] - halfWidth;
cropRight[1] = cropRect[1];
cropRight[2] = cropRect[2];
cropRight[3] = cropRect[3];</code></pre><br />
We do something similar for the new crop box for the right side of the page.</p>
<p><pre><code>if (i%2 == 0)
{
&nbsp;&nbsp;newDoc.setPageBoxes( {
&nbsp;&nbsp;cBox: &quot;Crop&quot;,
&nbsp;&nbsp;nStart: i,
&nbsp;&nbsp;rBox: cropLeft
});
}
else
{
&nbsp;&nbsp;newDoc.setPageBoxes( {
&nbsp;&nbsp;cBox: &quot;Crop&quot;,
&nbsp;&nbsp;nStart: i,
&nbsp;&nbsp;rBox: cropRight
});
}
}
}
)</code></pre></p>
<p>This is a bit tricky&#8230; Acrobat starts to count pages with page 0. The first page in the document is on the left half of our first sheet. All of a sudden, our first page is actually an even page number (0), and not like in &#8220;normal&#8221; books an odd number (1). This means that for all even numbers we need to crop the left half, and for all odd numbers we need to crop the right half.</p>
<p>We test for &#8220;evenness&#8221; by performing the modulo operation on our page number. If the result is 0, we know we have an even number, so we can use the left side crop box. If the operation returns 1, we are dealing with an odd page number, and we will use the ride side crop box.</p>
<p>The new crop box gets applied with the doc.setPageBoxes() method.</p>
<p><pre><code>// add the menu item
app.addMenuItem({
&nbsp;&nbsp;cName: &quot;splitPagesJS&quot;,&nbsp;&nbsp;&nbsp;&nbsp; // this is the internal name used for this menu item
&nbsp;&nbsp;cUser: &quot;Split Pages&quot;,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // this is the label that is used to display the menu item
&nbsp;&nbsp;cParent: &quot;Document&quot;,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// this is the parent menu. The file menu would use &quot;File&quot;
&nbsp;&nbsp;cExec: &quot;ProcessDocument()&quot;,&nbsp;&nbsp;// this is the JavaScript code to execute when this menu item is selected
&nbsp;&nbsp;cEnable: &quot;event.rc = (event.target != null);&quot;,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // when should this menu item be active?
&nbsp;&nbsp;nPos: 0
});</code></pre></p>
<p><code> </code></p>
<p>Almost done&#8230; We&#8217;ve implemented the functionality to split the pages, now we just need a mechanism to actually start our little program. I&#8217;ve chosen to create a menu item under the &#8220;Document&#8221; menu. That menu item is only available (not grayed out), if we have an active document.</p>
<p>Disclaimer: Of course, there is no such thing as a sheet splitter, and therefore there is no patent application. It&#8217;s a joke.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.khk.net/wordpress/2009/03/30/splitting-pdf-pages/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>Acrobat, JavaScript and VB walk into a bar&#8230;</title>
		<link>http://www.khk.net/wordpress/2009/03/11/acrobat-javascript-and-vb-walk-into-a-bar/</link>
		<comments>http://www.khk.net/wordpress/2009/03/11/acrobat-javascript-and-vb-walk-into-a-bar/#comments</comments>
		<pubDate>Thu, 12 Mar 2009 00:37:36 +0000</pubDate>
		<dc:creator>khk</dc:creator>
				<category><![CDATA[Acrobat]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PDF]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Acrobat SDK]]></category>
		<category><![CDATA[Adobe Acrobat]]></category>
		<category><![CDATA[VB]]></category>

		<guid isPermaLink="false">http://khk.net/wordpress/?p=256</guid>
		<description><![CDATA[OK, let&#8217;s just forget about that old joke and concentrate on how to combine all three into something that is quite useful. As I&#8217;ve described in one of my previous posting, it is quite easy to automate Acrobat from VB or VBA. So how does JavaScript fit into this picture? As you may know, Acrobat [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.khk.net%2Fwordpress%2F2009%2F03%2F11%2Facrobat-javascript-and-vb-walk-into-a-bar%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.khk.net%2Fwordpress%2F2009%2F03%2F11%2Facrobat-javascript-and-vb-walk-into-a-bar%2F&amp;source=khkremer&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>OK, let&#8217;s just forget about that old joke and concentrate on how to combine all three into something that is quite useful.</p>
<p>As I&#8217;ve described in one of my <a href="http://khk.net/wordpress/2009/03/04/adobe-acrobat-and-vba-an-introduction/">previous posting</a>, it is quite easy to automate Acrobat from VB or VBA. So how does JavaScript fit into this picture? As you may know, Acrobat comes with a very powerful JavaScript engine that provides access to a lot of functionality &#8211; more functions actually than what you have access to from your VB program. So, if you want to access some of these features, but you are stuck with VB, how can you do that?</p>
<p>Adobe provides a VB/JavaScript bridge with Acrobat &#8211; the JSObject, and the <a href="http://livedocs.adobe.com/acrobat_sdk/9/Acrobat9_HTMLHelp/IAC_DevApp_OLE_Support.100.13.html">Acrobat SDK describes how to use that feature</a>.</p>
<p>There is quite a bit of good information in the documentation. When you access the online documentation, expand the tree to &#8220;Acrobat Interapplication Communication > Developing Applications Using Interapplication Communication > Using OLE > Using the JSObject interface&#8221;.</p>
<p><H3>JavaScript</H3></p>
<p>In this example, I want to illustrate how you can create a folder level JavaScript function, instantiate the JSObject, and then call the custom function and display the result in VB. My plan was to use the <a href="http://khk.net/wordpress/2009/03/11/counting-bookmarks/">JavaScript code from my last posting</a>, but I found one small problem in the way I wrote the code (it works fine as a standalone JavaScript program, but we cannot use it in the VB context), so here is it&#8217;s replacement:</p>
<p><pre><pre>
function CountBookmarks(bkm, nLevel)
{
&nbsp;&nbsp;&nbsp;&nbsp;var count = 0;
&nbsp;&nbsp;&nbsp;&nbsp;if (bkm.children != null)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;count = bkm.children.length;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for (var i = 0; i &lt; bkm.children.length; i++)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; count += CountBookmarks(bkm.children[i], nLevel + 1);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;return count;
}

function CountAllBookmarks()
{
&nbsp;&nbsp;&nbsp;&nbsp;console.clear(); console.show();
&nbsp;&nbsp;&nbsp;&nbsp;var n = CountBookmarks(this.bookmarkRoot, 0);
&nbsp;&nbsp;&nbsp;&nbsp;console.println(&quot;Number of bookmarks found: &quot; + n);

&nbsp;&nbsp;&nbsp;&nbsp;return n;
}

// add the menu item
app.addMenuItem({
&nbsp;&nbsp;&nbsp;&nbsp; cName: &quot;countBookmarks&quot;,
&nbsp;&nbsp;&nbsp;&nbsp; cUser: &quot;Count Bookmarks&quot;,
&nbsp;&nbsp;&nbsp;&nbsp; cParent: &quot;Document&quot;,
&nbsp;&nbsp;&nbsp;&nbsp; cExec: &quot;CountAllBookmarks();&quot;,
&nbsp;&nbsp;&nbsp;&nbsp; cEnable: &quot;event.rc = (event.target != null);&quot;
});

</pre></pre> </p>
<p>Save this JavaScript program as a folder level JavaScript file and make sure that it works.</p>
<p>So, why can&#8217;t we just implement the whole algorithm with the JSObject? The problem is with how VB handles objects that are actually JavaScript objects &#8211; in this case the root bookmark object. I cannot figure out how to access it&#8217;s &#8220;children&#8221; property through the JSObject. That&#8217;s the reason why I&#8217;m &#8220;cheating&#8221; by calling our custom JavaScript function &#8211; being able to do that is pretty cool IMHO.</p>
<p><H3>The VB Part</H3></p>
<p>We start out just like with any other VB program, by declaring some objects, initializing them and then it gets interesting&#8230;</p>
<p>Here is some sample code that shows how to initialize the JSObject, and how to call our own JavaScript function.  </p>
<p>Create a button on an Excel spreadsheet again, and put the following code into the button handler callback (just like before). </p>
<p><pre><pre>
Dim gApp As Acrobat.CAcroApp
Dim gPDDoc As Acrobat.CAcroPDDoc
Dim jso As Object

Sub Button1_Click()
&nbsp;&nbsp;&nbsp;&nbsp;Set gApp = CreateObject(&quot;AcroExch.App&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;Set gPDDoc = CreateObject(&quot;AcroExch.PDDoc&quot;)
&nbsp;&nbsp;&nbsp;&nbsp;If gPDDoc.Open(&quot;c:\temp\test.pdf&quot;) Then
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set jso = gPDDoc.GetJSObject
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MsgBox (jso.CountAllBookmarks())
&nbsp;&nbsp;&nbsp;&nbsp;End If
End Sub
</pre></pre></p>
<p>Now just make sure that you have a file c:\temp\test.pdf that has some bookmarks in it. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.khk.net/wordpress/2009/03/11/acrobat-javascript-and-vb-walk-into-a-bar/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Counting Bookmarks</title>
		<link>http://www.khk.net/wordpress/2009/03/11/counting-bookmarks/</link>
		<comments>http://www.khk.net/wordpress/2009/03/11/counting-bookmarks/#comments</comments>
		<pubDate>Thu, 12 Mar 2009 00:17:42 +0000</pubDate>
		<dc:creator>khk</dc:creator>
				<category><![CDATA[Acrobat]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PDF]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Adobe Acrobat]]></category>

		<guid isPermaLink="false">http://khk.net/wordpress/?p=251</guid>
		<description><![CDATA[Let&#8217;s assume you have a PDF document, and you want to know how many bookmarks you have in that document, how would you approach that? The JavaScript API has methods to traverse the bookmark tree. Here is a short program that &#8211; once installed in Acrobat&#8217;s JavaScript folder &#8211; will add a menu item &#8220;Count [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: left; margin-right: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.khk.net%2Fwordpress%2F2009%2F03%2F11%2Fcounting-bookmarks%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.khk.net%2Fwordpress%2F2009%2F03%2F11%2Fcounting-bookmarks%2F&amp;source=khkremer&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>Let&#8217;s assume you have a PDF document, and you want to know how many bookmarks you have in that document, how would you approach that? </p>
<p>The JavaScript API has methods to traverse the bookmark tree. Here is a short program that &#8211; once installed in Acrobat&#8217;s JavaScript folder &#8211; will add a menu item &#8220;Count Bookmarks&#8221; to the &#8220;Document&#8221; menu, and when executed will print the number of bookmarks encountered in the JavaScript console.</p>
<p><pre><pre>
function CountBookmarks(bkm, nLevel)
{
&nbsp;&nbsp;&nbsp;&nbsp;var count = 0;
&nbsp;&nbsp;&nbsp;&nbsp;if (bkm.children != null)
&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;count = bkm.children.length;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for (var i = 0; i &lt; bkm.children.length; i++)
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; count += CountBookmarks(bkm.children[i], nLevel + 1);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
&nbsp;&nbsp;&nbsp;&nbsp;}

&nbsp;&nbsp;&nbsp;&nbsp;return count;
}

function DoIt()
{
&nbsp;&nbsp;&nbsp;&nbsp;console.clear(); console.show();
&nbsp;&nbsp;&nbsp;&nbsp;var n = CountBookmarks(this.bookmarkRoot, 0);
&nbsp;&nbsp;&nbsp;&nbsp;console.println(&quot;Number of bookmarks found: &quot; + n);
}

// add the menu item
app.addMenuItem({
&nbsp;&nbsp;&nbsp;&nbsp; cName: &quot;countBookmarks&quot;,
&nbsp;&nbsp;&nbsp;&nbsp; cUser: &quot;Count Bookmarks&quot;,
&nbsp;&nbsp;&nbsp;&nbsp; cParent: &quot;Document&quot;,
&nbsp;&nbsp;&nbsp;&nbsp; cExec: &quot;DoIt();&quot;,
&nbsp;&nbsp;&nbsp;&nbsp; cEnable: &quot;event.rc = (event.target != null);&quot;
});

</pre></pre></p>
<p>Save this program in a file in e.g. C:\Program Files\Adobe\Acrobat 9.0\Acrobat\Javascripts (for Acrobat 9) and restart Acrobat. You should now find a new menu item in the Document menu. Load a file with bookmarks in it, and execute the menu item. </p>
<p>I have not implemented the privileged execution context that is required to make this work in all instances, so you  have to go into your JavaScript preferences in Acrobat and check the setting for &#8220;Enable menu items JavaScript execution privileges&#8221;:</p>
<div style="text-align:center;"><img src="http://khk.net/wordpress/wp-content/uploads/2009/03/preferencesjavascript.png" alt="PreferencesJavaScript.png" border="0" width="300" /></div>
]]></content:encoded>
			<wfw:commentRss>http://www.khk.net/wordpress/2009/03/11/counting-bookmarks/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

