Document Attachment with Item Journal Table in Business Central

Business Central already provides the Document Attachment framework, but sometimes you need to extend it to work with additional tables.
In this blog, I’ll show you how I extended the Document Attachment functionality to support the Item Journal Line table.

By the end, you’ll be able to attach documents (like invoices, PDFs, or scanned files) directly to item journal lines and view them from the journal page.

Step 1: Extend the Document Type

First, extend the Document Type in the Document Attachment table to include a new option for Item Journal.
This makes it possible to tag an attachment specifically for an item journal line.

enumextension 50500 "Attachment Dc" extends "Attachment Document Type"
{

    value(50500; "Item Journal")
    {
        Caption = 'Item Journal';
    }
}


Step 2: Add Template Name and Batch Name Fields

The standard Document Attachment table doesn’t store the Template Name and Batch Name fields that are needed to uniquely identify an Item Journal Line.

So we extend the table with two new fields:

tableextension 50501 DocumentAttachment extends "Document Attachment"
{
    fields
    {
        field(50500; "Template Name"; Code[20])
        {
            Caption = 'Template Name';
            DataClassification = ToBeClassified;
        }
        field(50501; "Batch Name"; Code[20])
        {
            Caption = 'Batch Name';
            DataClassification = ToBeClassified;
        }
    }
}


Step 3: Add a FactBox on the Item Journal Page

To make attachments visible from the journal, we add a FactBox on the Item Journal page.

This FactBox points to the Document Attachment List FactBox and links the relevant keys (Table ID, Template Name, Batch Name, and Line No.):

pageextension 50502 "Item Journal" extends "Item Journal"
{

    layout
    {
        addafter(JournalErrorsFactBox)
        {
            part("Attached Documents List"; "Doc. Attachment List Factbox")
            {
                ApplicationArea = All;
                Caption = 'Documents';
                UpdatePropagation = Both;
                SubPageLink = "Table ID" = const(Database::"Item Journal Line"),
                              "Template Name" = field("Journal Template Name"),
                              "Batch Name" = field("Journal Batch Name"),
                              "Line No." = field("Line No.");
            }
        }
    }
}

Now, the user can see attached documents for each journal line directly from the Item Journal.

Step 4: Create a Codeunit to Handle the Events

The last step is to hook into the Document Attachment events so that attachments are properly linked to Item Journal Lines.

We subscribe to three main events:

  • OnBeforeDrillDown (opens the record reference),

  • OnAfterOpenForRecRef (applies filters for the attachment list),

  • OnAfterInitFieldsFromRecRef (initializes fields when creating a new attachment).

codeunit 50501 DocumentAttachment
{
    [EventSubscriber(ObjectType::Page, Page::"Document Attachment Factbox",
                                     'OnBeforeDrillDown', '', false, false)]
    local procedure OnBeforeDrillDown(DocumentAttachment: Record "Document Attachment";
                                                                var RecRef: RecordRef);
    var
        ItemJournalLine: Record "Item Journal Line";
    begin
        case DocumentAttachment."Table ID" of
            DATABASE::"Item Journal Line":
                begin
                    RecRef.Open(DATABASE::"Item Journal Line");
                    ItemJournalLine.Reset();
                    if DocumentAttachment."Template Name" <> '' then
                        ItemJournalLine.SetRange("Journal Template Name", DocumentAttachment."Template Name");

                    if DocumentAttachment."Batch Name" <> '' then
                        ItemJournalLine.SetRange("Journal Batch Name", DocumentAttachment."Batch Name");

                    ItemJournalLine.SetRange("Line No.", DocumentAttachment."Line No.");
                    if DocumentAttachment."No." <> '' then
                        ItemJournalLine.SetRange("Document No.", DocumentAttachment."No.");
                    if ItemJournalLine.FindFirst() then;
                    RecRef.GetTable(ItemJournalLine);
                end;
        end;
    end;

    [EventSubscriber(ObjectType::Page, Page::"Document Attachment Details",
                                    'OnAfterOpenForRecRef', '', false, false)]
    local procedure OnAfterOpenForRecRef(var DocumentAttachment: Record "Document Attachment";
                                                                var RecRef: RecordRef);
    var
        FieldRef: FieldRef;
        TemplateName: Code[20];
        BatchName: Code[20];
        Lineno: Integer;

    begin
        case RecRef.Number of
            DATABASE::"Item Journal Line":
                begin
                    FieldRef := RecRef.Field(1);
                    TemplateName := FieldRef.Value;
                    DocumentAttachment.SetRange("Template Name", TemplateName);

                    FieldRef := RecRef.Field(2);
                    Lineno := FieldRef.Value;
                    DocumentAttachment.SetRange("Line No.", Lineno);

                    FieldRef := RecRef.Field(41);
                    BatchName := FieldRef.Value;
                    DocumentAttachment.SetRange("Batch Name", BatchName);
                end;
        end;
    end;

    [EventSubscriber(ObjectType::Table, Database::"Document Attachment",
                         'OnAfterInitFieldsFromRecRef', '', false, false)]
    local procedure OnAfterInitFieldsFromRecRef(var DocumentAttachment:
                     Record "Document Attachment"; var RecRef: RecordRef)
    var
        FieldRef: FieldRef;
        RecNo: Code[20];
        TemplateName: Code[20];
        BatchName: Code[20];
        LineNo: Integer;
    begin
        case RecRef.Number of
            DATABASE::"Item Journal Line":
                begin
                    TemplateName := GetFieldValueAsText(RecRef, 1);
                    DocumentAttachment.Validate("Template Name", TemplateName);

                    FieldRef := RecRef.Field(2);
                    Lineno := FieldRef.Value;
                    DocumentAttachment.Validate("Line No.", Lineno);

                    BatchName := GetFieldValueAsText(RecRef, 41);
                    DocumentAttachment.Validate("Batch Name", BatchName);

                    RecNo := GetFieldValueAsText(RecRef, 7);
                    DocumentAttachment.Validate("No.", RecNo);

                    DocumentAttachment.Validate("Document Type", DocumentAttachment."Document Type"::"Item Journal");
                end;
        end;
    end;

    local procedure GetFieldValueAsText(var R: RecordRef; FieldNumber: Integer): Text[250]
    var
        FieldRef: FieldRef;
    begin
        FieldRef := R.Field(FieldNumber);
        exit(Format(FieldRef.Value));
    end;
}

With this extension in place:

  • Users can attach documents directly to Item Journal Lines,

  • The attachments are visible in a FactBox on the Item Journal,

  • The system automatically links attachments using Template Name, Batch Name, and Line No.,

  • The standard Document Attachment framework is extended in a clean, upgrade-safe way.







This approach can be applied to other journal or document tables too — just extend the Document Attachment table with the necessary keys and subscribe to the same events.

Thank you for your time,
Dharmendra Chavda


Comments

Popular posts from this blog

Run a Dynamics 365 Plugin from JavaScript on Button Click

Data Upload into CRM from Excel Using Power Automate

Add Java Script and CSS in PowerApps Portal