> Note: Dash.NET is currently considered experimental. If your organization is interested in sponsoring Dash.NET, please get in touch.

# 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:

- Money
- Percentage

    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")

Account | Balance | Rate
--- | --- | ---
A | $522.31 | 13.90%
B | $1,607.90 | 10.44%
C | −$228.41 | 19.90%

## 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")

No groups | Groups of 3 | Groups of 4 | Groups of 2,3,2
--- | --- | --- | ---
123 | 123 | 123 | 1,23
123 | 123 | 123 | 1,23
1234 | 1,234 | 1234 | 12,34
12345 | 12,345 | 1,2345 | 123,45
123456789 | 123,456,789 | 1,2345,6789 | 12,34,567,89

### 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")

No fill | Align left (10) | Align right (8) | Align center (6)
--- | --- | --- | ---
123 | 123------- | -----123 | -123--
123 | 123------- | -----123 | -123--
1234 | 1234------ | ----1234 | -1234-
12345 | 12345----- | ---12345 | 12345-
123456789 | 123456789- | 123456789 | 123456789

### 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")

No padding | Padding 12 | Padding 9 | Padding 6
--- | --- | --- | ---
123 | 000000000123 | 000000123 | 000123
123 | 000000000123 | 000000123 | 000123
1234 | 000000001234 | 000001234 | 001234
12345 | 000000012345 | 000012345 | 012345
123456789 | 000123456789 | 123456789 | 123456789

### 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")

No precision | Default | Fixed | Decimal | Integer | Decimal/Exponent | Decimal SI | Exponent
--- | --- | --- | --- | --- | --- | --- | ---
123.1 | 1.2e+2 | 123.10 | 120 | 123 | 1.2e+2 | 120 | 1.23e+2
123.12 | 1.2e+2 | 123.12 | 120 | 123 | 1.2e+2 | 120 | 1.23e+2
1234.123 | 1.2e+3 | 1234.12 | 1200 | 1234 | 1.2e+3 | 1.2k | 1.23e+3
12345.12 | 1.2e+4 | 12345.12 | 12000 | 12345 | 1.2e+4 | 12k | 1.23e+4

Percentage | Rounded Percentage | Binary | Octal | hex | HEX | Unicode
--- | --- | --- | --- | --- | --- | ---
12310.00% | 12000% | 1111011 | 173 | 7b | 7B | 123.1
12312.00% | 12000% | 1111011 | 173 | 7b | 7B | 123.12
123412.30% | 120000% | 10011010010 | 2322 | 4d2 | 4D2 | 1234.123
1234512.00% | 1200000% | 11000000111001 | 30071 | 3039 | 3039 | 12345.12

4 decimals | 4 decimals / trimmed | Custom 4 decimals / trimmed
--- | --- | ---
123.1000 | 123.1 | 123.1
123.1200 | 123.12 | 123.12
1234.1230 | 1234.123 | 1234.123
12345.1200 | 12345.12 | 12345.12

### 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")

Default | Negative | Positive | Parentheses | Percentage/Parentheses |
--- | --- | --- | --- | --- | ---
123.1 | 123.1 | +123.1 | 123.1 | 12310.00% | 123.1
123.12 | 123.12 | +123.12 | 123.12 | 12312.00% | 123.12
1234.123 | 1234.123 | +1234.123 | 1234.123 | 123412.30% | 1234.123
12345.12 | 12345.12 | +12345.12 | 12345.12 | 1234512.00% | 12345.12
−123.1 | −123.1 | −123.1 | (123.1) | (12310.00%) | (123.1)
−123.12 | −123.12 | −123.12 | (123.12) | (12312.00%) | (123.12)
−1234.123 | −1234.123 | −1234.123 | (1234.123) | (123412.30%) | (1234.123)
−12345.12 | −12345.12 | −12345.12 | (12345.12) | (1234512.00%) | (12345.12)

### 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")

Default | No Symbol | $ Symbol | @ Symbol / Locale prefix | @ Symbol / Locale prefix+suffix
--- | --- | --- | --- | ---
123.1 | 123.1 | $123.1 | @123.1 | @123.1*
123.12 | 123.12 | $123.12 | @123.12 | @123.12*
1234.123 | 1234.123 | $1234.123 | @1234.123 | @1234.123*
12345.12 | 12345.12 | $12345.12 | @12345.12 | @12345.12*

Binary | Octal | Hex | Custom
--- | --- | --- | ---
0b1111011 | 0o173 | 0x7b | @123.1*
0b1111011 | 0o173 | 0x7b | @123.12*
0b10011010010 | 0o2322 | 0x4d2 | @1234.123*
0b11000000111001 | 0o30071 | 0x3039 | @12345.12*

## 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")

Symbol | Symbol prefix | Symbol suffix | Symbol custom
--- | --- | --- | ---
$123 | CAD$ 123 | 123 $CAD | @123*
$123 | CAD$ 123 | 123 $CAD | @123*
$1234 | CAD$ 1234 | 1234 $CAD | @1234*
$12345 | CAD$ 12345 | 12345 $CAD | @12345*
$123456789 | CAD$ 123456789 | 123456789 $CAD | @123456789*

Decimal | Custom decimal | Group | Custom group
--- | --- | --- | ---
123:00 | 123:00 | 1:23 | 1:23
123:00 | 123:00 | 1:23 | 1:23
1234:00 | 1234:00 | 12:34 | 12:34
12345:00 | 12345:00 | 1:23:45 | 1:23:45
123456789:00 | 123456789:00 | 1:23:45:67:89 | 1:23:45:67:89

Custom numerals | Percent symbol | Group 4 digits | SI | SI+space | Explicit SI
--- | --- | --- | --- | --- | ---
AAbCC | 12300.00@ | 123 | 123000m | 123000 m | 123000m
AAbCC | 12300.00@ | 123 | 123000m | 123000 m | 123000m
AAbCC | 123400.00@ | 1234 | 1234000m | 1234000 m | 1234000m
AAbCC | 1234500.00@ | 12,345 | 12345000m | 12345000 m | 12345000m
AAbCC778899 | 12345678900.00@ | 123,456,789 | 123456789000m | 123456789000 m | 123456789000m