DataTable - Number Formatting

DataTable offers extensive number formatting and localization possibilities with the columns nested prop Format and
table-wide localization prop LocaleFormat.

Most formatting and localization for columns can be done through the DashTable.FormatTemplate
and DashTable.Format helpers but it’s also possible to use the d3-format
specifier and locale directly.

Use Format.init() to access specifier and locale directly, and use Format.helper() to access the helper functions.

See d3-format for additional syntax details.

Using FormatTemplate

The FormatTemplate provides the following predefined templates:

open Dash.NET.Giraffe
open Dash.NET.DashTable

let money = FormatTemplate.money(2u)
let percentage = FormatTemplate.percentage(2u)

let columns = [|
    DataTable.Column.init("Account", "account")
    DataTable.Column.init("Balance", "balance", columnType = DataTable.ColumnType.Numeric, format=money)
    DataTable.Column.init("Rate", "rate", columnType = DataTable.ColumnType.Numeric, format=percentage)
|]

let data = [
    box {| account = "A"; balance = 522.3199; rate = 0.139 |}
    box {| account = "B"; balance = 1607.999; rate = 0.1044 |}
    box {| account = "C"; balance = (-228.4199); rate = 0.199 |}
]

let layout =
    DataTable.dataTable "datatable" [
        DataTable.Attr.columns columns
        DataTable.Attr.data data
    ]

[<EntryPoint>]
let main argv =
    DashApp.initDefault()
    |> DashApp.withLayout layout
    |> DashApp.run argv (DashGiraffeConfig.initDefault "localhost")

Using Format Helper

Group

Grouping is defined with the format nested props group and groups.
group takes values true or Group.Yes to toggle digit grouping.
groups takes a list of numbers used to define the digits grouping pattern.
If the number has more digits than what’s defined in groups, it cycles through the
list again until it runs out of numbers to group.

open Dash.NET.Giraffe
open Dash.NET.DashTable

let columns = [|
    DataTable.Column.init("No groups", "a", columnType=DataTable.ColumnType.Numeric,
                    format=Format.helper())
    DataTable.Column.init("Groups of 3", "a", columnType=DataTable.ColumnType.Numeric,
                    format=Format.helper().group(true))
    DataTable.Column.init("Groups of 4", "a", columnType=DataTable.ColumnType.Numeric,
                    format=Format.helper(group=Group.Yes, groups=[ 4u ]))
    DataTable.Column.init("Groups of 2,3,2", "a", columnType=DataTable.ColumnType.Numeric,
                    format=Format.helper(group=Group.Yes).groups([ 2u; 3u; 2u ]))
|]

let values = [ 123; 123; 1234; 12345; 123456789 ]

let layout =
    DataTable.dataTable "datatable" [
        DataTable.Attr.columns columns
        DataTable.Attr.data (values |> List.map (fun v -> box {| a = v |}))
    ]

[<EntryPoint>]
let main argv =
    DashApp.initDefault()
    |> DashApp.withLayout layout
    |> DashApp.run argv (DashGiraffeConfig.initDefault "localhost")

Align and Fill

Alignment and filling is defined with the format nested props align, fill, and paddingWidth.
The align helper takes values Left, Right, and Center.
fill is single character that will be used for filling.
paddingWidth is the minimum length of the filled string.
If the formatted number requires more space than paddingWidth allows for, it will do so.

open Dash.NET.Giraffe
open Dash.NET.DashTable

let columns = [|
    DataTable.Column.init("No fill", "a", columnType=DataTable.ColumnType.Numeric,
                    format=Format.init())
    DataTable.Column.init("Align left (10)", "a", columnType=DataTable.ColumnType.Numeric,
                    format=Format.helper().align(Left).fill('-').paddingWidth(10u))
    DataTable.Column.init("Align right (8)", "a", columnType=DataTable.ColumnType.Numeric,
                    format=Format.helper(align=Right, fill='-', paddingWidth=8u))
    DataTable.Column.init("Align center (6)", "a", columnType=DataTable.ColumnType.Numeric,
                    format=Format.init(specifier="-^6"))
|]

let values = [ 123; 123; 1234; 12345; 123456789 ]

let layout =
    DataTable.dataTable "datatable" [
        DataTable.Attr.columns columns
        DataTable.Attr.data (values |> List.map (fun v -> box {| a = v |}))
    ]

[<EntryPoint>]
let main argv =
    DashApp.initDefault()
    |> DashApp.withLayout layout
    |> DashApp.run argv (DashGiraffeConfig.initDefault "localhost")

Padding and Padding Width

Padding and padding width is defined with the format nested props padding and paddingWidth and they behave similarly
to fill and paddingWidth, but do not allow alignment.

open Dash.NET.Giraffe
open Dash.NET.DashTable

let columns = [|
    DataTable.Column.init("No padding", "a", columnType=DataTable.ColumnType.Numeric,
                    format=Format.init())
    DataTable.Column.init("Padding 12", "a", columnType=DataTable.ColumnType.Numeric,
                    format=Format.helper(padding=Padding.Yes, paddingWidth=12u))
    DataTable.Column.init("Padding 9", "a", columnType=DataTable.ColumnType.Numeric,
                    format=Format.helper(padding=Padding.Yes).paddingWidth(9u))
    DataTable.Column.init("Padding 6", "a", columnType=DataTable.ColumnType.Numeric,
                    format=Format.init(specifier="06"))
|]

let values = [ 123; 123; 1234; 12345; 123456789 ]

let layout =
    DataTable.dataTable "datatable" [
        DataTable.Attr.columns columns
        DataTable.Attr.data (values |> List.map (fun v -> box {| a = v |}))
    ]

[<EntryPoint>]
let main argv =
    DashApp.initDefault()
    |> DashApp.withLayout layout
    |> DashApp.run argv (DashGiraffeConfig.initDefault "localhost")

Precision and Scheme

open Dash.NET.Giraffe
open Dash.NET.DashTable
open Dash.NET.Html

let columns = [
    [|
        DataTable.Column.init("No precision", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.init())
        DataTable.Column.init("Default", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(precision=2u))
        DataTable.Column.init("Fixed", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(precision=2u, scheme=Fixed))
        DataTable.Column.init("Decimal", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(precision=2u, scheme=Decimal))
        DataTable.Column.init("Integer", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(precision=2u, scheme=DecimalInteger))
        DataTable.Column.init("Decimal/Exponent", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(precision=2u, scheme=DecimalOrExponent))
        DataTable.Column.init("Decimal SI", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(precision=2u, scheme=DecimalSiPrefix))
        DataTable.Column.init("Exponent", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(precision=2u, scheme=Exponent))
    |]
    [|
        DataTable.Column.init("Percentage", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(precision=2u, scheme=Percentage))
        DataTable.Column.init("Rounded Percentage", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(precision=2u, scheme=PercentageRounded))
        DataTable.Column.init("Binary", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(precision=2u, scheme=Scheme.Binary))
        DataTable.Column.init("Octal", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(precision=2u, scheme=Scheme.Octal))
        DataTable.Column.init("hex", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(precision=2u, scheme=LowerCaseHex))
        DataTable.Column.init("HEX", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(precision=2u, scheme=UpperCaseHex))
        DataTable.Column.init("Unicode", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(precision=2u, scheme=Unicode))
    |]
    [|
        DataTable.Column.init("4 decimals", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(precision=4u, scheme=Fixed))
        DataTable.Column.init("4 decimals / trimmed", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(precision=4u, scheme=Fixed, trim=Trim.Yes))
        DataTable.Column.init("Custom 4 decimals / trimmed", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.init(specifier=".4~f"))
    |]
]

let data =
    [ 123.1; 123.12; 1234.123; 12345.12 ]
    |> List.map (fun v -> box {| a = v |})

let layout =
    Html.div [
        Attr.children (
            columns
            |> List.mapi (fun i columns ->
                Html.div [
                    Attr.children [
                        DataTable.dataTable (sprintf "datatable_%i" i) [
                            DataTable.Attr.columns columns
                            DataTable.Attr.data data
                        ]
                        Html.br []
                    ]
                ]
            )
        )
    ]

[<EntryPoint>]
let main argv =
    DashApp.initDefault()
    |> DashApp.withLayout layout
    |> DashApp.run argv (DashGiraffeConfig.initDefault "localhost")


Sign

When to display a sign and what type of sign to display is defined with the format nested prop sign.
The Sign helper takes values Negative (show sign when negative), Positive (always show sign), Parantheses (when negative)

open Dash.NET.Giraffe
open Dash.NET.DashTable

let columns = [|
    DataTable.Column.init("Default", "a", columnType=DataTable.ColumnType.Numeric,
                    format=Format.init())
    DataTable.Column.init("Negative", "a", columnType=DataTable.ColumnType.Numeric,
                    format=Format.helper(sign=Negative))
    DataTable.Column.init("Positive", "a", columnType=DataTable.ColumnType.Numeric,
                    format=Format.helper(sign=Positive))
    DataTable.Column.init("Parentheses", "a", columnType=DataTable.ColumnType.Numeric,
                    format=Format.helper().sign(Parantheses))
    DataTable.Column.init("Percentage/Parentheses", "a", columnType=DataTable.ColumnType.Numeric,
                    format=Format.helper(scheme=Percentage, precision=2u, sign=Parantheses))
    DataTable.Column.init("Custom", "a", columnType=DataTable.ColumnType.Numeric,
                    format=Format.init(specifier="("))
|]

let values = [
    123.1; 123.12; 1234.123; 12345.12;
    -123.1; -123.12; -1234.123; -12345.12
]

let layout =
    DataTable.dataTable "datatable" [
        DataTable.Attr.columns columns
        DataTable.Attr.data (values |> List.map (fun v -> box {| a = v |}))
    ]

[<EntryPoint>]
let main argv =
    DashApp.initDefault()
    |> DashApp.withLayout layout
    |> DashApp.run argv (DashGiraffeConfig.initDefault "localhost")

Symbol

Displaying of symbols is defined with the format nested prop symbol and the prefix/suffix symbols are defined with the locale nested prop symbol.
The Symbol helper takes values Yes and No.
The locale symbol nested prop is a list of strings of length 2 of the form [prefix, suffix]. Strings in symbol can be of any length.

open Dash.NET.Giraffe
open Dash.NET.DashTable
open Dash.NET.Html

let columns = [
    [|
        DataTable.Column.init("Default", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.init())
        DataTable.Column.init("No Symbol", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(symbol=Symbol.No))
        DataTable.Column.init("$ Symbol", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper().symbol(Symbol.Yes))
        DataTable.Column.init("@ Symbol / Locale prefix", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper().symbol(Symbol.Yes).symbolPrefix("@"))
        DataTable.Column.init("@ Symbol / Locale prefix+suffix", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper().symbol(Symbol.Yes).symbolPrefix("@").symbolSuffix("*"))
    |]
    [|
        DataTable.Column.init("Binary", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(symbol=Binary))
        DataTable.Column.init("Octal", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(symbol=Octal))
        DataTable.Column.init("Hex", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(symbol=Hex))
        DataTable.Column.init("Custom", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.init(locale=DataTable.Locale.init(symbol=["@"; "*"]), specifier="$"))
    |]
]

let data =
    [ 123.1; 123.12; 1234.123; 12345.12 ]
    |> List.map (fun v -> box {| a = v |})

let layout =
    Html.div [
        Attr.children (
            columns
            |> List.mapi (fun i columns ->
                Html.div [
                    Attr.children [
                        DataTable.dataTable (sprintf "datatable_%i" i) [
                            DataTable.Attr.columns columns
                            DataTable.Attr.data data
                        ]
                        Html.br []
                    ]
                ]
            )
        )
    ]

[<EntryPoint>]
let main argv =
    DashApp.initDefault()
    |> DashApp.withLayout layout
    |> DashApp.run argv (DashGiraffeConfig.initDefault "localhost")

Localization

open Dash.NET.Giraffe
open Dash.NET.DashTable
open Dash.NET.Html

let columns = [
    [|
        DataTable.Column.init("Symbol", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(symbol=Symbol.Yes))
        DataTable.Column.init("Symbol prefix", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(symbol=Symbol.Yes, symbolPrefix="CAD$ "))
        DataTable.Column.init("Symbol suffix", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(symbol=Symbol.Yes, symbolSuffix=" CAD$"))
        DataTable.Column.init("Symbol custom", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.init(specifier="$", locale=DataTable.Locale.init(symbol = [ "@"; "*" ])))
    |]
    [|
        DataTable.Column.init("Decimal", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(decimalDelimiter=':').scheme("f").precision(2u))
        DataTable.Column.init("Custom decimal", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.init(specifier=".2f", locale=DataTable.Locale.init(decimal=':')))
        DataTable.Column.init("Group", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(groupDelimiter=':', group=Group.Yes, groups=[2u]))
        DataTable.Column.init("Custom group", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.init(specifier=",", locale=DataTable.Locale.init(group=':', grouping=[2u])))
    |]
    [|
        DataTable.Column.init("Custom numerals", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.init(locale=DataTable.Locale.init(numerals=["0"; "AA"; "b"; "CC"; ""; ""; ""; "77"; "88"; "99"])))
        DataTable.Column.init("Percent symbol", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.init(specifier=".2%", locale=DataTable.Locale.init(percent="@")))
        DataTable.Column.init("Group 4 digits", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.init(specifier=",.0f", locale=DataTable.Locale.init(separate4digits=false)))
        DataTable.Column.init("SI", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(siPrefix=Milli).precision(0u))
        DataTable.Column.init("SI+space", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(siPrefix=Milli, symbol=Symbol.Yes, symbolSuffix=" ").precision(0u))
        DataTable.Column.init("Explicit SI", "a", columnType=DataTable.ColumnType.Numeric,
                        format=Format.helper(siPrefix=Explicit (10. ** -3.)).precision(0u))
    |]
]

let data =
    [ 123; 123; 1234; 12345; 123456789 ]
    |> List.map (fun v -> box {| a = v |})

let layout =
    Html.div [
        Attr.children (
            columns
            |> List.mapi (fun i columns ->
                Html.div [
                    Attr.children [
                        DataTable.dataTable (sprintf "datatable_%i" i) [
                            DataTable.Attr.columns columns
                            DataTable.Attr.data data
                        ]
                        Html.br []
                    ]
                ]
            )
        )
    ]

[<EntryPoint>]
let main argv =
    DashApp.initDefault()
    |> DashApp.withLayout layout
    |> DashApp.run argv (DashGiraffeConfig.initDefault "localhost")