Posts in Category "Acrobat"

Compiling a PDF Portfolio in LiveCycle

Situation:

How to merge multiple PDFs (retreived from a Database BLOB) and compile them using DDX and LiveCycle (ADEP). The portfolio will build based on the number of documents stored inside the database.

In this situation we will be compiling a Cover Page, Content Document(s), and a Final Document. Depending on the workflow state, there could be 0-5 documents in the database under the Content Document(s) section. The process is flexible enough to handle this.

Create the DDX File:

  1. Start by looking at the Assembly Descriptor documentation and DDX Reference Guide.
  2. In Workbench: Create a New Application (File>New>Application)
  3. Inside the Application directory, create a new folder and name it Assets.
  4. Locate the Acrobat .nav File you want to use. It will be located on your filesystem here: [Acrobat Location]\Acrobat\Navigators. For this situation AdobeRevolve.nav is being used. Import the .nav file into your Application’s Assets folder.
  5. Create a DDX file
    1. Right Click on Asset Folder> New > Assembly Descriptor.
    2. Provide a name for the DDX document.
    3. Click Finish.
    4. The Document Builder Window should come up inside Workbench
  6. The DDX File in the End will look like this:
    1. Start by Selecting New Result>PDF and Name it CompiledPDF
    2. Drag the Portfolio Component Under the CompiledPDF
    3. Under the Portfolio Editor paste the following elements:
      <Portfolio>
        <ColorScheme scheme="darkblueScheme"/>
        <Header/>
        <WelcomePage/>
        <Schema/>
        <DisplayOrder/>
        <SortOrder/>
        <Navigator source="AdobeRevolve.nav"/>
      </Portfolio>
    4. Press Apply in the Editor
    5. Drag the Navigator icon under the Portfolio Icon
    6. Paste the following under the Navigator Editor:  <Navigator source=”AdobeRevolve.nav”/>
    7. Press Apply in the Editor
    8. Drag the Packaged Files Icon underneath the Portfolio Icon
    9. Then add Seven PDF Documents sources under the Packaged Files and Name them in their Source field accordingly
    10. For Only the CoverPage document (the first one), go under the Basic tab and select both “This is the Base Document” and “There must be at least one valid source in this document” and ensure both of these boxes are deselected for the other PDF Document.
  7. Validate the DDX and Save it

Create a Process that will retrieve the documents from the database BLOB, assign them to a document map, invoke the DDX, Output a single PDF Portfolio document

The process will be built to look something like this:

In this process you will need the following variables:

    • thePortfolio–document–Output–Required
    • retrievedDocument –document
    • mapPortfolioDocs–map <document>
    • totalContentDocs–int
    • counter–int
    • tempContentDocID– string
    • PortfolioAssemblerResult–AssemblerResult
Retrieve a specific PDF document from the Oracle database BLOB and store it in the local variable retrievedDocument by executing the following executeScript service.
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.sql.ResultSet;
import javax.sql.DataSource;
import javax.naming.InitialContext;
 try {
   InitialContext context = new InitialContext();
   String queryQuery = [input your query here to get blob]
   //If you need to pass a process variable use "patExecContext.getProcessDataValue("/process_data/@counter");
   try {
    DataSource ds = (DataSource) context.lookup("java:/DDXDocs_DS");
    connection = ds.getConnection();
    queryStatement = connection.prepareStatement(queryQuery);
    results = queryStatement.executeQuery();
    if (results.next()) {
        java.sql.Blob documentBlob = results.getBlob(1);
        com.adobe.idp.Document document = new com.adobe.idp.Document(documentBlob.getBinaryStream());|
        patExecContext.setProcessDataValue("/process_data/@retrievedDocument", document);
     }
   }catch(Exception ex){
	System.out.println(ex.printStackTrace());
} finally {
    if (results != null) {
    	 results.close();
    }
    if (queryStatement != null) {
        queryStatement.close();
    }
    if (connection != null) {
        connection.close();
    }
   }
 } catch (Exception e) {
   e.printStackTrace();
 }

 

To test if a BLOB had been retrieved use the following route condition:

getDocLength(/process_data/@retrievedDocument)==0

 

If the document  was successfully retrieved, map it to the map <document> variable (mapPortfolioDocs) based on the id you gave it in the DDX source, using the setValue mapping below:

After retrieving all of the documents available, it is time to InvokeDDX. Using the Invoke DDX Service:
Finally, using the setValue operation, map the AssemblerResult to the output document variable (thePortfolio):

 

Silent Print in Acrobat Using JavaScript

I received a question from a customer on whether or not it is possible to create a toolbar button that will perform a silent print in Acrobat.  Well, it turns out that using JavaScript it is possible and really isn’t all that difficult.

Here’s some code:

    
    // if the application is Adobe Acrobat...
    //then create the silent print button
    if(app.viewerType == "Exchange-Pro") {

        app.trustedFunction(customSilentPrint);

        app.addToolButton({
            cName: "customSilentPrint",
            cExec: "customSilentPrint()",
            cTooltext: "Print Silent",
            cLabel: "Print Silent",
            cEnable: "event.rc = (app.doc != null)" });
        }

    function customSilentPrint(){

        // explicitly raise privileges
        app.beginPriv();

        try{
            // get the printer params
            var pp = this.getPrintParams();

            // don't show the print dialog window
            pp.interactive = pp.constants.interactionLevel.silent;
        }
        catch(err){
            app.alert("Error setting up printing parameters.\n\n" + err);
        }

        try{
            this.print(pp);
        }
        catch(err){
            app.alert("Error Printing.\n\n" + err);
        }

        // end explicit privileges
        app.endPriv();
    }



As you can see, there really isn’t much to this code, but let’s break it down.

First we check to ensure we are in Acrobat and, if so, we add the button called “Print Silent” to the Acrobat toolbar:

    // if the application is Adobe Acrobat...then create the silent print button
    if(app.viewerType == "Exchange-Pro") {

        app.trustedFunction(customSilentPrint);

        app.addToolButton({
            cName: "customSilentPrint",
            cExec: "customSilentPrint()",
            cTooltext: "Print Silent",
            cLabel: "Print Silent",
            cEnable: "event.rc = (app.doc != null)" });
    }


Next we create the function called customSilentPrint and raise privileges:

    function customSilentPrint(){

        // explicitly raise privileges
        app.beginPriv();


Within the function we get to the meat of the work by creating a print params object and setting the interactionLevel to silent.

        try{
            // get the printer params
            var pp = this.getPrintParams();
        
            // don't show the print dialog window
            pp.interactive = pp.constants.interactionLevel.silent;
        }


Now that we are set up to print silent, call the print function with these lines:

        try{
            this.print(pp);
        }
        catch(err){
            app.alert("Error Printing.\n\n" + err);
        }


To finish off our code we lower our privileges and close out the function:

        // end explicit privileges
        app.endPriv();

    }


As you can see there’s really no magic here, but this JavaScript code is a nifty little way to print silently in Acrobat.

Also, I haven’t researched silent printing using reader, but if you have tried it and succeeded or failed, please feel free to add to the post via comments.

BTW – If you don’t know how to create a toolbar button or install JavaScript in Acrobat, check out my collegue Venkata’s post here.

Acrobat JavaScript Extensions – Hello World

When we think "adding a button to the Acrobat Toolbar or Menu Item" we think: C++ Plugin; There is a far easier and less known alternative via JavaScript. That’s what I’d like to write about today. I’ve finished a project using JavaScript extensions for Acrobat, the customer is very happy because he can and did modify the extension himself. The one caveat is that not all the C++ functions are available in JavaScript but nonetheless still powerful.

I like the traditional "Hello World" examples, that’s what I look for when ever I start coding in a new language, framework or library; so I’ll give the reader a "Hello World" example.

Check the JavaScript for Acrobat Documentation for the exact use of each library call.

So open up your favorite text editor and the following self-explanatory code to HelloWorld.js

function helloWorld()
{
     //Say Hello World
     app.alert("Hello World");
}

app.addToolButton({
       cName: "helloWorldBtn", // A name for your button
       cExec: "helloWorld()", //Function to Call
       cLabel: "Hello World", //The Text on the Button
       cTooltext: "Say Hello World" //The Help Text
});

Drop the HelloWorld.js to:

  • Mac – /Users/<user id>/Library/Application Support/Adobe/Acrobat/9.0_x86/ JavaScripts
  • Vista – C:\Users\<user id>\AppData\Roaming\Adobe\Acrobat\9.0\JavaScripts

Restart Acrobat and open-up any PDF and you should see the following button added to the tool-bar.

 

Clicking on the button you should see your Hello World alert.

 

Acrobat 9 is shipping and Here is how to communicate between PDF and Flash/Flex

Prior Acrobat 9, we were able to communicate between a PDF and a Flash/Flex application residing in the same browser window (e.g. the iframe approach). Acrobat 9 introduces a new feature called Rich Media Annotation that allows you to amazing stuff with Flash … one of them being the ability to embed Flash into a PDF and communicate with it via JavaScript. The example here is simple PDF document with an embedded Flex application that takes a product ID from the PDF and queries Amazon Web Services for product information (features, price, release date etc.).

Continue reading…

Using Image in Acrobat JavaScript Dialog

I have had customers asking about how to brand Acrobat JavaScript dialog boxes with images in Adobe LiveCycle Designer. I did some research and found that it was not as simple as defining an <img href=”image.png”/> tag (I wish it was that easy though). As an overview, images used in a Acrobat JavaScript dialog has to be in a icon stream format represented by a hex-encoded string. The data string also needs to be 32 bits per pixel with 4 channels (ARGB) or 8 bits per channel with the channels interleaved. The hex-encoded string looks something like this, "fffffffffff…efdf8fff0e3beffd3b". Beautiful. Anyway, moving on.

There are a number of free and commercial third party tools you could use to convert images to hex-encoded strings. However, none of the tools fits my workflow in terms of flexibility and extensibility. So I have created a Java utility library, called Acrobat Dialog Image Generator (ADIG), which allows you to generate a hex-encoded string or a skeleton Acrobat dialog box with an embedded image.

You can invoke ADIG via a command-line interface, ANT or an API call. Here are some sample invocations:

Command-line

java -jar adig.jar /Users/lerlop/Pictures/test.jpg /Users/lerlop/Desktop/

This will reads in test.jpg and generates a JavaScript dialog file called test.jpg.txt on my desktop. Here is a sample.

ANT

ant -buildfile adig.xml

This will also produce the same result as the command-line option but everything is defined in the following build file.


<?xml version="1.0" encoding="UTF-8"?>
<project name="MyProject" default="GeneratorAcrobatDialogImage" basedir=".">
<taskdef
name="adig"
classname="com.adobe.consulting.ant.tasks.GenerateAcrobatDialogImage"
classpath="../../build/adig.jar"/>

<target name="GeneratorAcrobatDialogImage">
<adig imagePath="/Users/lerlop/Pictures/test.jpg" outputPath="/Users/lerlop/Desktop"/>
</target>
</project>

API Call

String hexString = AcrobatDialogImageGenerator. generateHexEncodedString(imagePath);

By calling this static method in your Java code, you can generate a hex-encoded string from an image and assign it to a String object. This particular option is very useful when you try to perform any kind of batch operations. For instance, I can call this method to dynamically insert an image to a JavaScript dialog defined in an XDP before calling LiveCycle Forms to render it as a PDF.

To use the generated dialog JavaScript code in your form design, you can follow these simple steps:

  1. Run ADIG via command-line or ANT to get a generated file. The generate code should like this.
  2. Open your form in LiveCycle Designer (note: XFA form not AcroForm).
  3. Create and name a new script object. It does not matter where the script object is located as long as you can reference it later. For simplicity, create it on page 1 and let’s call it DialogSO.
  4. Copy all the code from the generated file and paste it into the script object.
  5. Now create a button object so you can use it to launch the dialog box. Note that you could launch the dialog box in any event such as form::docReady or form::initialize.
  6. The last thing is to make the button launch the dialog box. In the click event of the button, type in the following function call: DialogSO.launchDialog();

There you have it. You can extend the dialog box in any way you like by adding dialog elements to the dialog body. Please refer to the JavaScript for Acrobat API Reference.

I want to note that there are commercial tools out there that will let you design and extend Acrobat dialog boxes far more than just adding an image and generating dialog JavaScript template. If you are looking for a WYSIWYG tool to design dialog boxes, WindJack’s AcroDialogs may be more suitable for your needs.

Downloads: