Field property

Tableau field property guide.

Overview

OptionTypeDescription
uniqueboolCheck field uniqueness.
Default: false. Specially for map (or KeyedList) key, default will be auto deduced.
rangestringFormat: "left,right". E.g.: "1,10", "1,~", "~,10".
Different interpretations of range:
- number: value range.
- string: count of utf-8 code point.
referstringFormat: "SheetName(SheetAlias).ColumnName".
Ensure this field is in another sheet’s column value space. Multiple refers are comma-separated.
sequenceint64Ensure this field’s value is a sequence and begins with this value.
defaultstringUse this default value if cell is empty (not present).
fixedboolAuto-detected fixed size of horizontal list/map.
Default: false.
sizeuint32Specify fixed size of horizontal list/map.
formFormSpecify cell data form of incell struct.
- FORM_TEXT
- FORM_JSON
json_namestringSpecify field’s custom JSON name instead of lowerCamelCase name of proto field name.
presentboolMust fill cell data explicitly if present is true.
Default: false.
optionalboolWhether this field is optional (field name existence).
patchPatchField patch type.
- PATCH_REPLACE
- PATCH_MERGE
sepstringField-level separator.
subsepstringField-level subseparator.
patternstringSpecify the pattern of scalar, list element, and map value.
orderOrderEnsure the field’s values are ordered across rows/columns/elements.
- ORDER_ASC (>=)
- ORDER_DESC (<=)
- ORDER_STRICTLY_ASC (>)
- ORDER_STRICTLY_DESC (<)
validatestringprotovalidate field-level rules for scalar and well-known types.
E.g.: "string:{max_len:10}", "int32:{gt:0 lte:100}", "cel_expression:\"this >= timestamp('2024-01-01T00:00:00Z')\"".
validate_complexstringprotovalidate field-level rules for complex types (list/map).
E.g.: "repeated:{min_items:1}", "map:{min_pairs:1}".
validate_messagestringprotovalidate message-level rules for the nested message of a field.
E.g.: "cel_expression:\"this.start_time < this.end_time\"".
aggregateboolFor incell or horizontal list/map fields. If true, when the same parent record is visited across multiple rows/columns (e.g. vertical map / keyed-list with same key, vertical/horizontal list spanning multiple rows/columns), elements from each visit are merged into one aggregated collection on the parent. If false, every visit must produce identical values for that field, otherwise E2023 is reported.
Default: false.

Option unique

Option unique can be specified as true or false in the field property. It can check the uniqueness of any scalar field in list/map element.

  • If you set unique to true explicitly, tableau will report an error if a duplicate key appears.
  • If you set unique to false explicitly, no check will be performed.

Map (or KeyedList) key

Tableau will auto deduce the map (or KeyedList) key’s unique as true or not.

The rule is: if a map’s value type (or KeyedList element type) has no sub map/list field of the same layout (vertical/horizontal), then the key must be unique.

So in most cases, it’s not neccessary to config it explicitly.

General scalar field

If you specify a general scalar field’s property unique as true, then tableau will check the field’s uniquness in map or list.

Option range

[!WARNING] This check option is skipped when cell data is empty (not present). To enforce the check even on empty cells, set option present to true.

Option range can be specified as format: "left,right" (left and right are both inclusive).

Different interpretations of range:

  • number: value range, e.g.: "1,10", "1,~", "~,10".

Option refer

Option refer is similar to the FOREIGN KEY constraint in SQL, preventing actions that would break links between tables. Unlike SQL foreign keys, it can reference any sheet’s column — not just map key columns — and supports multiple refers (comma-separated). It ensures this field’s value exists in at least one of the referenced columns (i.e., the field value space of another sheet).

Format: "SheetName(SheetAlias).ColumnName[,SheetName(SheetAlias).ColumnName]...".

For example:

  • map<uint32, Reward>|{refer:"ItemConf.ID"}: single-refer without alias, so sheet name is just the generated protobuf message name.
  • map<uint32, Reward>|{refer:"ItemConf.ID,EquipConf.ID"}: multi-refer without alias, then sheet alias is the generated protobuf message name.
  • map<uint32, Reward>|{refer:"Sheet1(ItemConf).ID"}: single-refer with alias, then sheet alias is the generated protobuf message name.

Option sequence

Option sequence is used to ensure this field’s value is a sequence and begins with this value. It can be used for any fields even in nested list/map.

For example:

  • map<uint32, Item>|{sequence:1}: this map key must follow the sequence rule which begins with value 1.
  • int32|{sequence:1}: the parent list/map elements must follow the sequence rule which begins with value 1.

Option default

If option default is set, then use it as default value if cell is empty (not present).

Option fixed

If option fixed is set as true, then auto-detect fixed size of horizontal list/map.

For example:

Option size

Option size is used to specify fixed size of horizontal list/map.

For example:

Option form

Option form is used to specify cell data form of incell struct.

Two kinds of form can be specified:

For detailed demos, see Advanced predefined incell struct.

Option json_name

By default, JSON name is deduced from the field’s proto name by converting it to camelCase. Now you can explicitly specify it by json_name prop option.

For example, a worksheet ItemConf in HelloWorld.xlsx:

IDRarity_1SpecialEffect_2
map<int32, Item>int32|{json_name:“rarity_1”}int32|{json_name:“specialEffect_2”}
Item’s IDItem’s rarity.Item’s special effect.
110101
220102
330103

Option present

If option present is set as true, then cell data cannot be empty and must be filled explicitly. Otherwise an error will be reported.

Option optional

Specify whether this field is optional (field name existence).

If set to true, then:

  • table formats (Excel/CSV): field’s column can be absent.
  • document formats (XML/YAML): field’s name can be absent.

Option patch

See field-level patch in Option Patch.

Option sep

Field-level separator for separating:

  • incell list elements (scalar or struct).
  • incell map items.

If not set, it will use sheet-level seq in metasheet.

Option subsep

Field-level subseparator for separating:

  • key-value pair of each incell map item.
  • struct fields of each incell struct list element.

If not set, it will use sheet-level subseq in metasheet.

Option pattern

Specify the pattern of scalar field, list element, and map value.

Wellknown version field

For use cases, see Wellknown types: Version

Specify the dotted-decimal pattern of current cell. Each decimal number ranges from 0 to the corresponding part (MAX) of pattern.

Default pattern: 255.255.255.

Option order

Option order ensures the field’s values follow a specific order along the parsing direction (rows for vertical layout, columns for horizontal layout, or elements for incell list/map). If a later value violates the configured order against the previous one, tableau reports E2026.

Supported orders:

  • ORDER_ASC: ascending, the previous value must be <= the next.
  • ORDER_DESC: descending, the previous value must be >= the next.
  • ORDER_STRICTLY_ASC: strictly ascending, the previous value must be < the next.
  • ORDER_STRICTLY_DESC: strictly descending, the previous value must be > the next.

Supported field kinds:

Examples:

  • map<uint32, Item>|{order:ORDER_ASC}: the map key column must be ascending.
  • int32|{order:ORDER_STRICTLY_ASC}: the values down the column must be strictly increasing.
  • datetime|{order:ORDER_ASC}: timestamps must be non-decreasing.

[!NOTE] order differs from sequence: sequence requires the values to form a contiguous sequence starting at a specific value (e.g. 1, 2, 3, ...), while order only constrains the relative order between adjacent values without fixing the start or step.

Option validate

Tableau integrates protovalidate to declare validation rules directly in spreadsheet field properties. The rules are compiled into (buf.validate.field) options on generated .proto fields and enforced by tableau at config generation time. CEL expressions and protovalidate’s standard/predefined/custom rules are all supported.

Option validate is used to specify field-level rules for scalar and well-known types (e.g. int32, string, bool, google.protobuf.Timestamp, google.protobuf.Duration). Its value is the protobuf text format of buf.validate.FieldRules.

Examples:

  • int32|{validate:"int32:{gt:0 lte:100}"}: the value must be in (0, 100].
  • string|{validate:"string:{min_len:1 max_len:20}"}: the string length must be in [1, 20].
  • uint32|{validate:"uint32:{gt:0}"}: the value must be greater than 0.
  • datetime|{validate:"timestamp:{lt:{seconds:1893456000}}"}: the timestamp must be earlier than 2030-01-01T00:00:00Z (Unix seconds 1893456000).
  • datetime|{validate:"cel_expression:\"this >= timestamp('2024-01-01T00:00:00Z')\""}: a custom CEL expression.
  • int32|{validate:"int32:{[protoconf.is_zero]:true}"}: a custom rule defined as a proto extension.

[!WARNING] Avoid comparing a field value against the current time (e.g. timestamp:{gt_now:true} / lt_now:true, or CEL expressions referencing now). Configuration is generated and validated at build time, so a rule that depends on “now” will pass or fail depending on when the config is generated, making generation flaky and irreproducible. Prefer fixed boundaries (absolute timestamps) or constraints between fields of the same record (e.g. start_time < end_time).

For example, a worksheet ItemConf in HelloWorld.xlsx:

IDNameScore
map<uint32, Item>|{validate:“uint32:{gt:0}”}string|{validate:“string:{min_len:1 max_len:20}”}int32|{validate:“int32:{gt:0 lte:100}”}
Item IDItem NameItem Score
1sword80
2shield95

Generated:

hello_world.proto
// --snip--
import "buf/validate/validate.proto";

message ItemConf {
  option (tableau.worksheet) = {name:"ItemConf"};

  map<uint32, Item> item_map = 1 [(tableau.field) = {key:"ID" layout:LAYOUT_VERTICAL}];
  message Item {
    uint32 id = 1 [(tableau.field) = {name:"ID"}, (buf.validate.field) = {uint32:{gt:0}}];
    string name = 2 [(tableau.field) = {name:"Name"}, (buf.validate.field) = {string:{min_len:1 max_len:20}}];
    int32 score = 3 [(tableau.field) = {name:"Score"}, (buf.validate.field) = {int32:{gt:0 lte:100}}];
  }
}

Option validate_complex

Option validate_complex is used to specify field-level rules for complex types (i.e. list/map) — that is, rules that apply to the container itself rather than to its elements. Its value is the text format of buf.validate.FieldRules with repeated or map set.

Examples:

  • map<uint32, Item>|{validate_complex:"map:{min_pairs:1}"}: the map must have at least one entry.
  • []string|{validate_complex:"repeated:{min_items:1}"}: the list must have at least one element.
  • []string|{validate_complex:"repeated:{[protoconf.min_items_three]:true}"}: a custom rule.

[!NOTE] Use validate for the element/value type’s own rules, and validate_complex for the container’s rules. Both can be specified at the same time on a single field.

Option validate_message

Option validate_message is used to specify message-level rules for the nested message of a field. It is typically used when the field’s value type is a sub-message (e.g. a struct, or the value type of a map/list), and you want to validate cross-field constraints by CEL. Its value is the text format of buf.validate.MessageRules.

Examples:

  • map<uint32, Item>|{validate_message:"cel_expression:\"this.value <= 0 || this.name != ''\""}: every map value (Item) must satisfy the CEL expression.
  • {Timespan}datetime|{validate_message:"cel_expression:\"this.start_time < this.end_time\""}: every Timespan struct must have start_time < end_time.

The CEL expression operates on this, which refers to the nested message instance.

Option aggregate

Option aggregate applies to incell (layout:LAYOUT_INCELL) or horizontal (layout:LAYOUT_HORIZONTAL) list/map fields. When the same parent record is visited across multiple rows/columns (vertical map / keyed-list with same key across rows, vertical/horizontal list spanning multiple rows/columns, etc.), aggregate:true merges the elements produced by each visit into one combined collection on the parent, instead of requiring every visit to carry identical values.

[!NOTE] Without aggregate, when the parent record is visited more than once, tableau requires every visit to carry identical values for the field; otherwise it reports E2023. aggregate:true opts out of this consistency check and turns the field into a true cross-row/cross-column accumulator.

Where it applies

Parent layoutTarget of aggregateRepeated-visit scenario
Vertical map / vertical keyed-list (same key across rows)Incell list/map (LAYOUT_INCELL), horizontal list/map (LAYOUT_HORIZONTAL)Multiple rows mapped to one parent
Horizontal map (same key across columns)Incell list/map, horizontal list/mapMultiple columns mapped to one parent
Vertical/horizontal list spanning multiple rows/columnsSibling incell fields revisited per row/columnMultiple rows/columns mapped to one parent

Per-type behavior

Sub-field typeBehavior with aggregate:trueError code
Incell listElements from each visit are appended into one list
Incell mapEntries from each visit are merged; duplicate keys reported as errorE2005
Incell keyed-list ([]<T>)Elements appended with dedup by key; duplicate elements reportedE2028
Horizontal listCross-row horizontal list elements are appended into one list
Horizontal keyed-listCross-row elements appended with dedup by keyE2028
Horizontal mapCross-row entries merged; duplicate keys reported as errorE2005

Vertical aggregation

For end-to-end examples, see the corresponding entries in Vertical list:

Horizontal aggregation

For end-to-end examples of cross-row aggregation on horizontal-layout fields, see list-in-map / map-in-map:

Combining aggregate with key (keyed-list dedup)

When aggregate:true is combined with a keyed-list ([]<T> syntax, which sets key on the field), tableau also deduplicates elements during aggregation:

  • Scalar / enum keyed-list: the element itself is the key — duplicate elements across rows/columns trigger E2028.
  • Message keyed-list: only the configured key sub-field is compared between elements.

For end-to-end examples, see Vertical KeyedList (vertical aggregation) and Horizontal-aggregate-list in vertical-map (horizontal aggregation).

Notes

  • aggregate only takes effect on incell (layout:LAYOUT_INCELL) or horizontal (layout:LAYOUT_HORIZONTAL) list/map fields.
  • When the parent key is repeated across rows, also set prop:{unique:false} on the parent key field; otherwise E2005 blocks the duplicate.
  • Scalar field props such as range, refer, unique remain effective on the individual elements after aggregation.