An on-demand subscriber with AL

Use Case

An end-user wants the company address on all company reports, but, when printing checks, the address should be a different one.

Background

I had this use case in a few instances and meant to write a few lines about it, but kept postponing, until now. You can add custom address fields on the company information page (and table) or any other custom table/page pair. The idea is that the sales invoices (and all other system reports) should display one address(company address in the company information page), whereas some other report, like the check report, should print an alternate address. Why? Well, say Accounts Payable is in Los Angeles and the warehouse and the head office is in Denver.

How

How can we accommodate this, while fully taking advantage of the framework Microsoft has made available via Format Address codeunit 365?

I decided to call it on-demand subscribing. On one hand, when I run the check report I want to subscribe to OnBeforeCompany event and execute some custom code, whereas when the sales invoice runs – and all other system reports – I want to bypass the code in my subscriber.

This is the base Company function code in “Format Address” codeunit:

    procedure Company(var AddrArray: array[8] of Text[100]; var CompanyInfo: Record "Company Information")
    var
        IsHandled: Boolean;
    begin
        IsHandled := false;
        OnBeforeCompany(AddrArray, CompanyInfo, IsHandled);
        if IsHandled then
            exit;

        with CompanyInfo do
            FormatAddr(
              AddrArray, Name, "Name 2", '', Address, "Address 2",
              City, "Post Code", County, '');
    end;

And this would be my subscriber to the OnBeforeCompany event:

    [EventSubscriber(ObjectType::Codeunit, Codeunit::"Format Address", 'OnBeforeCompany', '', false, false)]
    local procedure CompanyAlternateAddress(var AddrArray: array[8] of Text[100]; var CompanyInfo: Record "Company Information"; var IsHandled: Boolean)
    var
        FormatAddr: Codeunit "Format Address";
    begin
        FormatAddr.FormatAddr(AddrArray, CompanyInfo."Alt. Name.SVI",
                                            CompanyInfo."Alt. Name 2.SVI",
                                            '',
                                            CompanyInfo."Alternate Address.SVI",
                                            CompanyInfo."Alternate Address2.SVI",
                                            CompanyInfo."Alternate City.SVI",
                                            CompanyInfo."Alternate Zip Code.SVI",
                                            '',
                                            CompanyInfo."Alternate Country.SVI");
        IsHandled := true;
    end;

How would I execute the subscriber only when coming from the check report and not on all other reports utilizing FormatAddr.Company function?

There might be other ways, but the way I always go with is using BindSubscription and UnBindSubscription platform functions.

Then, in the check report, wrap FormatAddr.Company call, with BindSubscription and UnBindSubscription like below:

var
        Codeunit50010: Codeunit "Check Address Manual Events";
//code for check report        
        BindSubscription(Codeunit50010);
        FormatAddr.Company(CompanyAddr, CompanyInfo);
        UnbindSubscription(Codeunit50010);

Do not forget to set the property EventSubscriberInstance, of the bound codeunit, to Manual.

codeunit 50010 "Check Address Manual Events"
{
    EventSubscriberInstance = Manual;
    [EventSubscriber(ObjectType::Codeunit, Codeunit::"Format Address", 'OnBeforeCompany', '', false, false)]
    local procedure CompanyAlternateAddress(var AddrArray: array[8] of Text[100]; var CompanyInfo: Record "Company Information"; var IsHandled: Boolean)
    var
        FormatAddr: Codeunit "Format Address";
    begin
        FormatAddr.FormatAddr(AddrArray, CompanyInfo."Alt. Name.SVI",
                                            CompanyInfo."Alt. Name 2.SVI",
                                            '',
                                            CompanyInfo."Alternate Address.SVI",
                                            CompanyInfo."Alternate Address2.SVI",
                                            CompanyInfo."Alternate City.SVI",
                                            CompanyInfo."Alternate Zip Code.SVI",
                                            '',
                                            CompanyInfo."Alternate Country.SVI");
        IsHandled := true;
    end;
}

Conclusions:

  • on-demand subscribers need to live in a codeunit whose EventSubscriberInstance = Manual;
  • on-demand subscribers are brought in memory with BindSubscription
  • Codeunits having EventSubscriberInstance = Manual should contain event subscribers serving one specific use case only.

Hope this helps!