Business Central Musings

For the things we have to learn before we can do them, we learn by doing them

An on-demand subscriber with AL

Share This Post

Use Case

An end-user wants the company address on all company reports, but, when printing checks, the address should be a different one. Hence, the current topic is how to execute AL subscriber on demand with BindSubscription.

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 executing AL subscriber on demand with 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:

  • Running an AL subscriber with BindSubscription needs to happen 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 use case is a good and easy to comprehend example of how to execute AL subscriber on demand with BindSubscription.

Share This Post

Related Articles

3 Responses

  1. Cool! I didn’t know this feature. In your use case the advantage compared to coding in the report is small. It could be more useful when the code block is bigger…I’m trying to think of a situation where this approach really pays off!

Leave a Reply

Recent Posts

Get Notified About New Posts

Categories