You are on page 1of 197

6/9/2019 APEX Office Print

APEX Office Print (AOP) - User


Manual
Release 19.1.5 April 2019

Provided by:

(https://www.apexrnd.be)

1 About AOP
1.1 Goal
APEX Office Print makes printing and exporting (docx, xlsx, pptx, pdf, html, md, txt, csv, ics) in Oracle
Application Express (APEX) or just in PL/SQL a lot easier.

Make a template in Office, HTML or Markdown, choose data from your database and merge them into one. You
can easily print PDFs, Office documents, HTML or Markdown in no time. It saves you time and effort by creating
templates in which you can easily integrate your data.

APEX Office Print (AOP) is a product of APEX R&D, located in Leuven, Belgium.

We are an experienced partner that helps you facilitate, improve and accelerate your business through new and
innovative solutions. Built on in-depth technical expertise, our company provides custom-made IT services for
managing business data and processes.

1.2 AOP Main Features


APEX Office Print focusses on following:

1. Simple Printing It is fast, easy and saves you money. It's the only solution on the market that is fully
integrated with APEX. For example, you can print or export your Interactive Reports and Grids data in a
second.

2. Quick and Easy Setup Simply Import the APEX Plug-in in your application

3. Any Data Type Support Text, images, barcodes, formulas…. it is easy to merge your data with any
template you create

https://www.apexofficeprint.com/docs/ 1/197
6/9/2019 APEX Office Print

4. Scalable and Secure APEX Office Print is a scalable and secure product that fits your every printing
requirement.

5. PL/SQL API support It gives you the ability to run and retrieve reports from AOP server directly from your
PL/SQL code.

6. Optimized for Performance Great design with finest details to enhance your business productivity.

7. Flexible APEX Office Print is a print server allowing you to create templates in Word, Excel, and
PowerPoint for any type of data.

1.3 AOP Architecture

It's the database (APEX Plug-in, PL/SQL API, REST Webservice) that is doing a request to the AOP Server
(either on-premise or our cloud). The template together with the data is send in JSON format to the AOP Server.
The browser doesn't need to have access to the AOP server.

1.4 How it works (overview)

https://www.apexofficeprint.com/docs/ 2/197
6/9/2019 APEX Office Print

1.5 How it works (technical)

https://www.apexofficeprint.com/docs/ 3/197
6/9/2019 APEX Office Print

The APEX Office Print package consists of a server component, an Oracle APEX plug-in and PL/SQL API.

The server part returns generated documents upon receiving HTTP POST requests. These requests require a
structured JSON file that for example can be inferred from a SQL database. The data from the database in
combination with a template will generate relevant output files.

The Oracle Application Express (APEX) plug-in will generate the HTTP POST requests that the server part
understands. The plug-in makes it easy to select a template, your data source and the output format straight
from within your APEX application.

The PL/SQL API allows to print directly from the Oracle database. The PL/SQL API fits perfectly if you need to
setup automatic printing through a job or do a mail merge.

A sample application comes with the download, so you see plenty of use cases in action.

1.6 Cloud vs On-Premise


There are two type of versions to buy:

a cloud version, which will send the requests to APEX Office Print in the cloud
an on-premise version, which includes the server component of APEX Office Print. It's an executable you
run on your own server and in the APEX Plug-in you reference your own local version of APEX Office
Print. In this case nothing is sent to the AOP cloud.

1.7 License
This is commercial software; you need to obtain a valid license in order to use this software and plug-in in your
application. For the on-premise version a license is required per server (MID i.e. machine id) you are running
APEX Office Print of or you can go for an Enterprise License which is not tied to MID.

Please visit our website https://www.apexofficeprint.com/ (https://www.apexofficeprint.com/) for the different


packages.

You can even sign up for a FREE Cloud account.

1.8 Signup and Download


1. Open https://www.apexofficeprint.com/ (https://www.apexofficeprint.com/)

2. Click on the "Sign Up" button

https://www.apexofficeprint.com/docs/ 4/197
6/9/2019 APEX Office Print

3. Enter your details

https://www.apexofficeprint.com/docs/ 5/197
6/9/2019 APEX Office Print

4. You'll receive an email with a confirmation link, please click that

5. At the same time, you'll be logged into your AOP Dashboard. Select Downloads

https://www.apexofficeprint.com/docs/ 6/197
6/9/2019 APEX Office Print

6. Choose the package you want and click to download it

Important – API key number activation

In your AOP dashboard your unique API key number can be found under the Account Info region on the home
page. This number will need to be added to your Plug-in settings in order for it to work. For more information on
how to do this check the APEX Plugin Section.

1.9 Quick Install Guide


1. Unzip the file you downloaded from https://www.apexofficeprint.com (https://www.apexofficeprint.com)

2. Run aop_db_pkg.sql (in the "db"-directory) in your Oracle Schema (SQL Workshop -> SQL Scripts ->
Upload -> Select file and hit Upload)

3. Import dynamic_action_plugin_be_apexrnd_aop_da.sql and process_type_plugin_be_apexrnd_aop.sql


(in the "apex/apex release"-directory) in Shared Components > Plug-ins

4. On the page you want to use AOP, add the "APEX Office Print" Dynamic Action or Process

1.10 Quick Upgrade Guide


When you already have an older version of AOP installed.

1. Unzip the file you downloaded from https://www.apexofficeprint.com (https://www.apexofficeprint.com)

2. Run aop_db_pkg.sql (in the "db"-directory) in your Oracle Schema (SQL Workshop -> SQL Scripts ->
Upload -> Select file and hit Upload)

https://www.apexofficeprint.com/docs/ 7/197
6/9/2019 APEX Office Print

3. Import dynamic_action_plugin_be_apexrnd_aop_da.sql and process_type_plugin_be_apexrnd_aop.sql


(in the "apex/apx release"-directory) in Shared Components > Plug-ins

4. Optional: run aop_db_sample_pkg.sql (in the "db"-directory) in your Oracle Schema (SQL Workshop ->
SQL Scripts -> Upload -> Select file and hit Upload), which will create some sample PL/SQL Scripts. We
also recommend you to install the latest version of AOP Sample App.

5. For on-premises versions of AOP, on the server stop AOP, copy the server directory and restart AOP with
the new executable.

2 AOP APEX Sample Application


2.1 Prerequisites
APEX Office Print requires Oracle APEX 5.0.4 or higher. Interactive Grid support is included in Oracle APEX 5.1
and above. Remote Databases and Web Sources are support in Oracle APEX 18.1 and above.

Note that the higher the APEX version, the more samples the AOP Sample App will include. We recommend
looking at the latest version of the AOP Sample App, even if you are not yet on the latest version of APEX. Many
examples will work in previous versions of APEX too, but they don't necessarily exist in that version of the AOP
Sample App.

In order to run the AOP Sample Application an Oracle APEX Packaged application called Sample Database
Application has to be installed first. The reason is that the source and templates are using data from the tables
(demo_orders, demo_order_items, demo_product_info, ….) which are installed by the packaged application.

Follow these steps to install the packaged application in your workspace:

https://www.apexofficeprint.com/docs/ 8/197
6/9/2019 APEX Office Print

1. Access your target Workspace


2. Select the Application Builder
3. Select Create

4. Select Packaged Application

5. Select Sample Database Application and click Install Application button

https://www.apexofficeprint.com/docs/ 9/197
6/9/2019 APEX Office Print

6. Select to use existing Application ID Note: When you selected Auto Reassign Application ID you need to
make sure that you change the values of aop_api_pkg that uses APP_ID and AOP_URL as global
variables.

7. Select to install Supporting Objects


8. Follow the wizard to complete the installation.

2.2 Import the AOP Sample Application


1. Access your target Workspace
2. Select the Application Builder
3. Select Import and select the file in apex/version/aop_sample_apex_app.sql
4. Follow the wizard to finish the import
5. The AOP Sample Application will also install all supporting objects, so after the import you can simply
start using the application.

2.3 Trying the AOP Sample Application


The APEX application that comes with AOP shows different examples of how APEX Office Print can be used
inside an application.

By inspecting elements of these pages, you can quickly learn how to use AOP Plug-in.

https://www.apexofficeprint.com/docs/ 10/197
6/9/2019 APEX Office Print

Note that the AOP Sample Application for APEX 5.0, 5.1 and 18.1 are different. The higher the APEX
version, the more features you will find in the AOP Sample App.

2.3.1 AOP Sample Application for APEX 5.0

AOP Sample application consist out of 19 parts:

1. Sample Print

This page contains different buttons all linked to different AOP processes and dynamic actions that show
different use cases of the AOP plug-in.

2. Top Features

This section highlights some of the key differentiators of APEX Office Print compared to other print
solutions.

https://www.apexofficeprint.com/docs/ 11/197
6/9/2019 APEX Office Print

3. Dynamic Print

Dynamically you can select your template in Word, Excel or PowerPoint and output depending on the
customer you selected.

https://www.apexofficeprint.com/docs/ 12/197
6/9/2019 APEX Office Print

4. Reports Print

This section shows examples where a classic and interactive report and grid is used as the source of the
data. There is also an example to print labels. You can even use a combination of multiple classic and
interactive reports as your data source. This feature is one of the most impressive of AOP and not found
in any other tool.

https://www.apexofficeprint.com/docs/ 13/197
6/9/2019 APEX Office Print

5. Chart Print

This section shows examples how to print charts: Line, Bar, Column, Pie, Radar, Area, ... The charts are
native Office charts, so they can even be adapted after creation in Word, Excel and PowerPoint.

https://www.apexofficeprint.com/docs/ 14/197
6/9/2019 APEX Office Print

6. Rich Text Editor

You can also write your mark-up in a Rich Text Editor and AOP will understand and translate the mark-up
(bold, color, etc.) into native Word markup. In your template you need to put an underscore in front of the
tag name e.g. {_htmlcontent}

https://www.apexofficeprint.com/docs/ 15/197
6/9/2019 APEX Office Print

7. Images

APEX Office Print is able to print images in different formats. This screen shows an example how to
configure it. In order to show images, you base64 encode those and put a % in your tag e.g. {%image}

https://www.apexofficeprint.com/docs/ 16/197
6/9/2019 APEX Office Print

8. QR and Barcodes

APEX Office Print is able to print different Bar- and QR codes. This screen shows an example how to
configure it.

https://www.apexofficeprint.com/docs/ 17/197
6/9/2019 APEX Office Print

9. Inline PDF

If you want to show the PDF inline in a modal dialog or in a certain div (region), this page shows exactly
how to do that. The value of the tag data-aop-inline-pdf should be the name of dynamic action that calls
AOP.

https://www.apexofficeprint.com/docs/ 18/197
6/9/2019 APEX Office Print

10. Complex Print

The Complex Print section shows different use cases for Word, Excel and PowerPoint. There are different
templates that show how to create more complex layouts. There are also some examples that show some
specific features like how to use line breaks in your data or how to download two documents at the same
time.

https://www.apexofficeprint.com/docs/ 19/197
6/9/2019 APEX Office Print

11. Mailings Print

Word has a feature to create labels via the mailings option. This screen shows an example with some
specific Avery size labels.

https://www.apexofficeprint.com/docs/ 20/197
6/9/2019 APEX Office Print

12. Email Print

This example shows how you can call a procedure and send an email as attachment. There is also an
option to send the email but also downloading the file.

https://www.apexofficeprint.com/docs/ 21/197
6/9/2019 APEX Office Print

13. PL/SQL API Sample

Here you can see AOP PL/SQL API in action. It shows how to retrieve a document from AOP server and
store it in custom table. This is extremely useful when you want to schedule your print jobs and send
automated emails.

14. Scheduled Print

You can schedule a job to print every day, week, month etc. a specific report by using dbms_scheduler
and the AOP PL/SQL API.

https://www.apexofficeprint.com/docs/ 22/197
6/9/2019 APEX Office Print

15. Batch Print

If you want to print documents in batch, this page shows you three ways of doing it.

First one will generate one document with the pages in here. Second will generate multiple documents.
And last option will generate multiple documents but present it back as a zip file.

16. Template and Data Types

https://www.apexofficeprint.com/docs/ 23/197
6/9/2019 APEX Office Print

This page gives an overview and example of the different template and data types that are possible in the
APEX Office Print (AOP) Plug-in and API. The template type defines where your template is defined
(table, filesystem, URL, APEX, ...). The data type defines where the data can be found to be merged with
the template (SQL, PL/SQL, JSON, REST, ...).

17. AOP Usage

This page gives an overview of the pages where and how the APEX Office Print (AOP) Plug-in is used.

https://www.apexofficeprint.com/docs/ 24/197
6/9/2019 APEX Office Print

18. Automated Test

You can automatically test all your documents in this screen and see if all of your defined templates and
data sources merged correctly. This option is especially useful after an upgrade of AOP or Office.

19. Templates

Here you can upload your templates into a custom table.

The idea here is that in your own application, you allow people to create or update their own templates
and upload them to the application without the need for developer to code other documents.

https://www.apexofficeprint.com/docs/ 25/197
6/9/2019 APEX Office Print

2.3.2 AOP Sample Application for APEX 5.1


For Oracle Application Express (APEX) 5.1 we wanted to take the AOP Sample App to another level and include
more insight how AOP is working. We know reading documentation isn't the most fun, so we put a lot of
information into the sample app, so by navigating through it you learn about AOP.

https://www.apexofficeprint.com/docs/ 26/197
6/9/2019 APEX Office Print

The different parts of the sample app:

1. Start walks you step-by-step how you can get AOP working in your own application.

https://www.apexofficeprint.com/docs/ 27/197
6/9/2019 APEX Office Print

2. Tour shows the different techniques you can use and goes in more detail when to use which plug-in, the
PL/SQL API or do a manual REST request.

https://www.apexofficeprint.com/docs/ 28/197
6/9/2019 APEX Office Print

3. Examples shows different use cases of AOP, so you can see exactly behind the scenes how AOP is
used.

https://www.apexofficeprint.com/docs/ 29/197
6/9/2019 APEX Office Print

4. Doc is a link to the latest version of our online documentation.

5. More is a link to our website where you find the release history, FAQ, Tutorials etc.

6. Support will open your default email client so you can write us.

2.3.3 AOP Sample Application for APEX 18.x


For Oracle Application Express (APEX) 18.1 and above we recreated the AOP Sample App from scratch. We
really recommend going through this sample application. This app showcases the different features AOP has,
both specific for APEX as what many people are looking for in a reporting solution. Where possible we added
extra information so you have a thorough understanding how AOP works and how to create what you dream of.

https://www.apexofficeprint.com/docs/ 30/197
6/9/2019 APEX Office Print

The different parts of the sample app:

1. Installation walks you step-by-step how you can get AOP working in your own application.

https://www.apexofficeprint.com/docs/ 31/197
6/9/2019 APEX Office Print

2. Architecture shows the flow of the different components and techniques you can use and goes in more
detail when to use which plug-in, the PL/SQL API or do a manual REST request.

https://www.apexofficeprint.com/docs/ 32/197
6/9/2019 APEX Office Print

3. APEX Features shows the integration of AOP with specific APEX features like Interactive Reports,
Interactive Grid and Calendar.

4. Examples shows different possibilities of AOP, so you can see exactly behind the scenes how AOP is
used.

5. Use Cases show different use cases people requested or had issues with (coming soon).

6. Debugging includes how to debug and test AOP.

https://www.apexofficeprint.com/docs/ 33/197
6/9/2019 APEX Office Print

7. User Manual is a link to the latest version of our online documentation.

8. Support will open your default email client so you can write us.

9. Administration of the application as generated by APEX.

3 APEX Plug-in
3.1 Pre-requisites
The APEX Office Print APEX plug-in requires Oracle APEX 5.0.4 or higher.

The AOP plug-ins are relying on a PL/SQL package (aop_api_pkg which is a synonym for
aop_api19_pkg) that needs to be compiled first.

To make the package available, go into SQL Plus, SQLcl, SQL Developer or SQL Workshop and run the SQL
Script aop_db_pkg.sql which you find in the db directory of the zip you downloaded.

Alternatively, you can run the install.sql file which will install some additional packages which show case how to
use AOP from PL/SQL.

If you imported the AOP Sample App and ran the Supporting Objects, the packages are automatically installed.

3.2 Import and plug-in Attributes


Follow these steps to import the plug-in in your application:

1. Access your target Workspace


2. Select the Application Builder
3. Select the Application where you wish to import the plug-in > (plug-ins belong to an application, not a
workspace)
4. Access Shared Components > Plug-Ins
5. Click Import >
6. Browse and locate the installer files in apex/version/process_type_plugin_be_apexrnd_aop.sql)

https://www.apexofficeprint.com/docs/ 34/197
6/9/2019 APEX Office Print

7. Complete the wizard.


8. Do the same for the dynamic action plug-in in apex/version/dynamic_action_plugin_be_apexrnd_aop.sql)

Follow these steps to finish your Plug-in installation by adding your Plug-in API key:

1. Login into https://www.apexofficeprint.com (https://www.apexofficeprint.com)


2. Copy your API key from the Dashboard
3. Access your target APEX Workspace
4. Select the Application Builder
5. Select the Application where you wish to import the plug-in (plug-ins belong to an application, not a
workspace)
6. Access Shared Components > Component Settings
7. Here select APEX Office Print (AOP) [Plug-in]
8. Add you API key that you copied in step 2

9. Click Apply

10. Installation is now completed

Installation note: To use AOP PL/SQL API you may need to configure your ACL (Access Control List) settings to
allow access to: http(s)://api.apexofficeprint.com

For more details please refer to Oracle APEX installation guide: for APEX 5.0
(https://docs.oracle.com/cd/E59726_01/install.50/e39144/listener.htm#HTMIG29160) or for APEX 5.1
(http://docs.oracle.com/database/apex-5.1/HTMIG/enabling-network-services-in-Oracledb-11g-or-
later.htm#HTMIG29160) or for APEX 18.1 (https://docs.oracle.com/database/apex-18.1/HTMIG/enabling-
network-services-in-Oracle-db11g-or-later.htm#HTMIG29161)

In case you want to update some plug-in settings, you find the plug-in settings in Shared Components >
Component Settings > APEX Office Print (AOP) [Plug-in]

https://www.apexofficeprint.com/docs/ 35/197
6/9/2019 APEX Office Print

You can change the AOP URL, AOP Failover URL (and Procedure which is being called on failover), API Key,
Debug and specify a package where those settings are specified. Since AOP 3.5 you can also specify a Log
package which will be called on every request, so you can monitor directly from your Oracle database if prints
are successful. If you use the on-premise version of AOP you can also change the Converter.

Since AOP 19.1 it's possible to change the AOP Mode to Development, which means you don't use any credits
in our AOP Cloud and have unlimited prints/reports (ignored by AOP On-Premises version). In AOP
Development Mode a text box (watermark) will be included at the top of the document.

To generate a PDF, APEX Office Print is using an external converter. By default, LibreOffice is used (available on
all platforms), but this can be changed to MS Office (Windows only). It is also possible to use a custom
converter. The custom conver needs to be defined inside the aop_config.json file. See section 8.1 for more
information.

3.3 How to use the AOP Plug-in


Simply add a new process called AOP (plug-in) on your APEX page once you completed steps in 3.2.

https://www.apexofficeprint.com/docs/ 36/197
6/9/2019 APEX Office Print

3.4 Quick Start Demo


Once the plug-in has been imported into your APEX 5 application navigate to the Sample Database Application
– Page 4.

1) Create a new button called PRINT and place it right of the RESET button.

2) Create a new process (APEX 5.0) or dynamic action (APEX 5.1) called AOP and select as type AOP [Plug-in]

3) Set the Data Type option of the plug-in to SQL and paste following select in the Data Source. Please note the
use of cursor data. The tags that you use in the template should be inside this data cursor.

https://www.apexofficeprint.com/docs/ 37/197
6/9/2019 APEX Office Print

```sql
select
'file1' as "filename",
cursor(
select
c.cust_first_name as "cust_first_name",
c.cust_last_name as "cust_last_name",
c.cust_city as "cust_city",
cursor(
select
o.order_total as "order_total",
'Order ' || rownum as "order_name",
cursor(
select
p.product_name as "product_name",
i.quantity as "quantity",
i.unit_price as "unit_price",
APEX_WEB_SERVICE.BLOB2CLOBBASE64(p.product_image) as "image"
from
demo_order_items i, demo_product_info p
where
o.order_id = i.order_id
and i.product_id = p.product_id
) "product"
from
demo_orders o
where
c.customer_id = o.customer_id
) "orders"
from
demo_customers c
where
customer_id = 1
) as "data"
from dual
```

4) As Output Type select docx.

5) Add as Condition for the process set only to run when button clicked PRINT.

6) Hit Save and Run the page.

When clicking on the Print button you should now get your first Word document. This document represents a
starting template based on your data. You'll see all tags that you can use and some more explanations how to
use expressions and certain features of AOP. You can now create your template in MS Word (or Excel or
PowerPoint) and use the tags in your template. Follow the next steps to do this.

7) Create your template in Word and use the tags that came in the first document you got.

8) Go to Shared Components > Static Application Files and upload your template

9) Go back to your page and select the AOP process

10) Change the Template Type to "Static Application Files"

11) In Template Source enter your document you uploaded in step 8 e.g. my_template.docx

https://www.apexofficeprint.com/docs/ 38/197
6/9/2019 APEX Office Print

12) Run your page again

When clicking on the Print button you should now get your Word document based on your template with the tags
replaced by the data coming from the database.

3.5 Plug-in options


Since AOP v2.3 there are two plug-ins included: a process type plug-in and a dynamic action plug-in. If you are
using APEX 5.1, the Dynamic Action plug-in will always work, whereas the Process plug-in only works if the
“Reload on Submit” attribute (of the page) is set to “Always” (note this attribute is new in 5.1). This is due to a
change how APEX 5.1 is handling Page Processing. If you would import an APEX 5.0 app in 5.1 by default it’s
set to Always reload on submit, but if you create a new app in 5.1 it’s set to “Only for Success” which causes the
process type plug-in to fail.

There are different configuration options that can be used in AOP.

In subsections to follow you can find more details for each of them.

3.5.1 Template Type


It stands for what will the source of your templates be.

AOP Plug-in allows you to:

Use AOP default templates

Use static files kept on a server or as Application/Workspace files (acting as as global templates)

Dynamically define your templates

AOP Template

Will generate a Word document with a starting template based on the data (JSON) that is submitted.

Static Application Files

Will reference files you find in Shared Components > Static Application Files

Static Workspace Files

Will reference files you find in Shared Components > Static Workspace Files

SQL

Query that returns two columns: template_type and file (in this order)

template_type can be: docx,xlsx,pptx,html,md,txt,csv


while file column supports: clob base64 of the blob (hint: use apex_web_service.blob2clobbase64 to
convert blob to clob).

PL/SQL Function (returning SQL)

Return a select statement as with SQL.

PL/SQL Function (returning JSON)

Return JSON object with following format:

https://www.apexofficeprint.com/docs/ 39/197
6/9/2019 APEX Office Print

{
"file":"clob base64 data",
"template_type":"docx,xlsx,pptx,html,md,txt,csv,ics"
}

Filename (with path relative to AOP server)

Enter the path and filename of the template which is stored on the same server AOP is running at.

URL (call from DB)

Enter the URL to your template in docx, xlsx, pptx, html, md, txt, ics, or csv. e.g.
https://www.apexofficeprint.com/templates/aop_template_d01.docx Always make sure your URL ends with the
filename. E.g. for Google Drive add to the end of the URL &aop=.docx This call is done from the database, so
the database server needs to have access to the URL.

URL (call from AOP)

Enter the URL to your template in docx, xlsx, pptx, html, md, txt, ics, or csv. e.g.
https://www.apexofficeprint.com/templates/aop_template_d01.docx Always make sure your URL ends with the
filename. E.g. for Google Drive add to the end of the URL &aop=.docx This call is done from AOP, so the AOP
server needs to have access to the URL.

3.5.2 Template Source


All types except the default AOP Template type will allow you to configure this setting. It can represent a name of
your file or contain code for your SQL and PL/SQL.

Some Template Source examples can be found here:

Static Application Files

aop_simple_letter.docx

Static Workspace Files

aop_simple_letter.docx

SQL

https://www.apexofficeprint.com/docs/ 40/197
6/9/2019 APEX Office Print

select
a.TEMPLATE_TYPE as template_type,
apex_web_service.blob2clobbase64(a.TEMPLATE_BLOB) as file
from aop_template a
where id = 1

PL/SQL Function (returning SQL)

declare
l_return clob;
begin
l_return := q'[
select
a.TEMPLATE_TYPE as template_type,
apex_web_service.blob2clobbase64(a.TEMPLATE_BLOB) as file
from aop_template a
where id = 1
]';
return l_return;
end;

PL/SQL Function (returning JSON)

declare
l_return clob;

begin
l_return := '{ "file": "", "template_type": "docx" }';
return l_return;
end;

declare
l_return clob;
l_template clob;
l_template_type aop_template.template_type%type;

begin
select template_type, apex_web_service.blob2clobbase64(template_blob) template
into l_template_type, l_template
from aop_template
where id = :p4_template;

l_return := '{ "file": "' || replace(l_template,'"', '\u0022') || '",'


|| ' "template_type": "' || replace(l_template_type,'"', '\u0022')
|| '" }';
return l_return;
end;

You can use this technique to load html as template. Please have a look at page 114 of the sample application.

Filename (with path relative to AOP server)

aop_template.docx

Note: Filename supports Substitutions like Application Items, Page Items and System Variables

https://www.apexofficeprint.com/docs/ 41/197
6/9/2019 APEX Office Print

URL (returning file)

http://apexofficeprint.com/templates/aop_template_d01.docx

3.5.3 Data Type


Data Type states what kind of data source you will be using.

Available options include:

SQL

Select statement in which you can use cursor to do nested records. Use "" as alias column names to force lower
case column names. The data you select should be inside the data cursor. AOP plug-in expects two columns:
filename and data.

select
'file1' as "filename",
cursor
(
***Your select statement***
) as "data"
from dual

PL/SQL Function (returning SQL)

Return a select statement as with SQL.

PL/SQL Function (returning JSON)

Return JSON defined in URL example above.

URL (returning JSON)

Source should point to URL that returns JSON object with following format: { "filename": "file1", "data":[{...}] } If
the URL is using an APEX ORDS REST call it will automatically be wrapped with additional JSON: {"items":[...]}
All of this will be handled for you by AOP Plug-in.

Region(s): Classic and/or Interactive Report(s) and/or Interactive Grid(s) and/or Charts

One or more classic and/or interactive reports and/or interactive grids will be used as the source for your data.
The Dynamic Action plug-in also has the possibility to take a screenshot of for example a JET chart or any other
div (svg/canvas).

Note that you can use bind variables like :PX_ITEM as well in your SQL-statement. You find examples when you
click on Help in the APEX Plug-in when you're on the Data Source field

3.5.4 Data Source


Depends on selected Data Type and it can be:

SQL

https://www.apexofficeprint.com/docs/ 42/197
6/9/2019 APEX Office Print

select
'file1' as "filename",
cursor(
select
c.cust_first_name as "cust_first_name",
c.cust_last_name as "cust_last_name",
c.cust_city as "cust_city",
cursor(
select
o.order_total as "order_total",
'Order ' || rownum as "order_name",
cursor(
select
p.product_name as "product_name",
i.quantity as "quantity",
i.unit_price as "unit_price",
APEX_WEB_SERVICE.BLOB2CLOBBASE64(p.product_image) as "image"
from
demo_order_items i, demo_product_info p
where
o.order_id = i.order_id
and i.product_id = p.product_id
) "product"
from
demo_orders o
where
c.customer_id = o.customer_id
) "orders"
from
demo_customers c
where
customer_id = :P4_CUSTOMER_ID
) as "data"
from dual

Be sure to put the the returned data inside the data cursor.

select
'file1' as "filename",
cursor(
***Your Select Statement***
)
as "data"
from dual

PL/SQL Function (returning SQL)

The returned SQL should contain the data inside data cursor like above.

https://www.apexofficeprint.com/docs/ 43/197
6/9/2019 APEX Office Print

declare
l_return clob;
begin
l_return := q'[
select
'file1' as "filename",
cursor(
select
c.cust_first_name as "cust_first_name",
c.cust_last_name as "cust_last_name",
c.cust_city as "cust_city",
cursor(
select
o.order_total as "order_total",
'Order ' || rownum as "order_name",
cursor(
select
p.product_name as "product_name",
i.quantity as "quantity",
i.unit_price as "unit_price",
APEX_WEB_SERVICE.BLOB2CLOBBASE64(p.product_image) as "image"
from
demo_order_items i, demo_product_info p
where
o.order_id = i.order_id
and i.product_id = p.product_id
) "product"
from
demo_orders o
where
c.customer_id = o.customer_id
) "orders"
from
demo_customers c
where
customer_id = :P4_CUSTOMER_ID
) as "data"
from dual
]';
return l_return;
end;

PL/SQL Function (returning JSON)

Note how the JSON contains the data object with the actual data inside it.

https://www.apexofficeprint.com/docs/ 44/197
6/9/2019 APEX Office Print

declare
l_cursor sys_refcursor;
l_return clob;
begin
apex_json.initialize_clob_output(dbms_lob.call, true, 2) ;
open l_cursor for
select 'file1' as "filename",
cursor
(select
c.cust_first_name as "cust_first_name",
c.cust_last_name as "cust_last_name" ,
c.cust_city as "cust_city" ,
cursor
(select
o.order_total as "order_total",
'Order ' || rownum as "order_name" ,
cursor
(select
p.product_name as "product_name",
i.quantity as "quantity" ,
i.unit_price as "unit_price" ,
apex_web_service.blob2clobbase64(p.product_image) as "image"
from
demo_order_items i,
demo_product_info p
where
o.order_id = i.order_id
and i.product_id = p.product_id
) "product"
from
demo_orders o
where
c.customer_id = o.customer_id
and rownum < 2
)"orders"
from
demo_customers c
where
customer_id = :P4_CUSTOMER_ID
) as "data"
from dual;
apex_json.write(l_cursor);
l_return := apex_json.get_clob_output;
return l_return;
end;

URL with ORDS RESTful Web Service

For this you need to create a new Webservice following these steps:

1. Open SQL Workshop -> RESTful services.

Click Create button and follow the wizard. For RESTful Services Module set

https://www.apexofficeprint.com/docs/ 45/197
6/9/2019 APEX Office Print

Name can be of your preference.

2. For Resource Template enter:

https://www.apexofficeprint.com/docs/ 46/197
6/9/2019 APEX Office Print

3. For Resource Handler enter:

The statement we used in this example is:

https://www.apexofficeprint.com/docs/ 47/197
6/9/2019 APEX Office Print

select
file1' as "filename",
cursor(
select
c.cust_first_name,
c.cust_last_name,
c.cust_city,
cursor(
select
o.order_total,
'Order ' || rownum as order_name,
cursor(
select
p.product_name,
i.quantity,
i.unit_price,
APEX_WEB_SERVICE.BLOB2CLOBBASE64(p.product_image) as image
from
demo_order_items i,
demo_product_info p
where
o.order_id = i.order_id
and i.product_id = p.product_id
) product
from
demo_orders o
where
c.customer_id = o.customer_id
and rownum < 2
) orders
from
demo_customers c
where
customer_id = :id
) as "data"
from dual

4.Finally click Create Module button.

Note: For Resource Handler: GET setting after you created your RESTful service you may need to change
Requires Secure Access setting from default Yes to No.

Classic and/or Interactive Report(s) and/or Interactive Grid(s)

not defined in Data Source but in Region Static ID(s) (see 3.5.5)

3.5.5 Region Static ID(s)


Define one or more Static Id(s) of the report region (Classic or Interactive Report or Interactive Grid). Static ids
should be separated by a comma. e.g. classic1,ir1,ir2 You can set the Static ID of the region in the region
attributes. You can call a specific Interactive Report by adding a pipe next to it e.g. ir1|my_saved_report.

3.5.6 Special

https://www.apexofficeprint.com/docs/ 48/197
6/9/2019 APEX Office Print

Specific features of APEX Office Print which become available when the data type is SQL or Classic and/or
Interactive Report(s)

Available options include:

Treat all numbers as strings There's a limitation in APEX with the cursor() statement in SQL that it doesn't
remember which datatype the column is in. So when doing to_char(0.9,'990D00') it will return 0.9 as number
instead of as string '0.90'. To resolve this, enable this checkbox and concatenate your number with '!FMT!' e.g.
'!FMT!'||to_char(35, '990D00') - !FMT! stands for format.

Alternatively if you format your number with the currency sign to_char(35,'FML990D00') Oracle will recognise it
as a string and you don't need to use this checkbox.

Report as Labels Check this box in case you want to use the Classic or Interactive Report data source but print
them as Labels (using the Mailings feature in Word). * this option is deprecated since AOP 3.0 as AOP
understands labels depending the template.

IR/IG: Show Filters on top When there're filters applied to the Interactive Report/Grid, this checkbox will print
them above the report.

IR/IG: Show Highlights on top When there're highlights applied to the Interactive Report/Grid, this checkbox
will print them above the report.

IR/IG: Show header with filter (Excel) When checked AOP will make the header of the Interactive Report/Grid
in Excel a filter.

IR/IG: Use Saved Report instead of Report in Session If you want to make sure you always call a specific
Interactive Report/Grid, without taking into account what the person is doing with it, you can check this box and
the named (saved) Interactive Report will be taken. e.g. ir1|my_saved_report would be in your source.

IR/IG: Repeat header on every page When the table spans multiple pages, the header row will be repeated on
every page.

3.5.7 Output Filename (only in the Process Plug-in)


The filename can be a hard-coded string or reference an APEX item. It does not need to include the file
extension. If a file extension is defined that is different than the output type selected, a new file extension will be
appended to the filename. See further how to specify the output filename in the Dynamic Action plug-in (Init
PL/SQL Code).

Filename examples

Static: my_file

APEX Item: &P1_FILENAME.

3.5.8 Init PL/SQL Code (only in the Dynamic Action Plug-in)


You can define global variables of the aop_api_pkg in this area.

For example, you can set the output filename or a font:

aop_api_pkg.g_output_filename := 'output';
aop_api_pkg.g_output_filename := v('P1_FILENAME');
aop_api_pkg.g_rpt_header_font_size := '12';

https://www.apexofficeprint.com/docs/ 49/197
6/9/2019 APEX Office Print

3.5.9 Output Type


Available options include:

Word (docx)
Excel (xlsx)
PowerPoint (pptx)
PDF (pdf)
HTML (html)
Markdown (md)
Comma/Column Separated Values (CSV)
Word (rtf)
Defined by APEX Item

3.5.10 Output To
Available options include:

Browser

The browser will download the file to your Downloads folder.

Procedure

This option will call a procedure in a specific format e.g. send_email_prc. This option is useful in case you do not
need the file on your own hard drive, but for example you want to mail the document automatically. In that case
you can create a procedure that adds the generated document as an attachment to your apex_mail.send.

In the database the procedure needs to have following parameters:

procedure send_email_prc(
p_output_blob in blob,
p_output_filename in varchar2,
p_output_mime_type in varchar2)

Procedure and Browser

This option allows you to call a procedure first and next download the file to your hard drive. An example is when
you first want to store the generated document in a table before letting the browser to download it.

Inline Region (pdf/html/md only)

If you want to output a PDF in a certain region or as a pop-up modal dialog, use this option. See section: 2.3.1.9
for more info. Please note that feature is not available on IE. You can use the modal page options instead.

Directory (on AOP Server)

Save the file to a directory specified with g_output_directory. The default directory on the AOP Server is
outputfiles. If you point this to a directory on a shared server or to a directory known by Google Drive or
Dropbox, you can easily generate and share documents. Note that the AOP server should enable this option by
using the --enable_save argument. It goes without saying that this option is not available while using cloud
subscription.

https://www.apexofficeprint.com/docs/ 50/197
6/9/2019 APEX Office Print

4 PL/SQL API
4.1 Pre-requisites
APEX 5.0.4 or higher needs to be installed in the database as the PL/SQL API uses some packages that come
with APEX e.g. apex_json

4.2 Install in the Database


Go into SQL Plus, SQLcl, SQL Developer or SQL Workshop and make sure following packages exist
aop_api19_pkg and aop_plsql19_pkg and the synonyms aop_api_pkg and aop_plsql_pkg. As part of the
installation those packages should have been compiled.

4.3 How to use


You can call AOP straight from PL/SQL. APEX Office Print comes with two different ways of calling AOP; one
package is aop_api_pkg which is also used behind the scenes in the APEX Plug-in and the other on is
aop_plsql_pkg. aop_plsql_pkg is especially useful when you just want to do the call to the AOP server
component or cloud.

Next to the above two packages we also provide two additional packages that show how to do the pl/sql calls.
See the packages aop_sample_pkg and aop_test_pkg.

4.4 Parameters
aop_api_pkg

Global variables which can be set

https://www.apexofficeprint.com/docs/ 51/197
6/9/2019 APEX Office Print

-- Logger
g_logger_enabled boolean := true; -- In case you use Logger (https://github.com/OraOp
-- SQL> ALTER PACKAGE aop_api19_pkg COMPILE PLSQL_C
-- When compiled and this global variable is set to
-- Call to AOP
g_aop_url varchar2(100) := null; -- AOP Server URL
g_api_key varchar2(50) := null; -- AOP API Key; only needed when AOP Cloud is used
g_aop_mode varchar2(15) := null; -- AOP Mode can be development or production; when
g_failover_aop_url varchar2(100) := null; -- AOP Server URL in case of failure of AOP URL
g_failover_procedure varchar2(200) := null; -- When the failover URL is used, the procedure spe
g_output_converter varchar2(50) := null; -- Set the converter to go to PDF (or other format
g_proxy_override varchar2(300) := null; -- null=proxy defined in the application attributes
g_transfer_timeout number(6) := 1800; -- default of APEX is 180
g_wallet_path varchar2(300) := null; -- null=defined in Manage Instance > Instance Setti
g_wallet_pwd varchar2(300) := null; -- null=defined in Manage Instance > Instance Setti
g_output_filename varchar2(300) := null; -- output
g_cloud_provider varchar2(30) := null; -- dropbox, gdrive, onedrive, aws_s3
g_cloud_location varchar2(300) := null; -- directory in dropbox, gdrive, onedrive, aws_s3 (
g_cloud_access_token varchar2(500) := null; -- access token for dropbox, gdrive, onedrive, aws_
g_language varchar2(2) := c_en; -- Language can be: en, fr, nl, de, used for the tr
g_app_language varchar2(20) := null; -- Language specified in the APEX app (primary lang
g_logging clob := ''; -- ability to add your own logging: e.g. "request_i
g_debug varchar2(10) := null; -- set to 'Local' when only the JSON needs to be ge
g_debug_procedure varchar2(4000):= null; -- when debug in APEX is turned on, next to the nor
-- e.g. to write to your own debug table. The def
-- APEX Page Items
g_apex_items varchar2(4000):= null; -- colon separated list of APEX items e.g. P1_X:P1_
-- Layout for IR
g_rpt_header_font_name varchar2(50) := ''; -- Arial - see https://www.microsoft.com/typography
g_rpt_header_font_size varchar2(3) := ''; -- 14
g_rpt_header_font_color varchar2(50) := ''; -- #071626
g_rpt_header_back_color varchar2(50) := ''; -- #FAFAFA
g_rpt_header_border_width varchar2(50) := ''; -- 1 ; '0' = no border
g_rpt_header_border_color varchar2(50) := ''; -- #000000
g_rpt_data_font_name varchar2(50) := ''; -- Arial - see https://www.microsoft.com/typography
g_rpt_data_font_size varchar2(3) := ''; -- 14
g_rpt_data_font_color varchar2(50) := ''; -- #000000
g_rpt_data_back_color varchar2(50) := ''; -- #FFFFFF
g_rpt_data_border_width varchar2(50) := ''; -- 1 ; '0' = no border
g_rpt_data_border_color varchar2(50) := ''; -- #000000
g_rpt_data_alt_row_color varchar2(50) := ''; -- #FFFFFF for no alt row color, use same color as
/* see also Printing attributes in Interactive Report */
-- Settings for Calendar
g_cal_type varchar2(10) := c_cal_month; -- can be month (default), week, day, list; c
g_start_date date := null; -- start date of calendar
g_end_date date := null; -- end date of calendar
g_weekdays varchar2(300) := null; -- translation for weekdays e.g. Monday:Tuesday:W
g_months varchar2(300) := null; -- translation for months e.g. January:February
g_color_days_sql varchar2(4000):= null; -- color the background of certain days.
-- e.g. select 1 as "id", sysdate as "date", 'FF8
-- HTML template to Word/PDF
g_orientation varchar2(50) := ''; -- empty is portrait, other option is 'landscape'
-- Call to URL data source
g_url_username varchar2(300) := null;
g_url_password varchar2(300) := null;
g_url_proxy_override varchar2(300) := null;

https://www.apexofficeprint.com/docs/ 52/197
6/9/2019 APEX Office Print

g_url_transfer_timeout number := 180;


g_url_body clob := empty_clob();
g_url_body_blob blob := empty_blob();
g_url_parm_name apex_application_global.vc_arr2; --:= empty_vc_arr;
g_url_parm_value apex_application_global.vc_arr2; --:= empty_vc_arr;
g_url_wallet_path varchar2(300) := null;
g_url_wallet_pwd varchar2(300) := null;
g_url_https_host varchar2(300) := null; -- parameter for apex_web_service, not used, plea
-- Web Source Module (APEX >= 18.1)
g_web_source_first_row pls_integer := null; -- parameter for apex_exec.open_web_source_query
g_web_source_max_rows pls_integer := null; -- parameter for apex_exec.open_web_source_query
g_web_source_total_row_cnt boolean := false; -- parameter for apex_exec.open_web_source_query
-- REST Enabled SQL (APEX >= 18.1)
g_rest_sql_auto_bind_items boolean := true; -- parameter for apex_exec.open_remote_sql_query
g_rest_sql_first_row pls_integer := null; -- parameter for apex_exec.open_remote_sql_query
g_rest_sql_max_rows pls_integer := null; -- parameter for apex_exec.open_remote_sql_query
g_rest_sql_total_row_cnt boolean := false; -- parameter for apex_exec.open_remote_sql_query
g_rest_sql_total_row_limit pls_integer := null; -- parameter for apex_exec.open_remote_sql_query
-- IP Printer support
g_ip_printer_location varchar2(300) := null;
g_ip_printer_version varchar2(300) := '1';
g_ip_printer_requester varchar2(300) := nvl(apex_application.g_user, USER);
g_ip_printer_job_name varchar2(300) := 'AOP';
g_ip_printer_return_output varchar2(5) := null; -- null or 'Yes' or 'true'
-- Post Processing
g_post_process_command varchar2(100) := null; -- The command to execute. This command should be
g_post_process_return_output boolean := true; -- Either to return the output or not. Note this o
g_post_process_delete_delay number(9) := 1500; -- AOP deletes the file provided to the command di
-- Convert characterset
g_convert varchar2(1) := c_n; -- set to Y (c_y) if you want to convert the JSON
g_convert_source_charset varchar2(20) := null; -- default of database
g_convert_target_charset varchar2(20) := 'AL32UTF8';
-- Output
g_output_directory varchar2(200) := '.'; -- set output directory on AOP Server
-- if . is specified the files are saved in the def
g_output_split varchar2(5) := null; -- split file: one file per page: true/false
g_output_even_page varchar2(5) := null; -- PDF option to always print even pages (necessar
g_output_merge_making_even varchar2(5) := null; -- PDF option to merge making all documents even p

-- Files
g_prepend_files_sql clob := null; -- format: select filename, mime_type, [file_blob, file_ba
g_append_files_sql clob := null; -- from my_table

-- Sub-Templates
g_sub_templates_sql clob := null; -- format: select filename, mime_type, [file_blob, file_ba

-- Password protected PDF


g_output_read_password varchar2(200) := null; -- protect PDF to read
g_output_modify_password varchar2(200) := null; -- protect PDF to write (modify)
g_output_pwd_protection_flag number(4) := null; -- optional; default is 4.
-- Number when bit calculation is done as specified
g_output_watermark varchar2(4000) := null; -- Watermark in PDF

Function call

https://www.apexofficeprint.com/docs/ 53/197
6/9/2019 APEX Office Print

function plsql_call_to_aop(
p_data_type in varchar2 default c_source_type_sql,
p_data_source in clob,
p_template_type in varchar2 default c_source_type_apex,
p_template_source in clob,
p_output_type in varchar2,
p_output_filename in out nocopy varchar2,
p_output_type_item_name in varchar2 default null,
p_output_to in varchar2 default null,
p_procedure in varchar2 default null,
p_binds in wwv_flow_plugin_util.t_bind_list default c_binds,
p_special in varchar2 default null,
p_aop_remote_debug in varchar2 default c_no,
p_output_converter in varchar2 default null,
p_aop_url in varchar2,
p_api_key in varchar2 default null,
p_aop_mode in varchar2 default null,
p_app_id in number default null,
p_page_id in number default null,
p_user_name in varchar2 default null,
p_init_code in clob default c_init_null,
p_output_encoding in varchar2 default c_output_encoding_raw,
p_output_split in varchar2 default c_false,
p_output_even_page in varchar2 default c_false,
p_output_merge_making_even in varchar2 default c_false,
p_failover_aop_url in varchar2 default null,
p_failover_procedure in varchar2 default null,
p_log_procedure in varchar2 default null,
p_prepend_files_sql in clob default null,
p_append_files_sql in clob default null,
p_sub_templates_sql in clob default null)
return blob;

Note that some other procedures and functions are available in the package which could be helpful.

aop_plsql_pkg

function make_aop_request(
p_aop_url in varchar2 default g_aop_url,
p_api_key in varchar2 default g_api_key,
p_json in clob,
p_template in blob,
p_output_encoding in varchar2 default 'raw', -- change to raw to have binary, change to base64 to ha
p_output_type in varchar2 default null,
p_output_filename in varchar2 default 'output',
p_aop_remote_debug in varchar2 default 'No')
return blob;

4.5 Example
Example with aop_api_pkg

https://www.apexofficeprint.com/docs/ 54/197
6/9/2019 APEX Office Print

declare
l_binds wwv_flow_plugin_util.t_bind_list;
l_return blob;
l_output_filename varchar2(100) := 'output';
begin
-- define bind variables
l_binds(1).name := 'p_id';
l_binds(1).value := '1';

l_return := aop_api_pkg.plsql_call_to_aop (
p_data_type => 'SQL',
p_data_source => q'[
select
'file1' as "filename",
cursor(
select
c.cust_first_name as "cust_first_name",
c.cust_last_name as "cust_last_name",
c.cust_city as "cust_city",
cursor(select o.order_total as "order_total",
'Order ' || rownum as "order_name",
cursor(select p.product_name as "product_name",
i.quantity as "quantity",
i.unit_price as "unit_price", APEX_WEB_SERVICE.BLOB2CLO
from demo_order_items i, demo_product_info p
where o.order_id = i.order_id
and i.product_id = p.product_id
) "product"
from demo_orders o
where c.customer_id = o.customer_id
) "orders"
from demo_customers c
where customer_id = :p_id
) as "data"
from dual
]',
p_template_type => 'SQL',
p_template_source => q'[
select template_type, template_blob
from aop_template
where id = 1
]',
p_output_type => 'docx',
p_output_filename => l_output_filename,
p_binds => l_binds,
p_aop_url => 'http://api.apexofficeprint.com/',
p_api_key => 'your API key',
p_app_id => 232);
end;

Example with aop_plsql_pkg

https://www.apexofficeprint.com/docs/ 55/197
6/9/2019 APEX Office Print

declare
l_template blob;
l_output_file blob;
begin
select template_blob
into l_template
from aop_template
where id = 1;

l_output_file := aop_plsql_pkg.make_aop_request(
p_json => '[{ "filename": "file1", "data": [{ "cust_first_name": "APEX Offi
p_template => l_template,
p_output_type => 'docx',
p_aop_remote_debug => 'Yes');
end;

In aop_sample_pkg you find the above examples and you can run them with following command:

begin
aop_sample_pkg.call_aop_plsql_pkg;
aop_sample_pkg.call_aop_api_pkg;
end;

Note that there are more examples in the aop_sample_pkg, so it's worthwhile to check it out.

4.6 PL/SQL API Documentation


The complete reference can be found in the AOP PL/SQL API documentation (./plsql/index.html).

5 Manual (REST) call


5.1 Overview
Behind the scenes the APEX plug-in is creating a JSON file that will be sent to the AOP server. Below you find
more details about the JSON structure that is used. By understanding this JSON structure you can manually
interact with the AOP server in case you wanted to code in PL/SQL or other languages.

5.2 JSON File


The JSON file is a file that follows the standard JSON structure (http://json.org/ (http://json.org/)).

This JSON file contains an JSON object meaning it starts with { and ends with }. This JSON object contains four
compulsory JSON objects namely "template", "output", "files", "api_key" and a few optional object "version",
"logging", "apex_version", "aop_remote_debug" and "ipp". The purpose of each object will now be explained.

5.2.1 "version" object

https://www.apexofficeprint.com/docs/ 56/197
6/9/2019 APEX Office Print

This object contains the version of AOP JSON format used. The current version is 18.2 and backwards
compatible thus optional. This will be used for future upgrades and if the newer version is not backwards
compatible.

5.2.2 "template" object


This object has the necessary information about the template. It contains:

JSON Explanation

"file" This contains the template to be used, encoded in base64.

"filename" This option is for on-premise users. The template defined by this object will be
used for processing. Note that the filename either contains a relative path from
where the server is running from (or the folder/directory containing application) or
an absolute path.

"url" This option allows you to give the URL containing the template. The URL will also
work with google drive (also with google docs/slides/powerpoint) and dropbox file
sharing link. However this might not work in the future since the way links work
might be changed by google or dropbox. Note this URL can also use ftp protocol.

"template_type" This states what kind of template is being used. It must be either "docx", "pptx",
"xlsx", "html" or "md".

"html_template_content" Since AOP 3.4 it is possible to just pass html as template. This is equivalent as
using {_html} tag in word to create the template which is then again passed to the
AOP with the data for rendering.

"orientation" nothing or "landscape". If landscape is provided then the html template content will
be rendered in a landscape A4 word template. Taken only into account when
html_template_content is provided.

If "file","filename" or "url" objects are not present in the "template" object then the server will respond with a
custom template file of "template_type" made from this given JSON file. Currently only Word, Excel and
PowerPoint template generation is supported.

The sharing link made by dropbox and google drive will be modified to that the online editor will not be triggered,
and are subject to change by google drive and dropbox. For this reason using share link for production is
discouraged. The change happens in the following way:

https://www.apexofficeprint.com/docs/ 57/197
6/9/2019 APEX Office Print

Google Docs Share URL:


https://docs.google.com/document/d/{ID}/edit?usp=sharing
will be changed to:
https://docs.google.com/document/d/{ID}/export?format=docx&id={ID}

Google Sheets Share URL:


https://docs.google.com/spreadsheets/d/{ID}/edit?usp=sharing
will be changed to:
https://docs.google.com/spreadsheets/d/{ID}/export?format=xlsx&id={ID}

Google Slides Share URL:


https://docs.google.com/presentation/d/{ID}/edit?usp=sharing
will be changed to:
https://docs.google.com/presentation/d/{ID}/export/pptx?id={ID}&pageid=p

Dropbox Share URL:


https://www.dropbox.com/s/{ID}/{filename}?dl=0
will be changed to:
https://www.dropbox.com/s/{ID}/{filename}?dl=1

Google Drive Share URL:


https://drive.google.com/file/d/{ID}/view?usp=sharing
will be changed to:
https://drive.google.com/uc?export=download&id={ID}

https://www.apexofficeprint.com/docs/ 58/197
6/9/2019 APEX Office Print

5.2.3 "output" object


This object has the necessary information for producing an output file from the given JSON file. It contains:

JSON Explanation

"output_type" This states what kind of output file type is required. It can be either the
same as template_type ("docx", "pptx", "xlsx", "html", "md"), "pdf" or any
other output file supported by libreoffice/openoffice. Special output type:
"onepagepdf", this will cause the ouptut to be converted to pdf and all
the pages will be merged into one single page. Default: the same as
template_type.

"output_encoding" This states what kind of output encoding is wished for the output file. It
must be either "raw" or "base64".

"output_converter" This states which software should be used to convert to pdf. The
ApexOfficePrint server usages LibreOffice. On premise users may use
MS Office but will need to do some configuration first. Available values:
"officetopdf" (Windows only) or "libreoffice" (Windows, Linux, OSX) or
any other custom defined converters in aop_config.json file (see setting
up AOP) if you are using On Premise Version.

"output_directory" If save on disk is enabled, then the document will be saved on the path
resulted by combining this given path with the specified directory.

"output_even_page" If you want your output to have even pages, for example printing on
both sides after merging, you can set this to be true. This option is only
available when the output is pdf. Optional.

"output_merge_making_even" Merge each given document making even paged. This option is only
available when the output is pdf. Optional.

"output_modify_password" Requires output pdf, the password needed to modify the pdf. Optional.
Read password, if given, will be used if this field is empty.

"output_read_password" Requires output pdf, the password needed to open the pdf. Optional.

"output_password_protection_flag" Requires output pdf, bit field explained in the PDF specs in table 3.20 in
section 3.5.2, should be given in decimal more info
(http://pdfhummus.com/post/147451287581/hummus-1058-and-pdf-
writer-updates-encryption). Optional. Default (4).

"output_watermark" Requires output pdf, generates a diagonal custom watermark on every


page in the PDF file. Optional.

"lock_form" Requires output pdf, locks/flattens the forms in the pdf. Optional.

https://www.apexofficeprint.com/docs/ 59/197
6/9/2019 APEX Office Print

5.2.4 "api_key"
The value of this key is the API key given by ApexOfficePrint. Only applicable for service users.

5.2.5 "file" array

https://www.apexofficeprint.com/docs/ 60/197
6/9/2019 APEX Office Print

This array contains the data that will be used for the given template. If this array contains more than one object
then the output files, which are generated using the same template for each item, will be returned in a zip file.
This array contains JSON objects with following fields:

JSON Explanation

"filename" This field contains the name of the output file.

"data" This array (containing one object) or object contains the data that will be replaced in the
template.

Example showing a basic JSON file which should be populated with data:

{
"template": {
"filename" :"template.docx",
"template_type" :"docx"
},
"output": {
"output_encoding" :"raw",
"output_type" :"docx",
"output_directory" :"."
},
"files": [{
"filename" :"file1",
"data" : [{...}]
}]
}

5.2.6 "logging" object


When AOP is started with --enable_printlog, it will create a file on the server called server_printjob.log. You can
add additional logging information next to the one AOP is logging by default, by adding additional keys and
values in the logging object.

For example:

"logging": {
"template_filename": "AOP template",
"output_filename": "output.docx"
}

5.2.7 "ipp" object


AOP supports to print directly to an IP Printer by using this setting. If your IPP printer supports pdf files, your
documents will be converter to pdf and sent to IPP printer. If your printer does not support PDF and supports
Postscript then the pdf generated is converter to pdf using pdftops. You need download xpdf tools from:
https://www.xpdfreader.com/download.html. Make sure that the binary pdftops is on PATH variable. You can
download executables from apexofficeprint.com to check whether or not your IPP printer supports
PDF/postscript. The structure is:

https://www.apexofficeprint.com/docs/ 61/197
6/9/2019 APEX Office Print

"ipp": {
"location": "http://10.0.14.223:631/",
"version": "1.1",
"requester": "YOUR NAME",
"job_name": "AOP"
}

5.2.8 "post_process" object


This option is available since AOP version 19.1. This option allows the request to run a command after post
processing. The structure is:

"post_process":{
"command":"echo", //The command to execute. This command should be present on aop_config.json file
"return_output":true, //Either to return the output or not. Note this output is AOP's output and no
"delete_delay": 1500 // AOP deletes the file provided to the command directly after executing it. T

6 Templates
The templates are standard office files in which tags will be replaced by structured data from the JSON file.
These tags are quite standardized for either .docx, .pptx or .xlsx, however there are some subtle differences.
They are all able to handle JavaScript angular expressions, on which some of the basics will follow.

6.0 Tag Overview


In the table below is an overview of the available tags and their support in Word, Excel and PowerPoint
respectively. For more information on each tag, see the sections that follow.

Tag Word Excel PowerPoint HTML Markdown Txt CSV

{data_string} Yes Yes Yes Yes Yes Yes Yes

{data_string_with_cell_markup$} Yes Yes No No No N.A N.A

{-labels} Yes N.A N.A N.A N.A N.A N.A

{_htmlcontent} Yes No No Yes (by Yes (by N.A N.A


default) default)

{!slide_loop} N.A N.A Yes N.A N.A N.A N.A

{!excelsheet_loop} N.A Yes N.A N.A N.A N.A N.A

{#data_loop} … {/data_loop} Yes Yes Yes Yes Yes Yes Yes

https://www.apexofficeprint.com/docs/ 62/197
6/9/2019 APEX Office Print

Tag Word Excel PowerPoint HTML Markdown Txt CSV

{:inline_data_loop} … No No No No No No Yes
{/inline_data_loop}

{:data_loop_horizontal} … Yes Yes No No No No No


{/data_loop_horizontal}

{=table_row_loop} … N.A N.A Yes N.A N.A N.A N.A


{/table_row_loop}

{%imageKey} Yes Yes Yes Yes Yes N.A N.A

{|barcode} Yes Yes Yes Yes Yes N.A N.A

{|qrcode} Yes Yes Yes Yes Yes N.A N.A

{$chart} Yes Yes Yes No No N.A N.A

{&interactive_report} Yes Yes No No No N.A N.A

{&interactive_grid&} Yes Yes No No No N.A N.A

{<rightToLeft} Yes Not Not Not Not N.A N.A


Necessary Necessary Necessary Necessary

{+footnote} Yes No No No No N.A N.A

{*hyperlink} Yes Yes Yes Not Not N.A N.A


Necessary Necessary

{~} Yes N.A N.A N.A N.A N.A N.A

Note: tags can't start with a number and should start with an alphabetical character (a-z,A-Z)

Special Tags:

{current_child_index}: Will resolve to current index of the record array, starting from 0.

{#object|keys}{.}{/object|keys}: Will iterate over the names of the keys from the given object. If it's

{#object|values}{.}{/object|values}: Will iterate over the values of the given object.

6.1 Word (docx) template


These templates can contain the following tags:

6.1.1 {data_string} tags

https://www.apexofficeprint.com/docs/ 63/197
6/9/2019 APEX Office Print

This tag, {data_string}, will be replaced by the value of the key "data_string" in the JSON file.

6.1.1.1 Data string example


Given the JSON file with following content:

{
"template": {
"filename" :"template.docx",
"template_type" :"docx"
},
"output": {
"output_encoding" :"raw",
"output_type" :"docx"
},
"files": [{
"filename" :"output",
"data": [{
"first_name" :"DemoName",
"last_name" :"DemoLastName",
"city" :"DemoCity"
}]
}]
}

and template.docx with following content:

{last_name} {first_name}
{city}

will result in:

DemoLastName DemoName
DemoCity

Since the template and the output objects from the json will not change, these will be omitted from the examples
given below.

6.1.2 {%imagekey} tags


This tag is the same as {data_string} but instead getting replaced by a string this tag is replaced by an image
that is placed in the value of key "imagekey" after base64 encoding. Note that imagekey is just a variable. An
image tag is represented by "%" after curly bracket. You can also specify a fixed width and the height by adding
following values "imagekey_width" and "imagekey_height". If you want to scale your image proportionally you
can use the "imagekey_max_width" and "imagekey_max_height" tags. An example is created in the AOP
Sample Application which shows how it works. The imagekey is pic, so we can use pic_max_width for example.
The given data can be a base64 encoded image or a URL pointing to an image(the URL must have image
extension) or a ftp server image.

6.1.2.1 Image tag example


Replace /...code..../ for the base64 encoded string of the image

https://www.apexofficeprint.com/docs/ 64/197
6/9/2019 APEX Office Print

{
...
"files":[{
"filename" :"output",
"data":[{
"product_name" :"Wallet",
"price" :"$500.00",
"pic" :"/...code..../",
"pic_max_width" : 100,
"pic_max_height" : 100
}]
}]
}

with template:

Product Image Price

{product_name} {%pic} {price}

will result in:

https://www.apexofficeprint.com/docs/ 65/197
6/9/2019 APEX Office Print

Tip: in case you want to make your images equal in size, you can use PL/SQL to resize your images. Here's an
example to put the size of the image to a maximum of 200px.

declare
l_img blob;
begin
select image
into l_img
from my_table
where id = 1 for update;
ordsys.ordimage.process(l_img, 'maxscale=200 200');
update my_table
set image = l_img
where id = 1;
end;

6.1.3 {|barcode} / {|qrcode} tags


This tag will be replaced by the barcode or QR code created using the data of the key named "barcode" or
"qrcode". Notice that these are also variable. Barcode or qrcode tags are represented by | after curly bracket. If
this tag is found in the document there must be additional supporting keys containing the options for these tags.
These options are:

https://www.apexofficeprint.com/docs/ 66/197
6/9/2019 APEX Office Print

1. key_type, e.g. "barcode_type" if the key used is "barcode". This field contains the type of barcode
required. The options are: codabar
code128
code128a
code128b
code128c
code39
ean13
ean2
ean5
ean8
itf
itf14
msi
msi10
msi1010
msi11
msi1110
pharmacode
upc
upce

2. key_height, e.g. "barcode_height" if the key used is "barcode". This field contains the height for the
generated image. Default is 200 for QR, 50 for the rest.

3. key_width, e.g. "barcode_width" if they key used is "barcode". This field contains the width for the
generated image. Default is 200.

4. key_errorcorrectlevel (only for QR code), e.g. "qrcode_errorcorrectlevel" if the key used is "qrcode". This
field contains the level of which the QR code should be recoverable. The options are: "L" (up to 7%
damage) "M" (up to 15% damage) "Q" (up to 25% damage) "H" (up to 30% damage) Extra info:
http://www.qrcode.com/en/about/error_correction.html
(http://www.qrcode.com/en/about/error_correction.html)

5. key_cellsize (only for QR code), e.g. "qrcode_cellsize". This field contains the dot size of a module.
Default is 4. Extra info: http://www.qrcode.com/en/howto/cell.html
(http://www.qrcode.com/en/howto/cell.html)

6.1.3.1 Barcode tag example


Given the JSON file:

https://www.apexofficeprint.com/docs/ 67/197
6/9/2019 APEX Office Print

{
...
"files":[{
"filename" :"output",
"data":[{
"product_name" :"Wallet",
"product_code" :"1896547832148",
"product_code_type" :"ean13",
"product_link" :"https://www.google.be/search?q=wallet",
"product_link_type" :"qrcode"
}]
}]
}

and template as:

will result in:

https://www.apexofficeprint.com/docs/ 68/197
6/9/2019 APEX Office Print

For barcodes, instead of doing the above, you could also choose to install a barcode font, for example Free 3of9
(https://www.barcodesinc.com/free-barcode-font/) or http://www.dafont.com/3of9-barcode.font
(http://www.dafont.com/3of9-barcode.font). Barcode fonts are more performant than images. See the other
section for more information about language and font support.

6.1.4 {$chart} tags


This tag will be replaced by chart created using the data of the key named "chart". Notice that this key is a
variable. Charts are represented by $ after curly bracket. If this tag is found in the document the chart object in
the json must follow certain structure. Firstly, an optional object with key "options" to determine the options for
the chart. The default options are:

https://www.apexofficeprint.com/docs/ 69/197
6/9/2019 APEX Office Print

defaultOptions = {
width: 5486400 / 9525, // width of the chart
height: 3200400 / 9525, // height of the chart
grid: true, // if a grid should be shown
border: true, // if a border should be shown
title: false,
legend: {
showLegend: true, // if the legend should be shown
position: 'r' // 'l' for left, 'r' right, 'b' bottom, 't' top
},
dataLabels: { //Available only after AOP 19.1
showDataLabels: false, // can be true or false, default true for pie/pie3d and doughnut
seperator: false, // can be either false or anything else for example \n or \t or ; or
showSeriesName: false, // include the series name in the data label, true or false
showCategoryName: false, // include the series category name in the data label, true or
showLegendKey: false, // include the legend key (i.e the color of the series) in the
showValue: false, // include the actual value in the data label
showPercentage: false, // include the percentage, default true for pie/pie3d and doughn
position: 'center' // position to show the data label, can be 'center', 'left', 'right'
},
axis: {
x: {
orientation: 'minMax', // or "maxMin"
min: undefined, // a specific number
max: undefined, // a specific number
type: undefined, // or "date"
date: { //date options
format: 'unix',
code: 'mm/yy',
unit: 'months',
step: '1'
},
title:'title for x axis', //From 19.1.1
showValues: true //options to disable showing the values in axis

},
y: {
orientation: 'minMax',
mix: undefined,
max: undefined,
title: 'Title for y axis', //From 19.1.1
showValues: true // options to disable showing the values in axis
},
y2: { //If using multiple charts and axis on the right side
orientation: 'minMax',
mix: undefined,
max: undefined,
title: 'Title for y2 axis', //From 19.1.1
showValues: true // options to disable showing the values in axis
}
}
}

https://www.apexofficeprint.com/docs/ 70/197
6/9/2019 APEX Office Print

Secondly the type of chart should be determined by "type" key. The generation of following types of charts is
supported:

6.1.4.1 Line
This is a normal chart where the data's are connected with lines. Multiple lines can be generated. The chart key
should contain lines array inside with the data of the lines that should be generated and the name of the line.
E.g.:

"chart": {
"lines": [
{
"data": [
{
"x": "day 1",
"y": "4.3"
},
{
"x": "day 2",
"y": "2.5"
},
{
"x": "day 3",
"y": "3.5"
}
],
"name": "line 1",
"smooth": true, //Can be false
"symbol": "square" // can be diamond triangle
},
{
"data": [
{
"x": "day 1",
"y": "2.4"
},
{
"x": "day 2",
"y": "4.4"
},
{
"x": "day 3",
"y": "1.8"
}
],
"name": "line 2"
}
],
"type": "line"
}

will result in :

https://www.apexofficeprint.com/docs/ 71/197
6/9/2019 APEX Office Print

6.1.4.2 bar
In order to generate the bar chart, the chart object should contain array named bars. This array contains the
objects with data about the bar and the name of the bar. For example, given the following:

https://www.apexofficeprint.com/docs/ 72/197
6/9/2019 APEX Office Print

...
"chart": {
"bars": [
{
"data": [
{
"x": "day 1",
"y": "4.3"
},
{
"x": "day 2",
"y": "2.5"
},
{
"x": "day 3",
"y": "3.5"
}
],
"name": "bar 1"
},
{
"data": [
{
"x": "day 1",
"y": "2.4"
},
{
"x": "day 2",
"y": "4.4"
},
{
"x": "day 3",
"y": "1.8"
}
],
"name": "bar 2"
}
],
"type": "bar"
}
...

will result in:

https://www.apexofficeprint.com/docs/ 73/197
6/9/2019 APEX Office Print

Single bar chart is generated as follows:

...
"chart": {
"bars": [
{
"data": [
{
"x": "day 1",
"y": "4.3"
},
{
"x": "day 2",
"y": "2.5"
},
{
"x": "day 3",
"y": "3.5"
}
],
"name": "bar 1"
}
],
"type": "bar"
}
...

will result in:

https://www.apexofficeprint.com/docs/ 74/197
6/9/2019 APEX Office Print

6.1.4.3 barStacked
This is similar to bar chart but the bars from same category will be stacked. For example, given the following:

https://www.apexofficeprint.com/docs/ 75/197
6/9/2019 APEX Office Print

...
"chart": {
"bars": [
{
"data": [
{
"x": "day 1",
"y": "4.3"
},
{
"x": "day 2",
"y": "2.5"
},
{
"x": "day 3",
"y": "3.5"
}
],
"name": "bar 1"
},
{
"data": [
{
"x": "day 1",
"y": "2.4"
},
{
"x": "day 2",
"y": "4.4"
},
{
"x": "day 3",
"y": "1.8"
}
],
"name": "bar 2"
}
],
"type": "barStacked"
}
...

will result in:

https://www.apexofficeprint.com/docs/ 76/197
6/9/2019 APEX Office Print

6.1.4.4 barStackedPercent
This is similar to bar stacked chart, but the x axis will be in expressed in percentage. For example, given the
following:

https://www.apexofficeprint.com/docs/ 77/197
6/9/2019 APEX Office Print

...
"chart": {
"bars": [
{
"data": [
{
"x": "day 1",
"y": "4.3"
},
{
"x": "day 2",
"y": "2.5"
},
{
"x": "day 3",
"y": "3.5"
}
],
"name": "bar 1"
},
{
"data": [
{
"x": "day 1",
"y": "2.4"
},
{
"x": "day 2",
"y": "4.4"
},
{
"x": "day 3",
"y": "1.8"
}
],
"name": "bar 2"
}
],
"type": "barStacked"
}
...

will result in:

https://www.apexofficeprint.com/docs/ 78/197
6/9/2019 APEX Office Print

6.1.4.5 column
This will produce a normal column chart. The chart object should contain an array named columns with objects
containing the data and name of the column. E.g.:

https://www.apexofficeprint.com/docs/ 79/197
6/9/2019 APEX Office Print

"chart": {
"columns": [
{
"data": [
{
"x": "day 1",
"y": "4.3"
},
{
"x": "day 2",
"y": "2.5"
},
{
"x": "day 3",
"y": "3.5"
}
],
"name": "column 1"
},
{
"data": [
{
"x": "day 1",
"y": "2.4"
},
{
"x": "day 2",
"y": "4.4"
},
{
"x": "day 3",
"y": "1.8"
}
],
"name": "column 2"
}
],
"type": "column"
}

will result in:

https://www.apexofficeprint.com/docs/ 80/197
6/9/2019 APEX Office Print

A single column chart can be generated by following json:

"chart": {
"columns": [
{
"data": [
{
"x": "day 1",
"y": "4.3"
},
{
"x": "day 2",
"y": "2.5"
},
{
"x": "day 3",
"y": "3.5"
}
],
"name": "column 1"
}
],
"type": "column"
}

will result in:

https://www.apexofficeprint.com/docs/ 81/197
6/9/2019 APEX Office Print

6.1.4.6 columnStacked
This will produce a column stacked chart. The chart object should contain an array named columns with objects
containing the data and the name of the column. E.g:

https://www.apexofficeprint.com/docs/ 82/197
6/9/2019 APEX Office Print

"chart": {
"columns": [
{
"data": [
{
"x": "day 1",
"y": "4.3"
},
{
"x": "day 2",
"y": "2.5"
},
{
"x": "day 3",
"y": "3.5"
}
],
"name": "column 1"
},
{
"data": [
{
"x": "day 1",
"y": "2.4"
},
{
"x": "day 2",
"y": "4.4"
},
{
"x": "day 3",
"y": "1.8"
}
],
"name": "column 2"
}
],
"type": "columnStacked"
}

will result in:

https://www.apexofficeprint.com/docs/ 83/197
6/9/2019 APEX Office Print

6.1.4.7 columnStackedPercent
This will produce a column stacked percent chart. The chart object should contain an array named columns with
objects containing the data and the name of the column. E.g:

https://www.apexofficeprint.com/docs/ 84/197
6/9/2019 APEX Office Print

"chart": {
"columns": [
{
"data": [
{
"x": "day 1",
"y": "4.3"
},
{
"x": "day 2",
"y": "2.5"
},
{
"x": "day 3",
"y": "3.5"
}
],
"name": "column 1"
},
{
"data": [
{
"x": "day 1",
"y": "2.4"
},
{
"x": "day 2",
"y": "4.4"
},
{
"x": "day 3",
"y": "1.8"
}
],
"name": "column 2"
}
],
"type": "columnStackedPercent"
}

will result in:

https://www.apexofficeprint.com/docs/ 85/197
6/9/2019 APEX Office Print

6.1.4.8 pie
This will produce a pie chart. The chart object should contain an array named pies with one element containing
the data and name of the pie chart. E.g:

https://www.apexofficeprint.com/docs/ 86/197
6/9/2019 APEX Office Print

"chart": {
"pies": [
{
"data": [
{
"x": "Order 1",
"y": 1890
},
{
"x": "Order 2",
"y": 2380
},
{
"x": "Order 3",
"y": 1640
},
{
"x": "Order 4",
"y": 1090
},
{
"x": "Order 5",
"y": 950
},
{
"x": "Order 6",
"y": 1515
},
{
"x": "Order 7",
"y": 905
},
{
"x": "Order 8",
"y": 1060
},
{
"x": "Order 9",
"y": 730
},
{
"x": "Order 10",
"y": 870
}
],
"name": "pie 1"
}
],
"type": "pie"
}

will result in:

https://www.apexofficeprint.com/docs/ 87/197
6/9/2019 APEX Office Print

6.1.4.9 radar
This will produce a radar chart. The chart object should contain an array named radars with one element
containing the data and name of the radar chart. E.g:

https://www.apexofficeprint.com/docs/ 88/197
6/9/2019 APEX Office Print

"chart": {
"radars": [
{
"data": [
{
"x": "Order 1",
"y": 1240
},
{
"x": "Order 2",
"y": 380
},
{
"x": "Order 3",
"y": 840
},
{
"x": "Order 4",
"y": 490
},
{
"x": "Order 5",
"y": 1230
}
],
"name": "radar 1"
}
],
"type": "radar"
}

will result in:

https://www.apexofficeprint.com/docs/ 89/197
6/9/2019 APEX Office Print

6.1.4.10 area
This will produce an area chart. The chart object should contain an array named areas with one element
containing the data and name of the area chart. E.g:

https://www.apexofficeprint.com/docs/ 90/197
6/9/2019 APEX Office Print

"chart": {
"areas": [
{
"data": [
{
"x": "day 1",
"y": "4.3"
},
{
"x": "day 2",
"y": "2.5"
},
{
"x": "day 3",
"y": "3.5"
}
],
"name": "area 1"
},
{
"data": [
{
"x": "day 1",
"y": "2.4"
},
{
"x": "day 2",
"y": "4.4"
},
{
"x": "day 3",
"y": "1.8"
}
],
"name": "area 2"
}
],
"type": "area"
}

will result in:

https://www.apexofficeprint.com/docs/ 91/197
6/9/2019 APEX Office Print

6.1.4.11 scatter
This will produce a scatter chart. The chart object should contain an array named scatters with one element
containing the data and name of the scatter chart. Similar to previous charts however the x axis should contain
only numbers.

6.1.4.13 bubble
This will produce a bubble chart. The chart object should contain an array named bubbles with one element
containing the data and name of the bubble chart. It is similar to previous charts however, the data should can
now contain size value to determine the size of a bubble. Example JSON:

https://www.apexofficeprint.com/docs/ 92/197
6/9/2019 APEX Office Print

{
"chart": {
"bubbles": [
{
"data": [
{
"x": "day 1",
"y": "4.3",
"size":"1"
},
{
"x": "day 2",
"y": "2.5",
"size":"3"
},
{
"x": "day 3",
"y": "3.5",
"size":"2"
}
],
"name": "Bubble series 1"
},
{
"data": [
{
"x": "day 1",
"y": "2.4",
"size":"4"
},
{
"x": "day 2",
"y": "4.4",
"size":"5"
},
{
"x": "day 3",
"y": "1.8",
"size":"1"
}
],
"name": "Bubble series 2"
}
],
"type": "bubble"
}
}

will result in:

https://www.apexofficeprint.com/docs/ 93/197
6/9/2019 APEX Office Print

6.1.4.14 stock
This will produce a stock chart. The chart object should contain an array named stocks with one element
containing the data and name of the stock chart. Here instead of y value: volume, open, close, high and low
value should be given. The format of the x axis can also be given. The x axis contains the date starting using
1900 notation, i.e. 1 will represent January 1 1900 more info (https://support.office.com/en-us/article/Change-
the-date-system-format-or-two-digit-year-interpretation-aaa2159b-4ae8-4651-8bce-d4707bc9fb9f).

Example:

https://www.apexofficeprint.com/docs/ 94/197
6/9/2019 APEX Office Print

{
"chart": {
"stocks": [
{
"data": [
{
"x": "1",
"volume": "70",
"open": "44",
"high": "55",
"low": "11",
"close": "25"
},
{
"x": "2",
"volume": "120",
"open": "25",
"high": "57",
"low": "12",
"close": "38"
},
{
"x": "3",
"volume": "150",
"open": "38",
"high": "57",
"low": "13",
"close": "50"
},
{
"x": "4",
"volume": "135",
"open": "50",
"high": "58",
"low": "11",
"close": "35"
},
{
"x": "5",
"volume": "148",
"open": "34",
"high": "58",
"low": "25",
"close": "43"
}
],
"name": "s"
}
],
"type": "stock",
"options":{
"axis":{
"x":{
"date":{
"unit":"days",
"step":1,

https://www.apexofficeprint.com/docs/ 95/197
6/9/2019 APEX Office Print

"code":"dd"
}
}
}
}
},
"name": "Stocks"
}

will result in:

6.1.4.11 Combining Charts


It is possible to combine multiple charts. For example, a column and a line chart. If a second value axis is
wished on the right side, then the values should be given as y2 instead of y. The type should be "multiple" and
the chart should contain a multiples array which contains the different charts defined previously. It is possible to
combine more than 2 types of chart but there can only be two value axes. An example is given below:

https://www.apexofficeprint.com/docs/ 96/197
6/9/2019 APEX Office Print

"chart": {
"multiples": [
{
"columns": [
{
"data": [
{
"x": "day 1",
"y": "4.3"
},
{
"x": "day 2",
"y": "2.5"
},
{
"x": "day 3",
"y": "3.5"
}
],
"name": "bar 1"
},
{
"data": [
{
"x": "day 1",
"y": "2.4"
},
{
"x": "day 2",
"y": "4.4"
},
{
"x": "day 3",
"y": "1.8"
}
],
"name": "bar 2"
}
],
"type": "column"
},
{
"lines": [
{
"data": [
{
"x": "day 1",
"y2": "43"
},
{
"x": "day 2",
"y2": "25"
},
{
"x": "day 3",
"y2": "35"

https://www.apexofficeprint.com/docs/ 97/197
6/9/2019 APEX Office Print

}
],
"name": "line 1"
},
{
"data": [
{
"x": "day 1",
"y2": "24"
},
{
"x": "day 2",
"y2": "44"
},
{
"x": "day 3",
"y2": "18"
}
],
"name": "line 2"
}
],
"type": "line"
}
],
"options": {
"border": true,
"grid": true,
"height": 700,
"legend": {
"position": "r",
"showLegend": true
},
"title": false,
"width": 500
},
"type": "multiple"
}

will result in:

https://www.apexofficeprint.com/docs/ 98/197
6/9/2019 APEX Office Print

The following SQL can be used:

https://www.apexofficeprint.com/docs/ 99/197
6/9/2019 APEX Office Print

select
'file1' as "filename",
cursor(select
cursor(select
c.cust_first_name || ' ' || c.cust_last_name as "customer",
c.cust_city as "city" ,
o.order_total as "total" ,
o.order_timestamp as "timestamp"
from demo_customers c, demo_orders o
where c.customer_id = o.customer_id
order by c.cust_first_name || ' ' || c.cust_last_name
) as "report",
cursor(select
'multiple' as "type",
'My Combo: Column with Line Chart' as "name",
cursor(select
576 as "width" ,
336 as "height",
'Title' as "title" ,
'true' as "grid",
'true' as "border",
cursor(select
'true' as "showLegend",
'r' as "position"
from dual
) as "legend"
from dual
) as "options",
cursor(select
tp as "type",
cursor(select
nm as "name",
cursor(select to_char(o.order_timestamp, 'MON RRRR') "label",
to_char(o.order_timestamp, 'MON RRRR') "x",
sum (decode(p.category,nm,oi.quantity * oi.unit_price,0)
from demo_product_info p, demo_order_items oi, demo_orders o
where oi.product_id = p.product_id
and o.order_id = oi.order_id
group by to_char(o.order_timestamp, 'MON RRRR'), to_char(o.ord
order by to_char(o.order_timestamp, 'RRRR MM')
) as "data"
from (select 'Mens' nm from dual union all select 'Womens' nm from dua
where tp = 'column'
) as "columns",
cursor(select
nm as "name",
cursor(select to_char(o.order_timestamp, 'MON RRRR') "label",
to_char(o.order_timestamp, 'MON RRRR') "x",
sum (decode(p.category,nm,oi.quantity * oi.unit_price,0)
from demo_product_info p, demo_order_items oi, demo_orders o
where oi.product_id = p.product_id
and o.order_id = oi.order_id
group by to_char(o.order_timestamp, 'MON RRRR'), to_char(o.ord
order by to_char(o.order_timestamp, 'RRRR MM')
) as "data"
from (select 'Accessories' nm from dual)

https://www.apexofficeprint.com/docs/ 100/197
6/9/2019 APEX Office Print

where tp = 'line'
) as "lines"
from (select 'column' tp from dual union all select 'line' tp from dua
) as "multiples"
from dual
) as "chart"
from dual
) as "data"
from dual
```

### 6.1.5 D3 (Data Driven Documents) images

With Word/Excel/PowerPoint documents, it's possible to let AOP execute some JavaScript code to generate

Given the JSON file with following content:

```json
{
...
"files": [{
"filename": "output",
"data": {
"test": "CODE"
}
}]
}

With as (JSON-encoded) code:

https://www.apexofficeprint.com/docs/ 101/197
6/9/2019 APEX Office Print

// Based on https://bl.ocks.org/mbostock/7f5f22524bd1d824dd53c535eda0187f
const d3 = require('d3');
const D3Node = require('d3-node')
const d3n = new D3Node()

const svg = d3n.createSVG(512, 512);


const [width, height] = [512, 512];
const margin = { top: 20, right: 30, bottom: 30, left: 40 };

var x = d3.scaleLog().domain([2e-1, 5e0])


.rangeRound([margin.left, width - margin.right]);
var y = d3.scaleLog().domain([3e2, 2e4])
.rangeRound([height - margin.bottom, margin.top]);
var color = d3.scaleSequential(d3.interpolateYlGnBu).domain([0, 1.8]); // Points per square pixel.

svg.append("g")
.attr("transform", "translate(0," + (height - margin.bottom) + ")")
.call(d3.axisBottom(x).ticks(null, ".1f"))
.select(".tick:last-of-type text")
.select(function () { return this.parentNode.appendChild(this.cloneNode()); })
.attr("y", -3).attr("dy", null)
.attr("font-weight", "bold").text("Carats");

svg.append("g")
.attr("transform", "translate(" + margin.left + ",0)")
.call(d3.axisLeft(y).ticks(null, ".1s"))
.select(".tick:last-of-type text")
.select(function () { return this.parentNode.appendChild(this.cloneNode()); })
.attr("x", 3).attr("text-anchor", "start")
.attr("font-weight", "bold").text("Price (USD)");

d3.tsv("https://bl.ocks.org/mbostock/raw/7f5f22524bd1d824dd53c535eda0187f/diamonds.tsv", d => ({ carat:


if (error) throw error;
if (diamonds[0] instanceof Error) throw diamonds[0];
svg.insert("g", "g").attr("fill", "none")
.attr("stroke", "#000").attr("stroke-width", 0.5)
.attr("stroke-linejoin", "round").selectAll("path")
.data(d3.contourDensity()
.x(d => x(d.carat)).y(d => y(d.price))
.size([width, height]).bandwidth(10)
(diamonds))
.enter().append("path")
.attr("fill", d => color(d.value))
.attr("d", d3.geoPath());
finish(d3n);
});

And a Word document containing {?d3 test} would produce the following result:

https://www.apexofficeprint.com/docs/ 102/197
6/9/2019 APEX Office Print

https://www.apexofficeprint.com/docs/ 103/197
6/9/2019 APEX Office Print

Should a field "test_data": [1,2,3] be present in the JSON (at the same place as "test": "CODE" ), then
the code will have access to the global data which would be [1,2,3] , or whatever "test_data" is. String,
booleans, nunbers and objects are also possible.

6.1.5.1 Code structure


This is how the code is supposed to be organized:

// Import D3
const d3 = require('d3');
// Import D3-Node
const D3Node = require('d3-node');
// Instantiate a new D3Node, which will provide the SVG and will be required to finish
const d3n = new D3Node();
// Create a SVG (instead of selecting one from the (here non-existing) document)
const svg = d3n.createSVG(512, 512); // Different sizes are possible
// Start working on the SVG
svg.append('g').text('Test');
// etc
// We can access the _data field if it was given:
svg.append('g').text(data ? data.toString() : 'No data passed!');
// When the SVG is finished, call the global finish() with the used D3Node object
finish(d3n);
// We can also call the global fail() (or throw an error) should something fail:
fail(new Error('We are missing something!'));

6.1.5.2 Specifications and limitations


The d3 library is version 4.12.0
d3-contour and d3-scale-chromatic (along with all default 4.12.0 submodules) are preloaded, e.g.
d3.contour() is available
The code is run in an async environment, meaning await is available
The code has to either have a return statement with a D3Node object, or call finish() with one
After the code has successfully finished, the SVG will be extracted from the D3Node, converted to PNG
and pasted in the Word/Excel/...
ES2015, ES2016 and ES2017 are supported, run inside a Node environment
Only d3 libraries (including sub-libraries like d3-polygon) can be returned by require()
d3-request can only use http:// and https:// URLs
There are time limitations, e.g. the whole script will time out after 30s, even when it's still fetching data
over HTTP(S)
All errors are caught and will cause the whole PrintJob to fail. The stack trace will be shown

6.1.6 {#data_loop} … {/data_loop} tags


Using the opening tag {#data_loop} and closing tag {/data_loop}, we can loop inside the JSON array named
"data_loop", meaning the items that are inside the tags will be repeated for each array element. Again, like in
image tag "data_loop" is a variable. A loop tag is represented by "#" after the curly bracket.

6.1.6.1 General Data loop example


Given the JSON file with following content:

https://www.apexofficeprint.com/docs/ 104/197
6/9/2019 APEX Office Print

{
...
"files":[{
"filename" :"output",
"data":[{
"people":[{
"first_name" :"DemoName1",
"last_name" :"DemoLastName1",
"city" :"DemoCity1"},
{
"first_name" :"DemoName2",
"last_name" :"DemoLastName2",
"city" :"DemoCity2"},
{
"first_name" :"DemoName3",
"last_name" :"DemoLastName3",
"city" :"DemoCity3"}
]
}]
}]
}

and template.docx with following content:

The name of the employees are: {#people}{first_name}{last_name} from city {city}. {/people}

will result in:

The name of the employees are: DemoName1 DemoLastName1 from City DemoCity1. DemoName2
DemoLastName2 from City DemoCity2. DemoName3 DemoLastName3 from City DemoCity3.

6.1.6.2 Loops in table example


Using the previous data, if the template is changed to:

the result will then be:

6.1.6.3 Loops with numbering example

https://www.apexofficeprint.com/docs/ 105/197
6/9/2019 APEX Office Print

Using the previous data, if the template is changed to:

the result will be:

6.1.6.4 Loops in bullets


The same can be done with bullets:

will result in:

6.1.6.5 Math operations during a loop


Numeric operations inside a loop are supported by using the | operator. The following operations are
supported: |sum , calculates the total sum of a numeric property during a loop. |avg , calculates the total
average of a numeric property during a loop. |min , returns the minimum numeric value of a property during a
loop. |max , returns the maximum numeric value of a property during a loop.

The following template is given:

https://www.apexofficeprint.com/docs/ 106/197
6/9/2019 APEX Office Print

Results in:

https://www.apexofficeprint.com/docs/ 107/197
6/9/2019 APEX Office Print

6.1.7 Horizontal Tabular Looping


Since verion 18.1 AOP also supports horizontal tabular looping using the {:horizontal_loop} ... {/horizontal_loop}
tags. However, this tag can be used to repeat only one row (in Word, in Excel this works like normal loop tag and
repeats the cells defined by the rectangular boundary of starting and closing tag). Following is an example on

https://www.apexofficeprint.com/docs/ 108/197
6/9/2019 APEX Office Print

how this could be used:

6.1.8 Simple angular like expressions

https://www.apexofficeprint.com/docs/ 109/197
6/9/2019 APEX Office Print

Simple angular like expressions are also supported that can perform simple mathematical operations.

A full list of Angular expression can be found at https://docs.angularjs.org/guide/expression


(https://docs.angularjs.org/guide/expression).

6.1.8.1 Simple Expressions


Expressions like {num1 + num2} will print the sum of num1 and num2. Division, multiplication, addition and
subtraction are allowed.

If the given key has a boolean value then you can use {#boolean key}…{/boolean key} to print the content
inside tags if the value of boolean key is true. For negation {^boolean key}…{/boolean key} is used. The
content inside these tags will be printed if the boolean key has false as value or if boolean key does not exists or
if boolean key is an empty array.

6.1.8.2 String/Number Comparison


You can also check the value of keys with {#key=='value'}…{/key=='value'}. The content inside the tags will be
only printed if the value of the key is equal to "value". Note here in {#key=='value'}, that straight single quotes
are used!

The numbers can also be compared in the same way as strings {#key>;50}…{/key>;50}.The content inside the
tags will be only printed if the value of the key is greater than 50. The following operators are supported: <, >,
<=, >=, ==, !=

6.1.8.3 Conditional and Comparison operator


Another way to compare variables is as follows: {key == 'value' ? key2 : key3}. This way other keys/variables
can also be inserted. This will print out value of key2 if the expression is true and key3 if the expression is false.

Possible conditional operators are:

Equal: == (equal to) or === (equal value and equal type)


Not Equal: != or !== (not equal value or not equal type)
And: &&
Or: ||
Greater than: >
Less than: <
Greater than or equal: >=
Less than or equal: <=

6.1.8.4 Conditional example


For the JSON given in example below {currency == 'EUR' ? '€'+price : price+'$'} prints €50 if true and 50$ if false
and given price variable is 50.

Given the JSON file with following content:

https://www.apexofficeprint.com/docs/ 110/197
6/9/2019 APEX Office Print

{
...
"data":[{
"product":[{
"product_name" :"Business Shirt",
"quantity" :3,
"unit_price" :50,
"onstock" :true,
"cur" :"EUR"
},
{
"product_name" :"Trousers",
"quantity" :3,
"unit_price" :80,
"onstock" :false,
"cur" :"USD"
},
{
"product_name" :"Jacket",
"quantity" :3,
"unit_price" :15,
"onstock" :true,
"cur" :"USD"
},
{
"product_name" :"Blouse",
"quantity" :3,
"unit_price" :60,
"onstock" :false,
"cur" :"EUR"
}]
}]
}

and template with following content:

will result in:

https://www.apexofficeprint.com/docs/ 111/197
6/9/2019 APEX Office Print

Angular expressions can also be used inside floating texts. Below an example where the images are put inside
floating textbox and are shown under condition.

6.1.8.5 String operations


If you tag resolves to a string then you can also use string manipulation functions like: substr, length, substring,
replace, split. see prototype methods https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Global_Objects/String

https://www.apexofficeprint.com/docs/ 112/197
6/9/2019 APEX Office Print

6.1.8.5 Array Operations


If your tag resolves to array, i.e for using on {#loop} tag. You can access the length of the loop array by .length
property for example {loop.length}. You can also access individual array element with array access notation of
javascript, for example {loop[0].loop_inisde_element}.

6.1.9 Labels printing


AOP also provides a way to print the labels in word document. To do so you can create a document with labels
from going to Mailings options and then to Labels. Fill in the tags in address field and choose the type of label by
clicking in Label option. A document can then be generated by clicking New document. Currently however if
labels are getting printed then we expect the document only containing labels and no other information, and that
the tag keys are not used more than once. Given the JSON file:

...
"data": {
"labels": [
{
"city": "city1",
"first_name": "firstname1",
"last_name": "lastname1",
"title": "Mr.",
"tracking_number_text": "TN49775377172",
"tracking_number": "TN49775377172",
"tracking_number_type": "code128",
"zip_code": 6981
},
...
{
"city": "city12",
"first_name": "firstname12",
"last_name": "lastname12",
"title": "Mr.",
"tracking_number_text": "TN49709864775",
"tracking_number": "TN49709864775",
"tracking_number_type": "code128",
"zip_code": 9740
}
]
}
...

and template:

https://www.apexofficeprint.com/docs/ 113/197
6/9/2019 APEX Office Print

will produce:

https://www.apexofficeprint.com/docs/ 114/197
6/9/2019 APEX Office Print

Note that in the first cell you need to add the {labels} tag. See also the Sample app.

6.1.10 HTML tag


HTML tags can also be converted to Word. The tag that has to be used is {_key}, thus underscore followed by
the key which has HTML content in JSON. The tags that are currently supported are:

https://www.apexofficeprint.com/docs/ 115/197
6/9/2019 APEX Office Print

<br /> : in order to introduce breaks (newline)


<p> .. </p> : represents a paragraph
<strong> .. </strong> : bold text
<b> .. </b> : bold text
<s> .. </s> : strike through
<u> .. </u> : underline
<em> .. </em> : italics
<h1> .. </h1> : heading 1
<h2> .. </h2> : heading 2
<h3> .. </h3> : heading 3
<h4> .. </h4> : heading 4
<h5> .. </h5> : heading 5
<h6> .. </h6> : heading 6
<sub> .. </sub> : subscript
<sup> .. </sup> : superscript
<ol> .. </ol> : ordered list
<ul> .. </ul> : unordered list
<li> .. </li> : list item
<table> .. </table> : table (including th, tr, td)
<caption> .. </caption> : caption
<img> : image
<pre> .. </pre> : preformatted text

<span style="..">..</span> : text between the span will have the style defined, background-color, color

Eg: Given the following key inside data:

"htmlcontent": "<p>This is text coming from the database / session in HTML format.
<br />It supports:
</p>
<ol>
<li>Lists</li>
<li><strong>Bold</strong></li>
<li><em>Italic</em></li>
<li><u>Underline</u></li>
<li><s>Strikethrough</s></li>
<li>Sub<sub>script</sub></li>
<li><sup>Super</sup>script</li>
<li><span style="color:#FF0000">Text Color</span></li>
<li><span style="background-color:#FFFF00">Background Text Color</span>
</li>
</ol>

<h1>Heading 1</h1>
<h2>Heading 2</h2>
<h3>Heading 3</h3>
<h4>Heading 4</h4>
<p>Normalt text with<span style="font-family:comic sans ms,cursive"> Font Change</span></p>
<p><span style="font-family:courier new,courier,monospace">Code font</span>
</p>"

and the template:

https://www.apexofficeprint.com/docs/ 116/197
6/9/2019 APEX Office Print

will produce:

https://www.apexofficeprint.com/docs/ 117/197
6/9/2019 APEX Office Print

6.1.11 Interactive Report (IR) tag


{&interactive} will be replaced in the given template by the interactive report that has been selected in APEX.
Other than the simple interactive report, there are three other options that can be selected: Control Break, Group
By, Pivot. Those will be illustrated below. Keep in mind that the tag that gets replaced is {&interactive}, no matter
which of the above options is selected in APEX. For a concrete example, see section 11.

Control Break: By clicking on Actions and selecting Control Break, one or more columns can be selected on
which the table should be broken. For the purpose of illustration, assume we select Quantity.

https://www.apexofficeprint.com/docs/ 118/197
6/9/2019 APEX Office Print

This splits the table up into partitions based on the value of the selected column. Thus, rows sharing the same
value for Quantity, will be grouped together into the same partition. The resulting table can be seen below:

As a final note, this option also supports the application of aggregates on the table data.

https://www.apexofficeprint.com/docs/ 119/197
6/9/2019 APEX Office Print

Group By: By clicking on Actions and selecting Group By, one or more columns can be selected on which the
table data should be grouped by. For the purpose of illustration, assume we select Quantity. Furthermore, one or
more functions can be applied on the table data. In this example, we request the sum of the unit price for every
group.

The result is a new table with one column for every selected column on which the data should be grouped by,
and one column for every selected function to be applied on the group data.

The resulting table can be seen below:

https://www.apexofficeprint.com/docs/ 120/197
6/9/2019 APEX Office Print

Additionally, a custom label and format may be selected for each function column and a sum can be performed
over the values of each function column.

Pivot: By clicking on Actions and selecting Pivot, the user is prompted to select at least one pivot column, at
least one row column and at least one function over a particular column. Important to note is that the row
column, pivot column and function column need to be different. For the sake of the example, we select Quantity
as a pivot column, Product Name as a row column and sum over Unit Price as a function.

https://www.apexofficeprint.com/docs/ 121/197
6/9/2019 APEX Office Print

The resulting table can be seen below:

The additional options supported in this case are the same as the ones in Group By.

Chart: AOP can also print your Interactive Report Chart view directly in your template by using {\$interactive}.

https://www.apexofficeprint.com/docs/ 122/197
6/9/2019 APEX Office Print

The result in PowerPoint can be seen below:

https://www.apexofficeprint.com/docs/ 123/197
6/9/2019 APEX Office Print

Note that this is a native PowerPoint chart, so you can adapt, make bigger, change colors, etc. directly in
PowerPoint.

Width Manipulation: Since 18.2.2 it is possible to manipulate the widths of the interactive columns. You can do
so by specifying it on HTML_EXPRESSION. You can use the following in html expression.

<span data-aop-width-weight="2"></span>#COLUMN_NAME#

The default weight for each column is 1. Let's say you have 4 columns and you provide this html expression in
the first colum. This will double the size of the first column in comparison to the remaining 3.

The following formula is used to calculate the percentage of width a column gets:

(weight of column)/(total weight provided for all the columns) * 100. Please note that these widths are the
desired widths. If the content does not fit, it could be that the minimum width that fits will be taken by
Word/LibreOffice.

6.1.12 Multiple Interactive Reports in one template


In this case, the template needs to have tags of the form {&interactive_1},{&interactive_2} and these tags will be
replaced by the corresponding interactive reports. Many interactive reports can be selected by giving in their
static IDs in a particular order (ir1,ir2,...) and it is in that order that their data will be inserted in the template.
Thus, {&interactive_1} gets replaced by the data in the first interactive report (static Id: ir1) and similarly for
{&interactive_2} that will get replaced by the data in the second interactive report (static Id: ir2) and so on.

https://www.apexofficeprint.com/docs/ 124/197
6/9/2019 APEX Office Print

The result can be seen below:

https://www.apexofficeprint.com/docs/ 125/197
6/9/2019 APEX Office Print

6.1.13 Table cell background


You can give a background to a cell in a table in Word by using the column followed by _cell_background_color.
The tag in the template should end with a $.

cursor(select p.product_name as "product_name",


i.quantity as "quantity",
case
when i.quantity between 1 and 2 then '#00FF00'
when i.quantity between 2 and 3 then '#00FF00'
else '#0000FF'
end as "quantity_cell_background_color",
i.unit_price as "unit_price"
from demo_order_items i, demo_product_info p
where o.order_id = i.order_id
and i.product_id = p.product_id
) "backcolor"

https://www.apexofficeprint.com/docs/ 126/197
6/9/2019 APEX Office Print

6.1.14 Right to Left tag


In word when substituting the content in language written in right to left like Arabic, the {<rightToLeft} tag can be
used to properly format the language. If the substituting content does not contain any right to left language
character, then it will behave as normal substitution tag.

6.1.15 Footnote tag


A footnote tag can be used to insert footnote. The tag should start with "+" symbol. For example, given the
following template:

and the data as follows:

{
"quote":"Only I can change my life. No one can do it for me.",
"person":"Carol Burnett"
}

will result in:

https://www.apexofficeprint.com/docs/ 127/197
6/9/2019 APEX Office Print

6.1.16 Hyperlink tag


Since AOP3.3 hyperlink feature is added using a tag that start with a * like: {*tag}. Given the template:

https://www.apexofficeprint.com/docs/ 128/197
6/9/2019 APEX Office Print

And the data:

{
"name": "Support",
"company_url": "https://www.apexofficeprint.com",
"company_url_text": "APEX RND",
"mail": "support@apexofficeprint.com"
}

will result in:

https://www.apexofficeprint.com/docs/ 129/197
6/9/2019 APEX Office Print

The mail hyperlinks are automatically detected and mailto: will be appended for the link to work. The hyperlink
text can be given by giving extra data that ends with _text. e.g: {*tag_text}. (see json above).

This hyperlink will also work when output pdf is wished.

Please note that in Excel the hyperlink will be added but the style will remain normal. You can change the tag
style in template if another styling is wished. In Word your default hyperlink styling will be taken. If you wish
another styling, you can change the style of the tag and add tag_preserve_tag_style:true options in the data.

6.1.17 Table Of Content


AOP versions greater than 3.5, also support generation of table of content in Word. Placing the {~tockey} tag will
generate table of content at the place where this tag is used. Since AOP version 18.2.3, AOP allows you to
customize table of content. The following options are available:

"tockey_title":"Title of Table Of Content", //Default Contents


"tockey_show_level": 3, //The depth of heading to be shown, default 3
"tockey_tab_leader": "underscore", //How the space between title and page number should be filled. Can

6.1.18 Word Subtemplating


Inside Word documents, the tag {?include NAME} is available.

Given the following JSON:

https://www.apexofficeprint.com/docs/ 130/197
6/9/2019 APEX Office Print

{
...
"template": {
"filename": "Template",
"file": "UEsDBBAQBgQ...",
"template_type": "docx"
},
"templates": [
{
"name": "Subtemplate1",
"mime_type": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"file_source": "base64",
"file_content": "UEsDBBAQBgAIAA..."
}
]
}

with the template containing {?include Subtemplate1} would replace the tag with the contents of the
subtemplate.

This tag can be used inside loops, and tags inside the subtemplate will also be replaced.

For example:

{#products}
Product {name}
{?include Subtemplate1}
{/products}

Should the subtemplate just consist of the content Amount: {amount} , then this could be an example result:

Product Product1
Amount: 5
Product Product2
Amount: 36

This tag is currently only available inside Word templates, and the subtemplates currently can only be Word
documents (templates) too.

6.2 PowerPoint (pptx) template


For pptx template files same tags are supported as in docx template. Attention should be paid when using "#",
"%", "\$" and "\^" tags, namely they should be on their own text field. The position of the text field will
determine where the top left of the chart and image will start. Repeating a template slide is done by specifying
which array should be looped with "!" tag after the curly bracket for example {!products} to repeat over product
array. If none is declared the root object is taken as array. Multiple "!" tags are not allowed in one slide.

Given the JSON file with following content:

https://www.apexofficeprint.com/docs/ 131/197
6/9/2019 APEX Office Print

{
"template": {
"template_type": "pptx",
"filename": "demo.pptx"
},
"output": {
"output_encoding": "raw",
"output_type": "pptx"
},
"files": [
{
"filename": "output",
"data": [
{
"slide_title": "Slides Per Product",
"company_name": "Company A",
"product": [
{
"product_name": "Business Shirt",
"quantity": 3,
"unit_price": 50
},
{
"product_name": "Trousers",
"quantity": 3,
"unit_price": 80
},
{
"product_name": "Jacket",
"quantity": 3,
"unit_price": 15
},
{
"product_name": "Blouse",
"quantity": 3,
"unit_price": 60
}
]
}
]
}
]
}

and the pptx template as follows:

https://www.apexofficeprint.com/docs/ 132/197
6/9/2019 APEX Office Print

will result the following for the first slide:

https://www.apexofficeprint.com/docs/ 133/197
6/9/2019 APEX Office Print

Since there is only one item in root JSON object this is repeated only once. In template slide 2 we have specified
product array as our loop array with {!product} tag. Since there are 4 objects in our product array this template
will be repeated four times. The result is as follows:

https://www.apexofficeprint.com/docs/ 134/197
6/9/2019 APEX Office Print

https://www.apexofficeprint.com/docs/ 135/197
6/9/2019 APEX Office Print

6.3 Excel (xlsx) template


In the xslx templates, some of the same tags as the previous types of templates can be used, as shown in the
overview table at the start of this section. The JSON format should contain the same meta information elements
(e.g. template_type, filename, …) and the data information is stocked under files/data.

Regular tags can be used with corresponding keyword in the JSON file between brackets, like in the docx and
pptx templates. The xlsx templates can loop over elements in a list by using the same technique as in the docx
template: {#loop_element} to enter the loop and {/loop_element} to close it. The cells that are in the rectangle
bounded by these two tags will be looped over and filled in using the data available in the JSON file. Nested

https://www.apexofficeprint.com/docs/ 136/197
6/9/2019 APEX Office Print

loops are possible (however keep in mind to remain within the rectangle formed by the "parent" loop – see note
after example below). Style will be copied from the template to the generated file accordingly. As with the docx
templates, simple angular expressions can be used to perform mathematical operations.

Xlsx example:

Given the JSON file with following content:

{
"template": {
"template_type": "xlsx",
"filename": "simple.xlsx"
},
"output": {
"output_encoding": "raw",
"output_type": "xlsx"
},
"files": [
{
"filename": "file1",
"data": [
{
"cust_first_name": "Albert",
"cust_last_name": "Lambert",
"cust_city": "St. Louis",
"orders": [
{
"order_total": 310,
"order_name": "Casual Shop's Order",
"product": [
{
"product_name": "Shirt",
"quantity": 3,
"unit_price": 50
},
{
"product_name": "Trousers",
"quantity": 2,
"unit_price": 80
}]
},
{
"order_total": 200,
"order_name": "Sport Shop's order",
"product": [
{
"product_name": "Sport's shoes",
"quantity": 2,
"unit_price": 100
}]
}]
}]
}]
}

and the xlsx template as follows:

https://www.apexofficeprint.com/docs/ 137/197
6/9/2019 APEX Office Print

Note: in the example above the {/orders} closing tag must be in the last column. Otherwise the child loops inside
{#orders}…{/orders}, in this case {#product}…{/product}, would not be able to generate inside the rectangle
formed between the tags of its parent loop ({#orders}…{/orders}).

Interactive Report in Excel: As of version 2.2, all of the functionalities supported in Word regarding the
interactive report are also supported in Excel. For the purpose of illustration, let's take this template as input:

The resulting output is then:

https://www.apexofficeprint.com/docs/ 138/197
6/9/2019 APEX Office Print

6.3.1 {data_string_with_cell_markup$}
AOP 3.0 and above also supports cell settings. With a $ sign at the end of a tag, it is possible to specify different
styles in a cell. This allows user to change for example the background of the cell dynamically. An example of
such tag is {tag_with_style$}. The different styles then can be specified by appending either of the following in
the data: + cell_locked: [y/n] + cell_hidden: [y/n] + cell_background: hex color e.g: #ff0000 + font_name: name of
the font e.g: Arial + font_size: e.g 14, + font_color: hex color e.g: #00ff00 + font_italic: [y/n] + font_bold: [y/n] +
font_strike: [y/n] + font_underline: [y/n] + font_superscript:[y/n] + font_subscript:[y/n] + border_top: [dashed /
dashDot / hair / dashDotDot / dotted / mediumDashDot / mediumDashed / mediumDashDotDot / slantDashDot /
medium / double / thick ] + border_top_color: hex color e.g: #000000 + border_bottom: [dashed / dashDot / hair /
dashDotDot / dotted / mediumDashDot / mediumDashed / mediumDashDotDot / slantDashDot / medium /
double / thick ] + border_bottom_color: hex color e.g: #000000 + border_left: [dashed / dashDot / hair /
dashDotDot / dotted / mediumDashDot / mediumDashed / mediumDashDotDot / slantDashDot / medium /
double / thick ] + border_left_color: hex color e.g: #000000 + border_right: [dashed / dashDot / hair / dashDotDot
/ dotted / mediumDashDot / mediumDashed / mediumDashDotDot / slantDashDot / medium / double / thick ] +
border_right_color: hex color e.g: #000000 + border_diagonal: [dashed / dashDot / hair / dashDotDot / dotted /
mediumDashDot / mediumDashed / mediumDashDotDot / slantDashDot / medium / double / thick ] +
border_diagonal_direction: [up-wards|down-wards| both] + border_diagonal_color: hex color e.g: #000000 +
text_h_alignment: [top|bottom|center|justify] + text_v_alignment: [top|bottom|center|justify] + text_rotation:
rotation of text value from 0-90 degrees

Please note that if the tag is {example$} then the data provided should be inside example_cell_background,
example_font_italic ...e.t.c.

6.3.2 {!sheetgeneration}

https://www.apexofficeprint.com/docs/ 139/197
6/9/2019 APEX Office Print

With AOP 3.3 and above you can also generate sheets automatically by using {!tag} in any cell. This can be
used for example to generate a sheet report per customer. The sheet name can also be dynamically changed
and should be provided by the key "sheet_name". An example:

https://www.apexofficeprint.com/docs/ 140/197
6/9/2019 APEX Office Print

{
"customers": [
{
"sheet_name": "John Dulles", //sheet name!
"cust_first_name": "John",
"cust_last_name": "Dulles",
"cust_city": "Sterling",
"orders": [
{
"order_total": 2380,
"order_name": "Order 1",
"product": [
{
"product_name": "Business Shirt",
"quantity": 3,
"unit_price": 50
},
{
"product_name": "Trousers",
"quantity": 3,
"unit_price": 80
},
{
"product_name": "Jacket",
"quantity": 3,
"unit_price": 150
}
]
}
]
},
{
"sheet_name": "William Hartsfield",
"cust_first_name": "William",
"cust_last_name": "Hartsfield",
"cust_city": "Atlanta",
"orders": [
{
"order_total": 1640,
"order_name": "Order 1",
"product": [
{
"product_name": "Blouse",
"quantity": 4,
"unit_price": 60
},
{
"product_name": "Skirt",
"quantity": 4,
"unit_price": 80
}
]
},
{
"order_total": 730,
"order_name": "Order 2",

https://www.apexofficeprint.com/docs/ 141/197
6/9/2019 APEX Office Print

"product": [
{
"product_name": "Blouse",
"quantity": 4,
"unit_price": 60
}
]
}
]
}
]
}

And the template:

will result in:

https://www.apexofficeprint.com/docs/ 142/197
6/9/2019 APEX Office Print

6.3.4 {*hyperlink}
This is similar to hyperlink tag mentioned in section 6.1.16. In Excel, it is possible to hyperlink to a specific sheet
and cell inside the document itself. The URL then should be of structure: "SheetName!Cell". An example:

https://www.apexofficeprint.com/docs/ 143/197
6/9/2019 APEX Office Print

{
"examplehyperlink": "HyperlinkTarget!B2",
"examplehyperlink_text": "Go to HyperlinkTarget"
}

with template

will result in:

https://www.apexofficeprint.com/docs/ 144/197
6/9/2019 APEX Office Print

6.4 QRCode Image Replacing


AOP also allows you replace a QRcode image with another image. The qr code can contain the image tags and
barcode tags, i.e {%key} or {|key}. This method can be used if you are inserting a floating image, or need to
have certain border styles on the image. The tag replacing will work as look as there are no artistic effects used
for the image themselves.

Please note that the scope always starts at the default place, so the {#loop} tags have no effect.

https://www.apexofficeprint.com/docs/ 145/197
6/9/2019 APEX Office Print

6.5 Converter
This feature only works when the output_type is pdf

AOP can convert several types of files and/or append/prepend them to the outputted files.

6.5.1 Appending/prepending files


All append/prepend files will first be converted to PDF, after which the pages (as a whole) will be
prepended/appended to the outputted files. E.g. images will appear on their own page, not "pasted" into the
template file.

6.5.1.1 General structure


The JSON sent to AOP will have this structure:

https://www.apexofficeprint.com/docs/ 146/197
6/9/2019 APEX Office Print

{
...
"template": { ... },
"output": {
"output_encoding": "base64",
"output_type": "pdf" // Converter functionality only works with PDF as output_type
},
"files": [
{
"data": { ... },
"filename": "File1"
},
{
"data": { ... },
"filename": "File2"
},
...
],
"prepend_files": [
// Array of prepend files (see 6.5.1.2 File Structure)
{ ... },
{ ... },
...
],
"append_files": [
// Array of prepend files (see 6.5.1.2 File Structure)
{ ... },
{ ... },
...
]
}

6.5.1.2 File structure

{
"filename": "Filename",
"mine_type": "MIME TYPE",
// File source can be "plain", "base64", "url" or "file",
"file_source": "FILE SOURCE",
// Used by "file_source": "plain" and "base64",
"file_content": "...",
// Used by "file_source": "url",
"file_url": "http://...",
}

6.5.1.3 Multiple files


Should the JSON contain multiple files, e.g. like this:

https://www.apexofficeprint.com/docs/ 147/197
6/9/2019 APEX Office Print

{
...
"files": [
{
"data": { ... },
"filename": "File1"
},
{
"data": { ... },
"filename": "File2"
},
...
],
}

Then, as might be expected, a zip archive will be returned containing File1.pdf and File2.pdf. The
append/prepend files will be appended/prepended to each file.

6.5.2 Converting without template


AOP allows converting files without a template, resulting in the append/prepend files being converted and
stitched together.

6.5.2.1 General structure


The JSON sent to AOP will have this structure:

https://www.apexofficeprint.com/docs/ 148/197
6/9/2019 APEX Office Print

{
...
"template": {
// This template_type is template-less
"template_type": "converter"
},
"output": {
"output_encoding": "base64",
"output_type": "pdf", // Converter functionality only works with PDF as output_type
"icon_font": "Font Awesome 5" // Changes the rendering font used to generate icons when convert
},
// If the files array is empty, it'll default to a file with filename "Converted"
// Giving (multiple) files will just result in a zip archive with identical files, but with the giv
"files": [],
"prepend_files": [
// Array of prepend files (see 6.5.1.2 File Structure)
{ ... },
{ ... },
...
],
"append_files": [
// Array of prepend files (see 6.5.1.2 File Structure)
{ ... },
{ ... },
...
]
}

Should "files" be empty or only contain one file, and "append_files" or "prepend_files" only contain
one file, then the output file will just be that append/prepend file converted to PDF.

6.5.3 Supported mime types for


converting/appending/prepending
PDF application/pdf
Text text/plain
CSV text/csv
Markdown text/markdown
HTML text/html
Word application/vnd.openxmlformats-officedocument.wordprocessingml.document
Excel application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
PowerPoint application/vnd.openxmlformats-officedocument.presentationml.presentation
JPEG image/jpeg
PNG image/png
GIF image/gif
BMP image/bmp
MS-BMP image/x-ms-bmp

Mind that tags in append/prepend files will not be parsed! Append/prepend files are only converted and
appended/prepended to the output files.

https://www.apexofficeprint.com/docs/ 149/197
6/9/2019 APEX Office Print

7 SQL Structure
7.1 How to write SQL queries and map them to
template documents
Please refer to the image below containing SQL query and matching template.

AOP Plug-in supports PL/SQL cursor expressions which can be used in your templates as "data loops".

Left side corresponds to the SQL query that we used in our demo example. Right side is our Word template.

In SQL query you will notice three inner cursors called data, orders and product.

Idea is for each customer to find orders and products and display it as an invoice letter.

Data cursor is a standard part of AOP JSON structure and it needs to be present in all SQL queries. At the same
time you do not have to specify it as a loop in your template. For more details about this please reference
Section 9 of this Manual.

Other two cursor names can be of your preference as long as they are reflected in your template.

Why do we have cursor syntax?

This is the way AOP engine merges your data with your templates.

In our template example you want to display customer details (Data cursor) and then display all their orders
(Orders cursor) with products (Product cursor) so each represents a separate cursor.

This means that we want to be able to create a loop for orders and a separate loop for products. This is exactly
what we have done in this template.

The way AOP template loop works is by using {#loop element}….{/loop element} notation. In the template notice
that we are using the following:

"Thank you for shopping at. We have following products reserved for you:

{#orders}{#product}
- {product_name}{/product}
The total amount of your order is €{order_total}.
{/orders}"

First open Orders loop then open Product loop then doing a bullet numbering for all products. Before closing the
Product loop and then closing the Orders loop.

Once you create your SQL query it is very easy to implement it in your template following few simple tagging
rules depending on a template type you are creating.

https://www.apexofficeprint.com/docs/ 150/197
6/9/2019 APEX Office Print

8 Server (only On-Premise)


8.1 Installation
APEX Office Print is using an external converter. By default LibreOffice is used (available on all platforms), but
this can be changed to MS Office (Windows only). One of these products must be installed on the same server
where you will also install APEX Office Print.

You can register and then login at https://www.apexofficeprint.com (https://www.apexofficeprint.com). Go to


Downloads and download On Premise package for your platform. Currently we support Linux, Windows and
OSX.

https://www.apexofficeprint.com/docs/ 151/197
6/9/2019 APEX Office Print

Unzip the downloaded file, you will see a directory with the version downloaded version number of AOP e.g
v18.1/

Go to the version directory/server directory and copy executable file on the server where you want AOP running
in a directory of your choice

Executable files:

OSX: APEXOfficePrintOSX64
Linux (Redhat): APEXOfficePrintLinux64
Windows: APEXOfficePrintWin64

Decide on which port you want to let AOP run. By default it is using port 8010. You can change that later (for
example APEXOfficePrintLinux64 -p 5555).

https://www.apexofficeprint.com/docs/ 152/197
6/9/2019 APEX Office Print

If you want to run the On-Premise Trial version of AOP you can skip the activation step.
The on-premise version of AOP in Trial mode will work with Word and PDF, but it contains a trial waterm
The cloud version of AOP (free 100 days) has no limitations.

Following step is only necessary when you bought AOP, it's not necessary to run in Trial mode (Linux
example):

run ./APEXOfficePrintLinux64 -a
this will activate the software
you have to enter the email you registered with and it will try to generate the license key. License key will
be generated if you have an open connection to the internet. If there’s no internet connection, or
something goes wrong with the activation, AOP will generate a license request file. You can upload this
license request file on your dashboard at https://www.apexofficeprint.com/. You can also contact
support@apexofficeprint.com and send this generated file as attachment. We’ll send you the license file
per email.
exit AOP

To start APEX Office Print:

run ./APEXOfficePrintLinux64 &


or if you want it on a different port ./APEXOfficePrintLinux64 -p 8012 & ( on Linux using & at the end of the
command, will run this command in backround)

PDF converter options:

LibreOffice can be downloaded from https://www.libreoffice.org (https://www.libreoffice.org). Make sure you


download LibreOffice 5 or higher and no older version of LibreOffice is installed. Once the installation of
LibreOffice is complete check if you can run soffice --version in a terminal.

You should see something like:

LibreOffice 5.4.4.2 22b09f6418e8c2d508a9eaf86b2399209b0990f4

If that fails, make sure your environment variable PATH contains the directory of LibreOffice (bin directory). You
can also create a symbolic link to soffice e.g.

ln -s /opt/libreoffice5.4/program/soffice /usr/sbin/soffice

Note that if you choose to convert using libreoffice the conversion will be done in Parallel.

If you're on Windows, you can choose for LibreOffice or MS Office. In case you want to use MS Office, make
sure you have MS Office 2003 or higher installed and also install OfficetoPDF
(https://www.cognidox.com/officetopdf-converter/) (direct download
(https://github.com/cognidox/OfficeToPDF/releases)), which allows to run conversions from the command line.
Note: Place the OfficetoPDF executable location in the system PATH variable.

After installing LibreOffice or MS Office, restart AOP.

From version 18.1 onwards, it is possible to specify other converters. On the first run of APEXOfficePrint a
configuraion file, aop_config.json, is created. Below an example:

https://www.apexofficeprint.com/docs/ 153/197
6/9/2019 APEX Office Print

{
"config": {
"port": 8010,
"startat": "./",
"license": "./aop.license",
"silent": false,
"verbose": false,
"enable_printlog": false,
"idle_timeout": 120,
"instances": 1,
"https_key": "",
"https_cert": "",
"https_port": false,
"ipwhitelist": "",
"pdf_temp_folder": "",
"max_parallel_conversions":0,
"pdf_error_threshold": 3,
"enable_save": false,
"enable_local_resources": false,
"enable_macro": false
},
"converters": {
"abiword":{
"command": "abiword --to={outputFormat} --to-name={outputFile} {inputFile}",
"handlesParallel": false
}
},
"post_process_commands": {
"echo":"echo \"{inputFile} with input format ${inputFormat} has been successfully processed.\""
}

This allows for the users to use the converter of their choice. In the command section the following tags will be
replaced:

{outputFormat}: will be replaced by the output format needed. e.g: pdf


{outputFile}: the location and filename of the expected output. (includes output extension and is absol
{inputFile}: the location where the file for the conversion is located. (includes inputformat extenstio
{inputFormat}: the intput format of the input file. e.g. docx
{inputDir}: the directory where the inputFile is located. //After version 19.1.2
{outputDir}: the output dir where AOP expects the output PDF (will always be the same as inputDir) //Af

The other option handlesParallel should be true if the specified custom converter is capable of handling
multiple pdf conversions at the same time. If a custom converter is used and the specified converter cannot
handle parallel conversion, then the conversions are placed in a queue and called on first come first serve basis
(even when multiple instances of AOP are running).

Barcode option:

https://www.apexofficeprint.com/docs/ 154/197
6/9/2019 APEX Office Print

Before AOP 3.1 an external tool needed to be installed to be able to generate barcodes, but since AOP 3.1 and
above that is not necessary anymore. All the necessary components are within AOP itself.

Testing the connection to AOP:

Make sure the database server can connect to the port where AOP is running. If not, open the port so the
database server can connect to the webserver:port (note you don't need to open it up to everybody, just the
database server is fine)

For example by running curl webserver:port (curl can be downloaded for free for windows via
https://curl.haxx.se/download.html#Win64 (https://curl.haxx.se/download.html#Win64))

$ curl 127.0.0.1:8010

The installation on the server part is now complete.

In the downloaded zip file there is also a sample application (app directory) that can be imported or you can just
import the AOP plug-in (plugin directory) into your application. The only configuration there is to define the
webserver:port where AOP is running and which converter you are using (LibreOffice, MS Office). You can do
that under Shared Components > Component Settings. Then select APEX Office Print (AOP) Plug-in, change
AOP URL and select appropriate converter.

8.2 Configuration
Following parameters can be used:

-p or --port can set a different port the server should be running at

Example: to run AOP on port 8015 run:

APEXOfficePrintLinux64 -p 8015 (or ./APEXOfficePrintLinux64 -p 8015)

8.3 Unlock Trial version


By default AOP will run in TRIAL version.

Only Word, PowerPoint and Excel templates can be created/processed in the TRIAL version of AOP. Once you
have decided on a license level, the product can be activated by running -a or --activate:

\$ APEXOfficePrintLinux64 -a

It will prompt for an email. Please use the same email you used when you subscribed for a license on
https://www.apexofficeprint.com/ (https://www.apexofficeprint.com/)

When running AOP again, it will show the new licensed templates you can use.

If there’s no internet connection, or something goes wrong with the activation, AOP will generate a license file
which you can upload on the dashboard at https://www.apexofficeprint.com/. Add the generated file in the same
directory of AOP and restart AOP to get the full version.

8.4 Server Options


To view all available option, run ./APEXOfficePrintLinux64 -h

https://www.apexofficeprint.com/docs/ 155/197
6/9/2019 APEX Office Print

Following parameters can be used:


-a or --activate : Activate the software
-h or --help : Show this menu
-p or --port : For giving in the running port default: 8010
Example: APEXOfficePrint -p 5555
-s or --startat : Directory to start at.
--license : The location of license file.
Default looks at the startup directory
--silent : Do everything quietly even start message
-v or --version : Show the current version of AOP
--verbose : Log what AOP is currently doing.
--enable_printlog : Log data about the printjobs to server_printjob.log.
--idle_timeout : The maximum idle seconds for a request.
: Default: 2 (pdf conversion time is considered idle)
-i or --instances : The number of instances of AOP to start
Giving 0 will start max instances available
--https_cert : The location of the https certificate
--https_key : The location of the https private key file
--https_port : The port for the https server to run on.
Having a key/cert but no port will make the https
server use the port from -p/--port (or the default)
Example: .. -p 80 --https_port 443 -https_key ...
http runs on port 80, https on port 443
Example: .. -p 80 --https_key ...
https runs on port 80, no regular http
--ipwhitelist : The file to read the IP whitelist from
If this parameter is empty, but 'ipwhitelist.txt'
exists, ipwhitelist.txt will be used
File format: one IP (range) or subnetwork per line
Example: 127.0.0.1, abc::0-def::ffff
10.0.0.0/8, 192.0..
--pdf_error_threshold : Set the maximum amount of retries for processing a pdf
file.
--max_parallel_conversions : Set the maximum number of parallel conversions
(per converter). default: number of cores
--enable_save : This enables the option write to disk
Default: outputfiles dir of AOP directory
--enable_local_resources : This enables accessing local files (e.g. templates)
--check_configuration : Checks the configurations needed for AOP to run

Since version 18.2 AOP creates a config file. These options can be saved in this config file. If no config file is
there, AOP generates the config file in the first run. This configuration file is of JSON format. The default
configuration is as follows:

https://www.apexofficeprint.com/docs/ 156/197
6/9/2019 APEX Office Print

{
"config": {
"port": 8010, // The port where AOP should start.
"startat": "./", // The default location to start at. Handly if you are using local resources.
"license": "./aop.license", // The location of the license file.
"silent": false, // If true does not log anything.
"verbose": false, // If true logs what it is currently doing. (Ignores silent)
"enable_printlog": false, // If true logs the incoming printjobs into a log file.
"idle_timeout": 120, // The timeout for conversion in seconds.
"instances": 1, // The number of instace to start. Ideally is equal to number of cores (if 0 AO
"https_key": "", // The location for the https key for AOP to use when starting in HTTPS mode.
"https_cert": "", // The locatio for the https certificate for AOP to use when startin in HTTPS
"https_port": 433, // The port to use while starting as HTTPS.
"ipwhitelist": "", // The location of the ipwhitelist file.
"pdf_temp_folder": "", // The temp folder to use when converting to PDF.
"max_parallel_conversions": 0 // The number of maximum parallel conversions allowed. 0 -> numbe
"pdf_error_threshold": 3, // The number of retries after pdf failure.
"enable_save": false, // Enables saving output in local directories.
"enable_local_resources": false // Enables reading out the templates and resources (for e.g ima
"enable_macro": false, // This allows docm and pptm templates to run macro's on event while pdf
},
"converters": { //Placeholder for converters. You can specify your own converters here and pass the
"abiword":{
"command": "abiword --to={outputFormat} --to-name={outputFile} {inputFile}",
"handlesParallel": false //From version 19.1 this can be a number, meaning x number of para
}
}
"post_process_commands":{ // Available since version 19.1, this allows you to execute custom comman
"echo":"echo \"{inputFile} with input format ${inputFormat} has been successfully processed.\""
}
}

8.5 Running as Service in Windows


Using Microsoft Office as PDF converter
If you wish to use Microsoft office as PDF converter for your documents, some tweaks are necessary before
ApexOfficePrint can be used or started as service.

32-Bit Windows
Directory Creation
Create a directory "Desktop" if it does not already exist under \
"C:\Windows\system32\config\systemprofile\Desktop"
DCOM config

1. From Run (Windows + R), type dcomcnfg

2. Navigate to Component Services > Computers > My Computer > DCOM Config

https://www.apexofficeprint.com/docs/ 157/197
6/9/2019 APEX Office Print

3. Locate "Microsoft Excel Application" and right click properties of it

4. Navigate to Security Tab and Customize the Launch and Activation Permissions and Edit

5. Check that no instances of excel.exe are running before changing the properties, either close the
applications that are running the Excel or go to task manager and kill the excel.exe processes.

https://www.apexofficeprint.com/docs/ 158/197
6/9/2019 APEX Office Print

6. Add the current user (type the current user, click check names, and click ok) and grant permission for
Local Launch and Local Activation

7. Go to Identity Tab and change the radio button to "The User"

8. Do the same for "Microsoft PowerPoint Slide".

9. Do the same for "Microsoft Word 97-2003 Document".


Setting directory permissions
1. Navigate to: "C:\Windows\System32\config\systemprofile\AppData\Roaming\Microsoft".

2. Right click and go to Properties

3. Under Security Tab add the current user and grant the Modify, Read & Execute, List Folder Content,
Read, and Write permissions.

4. Do the same for "C:\Windows\Temp\".

64-Bit Windows

https://www.apexofficeprint.com/docs/ 159/197
6/9/2019 APEX Office Print

Directory Creation

Create a directory "Desktop" if it does not already exist under:

"C:\Windows\system32\config\systemprofile\Desktop" and
"C:\Windows\SysWOW64\config\systemprofile\Desktop"
DCOM config
1. From Run (Windows + R), type dcomcnfg (if your Microsoft Office is 32 bit then open command line
and change directory to "C:\Windows\SysWOW64" and run "mmc comexp.msc /32" command)

2. Navigate to Component Services > Computers > My Computer > DCOM Config

3. Locate "Microsoft Excel Application" and right click properties of it

4. Navigate to Security Tab and Customize the Launch and Activation Permissions and Edit

5. Check that no instances of excel.exe are running before changing the properties, either close the
applications that are running the Excel or go to task manager and kill the excel.exe processes.

https://www.apexofficeprint.com/docs/ 160/197
6/9/2019 APEX Office Print

6. Add the current user (type the current user, click check names, and click ok) and grant permission for
Local Launch and Local Activation

7. Go to Identity Tab and change the radio button to "The Interactive User" or "The Launching User"
(automatic start)

8. Do the same for "Microsoft PowerPoint Slide".

9. Do the same for "Microsoft 97-2003 Document".


Setting directory permissions
Navigate to:

1. "C:\Windows\System32\config\systemprofile\AppData\Roaming\Microsoft".

2. Right click and go to Properties

3. Under Security Tab add the current user and grant the Modify, Read & Execute, List Folder Content,
Read, and Write permissions.

https://www.apexofficeprint.com/docs/ 161/197
6/9/2019 APEX Office Print

Do the same for:

4. "C:\Windows\System32\config\systemprofile\AppData\Local\Microsoft"

5. Do the same for "C:\Windows\Temp\".

Using LibreOffice as pdf converter


No extra steps are necessary.

Managing the service


Navigate to Windows Service folder situated in the APEXOfficePrint folder.

Edit 1_SetupAsService.bat to include the full path to the executable APEXOfficePrintWin64.exe

Note that you can also add additional parameters for example for the port it should run on and the starting
directory.

terminal
nssm.exe install APEXOfficePrint %0\..\..\APEXOfficePrintWin64.exe --port 8090 -s
D:\apexofficeprint

Run 1_SetupAsService.bat.

The service should be installed and can be seen in Services (Control Panel > Administrative Tools >
Services).

To change how the APEXOfficePrint services starts you can change it from Services or start it manually
via 2_StartService.bat (should be run as Administrator).

To check if the service has started, navigate to http://localhost:8010/ (http://localhost:8010/)

To stop the service run 3_StopService.bat as Administrator or stop it from Services.

To remove the APEXOfficePrint as service run 4_RemoveService.bat.

The APEXOfficePrint service should now be removed from Services. If it says Disabled then it will be
removed after the service has been stopped.

8.6 Run APEX Office Print at startup or as service in


Linux
After reboot of the server where APEX Office print is installed, you have to make sure that you also run
APEXOfficePrintLinux64 command. If you want to automate the startup of AOP you can create in init.d. For
example: /etc/init.d/aop-server

https://www.apexofficeprint.com/docs/ 162/197
6/9/2019 APEX Office Print

#!/bin/bash
#
# Apex Office Print (AOP) Server
#
# chkconfig: 345 70 30
# description: AOP is a print server for Oracle Application Express and PL/SQL
# processname: APEXOfficePrint

# Source function library.


. /etc/init.d/functions

RETVAL=0
AOP_HOME=/opt/aop/v18.1/server
AOP_PROCESS_NAME=APEXOfficePrint
AOP_EXECUTABLE_NAME=APEXOfficePrintLinux64
AOP_PORT=8010
LIBREOFFICE_HOME=/opt/libreoffice5.4

PATH=$LIBREOFFICE_HOME/program:$PATH
export PATH

start() {
echo -n "Starting $AOP_PROCESS_NAME "
echo -n "Current path is $PATH"
$AOP_HOME/$AOP_EXECUTABLE_NAME -p $AOP_PORT -s $AOP_HOME &
RETVAL=$?
echo
return $RETVAL
}

stop() {
echo -n "Shutting down $AOP_PROCESS_NAME: "
pkill $AOP_PROCESS_NAME
RETVAL=$?
echo
return $RETVAL
}

status() {
echo -n "TODO: Print $AOP_PROCESS_NAME status here... "
RETVAL=$?
return $RETVAL
}

case "$1" in
start)
start
;;
stop)
stop
;;
status)
status
;;
restart)

stop

https://www.apexofficeprint.com/docs/ 163/197
6/9/2019 APEX Office Print

stop
start
;;
*)
echo "Usage: $prog {start|stop|status|restart}"
exit 1
;;
esac
exit $RETVAL

8.7 Start/Stop APEX Office Print on Linux 7 with


systemctl
On Linux 7 you can use systemd (systemctl) to start and stop services. For Red Hat and Oracle Enterprise Linux
you can follow the below instructions.

As user root or sudo privileged user

cd into /usr/lib/systemd/system
create a file aop.service

Paste the following in and adjust for your installation as required (personally I install AOP in /opt/oracle)

[Unit]
Description=APEX Office Print
After=network.target

[Service]
Type=simple
User=aop
Group=aop

Environment=AOP_HOME=/opt/aop/latest/server ### Please see comment below


Environment=AOP_PROCESS_NAME=APEXOfficePrint
Environment=AOP_EXECUTABLE_NAME=APEXOfficePrintLinux64
Environment=AOP_PORT=8010

Environment=PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/bin/
SyslogIdentifier=apexofficeprint
Restart=always
RestartSec=30
TimeoutStartSec=30
TimeoutStopSec=30

ExecStart=/usr/bin/env ${AOP_HOME}/${AOP_EXECUTABLE_NAME} -p ${AOP_PORT} -s ${AOP_HOME}

ExecStop=/usr/bin/env pkill ${AOP_PROCESS_NAME}

[Install]
WantedBy=multi-user.target

Reload the daemon

systemctl daemon-reload

https://www.apexofficeprint.com/docs/ 164/197
6/9/2019 APEX Office Print

A simple setup is to install the version of aop in /opt/aop. When you install a new version just unzip in this
directory. You will end up for example with the following directories v3.4, v3.5 and v18.1. Create in the
directory /opt/aop a symbolic link to point to the latest version.

ln -s /opt/aop/v18.1 /opt/aop/latest

Suppose something is not working properly and you need to revert back to your previous version, all you need to
do is to create the symbolic link to a previous version. For example

unlink latest
ln -s /opt/aop/v3.3 /opt/aop/latest

As root

start aop : systemctl start aop


stop aop : systemctl stop aop
status aop: systemctl status aop

Example output of systemctl status aop

[root@s2s-proddb-03 system]# systemctl status aop.service


● aop.service - APEX Office Print
Loaded: loaded (/usr/lib/systemd/system/aop.service; disabled; vendor preset: disabled)
Active: active (running) since Sat 2018-03-10 20:39:47 AEDT; 6s ago
Main PID: 28273 (APEXOfficePrint)
CGroup: /system.slice/aop.service
├─28273 /opt/aop/latest/server/APEXOfficePrintLinux64 -p 8010 -s /opt/oracle/aop/latest/serv
├─28283 /opt/aop/v3.4/server/APEXOfficePrintLinux64 --pkg-fallback --max_old_space_size=1638
└─28288 /opt/aop/v3.4/server/APEXOfficePrintLinux64 --pkg-fallback --max_old_space_size=1638
Mar 10 20:39:47 http://proddb-032.acme.com systemd[1]: Started APEX Office Print.
Mar 10 20:39:47 http://proddb-032.acme.com systemd[1]: Starting APEX Office Print...
Mar 10 20:39:48 http://proddb-032.acme.com apexofficeprint[28273]: Current license is activated to: xxx
Mar 10 20:39:48 http://proddb-032.acme.com apexofficeprint[28273]: The products activated are:
Mar 10 20:39:48 http://proddb-032.acme.com apexofficeprint[28273]: Word
Mar 10 20:39:49 http://proddb-032.acme.com apexofficeprint[28273]: Listening on port 8010
Mar 10 20:39:49 http://proddb-032.acme.com apexofficeprint[28273]: AOP 1 running

8.8 Step-by-step how to install LibreOffice on Linux


In case you need to install LibreOffice on Linux, here're the steps (see also other section):

https://www.apexofficeprint.com/docs/ 165/197
6/9/2019 APEX Office Print

# download LibreOffice for the PDF converter


cd /tmp
wget http://downloadarchive.documentfoundation.org/libreoffice/old/5.4.7.2/rpm/x86_64/LibreOffice_5.4.

# make sure no old versions exist


yum remove openoffice* libreoffice*

# extract tar
tar -xvf LibreOffice_5.4.7.2_Linux_x86-64_rpm.tar.gz

# install
cd /tmp/LibreOffice_5.4.7.2_Linux_x86-64_rpm/RPMS/

yum localinstall *.rpm

# install some missing dependencies (depending your linux version this is not necessary)
yum install cairo.x86_64
yum install cups.x86_64
yum install mesa-libGL.x86_64

# install Java dependency (not necessary if you already have Java)


yum install java-1.8.0-openjdk.x86_64

# create symbolic link


ln -s /opt/libreoffice5.4/program/soffice /usr/sbin/soffice

8.9 HTTPS Configuration


AOP also has support for the usages of https protocol. It requires a crt file and its private key file. A self-signed
certificate and key can also be used. The certificate can be generated by using openssl command:

openssl req -x509 -newkey rsa:2048 -keyout keytmp.pem -out aop.crt -days 365
openssl rsa -in keytmp.pem -out aop.key

Given aop.crt certificate file and aop.key private key file AOP can be started with:

APEXOfficePrint --https_cert aop.crt --https_key aop.key

The port number can also be specified with the --https_port argument. If this is provided HTTP and HTTPS
server will run.

You should see the following when started successfully on the console.

Starting HTTP and HTTPS on port 8010 and 443


AOP 1 (HTTP) running
AOP 1 (HTTPS) running

Please note that the certificate validation is done by the client. If you are using a self-signed certificate and visit
the https location with browser, you will get a security warning (see below).

https://www.apexofficeprint.com/docs/ 166/197
6/9/2019 APEX Office Print

https://www.apexofficeprint.com/docs/ 167/197
6/9/2019 APEX Office Print

You can configure the browsers to trust the self-signed certificate by adding it to the security exception. You will
also have to add this certificate in your oracle wallet to get rid of 'Certificate Validation Error'.

8.10 Installation errors


Linux installation port error
If you encounter this error:

-------------------------------------------------
Error on Thu Feb 04 2016 19:33:35 GMT-0800 (PST)
-------------------------------------------------
listen EADDRINUSE

It means that the port you tried running AOP server is already taken and you need to change it by running this
command:

./APEXOfficePrintLinux64 -p xxxx (replace xxxx by a free port)

8.11 Docker image


Pre-requisites
Define a Docker network, if you don't have one yet

https://www.apexofficeprint.com/docs/ 168/197
6/9/2019 APEX Office Print

docker network create my_network

Make sure your Oracle database container is in this network

docker network connect my_network oracle

Start your ORDS container on this network

docker run -t -i \
--name ords \
--network=my_network \
-e DATABASE_HOSTNAME="oracle" \
-e DATABASE_PORT="1521" \
-e DATABASE_SERVICENAME="ORCLPDB1" \
-e DATABASE_PUBLIC_USER_PASS=oracle \
-e APEX_LISTENER_PASS=oracle \
-e APEX_REST_PASS=oracle \
-e ORDS_PASS=oracle \
--volume /docker/apex/images:/usr/local/tomcat/webapps/i \
-p 8181:8080
ords/ords_apex:3.0.9

Download the AOP docker image


docker pull apexrnd/apexofficeprint

Activating APEX Office Print the first time (Gold license only - not necessary for Enterprise license). This step is
only needed once.

docker run -it \


--name apexofficeprint \
--network=my_network \
-p 8010:8010 \
-v /docker/apexofficeprint/:/apexofficeprintstartup/ \
apexrnd/apexofficeprint \
-s /apexofficeprintstartup/
-a

In case you have an Enterprise License, add the aop.license file in the directory you specified, in the below
example it's /docker/apexofficeprint/

Start an AOP container on the network of your Oracle database


container

https://www.apexofficeprint.com/docs/ 169/197
6/9/2019 APEX Office Print

docker run -d \
--name apexofficeprint \
--network=my_network \
-p 8010:8010 \
-v /docker/apexofficeprint/:/apexofficeprintstartup/ \
apexrnd/apexofficeprint \
-s /apexofficeprintstartup/

You should now be able to connect to APEX Office Print server by going to http://apexofficeprint:8010/. You can
view this video (https://www.youtube.com/watch?v=U2RomOX_4_8) to see the above in action.

Create an ACL for APEX_050100 to the AOP container


begin
DBMS_NETWORK_ACL_ADMIN.append_host_ace (
host => 'apexofficeprint',
lower_port => 8010,
upper_port => 8010,
ace => xs$ace_type(privilege_list => xs$name_list('http'),
principal_name => 'APEX_050100',
principal_type => xs_acl.ptype_db));
end;

Configure the APEX plug-in


Go to Shared Components > Component Settings > APEX Office Print and put in the AOP URL a reference to
your docker container e.g. http://apexofficeprint:8010/

9 Tutorials
You can check the APEX Office Print tutorial page (https://www.apexofficeprint.com/ords/f?p=328:1) to see
tutorials and videos.

10 Troubleshooting
10.1 Output generates invalid Office documents
In case Office documents are not opening as expected, probably there was an issue with the JSON that was
send to the AOP server. If you run in the AOP Cloud, you can enable Remote Debugging, which you can access
when you login in your APEX Office Print dashboard at https://www.apexofficeprint.com
(https://www.apexofficeprint.com). If you're running the on-premise version of AOP, on the server there is a
server_error.log file that contains the errors it found during rendering. First step is to check that file for more
information. Next make sure that your JSON is valid by validating the JSON in for example http://jsonlint.com
(http://jsonlint.com) or by doing Remote Debug (see further on in this document)

https://www.apexofficeprint.com/docs/ 170/197
6/9/2019 APEX Office Print

10.2 Invalid JSON generated by


apex_web_service.make_rest_request
Make sure APEX 5.0.4 or higher is installed. To download it login to support.oracle.com.

10.3 Invalid JSON generated by apex_json


Make sure you install an additional patch for APEX 5.0.4 PSE 24341756 or for APEX 5.1.0 PSE 25650850 or for
APEX 5.1.1 PSE 25853436 or for APEX 5.1.4 PSE 27963501 available at https://support.oracle.com
(https://support.oracle.com). Those will fix issues with apex_json which is used behind the scenes in AOP.

You also might hit Oracle database bug (in 12.1.0.2). A patch is made available on https://support.oracle.com
(https://support.oracle.com); search for patch #21424376. You won't experience this issue in 11.2.0.4 or 12.2.

When using PL/SQL Function returning JSON, you might hit a bug in apex_plugin_util, which can be fixed by
applying patch 26048323.

Finally if you still encounter issues, use ORDS (SQL Workshop > RESTful Services) as your datasource. ORDS
will generate the JSON instead of apex_json and AOP will use that JSON instead (see 3.5.4 Data Source - URL
with ORDS RESTful Web Service).

10.4 Running on Oracle Cloud


If you are running on Oracle Cloud you must use HTTPS in the AOP Plug-in Component setting and when you
call the aop_api_pkg package. Use https://www.apexrnd.be/aop (https://www.apexrnd.be/aop) as the URL.

10.5 Invalid PDF file


If you're running the on-premise version of AOP, check a file on the server called server_error.log or
server_uncaugt_exceptions.log and see which error you get. Try to run your example in the same format as your
template. If this also fails, there's an issue with the JSON or the template. Check your template and data again.
If you receive your document fine, but PDF is not working, there's an issue finding LibreOffice or MS Office.
Make sure those programs are installed correctly. Try to do a manual conversion on the command line in those
tools and see if that works. If not, check the error and try to reinstall. You can also do Remote Debugging (see
further on in this document), which will help identifying the real issue. If everything fails, please contact
support@apexofficeprint.com (mailto:support@apexofficeprint.com).

10.6 ORA-29273: HTTP request failed


ORA-29273: HTTP request failed ORA-06512: at "SYS.UTL_HTTP", line 1130 ORA-24247: network access
denied by access control list (ACL)

Make sure APEX_050000 or APEX_050100 schema has the rights to connect to APEX Office Print
(http(s)://www.apexofficeprint.com for the Cloud version or your local URL in case of the on-premise version).
The script to correct the issue can be found here: APEX 5.0
(https://docs.oracle.com/cd/E59726_01/install.50/e39144/listener.htm#HTMIG29162) or for APEX 5.1
(http://docs.oracle.com/database/apex-5.1/HTMIG/enabling-network-services-in-Oracledb-11g-or-
later.htm#HTMIG29160) (use the correct script for your database version - for XE use prior to 12c)

https://www.apexofficeprint.com/docs/ 171/197
6/9/2019 APEX Office Print

10.7 ORA-29024: Certificate validation failure


ORA-29273: HTTP request failed ORA-06512: at "SYS.UTL_HTTP", line 1130 ORA-29024: Certificate
validation failure

In case you run over HTTPS you need to take into account the certificates. There're two ways to get around this:

Option 1: You can load our certificates in your Oracle wallet (the Oracle DB is doing the call to our server).

Option 2: You can add an entry in your webserver so a local entry is called by the database (which doesn't
need a certificate) and the webserver is doing the redirect to handle the https call.

Here's an example when in the plug-in you would specify a local address: http://apexrnd.localdomain/aop/
(http://apexrnd.localdomain/aop/)

<VirtualHost *:80>
ServerName apexrnd.localdomain
ServerAlias apexrnd.localdomain
RewriteEngine On
ProxyVia On
ProxyRequests Off
SSLProxyEngine On
ProxyPass /aop/ https://api.apexofficeprint.com/
ProxyPassReverse /aop/ https://api.apexofficeprint.com/
</VirtualHost>

10.8 How to read and convert documents (docx,


xlsx, pptx, pdf) on Linux
You need to install LibreOffice https://www.libreoffice.org/download/libreoffice-fresh/
(https://www.libreoffice.org/download/libreoffice-fresh/). The steps to do this are outlined below:

Make a connection to your server with ssh or putty, but make sure you don't forward or tunnel your X Display.

Install supporting packages:

yum install wget

Download LibreOffice

cd /tmp
wget http://download.documentfoundation.org/libreoffice/stable/5.4.2/rpm/x86_64/LibreOffice_5.4.2_Linux

Install LibreOffice

tar xzvf LibreOffice_5.4.2_Linux_x86-64_rpm.tar.gz


cd LibreOffice_5.4.2.2_Linux_x86-64_rpm/RPMS
yum localinstall *.rpm
- or you can do rpm -ivh *.rpm

Add LibreOffice to the profile for your user (as it needs to be able to find soffice)

https://www.apexofficeprint.com/docs/ 172/197
6/9/2019 APEX Office Print

vi /etc/profile
export PATH=$PATH:/opt/libreoffice5.4/program
source /etc/profile

Or add a symbolic link to LibreOffice

ln -s /opt/libreoffice5.4/program/soffice /usr/sbin/soffice

Check the version of LibreOffice and try to run a conversion

soffice --version
soffice --headless --invisible --convert-to pdf --outdir /tmp aop_interactive.docx

If you get: Fontconfig warning: ignoring UTF-8: not a valid region tag

echo "$LC_CTYPE"
|-> you probably have UTF-8 defined; unset it
export LC_CTYPE=""

Make sure you restart APEX Office Print after installing LibreOffice.

Note: we sometimes see LibreOffice doesn't generate the same PDF as MS Office is generating, but we found
LibreOffice becoming more and more inline, so we recommend using the latest version of LibreOffice.

Note: Depending the version of LibreOffice converting to HTML from docx, xlsx, pptx might include the images
as base64 or include a link.

10.9 ORA-31011: XML parsing failed, ORA-19202:


Error occurred in XML processing, LPX-00651: VM
Stack overflow
You need to install an additional patch for APEX 5.0.4 which will fix this issue. Search in
https://support.oracle.com (https://support.oracle.com) for PSE 24341756.

10.10 Error occurred while acquiring license


You receive: "Error occurred while acquiring license. Please make sure that your API key is correct and that you
have enough printing credits. Contact AOP if the problem persists."

This means you ran out of credits. Go to https://www.apexofficeprint.com (https://www.apexofficeprint.com) and


upgrade your package or send an email to support@apexofficeprint.com (mailto:support@apexofficeprint.com)
to see what we can do for your case.

10.11 SyntaxError: unexpected token P in JSON at


position 0

https://www.apexofficeprint.com/docs/ 173/197
6/9/2019 APEX Office Print

If you are using APEX 5.1, the Dynamic Action plug-in will always work, whereas the Process plug-in might give
this error. When you put the process in the Processing part, it will only work if the “Reload on Submit” attribute
(of the page) is set to “Always” (note this attribute is new in 5.1). This is due to a change how APEX 5.1 is
handling Page Processing. If you would import an APEX 5.0 app in 5.1 by default it’s set to Always reload on
submit, but if you create a new app in 5.1 it’s set to “Only for Success” and then the process plug-in is not
working. Alternatively, you can put the AOP Process to be After Header and make it conditional, it will then work
regardless of the setting of "Reload on Submit".

10.12 Issues with Oracle XE


When using Oracle XE, make sure you have the execute grant on the UTL_HTTP package.

GRANT EXECUTE ON SYS.UTL_HTTP TO my_user;


GRANT EXECUTE ON SYS.UTL_FILE TO my_user;

If you receive "ORA-20000: Issue returned by AOP Service (REST call). Please verify the logs on the server.
Returned HTTP code: . (code: -29273)", see section 10.6.

10.13 Chinese and other language and font support


If you need special characters or language support, make sure the necessary fonts and languages are on your
system. For example to add Chinese support on RHEL Linux do:

yum install "@Chinese Support"

Further more if you want to install additional fonts here's a good link (http://mscorefonts2.sourceforge.net). AOP
Cloud API has Google Noto (https://www.google.com/get/noto/) fonts installed.

Installing a font is nothing more than installing the font on your system. For example on (RedHat) Linux, we copy
the *.ttf files (or directory) to /usr/share/fonts/ and run "fc-cache -f -v"

Depending if you have a GUI (Linux/Windows) you can just double click on the font and it will install it in your
system. If your system recognises is, MS Office or LibreOffice should be able to use it for the PDF conversion.

For barcodes, you could also choose to install a barcode font, for example Free 3of9
(https://www.barcodesinc.com/free-barcode-font/) or http://www.dafont.com/3of9-barcode.font
(http://www.dafont.com/3of9-barcode.font). Barcode fonts are more performant than images.

If you are using font awesome and using html tag or interactive reports/grid in Word, you will have to install the
font-awesome desktop fonts in order to render on the PDFs properly. (AOP cloud server has free versions
installed.)

10.14 Running AOP installed in a single schema but


shared across multiple schemas
It is possible to install AOP only once and call it from other places. In order to do this, after you install AOP - go
to the package aop_api19_pkg and aop_plsql19_pkg and remove the AUTHID CURRENT_USER and
recompile.

https://www.apexofficeprint.com/docs/ 174/197
6/9/2019 APEX Office Print

10.15 Running on-premise AOP under HTTPS


Since AOP version 3.1 AOP can be configured to use HTTPS server. The key and the certificate files can be
provided to AOP using the --https_key and --https_cert arguments.

For older versions however we recommend setting up an Apache Reverse Proxy which is doing the SSL in front
of AOP. From Apache to AOP it would be unencrypted, but if it’s on the same machine as Apache and the port of
AOP is not open and only accessible by localhost, we believe you're save.

To prevent access to AOP other than the Apache Reverse Proxy, you can do (on Linux):

iptables -A INPUT -p tcp --dport 8010 -s 127.0.0.0/8 -j ACCEPT


iptables -A INPUT -p tcp --dport 8010 -j DROP

(instead of DROP you can use REJECT too)

So that would mean only a program on localhost (like Apache) can connect to port 8010, all others are rejected.

10.16 The requested URL has been prohibited


If in APEX you force all outgoing connections to be HTTPS by setting: Manage Instance -> Security -> HTTP
Protocol -> Require Outbound HTTPS -> No.

make sure you're calling AOP also with HTTPS. If you're calling the AOP cloud https://api.apexofficeprint.com
(https://api.apexofficeprint.com) make sure to load the certificate in your database or setup a proxy on your end.

10.17 PDF output suddenly stopped working


Probably LibreOffice or MS Office process is stuck. A way to solve this is running a script that checks for long
running processes and that kills those. If you're using the AOP Cloud, please contact
support@apexofficeprint.com (mailto:support@apexofficeprint.com).

10.18 Map or Gantt or Other div not in output


In some occations divs are not screenshotted well enough, so they don't appear in the output. For example the
JET Gauge might not be taken. We are looking for a workaround for a future release.

10.19 ORA-29273: HTTP request failed ORA-


12535: TNS:operation timed out
Please check your firewall if it allows outgoing connection from the database to the AOP server. If you added the
AOP port to the firewall rules, make sure to restart the daemon.

If you're using a proxy, make sure to specify the proxy in Shared Components > Application Definition Attributes
> Proxy Server or specify the global variable in the AOP_API_PKG.g_proxy_override.

See also further in this doc at chapter 14 Debugging connections to AOP Server

https://www.apexofficeprint.com/docs/ 175/197
6/9/2019 APEX Office Print

10.20 Font in PDF is different from the font in my


Word template
This is most likely due to the fact that the font you chose in Word, is available on your local computer, but not in
the server. If you install that font also on the server where AOP is running, it should do the conversion well. See
also 10.13 Chinese and other language and font support.

10.21 The generation of my document is slow


You would need to figure out where you lose time:

creation of JSON: your SQL statement or other source is taken to transform in JSON. You can trace what
is going on by setting your page in debug mode (APEX) or running your SQL statement in a SQL window.

time needed on the server by AOP: you can trace that by enabling logging (only on-premise) Start the
AOP server with --enable_printlog or --verbose, which will show the incoming requests.

network time: measure the time to travel from your database to our cloud or to your own on-premise
install. If you would use the on-premise version and put AOP on the same machine as the database, it
would be the fastest. Or if you could add it on another server where the network is fast, that should get rid
of the transfer time.

If the conclusion is that everything is as fast as possible, we advise the reports that take a long time, to run in the
background with a job. You could also schedule the reports to run overnight and store the results in a table.

10.22 Invalid multi-column chart or Unexpected


Error
With some versions of the Oracle Database there's an issue with the Cost Based Optimiser. Till you upgrade
your database, you might want to try to use /+rule/ hint in your top level SQL statement.

10.23 Safe button in Components Settings not


available
Most likely you subscribed the plug-in from another place. Go to Shared Components > Plug-ins - Click on
References (number) and copy your logic where you used AOP. This is so you don't have to recreate your logic
later. Next, remove all the processes or dynamic actions that use the plug-in. - Now you should be able to go to
Shared Components > Plug-ins > AOP and hit the Delete button so the AOP plug-in is removed. - Import the
AOP plug-in again, but make sure you don't reference it from another app, so Import from file. - Use the logic
from step 1 to recreate your call(s) to AOP.

10.24 sqlerrm: ORA-31011: XML parsing failed


ORA-19202: Error occurred in XML processing LPX-
00664: VM Node-Stack overflow

https://www.apexofficeprint.com/docs/ 176/197
6/9/2019 APEX Office Print

The node stack of the XSL VM can be set with an event. It defaults to 300, the maximum is 4096. You can set it
with:

alter session set events='31153 trace name context forever, level 4096';

10.25 How to get a download to Excel button in the


Actions menu of an Interactive Report?
The below steps describe how to export an Interactive Report to Excel (XLSX) with AOP via the native IR
download dialog. The changes are done on the global page and works for all IR of the app without the need of
creating a DA on each page for each report, so reducing a lot of manual work.

Create a JS file with the following content and upload/reference it app-wide:

function addAOPXLSXDownloadToIR(pStaticIdItem) {
// hack into dialogopen event of jquery ui dialogs
$('body').on('dialogopen', function(event, ui) {
var dialogWindow$ = $(event.target);
// only process if it´s an IR download dialog
if (dialogWindow$.parents('div.ui-dialog').find('span.ui-dialog-title').text() === apex.lang.getMes
// get ID/static ID of IR
var currentRegionId = dialogWindow$.attr('id').match(/(.+)_dialog_js/)[1];
if (currentRegionId) {
// build html markup for XLSX download button
var html = apex.util.htmlBuilder();
html.markup('<li')
.attr('class', 'a-IRR-iconList-item')
.markup('>')
.markup('<a')
.attr('class', 'a-IRR-iconList-link')
.attr('href', 'javascript:$s("' + pStaticIdItem + '","' + currentRegionId + '")')
.attr('id', 'download_excel_aop')
.markup('>')
.markup('<span')
.attr('class', 'a-IRR-iconList-icon a-Icon icon-irr-dl-xls')
.markup('>')
.markup('</span>')
.markup('<span')
.attr('class', 'a-IRR-iconList-label')
.markup('>')
.markup('XLSX')
.markup('</span>')
.markup('</a>')
.markup('</li>');
// append html
$('.a-IRR-iconList').append(html.toString());
}
}
});
}

Create a page 0 item for holding the IR static ID:

https://www.apexofficeprint.com/docs/ 177/197
6/9/2019 APEX Office Print

P0_AOP_IR_STATIC_ID

Create a page load DA (Execute JavaScript Code) on page 0 to call above JS function

addAOPXLSXDownloadToIR('P0_AOP_IR_STATIC_ID’);

Create a page 0 DA (On Change of “P0_AOP_IR_STATIC_ID”) which calls the AOP plugin

1 True Action (AOP plugin)

2 True Action (Execute JavaScript - To close the IR download dialog after download)

https://www.apexofficeprint.com/docs/ 178/197
6/9/2019 APEX Office Print

var staticId = $v('P0_AOP_IR_STATIC_ID');


$('div#' + staticId + '_dialog_js').parent().find('button').click();

Note: every IR should have a static ID.

That´s it, the final result looks like this (on every IR in the app):

10.26 ORA-06550: PLS-00201: identifier


'AOP_API_PKG.xxx' must be declared
The APEX Plug-in can't find the AOP_API_PKG package. To fix the issue, run aop_db_pkg.sql (in the "db"-
directory) in your Oracle Schema (SQL Workshop -> SQL Scripts -> Upload -> Select file and hit Upload)

10.27 ORA-31186: Document contains too many


nodes
When there's a huge amount of data (>2 million rows) Oracle might give this error. If this amount is really
necessary to export, as a workaround we recommend splitting the query so there's less data in one document
and then merge the documents together with AOP.

10.28 ORA-31061: XDB error: special char to


escaped char conversion failed.

https://www.apexofficeprint.com/docs/ 179/197
6/9/2019 APEX Office Print

The data in the tables contains non-unicode characters. Most likely this is due to copy/paste of documents. It's
best to correct the data in the database, but if this can't be done, as a workaround in your query you can use
regexp_replace( COLUMN , '[[:cntrl:]]', '').

10.29 ORA-20001: Issue returned by AOP Service


(REST call: 504): Unknown error. Check AOP server
logs.
This means that your request was too big and the processing took longer that the gateway timeout. AOP API will
end the connection after 5 mins. Workaround would be to split the request into multiple files and merge them
back later. You could also go with AOP On-premise version where you do not have this limitation.

11 Debugging in APEX
AOP is fully instrumented with APEX debug messages, so when you turn debugging on in your APEX
application you will see many AOP: ... calls. Depending the level of APEX debug mode, more detailed debug
output will be available. See Dimitri Gielis's blog post (http://dgielis.blogspot.com/2018/06/error-whats-going-in-
apex-easiest-way.html) how to put APEX Trace on, which will show the most debug messages.

You can also specify a global variable g_debug_procedure if you want to call your own debug procedure which
for examples logs the information in your own table.

If you use Logger, you can also enable logger by compiling aop_api_pkg with a PL/SQL flag.

ALTER PACKAGE aop_api19_pkg COMPILE PLSQL_CCFLAGS = 'logger_on:TRUE';

12 Debugging in PL/SQL
If you're scheduling reports or calling the AOP packages with PL/SQL you can debug straight from PL/SQL.
Here's an example:

https://www.apexofficeprint.com/docs/ 180/197
6/9/2019 APEX Office Print

declare
l_binds wwv_flow_plugin_util.t_bind_list;
l_return blob;
l_output_filename varchar2(100) := 'output';
begin
-- remove previous debug
apex_debug.remove_debug_by_age(
p_application_id => 232,
p_older_than_days => -1);

-- create an APEX session with the debug enabled


aop_api_pkg.create_apex_session(
p_app_id => 232,
p_enable_debug => 'Y');

l_return := aop_api_pkg.plsql_call_to_aop (
p_data_type => aop_api_pkg.c_source_type_rpt,
p_data_source => 'ir1',
p_template_type => aop_api_pkg.c_source_type_apex,
p_template_source => 'aop_interactive.docx',
p_output_type => 'pdf',
p_output_filename => l_output_filename,
p_binds => l_binds,
p_aop_url => 'http://api.apexofficeprint.com/',
p_api_key => 'your API key',
p_app_id => 232,
p_page_id => 5,
p_init_code => 'aop_api_pkg.g_language := ''en'';');
end;
/

13 Remote Debugging
If you receive an error and you need some help of us, do following steps:

1) Go in your application to Shared Components > Component Settings > APEX Office Print (AOP) [Plug-in] and
enable remote debugging (see parameters screenshot)

![ ](media/aop_component_settings.png)

Note 1: you find your API key when you login in your dashboard on <https://www.apexofficeprint.com>

Note 2: Make sure APEX\_050000 or APEX\_050100 schema has the rights to connect to http(s)://www.apexof

2) Run your report again.

3) Login on https://www.apexofficeprint.com (https://www.apexofficeprint.com) and go to Remote Debug

![ ](media/aop_remote_debug.png)

https://www.apexofficeprint.com/docs/ 181/197
6/9/2019 APEX Office Print

4) Click on the magnifying glass, and the JSON that was generated behind the scenes which is send to the AOP
server component will be shown.

5) Investigate the received JSON:

-) JSON is valid, and valid output: this is how it should be.

-) JSON is invalid: this is probably due to your version of APEX. If you are below APEX 5.1.2, you need a patch
linked to apex_json.

-) JSON is valid, but invalid Office file (Word, Excel, PowerPoint): this means that AOP couldn't merge your
data with the template you provided. If the template and requested output is the same format (e.g. your template
is in Word and you request a Word document); check your template again if all substitution strings are correct. If
you believe everything is ok, click the button "Sent to Support" and contact support@apexofficeprint.com
(mailto:support@apexofficeprint.com).

-) JSON is valid, but invalid PDF (or other output format): if the template and output format are different, a
conversion is going on handled by LibreOffice or MS Office. Either the conversion goes wrong, or most likely the
initial file before the conversion was already wrong. To debug further, set the output format to the same format
as your template and run your report again. If the output is invalid, follow previous steps (see JSON is valid, but
invalid Office file). If the output is ok, click the button "Sent to Support" and send an email to
support@apexofficeprint.com (mailto:support@apexofficeprint.com) as it means there's a bug in the conversion.

14 Local Debugging
If you receive an error and you need some help of us, do following steps:

1. Go in your application to Shared Components > Component Settings > APEX Office Print (AOP) [Plug-in]
and set Debug to Local.

2. Run your report again. A JSON file will now be downloaded instead of the report. This JSON is what is
sent to the AOP server component behind the scenes.

3. Investigate the received JSON:

-) JSON is valid, and valid output: this is how it should be.

-) JSON is invalid: this is probably due to your version of APEX. If you are below APEX 5.1.2, you need a
patch linked to apex_json.

-) JSON is valid, but invalid Office file (Word, Excel, PowerPoint): this means that AOP couldn't
merge your data with the template you provided. If the template and requested output is the same format
(e.g. your template is in Word and you request a Word document); check your template again if all
substitution strings are correct. If you believe everything is ok, contact support@apexofficeprint.com
(mailto:support@apexofficeprint.com).

-) JSON is valid, but invalid PDF (or other output format): if the template and output format are
different, a conversion is going on handled by LibreOffice or MS Office. Either the conversion goes wrong,
or most likely the initial file before the conversion was already wrong. To debug further, set the output
format to the same format as your template and run your report again. If the output is invalid, follow
previous steps (see JSON is valid, but invalid Office file). If the output is ok, send an email to
support@apexofficeprint.com (mailto:support@apexofficeprint.com) as it means there's a bug in the
conversion.

https://www.apexofficeprint.com/docs/ 182/197
6/9/2019 APEX Office Print

4. If you didn't find a solution yourself, please send the JSON file to support@apexofficeprint.com

15 Debugging connections to AOP


Server
Open a first command prompt or shell and run AOP in verbose mode:

./APEXOfficePrintLinux64 —-verbose

Copy the test.json (./media/test.json) file to your server where AOP is running in /tmp folder

In another command prompt or shell go to /tmp folder and run (If you are in windows environment you can
download curl from https://curl.haxx.se/download.html#Win64 (https://curl.haxx.se/download.html#Win64)):

curl -X POST -H 'Content-Type: application/json' -d @test.json http://127.0.0.1:8010/ > output.docx

This should show the below output and have created an output.docx file

% Total % Received % Xferd Average Speed Time Time Time Current


Dload Upload Total Spent Left Speed
100 164k 100 68310 100 97k 335k 492k --:--:-- --:--:-- --:--:-- 494k

Check the first shell, AOP should have printed:

Prinjob received.
Sending back response.
Prinjob completed.

Try to run the same curl command but with your server name

curl -X POST -H 'Content-Type: application/json' -d @test.json http://<your server name>:8010/ > output

Same as before for output.

Go to the database server copy the test.json in the /tmp folder and run the curl command again

curl -X POST -H 'Content-Type: application/json' -d @test.json http://<your server name>:8010/ > output

This should do the same as before.

Instead of using curl you can also use a RESTClient like Postman. You will have to add the header 'Content-
Type: application/json' and give the data from the test.json into the body section.

Go into APEX > SQL Workshop, and try to connect to the AOP server

select apex_web_service.make_rest_request('http://<your server name>:8010/', 'GET') from dual

https://www.apexofficeprint.com/docs/ 183/197
6/9/2019 APEX Office Print

Try to generate a first document, adjust the below script to your settings and run

declare
l_return blob;
l_output_filename varchar2(100) := 'output';

begin
aop_api_pkg.g_proxy_override := null; -- set the proxy if you use that

l_return := aop_api_pkg.plsql_call_to_aop (
p_data_type => 'SQL',
p_data_source => q'[
select
'file1' as "filename",
cursor(
select 'hello world' as "string"
from dual
) as "data"
from dual
]',
p_template_type => null,
p_template_source => null,
p_output_type => 'docx',
p_output_filename => l_output_filename,
p_aop_url => 'http://<your server name>:8010/', -- change to the AOP server
p_api_key => '',
p_app_id => 232); -- change to the AOP sample app number
sys.htp.p(dbms_lob.getlength(l_return));
end;

In the shell where AOP is running you should see the incoming connection.

Hopefully the below steps give you more insight where your connection is failing so you can correct accordingly.

16 FAQ
-) Does AOP have to go on its own server, the database server or the application (ORDS) server?

You can choose. Having AOP on the same server as the database machine is most performant and easiest as
you don’t have network connections to other servers. If you install AOP on its own server you can size and
monitor that server better. AOP on the Application server is another option, as long as the database can connect
to the AOP server component, the AOP server doesn't need to be accessible from the outside (clients). So it’s
whatever you are most comfortable with.

-) Is there anything special we have to do with AOP to get it to work with SSL?

You can add a reverse proxy for the SSL or you can specify the https certificate when starting the AOP server
itself. Most people don’t do SSL as it’s only the database that needs to access the AOP server component, so
typically you don’t even pass the network where others are. However AOP can start in SSL mode if the SSL
certificate and its key are provided via --https_key and --https_cert argument.

-) Where do I get the SSL certificate of API server?

https://www.apexofficeprint.com/docs/ 184/197
6/9/2019 APEX Office Print

If you are using HTTPS (we always recommend you to do this) for connecting with the API server, you might get
a SSL certification validation error:

ORA-29273: HTTP request failed ORA-06512: at "SYS.UTL_HTTP", line 1130 ORA-29024: Certificate
validation failure In this case you will have to load the SSL certificate of the root certification authority, in our
case that of GoDaddy, into your oracle wallet. You can get this certificate by visiting https://apexofficeprint.com/
and looking at the certificate information. Example firefox:

It could be that you will have to change the URL to https://www.apexrnd.be/aop/

-) How resource intensive is it? Does it eat up a lot of CPU, RAM, or hard drive space?

It depends how many prints you do… AOP initially consumes about 400MB RAM, but depending the prints it can
go up to 4GB (a limit we put). In case you have larger documents, we recommend downloading the high
memory version which can consume up to 16GB. CPU is not much compared to the specs these days and hard
drive space is about 500MB. The executable is about 500MB and we might create some temporary files (during
pdf conversion) and a log and error file.

https://www.apexofficeprint.com/docs/ 185/197
6/9/2019 APEX Office Print

-) Do I have to install LibreOffice when we need Word and Excel output only?

No - LibreOffice or MS Office is only used when you want to convert from one format to another. So Word-Word
or Excel-Excel is working without. But if you want to do for example Word->PDF you need LibreOffice or MS
Office or another converter you prefer.

-) Can AOP print directly to a printer

AOP 3.1 and above includes the ability to print directly to an IP Printer, as long as it's available from the server
AOP is running on. If you want to print to a local printer, check the Sample app how to print to an inline region,
by adding a little bit of JavaScript to the dynamic action you can let the browser come up with a print window
automatically.

-) Can you repeat the Table header in Word and Excel?

Yes, this is a setting in Office. When you right click on your header row in Word, you can go to Table Properties -
Row and check the "Repeat as header row at the top of every page". An example is given on page 113 of
sample application.

-) Does AOP support Pivots in Excel

Yes, you can use the transpose function in Excel to pivot your data. AOP can also loop vertically by using the
{:tag}.

-) Why is there a difference between an output in Word and PDF

When going from Word to PDF, we use an external converter: MS Office or LibreOffice. It might be that if your
template was built on your desktop in MS Office (Word), but your server is using LibreOffice (Linux) a font is
different or there are minimal changes. The easiest way to find out what the difference is, is to open the template
in LibreOffice on your Desktop and see why LibreOffice is treating it different. In most use cases it works just fine
going from one to the other, but sometimes it's in the details.

-) Can I install the APEX Plug-in somewhere so all my apps have access to it?

You can make the aop_api_pkg a public synonym for aop_api19_pkg PL/SQL package in case you only want
the package in a global schema. The Oracle APEX plug-in itself you would still need to import in every APEX
application you want to use it in, but the plug-in can point to the public package.

-) Can I use dynamic page break in Word?

Yes. In some cases, you might want to start a new page for every record for example for certificates. You can put
the page break inside a conditional expression. You can use the rownum function to generate the id for every
record and check if that is equals to the record length. An example is shown in page 119 of our sample
application. Given the data:

https://www.apexofficeprint.com/docs/ 186/197
6/9/2019 APEX Office Print

select
'file1' as "filename",
cursor(
select
cursor(
select
rownum as "customerIndex",
c.cust_first_name as "cust_first_name",
c.cust_last_name as "cust_last_name"
from demo_customers c
) as "customers"
from dual
) as "data"
from dual

You can use the following tag to insert page break for every record except for the last.

{#customerIndex!=customers.length}
 -------------page break ------------
{/customerIndex!=customers.length}

Please note that if you wish to output to pdf, the same can be achieved by using the PowerPoint template and
{!slides_loop} tag. In this case there is no need to use the rownum function.

-) Can I adjust the width and height of interactive report/grid export in Word?

If you are exporting interactive grid, you can adjust the columns width as you like (due to meta data issue you
will also have to change the width a bit for all columns.). The ratio is then automatically taken into account.

In interactive report, you can use the following in html expression.

<span data-aop-width-weight="2"></span>#COLUMN_NAME#

The default weight for each column is 1. Let's say you have 4 columns and you provide this html expression in
the first column. This will double the size of the first column in comparison to the remaining 3.

The following formula is used to calculate the percentage of width a column gets:

(weight of column)/(total weight provided for all the columns) * 100.

Since version 19.1.4 AOP allows to specify the width in either px,in,cm,em or pt. Use the following HTML
EXPRESSION:

<span data-aop-width="10px"></span>#COLUMN_NAME#

If AOP detects this in one of the columns, the columns which do not have this expression will get the minimum
width specified.

-) How can I show custom success and error messages using AOP Dyncamic Action Plugin?

https://www.apexofficeprint.com/docs/ 187/197
6/9/2019 APEX Office Print

You can defines another TRUE action before the AOP Plugin is triggered and overwrite the
showSuccessMessage and showErrorMessage functions.

17 Example Templates
Below we illustrate some example templates and the generated output.

Example 1
This is the input template:

https://www.apexofficeprint.com/docs/ 188/197
6/9/2019 APEX Office Print

This is the result after AOP has processed the template and the given data:

https://www.apexofficeprint.com/docs/ 189/197
6/9/2019 APEX Office Print

Example 2
This is the input template:

https://www.apexofficeprint.com/docs/ 190/197
6/9/2019 APEX Office Print

This is the result after AOP has processed the template and the given data:

https://www.apexofficeprint.com/docs/ 191/197
6/9/2019 APEX Office Print

Example 3
This is the input template:

https://www.apexofficeprint.com/docs/ 192/197
6/9/2019 APEX Office Print

This is the result after AOP has processed the template and the given data:

https://www.apexofficeprint.com/docs/ 193/197
6/9/2019 APEX Office Print

Example 4
This is the input template:

https://www.apexofficeprint.com/docs/ 194/197
6/9/2019 APEX Office Print

This is the result after AOP has processed the template and the given data:

https://www.apexofficeprint.com/docs/ 195/197
6/9/2019 APEX Office Print

Copyright
Copyright © 2015-2019, APEX R&D (https://www.apexrnd.be)

All rights reserved.

Authors: Dimitri Gielis, Sunil Tandan and Lino Schildenfeld

This software and related documentation are provided under a license agreement containing restrictions on use
and disclosure that are protected by intellectual property laws. Except as expressly permitted in your license
agreement or allowed by law, you may not use, copy, reproduce, translate, broadcast, modify, license, transmit,
distribute, exhibit, perform, publish, or display any part, in any form, or by any means. Reverse engineering,
disassembly, or de-compilation of this software, unless required by law for interoperability, is prohibited. The
information contained herein is subject to change without notice and is not warranted to be error-free. If you find
any errors, please report them to us in writing.

https://www.apexofficeprint.com/docs/ 196/197
6/9/2019 APEX Office Print

APEX R&D - 2015-2019

Documentation built with MkDocs (http://www.mkdocs.org/).

https://www.apexofficeprint.com/docs/ 197/197

You might also like