Dynamics 365 Business Central: Select the only Year (Month or Day) when entering dates(Only year drop)

Dynamics 365 Business Central

Hi, Readers.
Today I would like to talk about an interesting question I was asked before, is there any way to select the only Year (Month or Day) when entering dates.
As you might know, any field displaying a calendar icon can be set using the calendar date picker in Business Central. To display the calendar date picker, activate the calendar icon or select the Ctrl+Home keyboard shortcut in the field. More details:

It displays like this on mobile.

So, is it possible to enter the date in the following way? Only Year (Month or Day).

Obviously this is not a standard feature, so what should we consider if we customize it? Without considering adding a new table, we can use the Date virtual table.

Let’s see more details about Date virtual table.

The Date virtual table (ID 2000000007) in Business Central gives you easy access to days, weeks, months, quarters, and years.
The Date virtual table has the following fields.

FieldDescription
Period TypeDays, weeks, months, quarters, or years.
Period StartThe date of the first day in the period.
Period EndThe date of the last day in the period.
Period No.The number of the period.
Period NameThe name of the period.

And the primary key is “Period Type”, “Period Start”.

You can force Business Central to run the “Date” table by adding the ?table=2000000007 parameter to the URL, such as in the following example: 
https://businesscentral.dynamics.com/d8f36038-1f93-4543-affc-5dc92b6ee871/Sandbox?table=2000000007

The dates from 01/03/0001 to 12/31/9999 will be displayed by different period types.

If Period Type is Date

Period No.: The day of the week (1=Monday, 2=Tuesday, 3=Wednesday, etc)
Period Name: Name of the date (Monday, Tuesday, Wednesday, etc)

If Period Type is Week

Period No.: Week Number of the year
Period Name: Week Number of the year

If Period Type is Month

Period No.: Month Number (1=Jaunary, 2=Frbruary, 3=March, etc)
Period Name: Name of the month

If Period Type is Quarter

Period No.: Quarter Number (1=Jaunary~March, 2=April~June, 3= July~September, etc)
Period Name: Quarter Number (1=Jaunary~March, 2=April~June, 3= July~September, etc)

If Period Type is Year

Period No.: Year
Period Name: Year

That’s all. So how to use it? First of all, it is not recommended to use TableRelation Property to lookup into this table, because there are no Field groups (DropDown controls) set in this table, and the primary key fields will be displayed by default.

And it’s a virtual table, we can’t extend it either.
Error: The system or virtual table ‘Date’ cannot be extended. ALAL0525

More details: Business Central 2023 wave 2 (BC23): Add a new FieldGroup (Brick & DropDown) to an existing table

So, we need to create the page first. As mentioned above, the Period No. includes the day of the week, week, month, quarter and year, but no day. The simplest way is to create two pages, one for selecting the year and month, and one for selecting the day. Of course, you can also just create one page and then use variables to control the fields displayed when it is opened. More details: Dynamic Visibility of Controls (Hide and show fields dynamically)
PS: If you don’t want it to show up when you use the search functionality, please remove the UsageCategory Property and ApplicationArea Property.

Then you can add year, month, and day fields to the required page to enter data. Here I have added some controls, such as the maximum value, minimum value, and the year needs to be entered before entering the month.

Finally, add the fields to the page and add the logic for selecting data in the OnLookup (Page Field) Trigger. More details: How to create a Lookup, Drop-Down, or Option list (Single and Multi select)
Please note that these dates need to be associated or the data will not be accurate.

Let’s test it briefly.

Year:

Month:

PS: If you display the Period Name on the lookup page, the user can select the name of the month. This has no effect on the year.

Day:

Result: Looks good.

Test video: This also allows the user to enter manually.

Of course, you can also add a new table to do this, but I won’t go into details in this post. And generally, I personally feel that this requirement should be avoided unless the user really needs it. Because if customers need it, it will not just be on one page, but many functions may need to be added, and this only changes the form of date input, and customers should get used to the standard approach. Give it a try!!!😁

Source code: Github  (Please note that the source code is for reference only, you can improve it according to your own needs)

page 50102 "Enter Year/Month"
{
    ApplicationArea = All;
    Caption = 'Enter Year/Month';
    PageType = List;
    SourceTable = "Date";
    UsageCategory = Lists;

    layout
    {
        area(content)
        {
            repeater(General)
            {
                field("Period No."; Rec."Period No.")
                {
                    ToolTip = 'Specifies the number of the period shown in the line.';
                }
            }
        }
    }
}

page 50103 "Enter Day"
{
    ApplicationArea = All;
    Caption = 'Enter Day';
    PageType = List;
    SourceTable = "Date";
    UsageCategory = Lists;

    layout
    {
        area(content)
        {
            repeater(General)
            {
                field(Day; Date2DMY(Rec."Period Start", 1))
                {
                    ToolTip = 'Specifies the start date of the period shown in the line.';
                }
            }
        }
    }
}

tableextension 50118 CustomerExt extends Customer
{
    fields
    {
        field(50100; Year; Integer)
        {
            Caption = 'Year';
            DataClassification = CustomerContent;
            MinValue = 2000;
            MaxValue = 2099;

            trigger OnValidate()
            begin
                if Year <> 0 then begin
                    Month := 0;
                    Day := 0;
                    EnteredDate := 0D;
                end;
            end;
        }
        field(50101; Month; Integer)
        {
            Caption = 'Month';
            DataClassification = CustomerContent;
            MinValue = 0;
            MaxValue = 12;

            trigger OnValidate()
            begin
                if Year = 0 then
                    Error('Please enter a year first');
                if Month <> 0 then begin
                    Day := 0;
                    EnteredDate := 0D;
                end;
            end;
        }
        field(50102; Day; Integer)
        {
            Caption = 'Day';
            DataClassification = CustomerContent;
            MinValue = 0;
            MaxValue = 31;

            trigger OnValidate()
            begin
                if Month = 0 then
                    Error('Please enter a month first');
                if Day <> 0 then
                    EnteredDate := DMY2Date(Day, Month, Year);
            end;
        }
        field(50103; EnteredDate; Date)
        {
            Caption = 'Entered Date';
            DataClassification = CustomerContent;
            Editable = false;
        }
    }
}

pageextension 50118 CustomerListExt extends "Customer Card"
{
    layout
    {
        addafter(Name)
        {
            field(Year; Rec.Year)
            {
                ApplicationArea = All;

                trigger OnLookup(var Text: Text): Boolean
                var
                    DateRec: Record Date;
                begin
                    DateRec.Reset();
                    DateRec.SetRange("Period Type", DateRec."Period Type"::Year);
                    DateRec.SetRange("Period No.", 2000, 2099);
                    if Page.RunModal(Page::"Enter Year/Month", DateRec) = Action::LookupOK then
                        Rec.Validate(Year, DateRec."Period No.");
                end;
            }
            field(Month; Rec.Month)
            {
                ApplicationArea = All;

                trigger OnLookup(var Text: Text): Boolean
                var
                    DateRec: Record Date;
                begin
                    if Rec.Year = 0 then
                        Error('Please enter a year first');
                    DateRec.Reset();
                    DateRec.SetRange("Period Type", DateRec."Period Type"::Month);
                    DateRec.SetRange("Period Start", DMY2Date(1, 1, Rec.Year), DMY2Date(1, 12, Rec.Year));
                    if Page.RunModal(Page::"Enter Year/Month", DateRec) = Action::LookupOK then
                        Rec.Validate(Month, DateRec."Period No.");
                end;
            }
            field(Day; Rec.Day)
            {
                ApplicationArea = All;
                trigger OnLookup(var Text: Text): Boolean
                var
                    DateRec: Record Date;
                begin
                    if Rec.Month = 0 then
                        Error('Please enter a month first');
                    DateRec.Reset();
                    DateRec.SetRange("Period Type", DateRec."Period Type"::Date);
                    DateRec.SetRange("Period Start", DMY2Date(1, Rec.Month, Rec.Year), CalcDate('<CM>', DMY2Date(1, Rec.Month, Rec.Year)));
                    if Page.RunModal(Page::"Enter Day", DateRec) = Action::LookupOK then
                        Rec.Validate(Day, Date2DMY(DateRec."Period Start", 1));
                end;
            }
            field(EnteredDate; Rec.EnteredDate)
            {
                ApplicationArea = All;
            }
        }
    }
}

PS: This can also be done with some Javascript or Html add-in. For example,

END

Hope this will help.

Thanks for reading.

ZHU

コメント

Copied title and URL