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

# Pdf - File

Codeunit `5523672` `bdev.Pdf - File` reads a PDF file that is stored in the app. `PDF Files` is where a user uploads the documents a stationery or a concatenate configuration refers to - a letterhead, a terms and conditions page, a leaflet - and the same documents are available to your extension.

```pascal
    pdfFile: Codeunit "bdev.Pdf - File";
```

## How a PDF file is resolved

A `PDF Files` record holds one document and, optionally, one translation per language in `PDF File Translations`. Which document is returned for a language code follows three rules:

1. the record is marked as **All Languages**, or no language code is asked for - the document of the record itself is returned;
2. a translation exists for the language code - the document of the translation is returned;
3. no translation exists for the language code - the document of the record itself is returned as the fallback.

A language that has no translation therefore never fails; it falls back to the default document. That is what makes it safe to pass the language of a sales document straight through.

## GetPdfFile()

Returns the document of the default language.

```pascal
    procedure GetPdfFile(): Codeunit "Temp Blob"
```

**Returns** the PDF file as a `Temp Blob` codeunit.

## GetPdfFile(Code)

Returns the document of the given language, with the fallback described above.

```pascal
    procedure GetPdfFile(languageCode: Code[10]): Codeunit "Temp Blob"
```

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `languageCode` | Code[10] | The language of the PDF file. An empty code returns the document of the default language. |

**Returns** the PDF file as a `Temp Blob` codeunit.

<Callout type="caution" title="Both methods return an empty document as of 20.5">
Neither overload takes the code of the `PDF Files` record to read, and the codeunit does not select one either - it reads from an uninitialized record and returns an empty `Temp Blob`. Until an overload that states which file to read is available, read the file through the `PDF Files` record itself, as shown below. The resolution rules are the same, they are implemented in the table.
</Callout>

## Reading a PDF file today

```pascal
    procedure GetLetterhead(languageCode: Code[10]): Codeunit "Temp Blob"
    var
        pdfFiles: Record "bdev.Pdf Files";
        letterheadNotFoundErr: Label 'The PDF file %1 does not exist.', Comment = '%1 = PDF file code';
    begin
        if (not pdfFiles.Get(LetterheadCodeLbl)) then
            Error(letterheadNotFoundErr, LetterheadCodeLbl);

        exit(pdfFiles.GetDocument(languageCode));
    end;

    var
        LetterheadCodeLbl: Label 'LETTERHEAD', Locked = true;
```

The document the record returns is the one a stationery configuration would use for the same language, so a letterhead you apply yourself through [Pdf - Stationery](pdf-stationery.mdx) matches the one the app applies during report processing.

## See also

- [365 business PDF - Overview](readme.mdx)
- [Pdf - Stationery](pdf-stationery.mdx)
- [Documentation - PDF Files](../../en-us/365-business-pdf/pdf-files.md)
