Building a Document Output extension app

The Continia Document Output Extension Builder lets you generate a ready-to-finish Document Output (DO) extension for your own documents and tables, without hand-writing the boilerplate that wires a page and its table into Document Output.

You tell the tool which email templates and which Microsoft Dynamics 365 Business Central pages you want to enable for Document Output, and it generates:

  • FactBox pages that host the Document Output actions (Open/Send/Queue email, Print PDF, Save PDF).
  • Page extensions that place those actions and a Document Output Log FactBox on your pages.
  • Table extensions that expose the same actions as callable procedures.
  • A subscriber codeunit that tells Document Output how to resolve your records (the OnGetVariantRecord event).
  • Optionally, a stub codeunit for supplying your own merge-field values.

Wichtig

The output is source code, not an installable app. The tool produces AL source files packaged into a .zip that your browser downloads. It does not produce a compiled .app. You open the ZIP in Visual Studio Code, review and finish the code, compile it yourself, and then publish it to your environment.

The feature is exposed to users through the page Document Output Extension Apps (found using the search () field). Internally, the objects are named Extension App (there's no object literally called "Extension Builder").

Prerequisites

Before you can download an app, the following must be filled in. These are enforced by the tool and will raise an error if missing.

On the app header (the card)

The following required fields must be filled in:

  • App Name
  • Publisher
  • Version
  • Object ID Range Min.
  • Object ID Range Max.

You must own (be licensed for) the object ID range you enter – the generated objects are numbered inside it.

For each email template you add (Templates list)

  • Template Code – an existing Document Output email template.
  • FactBox Page No. and FactBox Name – auto-filled when you pick the template, but must not be blank at download time.
  • The selected email template header must have a First Table in Report defined. This is the table the generated FactBox page and table extension are built on. A template without a first report table can't be used.

For each page you add (Pages to extend list)

  • Page No. to extend – the Business Central page you want to enable.
  • Page Extension Name – auto-filled from the page name, but must not be blank.
  • Email Template Code – see the following note:

Hinweis

A page row is only generated if its Email Template Code matches one of your Template rows.

Generation walks the templates and, for each one, emits page extensions only for the page rows whose Email Template Code equals that template's code. A page row with a blank or non-matching template code is silently skipped. Always set the template code on every page row.

Limitation: two primary-key fields at most

The source table behind a page you extend may have no more than two primary-key fields. If it has three or more, the download fails with the following message:

Table <no> <name> has more then 2 primary keys. This is not allowed.

This limit exists because the generated Document Output Log FactBox links to your record using only Primary Key Field 1 Value and Primary Key Field 2 Value. Tables with a three-part (or larger) primary key can't be wired up automatically – you'd need to build the extension by hand for those.

To generate an extension app

The editor is a standard Card page – there's no assisted setup guide. Work top to bottom.

To generate an extension app, follow these steps:

  1. Search () for and select Document Output Extension Apps. The list of previously created apps appears.

  2. To create a new app, click New. A card opens with sensible defaults already filled in:

    • App ID – a new GUID.
    • Version – 1.0.0.0.
    • App Name – an incrementing default such as DO extension for project1.
    • Publisher – Default publisher.
    • Object ID Range Min./Max. – the next free 50-ID window (see Object ID range handling below).
  3. Fill in the General group: Replace the defaults with your real App Name, Publisher, and Version, and set the Object ID Range Min./Max. to a range you own. Turn on Add MergeFieldValueFinder Codeunit if you want the merge-field stub included.

    Note

    The On Premise settings (Developer Services SSL Enabled/Port) only matter for on-premises debugging. Leave them blank for cloud.

  4. Optional: Add dependency apps: In Dependency Apps, add a row for every extra app your generated code will reference (beyond Continia Document Output, which is always added). Fill in App ID, App Name, App Publisher, App Version, and leave Enabled on. Disabled rows and rows with an empty App ID are ignored.

  5. Add email templates: In Templates used with this app, add a row and pick a Template Code. The tool auto-fills:

    • FactBox Page No. – the next free ID in your range.

    • FactBox Name – the template code in lower case followed by Actions (for example, salesinvoiceActions).

      Note

      It also shows the template's First Table in Report (number and name) so you can confirm which table the app will target.

  6. Add pages to extend: In Pages to extend with Document Output FactBoxes, add a row and set Page No. to extend. The tool auto-fills:

    • Page Extension No. – the next free ID in your range.
    • Page Extension Name – the page name without spaces followed by FactBox.
  7. Set the Email Template Code to match the template this page uses (required – see the note in Prerequisites above). Leave Document Output Action FactBox and Document Output Log FactBox on unless you want to omit one of them.

  8. Click Download App to download. The tool validates everything and builds the ZIP, and your browser downloads <App Name>.zip.

Object ID range handling

The generated objects are numbered from Object ID Range Min. upward, so getting the range right matters.

  • Defaults. A brand-new app starts at 52500–52549 (a 50-ID window).
  • Automatic free range. When you create a new app, the tool scans existing apps and, if the default window overlaps one, moves your window past it – preserving the same width. So the second app you create lands on 52550–52599, and so on.
  • Changing the minimum. If you edit Object ID Range Min. after adding templates or pages, the tool asks "Do you want to renumber existing pages?". Choosing Yes renumbers the FactBox pages and page extensions sequentially from the new minimum. Either way, Object ID Range Max. is recalculated to keep the original span.
  • How generated objects are numbered:
Generated objectID
FactBox pages and page extensionsAssigned from Min upward as you add rows (first come, first served)
Table extensions (one per source table)Min, Min+1, Min+2, etc.
OnGetVariantSubscriber codeunitMin
MyMergeFieldValueFinder codeunit (optional)Min+1

Pages, table extensions, and codeunits can share the same number (for example page 52500, table extension 52500, codeunit 52500) because AL object IDs are unique per object type. Make sure your range is wide enough for the number of pages you add – the generated page IDs climb from Min and are not capped at Max.

What the download contains

Unzipping <App Name>.zip gives you a normal AL project:

FilePurpose
app.jsonThe app manifest: your ID/name/publisher/version, your ID range, and dependencies. A dependency on Continia Document Output (Continia Software) is always declared, plus any dependency apps you added. application, platform, and runtime are derived from the environment you downloaded from; target is Cloud.
.vscode\launch.jsonA single AL launch configuration pre-filled from your current Business Central session (see Finishing the app in Visual Studio Code below).
Page <id> <FactBoxName>.alOne FactBox page (CardPart) per template. Hosts the Recipient field and the Open/Send/Queue email, Print PDF, and Save PDF actions, calling the CDO Email Handler codeunit.
Pageextension <id> <name>.alOne page extension per "page to extend" row. Adds the Document Output actions FactBox and/or Log FactBox to the page, plus a Document Output action group (and promoted group) with the five actions.
TableExtensions.alOne table extension per distinct source table, named DO<TableName>Ext, adding CDOOpenEMail, CDOSendEMail, CDOQueueEMail, CDOPrintPDF, and CDOSavePDF procedures.
Codeunit <id> OnGetVariantSubscriber.alSubscribes to CDO Events.OnGetVariantRecord and, per source table, hands Document Output the correct record variant. This is what lets Document Output resolve your documents.
Codeunit <id> MyMergeFieldValueFinder.alOnly if Add MergeFieldValueFinder Codeunit was on. A stub for returning your own merge-field values (see Finishing the app in Visual Studio Code below).

Finishing the app in Visual Studio Code

This is the developer part. The ZIP is a starting point, not a finished, compilable app.

To finish the app in Visual Studio Code, follow these steps:

  1. Unzip and open: Extract the ZIP and open the folder in VS Code with the AL Language extension installed.

  2. Download symbols: The generated .vscode\launch.json is pre-filled from the Business Central session you downloaded from – environment type (on-premises/production/sandbox), server, server instance, and (on-premises) port. Use it to run AL: Download Symbols.

    Note

    The launch configuration's authentication is hard-coded to Windows. For a cloud/SaaS target, you'll need to change it (for example to MicrosoftEntraID) before symbols download or publishing will work.

  3. Make dependency symbols available: Compilation needs the symbol packages for everything in app.json: Continia Document Output, the base Application/System apps, and any Dependency Apps you added. The Document Output dependency is pinned to a fixed version in app.json – adjust it to match the version installed in your target environment.

  4. Implement the merge-field finder (if generated): MyMergeFieldValueFinder ships as a placeholder. It contains the comment "Replace the sample code to return your merge field value here" and a SalesHeaderGetFullDocType sample that only works when the template's table is Sales Header. Replace the sample 'YourParameter' case and the sample procedure with your own logic for your tables.

  5. Review the rest: Update the placeholder brief/description in app.json, confirm the generated object names and IDs, and check that the FactBox/page extensions look right.

  6. Compile, then build and publish: Compile the project, build the .app yourself (there's no server-side build – nothing produced a .app for you), and publish/install it into the target environment.

Button and field reference

Page: Document Output Extension Apps (list)

ActionWhat it does
Download AppGenerates the source ZIP for the selected app and downloads it. (The tooltip currently says ".app", but it's in fact a source .zip.)

FieldMeaning
App IDThe app's GUID (generated).
App NameName of the app.
PublisherPublisher of the app.
VersionApp version.
TemplatesNumber of email templates configured on this app.
Pages to extendNumber of pages that will get Document Output FactBoxes.

New rows can't be inserted directly on the list. Clicking New opens the card.

Page: Extension App Card

General group

FieldWhat to enter
App IDGUID of the app (generated; normally leave as is).
App NameThe name of the extension app. Also used as the ZIP file name.
PublisherYour publisher name.
VersionThe app version (defaults to 1.0.0.0).
Object ID Range Min.First object ID to use. Must be in a range you own. Changing it can renumber existing pages.
Object ID Range Max.Last object ID to use. Recalculated to keep the range width when you change the minimum.
Add MergeFieldValueFinder CodeunitInclude the merge-field-finder stub codeunit in the download.

On Premise settings group (on-premises only)

FieldWhat to enter
Developer Services SSL EnabledWhether the dev services endpoint uses SSL. Written into launch.json.
Developer Services PortThe dev services port. Written into launch.json when non-zero.

Action

ActionWhat it does
Download AppValidates the setup and downloads the source ZIP.

Sub-page: Templates used with this app

FieldWhat to enter/meaning
Template CodeThe Document Output email template to expose. Selecting it auto-fills FactBox Page No. and FactBox Name.
FactBox Page No.ID of the generated FactBox page (auto-filled from the ID range).
FactBox NameObject name of the generated FactBox page (auto: template code + Actions).
First Table in ReportThe table number the template is built on (from the template header).
First Table in Report NameThe name of that table.

Sub-page: Pages to extend with Document Output FactBoxes

FieldWhat to enter/meaning
Page No. to extendThe Business Central page to extend. Selecting it auto-fills the extension no. and name.
Page No. to extend NameName of the page being extended (read-only).
Page Extension No.ID of the generated page extension (auto-filled from the ID range).
Page Extension NameObject name of the generated page extension (auto: page name + FactBox).
Email Template CodeThe template whose FactBox goes on this page. Must match a Templates row, or the page is skipped.
Document Output Action FactBoxInclude the Document Output actions FactBox on the page (default on).
Document Output Log FactBoxInclude the Document Output Log FactBox on the page (default on).

Sub-page: Dependency Apps

FieldWhat to enter / meaning
EnabledInclude this dependency in app.json (default on).
App IDGUID of the dependency app. Rows with an empty ID are ignored.
App NameName of the dependency app.
App PublisherPublisher of the dependency app.
App VersionVersion of the dependency app.