widthfielddynamics-business-centraldynamics-al

Dynamically set column width on page in Business Central


For some background, I'm a junior Business Central AL developer with not much experience. I am hoping to find some help with the syntax of what I'm trying to accomplish.

 

Situation:

I have several Sales Lines displaying in a Sales Order. I want to increase the width of the Sales Line "No." field based on the longest "No." value.

 

Example:

Sales Order abc123 has four Sales Line entries:

 

Desired outcome of example:

The "No." column of the Sales Line to have its width property set to the length of the longest "Sales Line"."No.". In this example, the width property would be set to 7 (Longest sales line is #4, with a length of 7).

 

What I have so far:

I have the following psuedo(ish)code and I'm not really sure how to put it into practice. The specific part I'm struggling with is inserting each "Sales Line"."No." length ("No.".StrLen(String: Text)) into the array (SalesLineNumbers), and then finding the largest integer in the array.

 

modify("No.") {
    trigger OnAfterValidate();
    var
        SalesLineNumbers: array of Integer;
        MaxSalesLineNumberLen: Integer;
    begin
        "Sales Header".Get(abc123);    //find the sales header we are working with

        foreach "Sales Line"."No." in "Sales Header":    //perform the following actions for each sales line within this sales header
            insert into SalesLineNumbers "No.".StrLen(String: Text);    //add the length of the "Sales Line"."No." into the array
                    
        MaxSalesLineNumberLen := max(value in SalesLineNumbers);    //set MaxSalesLineNumberLen to the largest integer in the array
    end;

    Width = MaxPartNoLen;    //set the width property of field "No." to MaxPartNoLen
}

 

If there is any more information you need me to provide, or if I'm not clear in what I'm trying to accomplish, please let me know.

Thank you in advance for reading.


Solution

  • first of all I like the format of your question:: Situation, Example, Desired outcome and What I have so far. Awesome, keep it up!

    I get two compiler errors saying that I can't use a variable and therefore have to use an integer literal. al compiler errors in vscode

    The code for determining the longest number would look similar to this:

    var
        SalesLine: Record "Sales Line";
        MaxLength: Integer;
    begin
        MaxLength := 0;
        SalesLine.SetRange("Document Type", Rec."Document Type");
        SalesLine.SetRange("Document No.", Rec."Document No.");
        if SalesLine.FindSet() then
            repeat
                if MaxStrLen(SalesLine."No.") > MaxLength then
                    MaxLength := StrLen(SalesLine."No.");
            until SalesLine.Next() = 0;
    
        Message(Format(MaxLength));
    end;
    

    Unfortunately, as already mentioned, we cannot use this variable for the width property.

    If the number is really so important that it needs to be displayed in full length, set the width to 20. Keep in mind that Users can override the width by personalizing the page that displays the field. Read more about the Width property: https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/developer/properties/devenv-width-property

    Transfering the pseudo(ish)code into AL, I would use a list instead of an array, and the code could look like this, for example:

    var
        SalesHeader: Record "Sales Header";
        SalesLine: Record "Sales Line";
        SalesLineNumbers: List of [Integer];
        MaxSalesLineNumberLen: Integer;
        Index: Integer;
    begin
        SalesHeader.Get(Enum::"Sales Document Type"::Order, 'S-ORD101009');    //find the sales header we are working with
    
        SalesLine.SetRange("Document Type", SalesHeader."Document Type");
        SalesLine.SetRange("Document No.", SalesHeader."No.");
        if SalesLine.FindSet() then //perform the following actions for each sales line within this sales header
            repeat
                SalesLineNumbers.Add(StrLen(SalesLine."No.")); //add the length of the "Sales Line"."No." into the list
            until SalesLine.Next() = 0;
    
        // loop through the list to find the largest value
        for Index := 1 to SalesLineNumbers.Count() do begin
            if SalesLineNumbers.Get(Index) > MaxSalesLineNumberLen then
                MaxSalesLineNumberLen := SalesLineNumbers.Get(Index); //set MaxSalesLineNumberLen to the largest integer in the list
        end;
    end;
    

    Please feel free to ask, if you have any further questions.