67
Printing with APEX: PL/PDF Scott Spendolini Executive Director, Enkitec 1

Printing with APEX: PL/PDF

  • Upload
    enkitec

  • View
    1.039

  • Download
    14

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: Printing with APEX: PL/PDF

Printing with APEX: PL/PDF

Scott SpendoliniExecutive Director, Enkitec

1

Page 2: Printing with APEX: PL/PDF

� Scott Spendolini

[email protected]

� @sspendol

� Ex-Oracle Employee of 10 years

� Senior Product Manager for Oracle APEXfrom 2002 through 2005

� Founded Sumner Technologiesin October 2005

� Co-Founded Sumneva in January 2010

� Joined Enkitec in June 2012

� Oracle Ace Director

� Author, Expert Oracle Application Express Security

� Co-Author, Pro Oracle Application Express

� “Scott” on OTN Forums

About the Presenter

2

Page 3: Printing with APEX: PL/PDF
Page 4: Printing with APEX: PL/PDF

Agenda� Overview

� Installation

� Integration

� Implementation

� Security

� Summary

4

Page 5: Printing with APEX: PL/PDF

OVERVIEW

5

Page 6: Printing with APEX: PL/PDF

What is PL/PDF?

6

�Third party product designed by Oranext

� http://plpdf.com

�Provides a set of PL/SQL based APIs that can generate PDF files from the Oracle database

�Easy to securely integrate with APEX

�Can be called from a Page or Application Process

Page 7: Printing with APEX: PL/PDF

PL/PDF Features� Robust reporting engine

� Charts

� Bar, Line & Pie

� Barcode Printing

� Use Existing PDF files as Templates

� TrueType Font Embedding

� Encrypted PDF Documents

� Native Support for PNG & JPEG images

� Other types supported via Oracle InterMedia

7

Page 8: Printing with APEX: PL/PDF

Licensing� Licensed per instance of Oracle

� $600 per instance

� Can download a trial for free

� 5 Page Maximum

� Watermark Appears on all pages

� No additional hardware is required

� PL/PDF installs into the same database as APEX

8

Page 9: Printing with APEX: PL/PDF

The BLOB!� Result of PL/PDF is nothing more than an Oracle

BLOB

� Thus, you can do anything with PL/PDF output that you can with an Oracle BLOB:

� E-Mail it as an attachment

� Download it to a browser

� Store it in a table

� Index it with Oracle Text

� Schedule a procedure to generate and e-mail PDF files

9

Page 10: Printing with APEX: PL/PDF

Simple Example

10

plpdf.init;plpdf.NewPage;plpdf.SetPrintFont('Arial',NULL,12);plpdf.PrintCell(50,10,'Hello World');plpdf.SendDoc(l_blob);

Page 11: Printing with APEX: PL/PDF

Complex Example� eSERT Evaluation Summary Report

11

Page 12: Printing with APEX: PL/PDF

Layout & Control

12

� All layout is handled via API calls

� There is no GUI tool to design a PL/PDF report

� Seems limiting, and can be at times

� Template feature allows you to use any tool to create the structure of a document and use PL/PDF APIs only to populate the data

� Also, there are APIs that minimize the amount of code required when creating reports

Page 13: Printing with APEX: PL/PDF

Extras

13

� In addition to its core APIs, PL/PDF offers a number of extra features

� Templates

� Charts

� Bar, Line & Pie

� Bar Codes

� Encryption

� OpenOffice Forms

� TrueType Font Support

Page 14: Printing with APEX: PL/PDF

Templates

14

� PL/PDF allows you to include a PDF template as a background for any page

� No need to use PL/PDF to create the structure of a document; focus on filling in the data

� Any PDF document can be used

� Easy to create PDF documents from Word, Acrobat, etc.

Page 15: Printing with APEX: PL/PDF

Templates

15

Page 16: Printing with APEX: PL/PDF

Charts

16

� Support for three types of charts

� Line

� Bar

� Pie

Page 17: Printing with APEX: PL/PDF

sumnevaSERT

Settings Summary 28 out of 37 possible points 75.68%Session Duration

0%0 out of 2 possible points

Security60%

6 out of 10 possible points

Application Settings84.62%

11 out of 13 possible points

Authentication Scheme91.67%

11 out of 12 possible points

Security: 4

Application Settings: 2

Session Duration: 2

Authentication Scheme: 1

Exceptions Awaiting Approval

No Data Found

Stale Exceptions

No Data Found

Printed on 19-JUN-2012 08:31 AM by ADMIN Page 5CONFIDENTIAL

Charts

17

Page 18: Printing with APEX: PL/PDF

Barcodes

18

� Support for a number of types of barcodes:

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

Feline Adult 20/22LB8543

$36.99101262640

P L / P D F T r i a l

Page 19: Printing with APEX: PL/PDF

Other Features

19

� Ability to encrypt PDF files

� Support for OpenOffice PDF Forms

� LZW compression

� TrueType Font Support

Page 20: Printing with APEX: PL/PDF

Sweet Spots� PL/PDF is the best solution when:

� The core report definition does not change often

� End Users do not need to create one-off reports

� You have an abundance of PL/SQL resources and little money

20

Page 21: Printing with APEX: PL/PDF

INSTALLATION

21

Page 22: Printing with APEX: PL/PDF

Installation Options

22

� PL/PDF is installed by running a series of SQL scripts

� Can use to install on any target OS

� Need to be able to connect to the target database via SQL*Net

� Some additional features may need to be manually installed

� Charts, Bar Codes, etc.

� Installation should take about 15 minutes

Page 23: Printing with APEX: PL/PDF

Where to Put It� Since PL/PDF is a set of PL/SQL objects, you’ll

need to select a schema to put it in

� Typically use PLPDF, but can name the schema anything

� Best to use its own schema and then create grants & synonyms to access from other schemas

� You’ll need to do this manually

� Start with just PLPDF & PLPDF_TYPE; synonyms for other objects can be added as needed

23

Page 24: Printing with APEX: PL/PDF

INTEGRATION

24

Page 25: Printing with APEX: PL/PDF

APEX Integration

25

� Once installed and the corresponding grants are created to your parse as schema, there is NOTHING ADDITIONAL TO CONFIGURE in order to integrate PL/PDF with APEX

� PL/PDF - like APEX - is PL/SQL

� Thus, as long as your parse-as schema can access the PL/PDF objects, that’s all you’ll need

� Seriously.

� There’s nothing else to configure.

� Try it. You’ll see.

Page 26: Printing with APEX: PL/PDF

APEX Integration� PL/PDF must be called as part of the Page

Rendering process in APEX

� And it must occur before anything else

� Best Practice:

� Create an On Load PL/SQL Process that calls PL/PDF

� Set the Condition to Request = Expression 1

� Add a button/link to that page which sets the Request to trigger the PL/PDF call

26

Page 27: Printing with APEX: PL/PDF

PL/SQL Package� It’s best to put the logic for a PL/PDF report into

a PL/SQL package

� Centralized

� Can re-use common functions

� More performant

� Easier to work with

� Be sure pass in parameters when possible so that a single package may be called from multiple pages or even outside of APEX

27

Page 28: Printing with APEX: PL/PDF

PL/SQL Process� A simple PL/SQL Process should be created to

call the report package

� Must be set to fire Before Header and be the first process executed

� Must be condition to only execute when Request = PRINT

� Can be an Application Process

� PL/SQL Code:

28

plpdf_print.print ( p_order_id => :P29_ORDER_ID );

Page 29: Printing with APEX: PL/PDF

Button

29

� A button can be used to trigger our PDF report

� Redirects to the page where the process is located

� Passes in PRINT to the Request value

Page 30: Printing with APEX: PL/PDF

Column Link� A Column Link can also be used to print a report

� Redirects to the page where the process is located

� Passes in PRINT to the Request value

� Sets the value of the APEX Item which is passed to the package

30

Page 31: Printing with APEX: PL/PDF

D E M O N S T R A T I O N

APEX INTEGRATION

31

Page 32: Printing with APEX: PL/PDF

IMPLEMENTATION

32

Page 33: Printing with APEX: PL/PDF

Goal

33

� To produce a Sales Receipt for an order generated in the Sample Database Application

� Receipt will encompass a master-detail report

� Single row from the header

� Variable number of rows from the detail

� Should look professional and include a logo

Page 34: Printing with APEX: PL/PDF

Report Types

34

� PL/PDF can produce two “types” of reports

� Row/Column

� Produce rows & columns of data based on a SQL query

� Forms

� Fill in the data for a form, such as a Tax Form or Job Application

� It’s important to determine which type is needed for a specific requirement up front

� OK to use both in a single report, if needed

Page 35: Printing with APEX: PL/PDF

Our Example

35

Form ReportBased on a single row of data across one or more tables

Row/Column ReportBased on a SQL Query returning multiple rows of data

Page 36: Printing with APEX: PL/PDF

Where to Start?

36

� PL/PDF can utilize a PDF document as a template

� Simplifies code greatly, as only the data needs to be printed via the APIs

Eugene BradleySchoephoester RoadWindsor Locks, CT 06906

10/1/13 000003

00001 Business Shirt 1 $50 $50 00003 Trousers 2 $100 $200

$250

12345 Check

Page 37: Printing with APEX: PL/PDF

The ABCs of the APIs

37

� PL/PDF is nothing more than a set of PL/SQL APIs

� Like any other API set, there’s a learning curve

� Most APIs have default values on most parameters

� Thus you only need to pass values to those you wish to set

� Use param => value notation for best results

� Refer to the documentation for full details

Page 38: Printing with APEX: PL/PDF

Where to Start� Like any other problem, it all starts with the data

� Analyze the data required and determine the best way to get what you need

� Create views where it makes sense to simplify SQL statements in APEX or PL/SQL

38

DEMO_ORDERS

DEMO_ORDER_ITEMS

DEMO_CUSTOMERS

Page 39: Printing with APEX: PL/PDF

DEMO_ORDERS� Since we’ll need to reference a row of DEMO_ORDERS, it can be created as a ROWTYPE variable and referenced throughout in the PL/PDF APIs

39

DECLARE l_order_t demo_orders%ROWTYPE;BEGIN

-- Get the Order RowSELECT * INTO l_order_t FROM demo_orders WHERE order_id = p_order_id;

Page 40: Printing with APEX: PL/PDF

init� Called once to initialize PL/PDF

� Parameters:

� p_orientation

� p_unit

� p_format

40

Page 41: Printing with APEX: PL/PDF

newPage� Creates a new page

� Called anytime a new page is needed

� PL/PDF will automatically create a new page when needed if data overflows the current page

� Parameters:

� p_orientation

41

Page 42: Printing with APEX: PL/PDF

Initializing PL/PDF

42

-- Get the TemplateSELECT blob_content INTO l_template_pdf FROM wwv_flow_files WHERE filename = 'sales_receipt.pdf';

l_template := plpdf_parser.getTemplate(l_template_pdf,1);

-- Initialize PL/PDFplpdf.init(p_format => 'letter');l_template_id := plpdf.InsTemplate(l_template);

-- Create a new pageplpdf.NewPage;

-- Place the template on the pageplpdf.useTemplate(l_template_id);

-- Get the TemplateSELECT blob_content INTO l_template_pdf FROM wwv_flow_files WHERE filename = 'sales_receipt.pdf';

l_template := plpdf_parser.getTemplate(l_template_pdf,1);

-- Initialize PL/PDFplpdf.init(p_format => 'letter');l_template_id := plpdf.InsTemplate(l_template);

-- Create a new pageplpdf.NewPage;

-- Place the template on the pageplpdf.useTemplate(l_template_id);

Page 43: Printing with APEX: PL/PDF

setCurrentXY� Sets the position of the cursor

� Parameters:

� p_x

� p_y

� Similar:

� setCurrentX

� setCurrentY

43

Page 44: Printing with APEX: PL/PDF

setPrintFont� Sets the font family and style used for text

� Parameters:

� p_family

� p_style

� p_size

44

Page 45: Printing with APEX: PL/PDF

printCell� Prints a line of text on the page

� Parameters:

45

• p_w

• p_h

• p_txt

• p_border

• p_ln

• p_align

• p_fill

• p_link

• p_clipping

Page 46: Printing with APEX: PL/PDF

lineBreak� Places the cursor on the next line

� Parameters:

� p_h

46

Page 47: Printing with APEX: PL/PDF

Printing Customer Details

47

plpdf.SetPrintFont( p_family => 'Courier', p_size => 10);plpdf.setCurrentXY(11,60);

-- Customer DetailsFOR x IN (SELECT * FROM demo_customers WHERE customer_id = l_order_t.customer_id)LOOP plpdf.printCell(70, 10, x.cust_first_name || ' ' || x.cust_last_name, NULL, NULL, 'L'); plpdf.LineBreak(4); plpdf.setCurrentX(11); plpdf.printCell(70, 10, x.cust_street_address1, NULL, NULL, 'L');

Page 48: Printing with APEX: PL/PDF

Printing Customer Details

48

plpdf.LineBreak(4); plpdf.setCurrentX(11); IF x.cust_street_address2 IS NOT NULL THEN plpdf.printCell(70,10, x.cust_street_address2, NULL, NULL, 'L'); plpdf.LineBreak(4); plpdf.setCurrentX(11); END IF; plpdf.printCell(70, 10, x.cust_city || ',' || x.cust_state || ' ' || x.cust_postal_code, NULL, NULL, 'L');END LOOP;

Page 49: Printing with APEX: PL/PDF

Other Details

49

-- Date and Order Numberplpdf.setCurrentXY(152,60);plpdf.printCell(26, 10, TO_CHAR(l_order_t.order_timestamp, 'DD-MON-YYYY'),NULL,NULL,'C');plpdf.printCell(30,10,'0000' || p_order_id,NULL,NULL,'C');

-- Payment Methodplpdf.setCurrentXY(10,95);plpdf.printCell(28,10,'n/a' ,NULL,NULL,'C');plpdf.printCell(28,10,'Credit',NULL,NULL,'C');

-- Reset Cursorplpdf.setCurrentXY(10,114);

Page 50: Printing with APEX: PL/PDF

row_print

50

� ROW_PRINT allows for a lot more flexibility than QUERY_PRINT

� Typically called from inside a loop

� FOR X IN (SELECT * FROM ...)

� DBMS_SQL

� Four different variations are available: ROW_PRINT through ROW_PRINT4

Page 51: Printing with APEX: PL/PDF

row_print� Sample Parameters

� p_data

� p_width

� p_align

� p_style

� p_maxline

� p_links

� p_h

� p_fill

� p_min_height

� p_clipping

51

Page 52: Printing with APEX: PL/PDF

Order Lines

52

� ROW_PRINT may or may not suffice for what you need

� Often times just looping through a query and printing the individual columns is just as effective

� Take some time to become familiar with it and what it can and can’t do

Page 53: Printing with APEX: PL/PDF

Order Lines

53

LOOP plpdf.printCell(29,10,'0000' || x.product_id ,NULL,NULL,'C'); plpdf.printCell(84,10,x.product_name, NULL,NULL,'L'); plpdf.printCell(28,10,x.quantity, NULL,NULL,'C'); plpdf.printCell(28,10,TO_CHAR(x.list_price, 'FML999G999G999G999G990D00'), NULL,NULL,'R'); plpdf.printCell(28,10,TO_CHAR(x.list_price * x.quantity,'FML999G999G999G999G990D00'), NULL,NULL,'R'); plpdf.LineBreak(4);END LOOP;

Page 54: Printing with APEX: PL/PDF

sendDoc� Returns the PDF document to a BLOB variable

� Parameters:

� p_blob

54

Page 55: Printing with APEX: PL/PDF

Download File API� You can also create a single procedure to handle

file downloads

� Pass in the BLOB and filename

� All PL/PDF reports can call this procedure

� In fact, it is recommended that PL/PDF reports be based on a package

� Reusability

� Security

55

Page 56: Printing with APEX: PL/PDF

Printing the PDF

56

-- Send the contents of the PDF document to l_blob and Print itplpdf.SendDoc(l_blob);

-- Send the PDF document to the browserowa_util.mime_header('application/pdf', FALSE);htp.p('Content-Disposition: inline; filename=' || p_filename || '.pdf') ;htp.p('Content-Length: ' || dbms_lob.getlength(l_blob)) ;owa_util.http_header_close;wpg_docload.download_file(l_blob);apex_application.g_unrecoverable_error := TRUE;

Page 57: Printing with APEX: PL/PDF

Table of Contents

57

� PL/PDF allows you to automatically crete a Table of Contents

� You can add “bookmarks” throughout your application that link back to the main table of contents

� Fully automated; no need to calculate anything

Page 58: Printing with APEX: PL/PDF

SECURITY

58

Page 59: Printing with APEX: PL/PDF

PL/PDF Security

59

� Since PL/PDF is all PL/SQL, there are no specific provisions when it comes to security

� Any database layer security will work

� Secure Views

� Label Security

� VPD

Page 60: Printing with APEX: PL/PDF

VPD Function

60

CREATE OR REPLACE FUNCTION plpdf_vpd (p_schema IN VARCHAR2 DEFAULT NULL, p_object IN VARCHAR2 DEFAULT NULL)RETURN VARCHAR2ASBEGIN

RETURN q'!user_name = '!' || v('APP_USER') || q'!'!';

END;/

Page 61: Printing with APEX: PL/PDF

Enabling VPD

61

BEGINDBMS_RLS.add_policy (object_schema => 'PLPDF_OOW', object_name => 'DEMO_ORDERS', policy_name => 'DEMO_ORDERS_VPD', function_schema => 'PLPDF_OOW', policy_function => 'PLPDF_VPD', statement_types => 'SELECT');END;/

Page 62: Printing with APEX: PL/PDF

Disabling VPD

62

BEGINDBMS_RLS.drop_policy (object_schema => 'PLPDF_OOW', object_name => 'DEMO_ORDERS', policy_name => 'DEMO_ORDERS_VPD');END;/

Page 63: Printing with APEX: PL/PDF

D E M O N S T R A T I O N

VPD & PL/PDF

63

Page 64: Printing with APEX: PL/PDF

SUMMARY

64

Page 65: Printing with APEX: PL/PDF

PL/PDF Report Card

65

Installation

Integration

Implementation & Ease of Use

Security

Cost

AADAA

Page 66: Printing with APEX: PL/PDF

Summary

66

� PL/PDF provides a robust, cost effective solution for producing high quality PDF documents from any APEX application

� Not always the right tool for every job; but in many cases, it works quite well

� Low cost and zero footprint means that it should at least be seriously considered

Page 67: Printing with APEX: PL/PDF

http://www.odtug.com

67