OpenBI Docs Buy

Privacy.Anonymize OpenBI

Personal data in a table's columns found and replaced, redacted, masked or hashed as the table loads, so it never reaches the model.

Group: Privacy. OpenBI’s own: Power Query M has no function of this name.

Syntax

Privacy.Anonymize(table as table, columns as any, optional options as nullable record) as table
ParameterTypeDescription
tabletableThe table to anonymize.
columnsanyThe column, or a list of columns, that may hold personal data.
optionsnullable record
optional
Detector, Operator, Entities, Whole, Type, Salt, PresidioUrl and Language: see Remarks.

Returns

table. The same table, the named columns anonymized as text; the other columns as they were.

Remarks

  • Detector "openbi" (the default) finds names, e-mail and IP addresses, Norwegian national identity numbers (fødselsnummer and D-number), phone numbers, account numbers, IBANs and card numbers, each number checked by its check digits. A name is a common first name followed by a capitalized word, or a first name after a greeting. "presidio" adds what Microsoft Presidio's analyzer finds, at PresidioUrl (OpenBI Studio's Privacy setting unless given) in Language ("en").
  • Operator "replace" (the default) writes the kind in its place: <EMAIL>, <PERSON>, <PHONE>, <CARD>, <IBAN>, <ACCOUNT>, <NO_ID>, <IP>, <LOCATION>. "redact" removes it; "mask" turns its letters and digits into * but the last two; "hash" writes the SHA-256 of Salt and the value, 64 hexadecimal digits: the same value always gets the same hash, so joins and counts still work.
  • Entities limits it to some kinds, as {"EMAIL", "PHONE"}. Whole = true treats each whole value as personal (an e-mail or customer column), named by Type (PII unless given).
  • It runs as part of the table's SQL, so a refresh reads the personal data only to anonymize it. When Presidio is asked for and doesn't answer, the load fails: nothing goes through un-anonymized.
  • Detection follows rules, check digits and lists of names: a name it has never seen, written alone, can slip through. Presidio finds more. In Transform data, Home › Anonymize writes this step.

Compared with Power Query

An OpenBI function: Power Query has none like it, so a query that uses it runs in OpenBI only, not in Power BI Desktop or the Power BI service.

Examples

Names, phone numbers and e-mail addresses in comments

Privacy.Anonymize(
    #table({"Ticket", "Comment"}, {
        {1, "Call Emma Hansen on +47 912 34 567"},
        {2, "Mail sent to kari@example.no"},
        {3, "Printer jammed again"}}),
    {"Comment"})
TicketComment
1Call <PERSON> on <PHONE>
2Mail sent to <EMAIL>
3Printer jammed again

Masked, and only e-mail addresses redacted

let
    Tickets = #table({"Ticket", "Comment"}, {{1, "Call Emma Hansen on +47 912 34 567"}, {2, "Mail sent to kari@example.no"}}),
    Masked = Privacy.Anonymize(Tickets, {"Comment"}, [Operator = "mask"]),
    Redacted = Privacy.Anonymize(Tickets, {"Comment"}, [Entities = {"EMAIL"}, Operator = "redact"])
in
    Table.Combine({Masked, Redacted})
TicketComment
1Call **** ****en on +** *** ** *67
2Mail sent to ****@*******.no
1Call Emma Hansen on +47 912 34 567
2Mail sent to

A customer column hashed: counts still add up

Each e-mail address becomes the same hash every time, so the orders still group by customer.

let
    Orders = #table({"Customer", "Amount"}, {{"kari@example.no", 120}, {"ola@example.no", 80}, {"kari@example.no", 45}}),
    Hashed = Privacy.Anonymize(Orders, "Customer", [Whole = true, Operator = "hash", Salt = "shop-2026"]),
    ByCustomer = Table.Group(Hashed, {"Customer"}, {{"Orders", Table.RowCount, Int64.Type}, {"Amount", each List.Sum([Amount]), type number}})
in
    ByCustomer[[Orders], [Amount]]
OrdersAmount
2165
180

Table.TransformColumns, Table.Group, Text.Replace.

Last updated · OpenBI Studio 0.3.79