import { Callout } from "zudoku/ui/Callout";

# Print Agent

Codeunit `5523742` `bdev.Print Agent` sends print jobs to a printer configuration. Three kinds of job are supported - a PDF document, ZPL commands for a Zebra label printer, and raw data for everything that speaks its own printer language.

```pascal
    printAgent: Codeunit "bdev.Print Agent";
```

Every print method exists in several overloads, differing in three ways:

- **where the document comes from** - a `Temp Blob` codeunit, an `InStream`, or a `Text`;
- **whether you name the document** - the name appears in the print job history of the app;
- **how the target is stated** - a `bdev.PrA Printer Configuration` record, or its code as a `Text[250]`.

## IsPrinted()

States whether the last print job was handed over successfully.

```pascal
    procedure IsPrinted(): Boolean
```

**Returns** `true` when the previous print job was executed successfully, `false` otherwise. Use `GetLastErrorText()` for the reason.

<Callout type="caution" title="The print methods report nothing by themselves">
None of the print methods returns a value or raises an error when the job fails. Check `IsPrinted` after **every** print, or a failed print goes unnoticed - the user believes the label was printed and only the missing label says otherwise.
</Callout>

```pascal
    procedure PrintLabel(documentName: Text; var document: Codeunit "Temp Blob"; printerConfigurationCode: Code[250])
    var
        printerConfiguration: Record "bdev.PrA Printer Configuration";
        printAgent: Codeunit "bdev.Print Agent";
        printJobFailedErr: Label 'The print job failed with the following error message: %1', Comment = '%1 = Error message';
    begin
        if (not printerConfiguration.Get(printerConfigurationCode)) then
            exit;

        if (not printerConfiguration.Enabled) then
            exit;

        printAgent.PrintPdf(documentName, document, printerConfiguration);

        if (not printAgent.IsPrinted()) then
            Error(printJobFailedErr, GetLastErrorText());
    end;
```

## PrintPdf(...)

Prints a PDF document.

```pascal
    procedure PrintPdf(documentName: Text; var document: Codeunit "Temp Blob"; printerConfiguration: Record "bdev.PrA Printer Configuration")
    procedure PrintPdf(documentName: Text; var document: Codeunit "Temp Blob"; printerName: Text[250])
    procedure PrintPdf(documentName: Text; var document: Codeunit "Temp Blob"; noOfCopies: Integer; printerConfiguration: Record "bdev.PrA Printer Configuration")
    procedure PrintPdf(documentName: Text; var document: Codeunit "Temp Blob"; noOfCopies: Integer; printerName: Text[250])
    procedure PrintPdf(var document: Codeunit "Temp Blob"; printerConfiguration: Record "bdev.PrA Printer Configuration")
    procedure PrintPdf(var document: Codeunit "Temp Blob"; printerName: Text[250])
    procedure PrintPdf(var document: Codeunit "Temp Blob"; noOfCopies: Integer; printerConfiguration: Record "bdev.PrA Printer Configuration")
    procedure PrintPdf(var document: Codeunit "Temp Blob"; noOfCopies: Integer; printerName: Text[250])
    procedure PrintPdf(documentName: Text; stream: InStream; printerConfiguration: Record "bdev.PrA Printer Configuration")
    procedure PrintPdf(documentName: Text; stream: InStream; printerName: Text[250])
    procedure PrintPdf(documentName: Text; stream: InStream; noOfCopies: Integer; printerConfiguration: Record "bdev.PrA Printer Configuration")
    procedure PrintPdf(documentName: Text; stream: InStream; noOfCopies: Integer; printerName: Text[250])
    procedure PrintPdf(stream: InStream; printerConfiguration: Record "bdev.PrA Printer Configuration")
    procedure PrintPdf(stream: InStream; printerName: Text[250])
    procedure PrintPdf(stream: InStream; noOfCopies: Integer; printerConfiguration: Record "bdev.PrA Printer Configuration")
    procedure PrintPdf(stream: InStream; noOfCopies: Integer; printerName: Text[250])
```

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `documentName` | Text | The name the job is listed under in the print job history. Omitted, it becomes `External PDF document`. |
| `document` / `stream` | Codeunit "Temp Blob" / InStream | The PDF document. |
| `noOfCopies` | Integer | Overrides the copies of the printer configuration, see below. |
| `printerConfiguration` / `printerName` | Record / Text[250] | The printer configuration, as a record or by its code. |

### Copies

`noOfCopies` counts the **additional** copies, not the total: `1` produces the original and one copy. It is the same value the `No. of Copies` field of the printer configuration holds.

<Callout type="caution" title="Zero does not mean one">
A `noOfCopies` of `0` does not suppress the copies of the configuration - it leaves the configuration untouched, so a configuration set to three copies still prints four sheets. To print exactly one document, use an overload without `noOfCopies` and a configuration whose `No. of Copies` is `0`.
</Callout>

## PrintZPL(...)

Sends Zebra Programming Language commands to a label printer.

```pascal
    procedure PrintZPL(documentName: Text; zplCommands: Text; printerConfiguration: Record "bdev.PrA Printer Configuration")
    procedure PrintZPL(documentName: Text; zplCommands: Text; printerName: Text[250])
    procedure PrintZPL(documentName: Text; zplCommands: Text; encoding: TextEncoding; printerConfiguration: Record "bdev.PrA Printer Configuration")
    procedure PrintZPL(documentName: Text; zplCommands: Text; encoding: TextEncoding; printerName: Text[250])
    procedure PrintZPL(zplCommands: Text; printerConfiguration: Record "bdev.PrA Printer Configuration")
    procedure PrintZPL(zplCommands: Text; printerName: Text[250])
    procedure PrintZPL(zplCommands: Text; encoding: TextEncoding; printerConfiguration: Record "bdev.PrA Printer Configuration")
    procedure PrintZPL(zplCommands: Text; encoding: TextEncoding; printerName: Text[250])
    procedure PrintZPL(documentName: Text; stream: InStream; printerConfiguration: Record "bdev.PrA Printer Configuration")
    procedure PrintZPL(documentName: Text; stream: InStream; printerName: Text[250])
```

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `documentName` | Text | The name in the print job history. Omitted, it becomes `ZPL commands`. |
| `zplCommands` / `stream` | Text / InStream | The ZPL commands. |
| `encoding` | TextEncoding | How the commands are written to the stream. Defaults to `MSDos`, which is what a Zebra printer expects for the standard code page. |
| `printerConfiguration` / `printerName` | Record / Text[250] | The printer configuration, as a record or by its code. |

<Callout type="caution" title="ZPL is for Zebra printers">
ZPL commands are understood by ZPL-compatible printers. Sending them to another printer produces pages of command text at best. The app does not check the printer model.
</Callout>

The command language is documented by Zebra: [ZPL Command Information and Details](https://supportcommunity.zebra.com/s/article/ZPL-Command-Information-and-DetailsV2).

```pascal
    procedure PrintShippingLabel(shipmentNo: Code[20]; printerConfiguration: Record "bdev.PrA Printer Configuration")
    var
        printAgent: Codeunit "bdev.Print Agent";
        zpl: TextBuilder;
    begin
        zpl.AppendLine('^XA');
        zpl.AppendLine('^FO50,50^A0N,40,40^FD' + shipmentNo + '^FS');
        zpl.AppendLine('^XZ');

        printAgent.PrintZPL(shipmentNo, zpl.ToText(), printerConfiguration);

        if (not printAgent.IsPrinted()) then
            Error(GetLastErrorText());
    end;
```

## PrintRAW(...)

Sends data to the printer unchanged - for printer languages the app knows nothing about, or for a document that is already in the printer's own format.

```pascal
    procedure PrintRAW(documentName: Text; rawData: Text; printerConfiguration: Record "bdev.PrA Printer Configuration")
    procedure PrintRAW(documentName: Text; rawData: Text; printerName: Text[250])
    procedure PrintRAW(rawData: Text; printerConfiguration: Record "bdev.PrA Printer Configuration")
    procedure PrintRAW(rawData: Text; printerName: Text[250])
    procedure PrintRAW(documentName: Text; stream: InStream; printerConfiguration: Record "bdev.PrA Printer Configuration")
    procedure PrintRAW(documentName: Text; stream: InStream; printerName: Text[250])
    procedure PrintRAW(stream: InStream; printerConfiguration: Record "bdev.PrA Printer Configuration")
    procedure PrintRAW(stream: InStream; printerName: Text[250])
```

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `documentName` | Text | The name in the print job history. Omitted, it becomes `RAW data`. |
| `rawData` / `stream` | Text / InStream | The data, sent to the printer as it is. A `Text` is written with `MSDos` encoding. |
| `printerConfiguration` / `printerName` | Record / Text[250] | The printer configuration, as a record or by its code. |

<Callout type="info" title="Version">
`PrintRAW` has been introduced with 365 business Print Agent **18.12**, and it needs a Print Agent Client of version **1.8.0.0** or newer. Against an older client the call fails with an error naming the client and the required version - before anything is sent, so nothing is printed twice.
</Callout>

## See also

- [365 business Print Agent - Overview](readme.mdx)
- [Extensibility Events](extensibility-events.mdx)
- [Documentation - Printer Configuration](../../en-us/365-business-print-agent/printer-configuration.mdx)
