List

This guide demonstrates different features of list type.

Horizontal list

There are three kinds of horizontal list:

  1. Horizontal scalar/enum list, as element type is scalar. E.g: []int32.
  2. Horizontal incell struct list, as element type is incell struct. E.g: []{int32 ID, string Name}Item.
  3. Horizontal struct list, as element type is struct. E.g: [Item]int32.

Horizontal scalar list

A worksheet ItemConf in HelloWorld.xlsx:

Param1Param2Param3
[]int32int32int32
Param1’s valueParam2’s valueParam3’s value
123

Generated:

hello_world.proto
// --snip--
option (tableau.workbook) = {name:"HelloWorld.xlsx"};

message ItemConf {
  option (tableau.worksheet) = {name:"ItemConf" namerow:1 typerow:2 noterow:3 datarow:4};

  repeated int32 param_list = 1 [(tableau.field) = {name:"Param" layout:LAYOUT_HORIZONTAL}];
}
ItemConf.json
{
    "paramList": [
        1,
        2,
        3
    ]
}

Horizontal enum list

FruitType in common.proto is predefined as:

enum FruitType {
  FRUIT_TYPE_UNKNOWN = 0 [(tableau.evalue).name = "Unknown"];
  FRUIT_TYPE_APPLE   = 1 [(tableau.evalue).name = "Apple"];
  FRUIT_TYPE_ORANGE  = 3 [(tableau.evalue).name = "Orange"];
  FRUIT_TYPE_BANANA  = 4 [(tableau.evalue).name = "Banana"];
}

A worksheet ItemConf in HelloWorld.xlsx:

Param1Param2Param3
[]enum<.FruitType>enum<.FruitType>enum<.FruitType>
Param1’s valueParam2’s valueParam3’s value
1FRUIT_TYPE_ORANGEBanana

Generated:

hello_world.proto
// --snip--
option (tableau.workbook) = {name:"HelloWorld.xlsx"};

message ItemConf {
  option (tableau.worksheet) = {name:"ItemConf" namerow:1 typerow:2 noterow:3 datarow:4};

  repeated protoconf.FruitType param_list = 1 [(tableau.field) = {name:"Param" layout:LAYOUT_HORIZONTAL}];
}
ItemConf.json
{
    "paramList": [
        "FRUIT_TYPE_APPLE",
        "FRUIT_TYPE_ORANGE",
        "FRUIT_TYPE_BANANA"
    ]
}

Horizontal struct list

A worksheet ItemConf in HelloWorld.xlsx:

Item1IDItem1NameItem2IDItem2NameItem3IDItem3Name
[Item]uint32stringuint32stringuint32string
Item1’s IDItem1’s nameItem2’s IDItem2’s nameItem3’s IDItem3’s name
1Apple2Orange3Banana

Generated:

hello_world.proto
// --snip--
option (tableau.workbook) = {name:"HelloWorld.xlsx"};

message ItemConf {
  option (tableau.worksheet) = {name:"ItemConf" namerow:1 typerow:2 noterow:3 datarow:4};

  repeated Item item_list = 1 [(tableau.field) = {name:"Item" layout:LAYOUT_HORIZONTAL}];
  message Item {
    uint32 id = 1 [(tableau.field) = {name:"ID"}];
    string name = 2 [(tableau.field) = {name:"Name"}];
  }
}
ItemConf.json
{
    "itemList": [
        {
            "id": 1,
            "name": "Apple"
        },
        {
            "id": 2,
            "name": "Orange"
        },
        {
            "id": 3,
            "name": "Banana"
        }
    ]
}

Horizontal predefined-struct list

Item in common.proto is predefined as:

message Item {
    int32 id = 1 [(tableau.field) = {name:"ID"}];
    int32 num = 2 [(tableau.field) = {name:"Num"}];
}

A worksheet ItemConf in HelloWorld.xlsx:

Item1IDItem1NumItem2IDItem2NumItem3IDItem3Num
[.Item]int32int32int32int32int32int32
Item1’s IDItem1’s numItem2’s IDItem3’s numItem3’s IDItem3’s num
110022003300

Generated:

hello_world.proto
// --snip--
option (tableau.workbook) = {name:"HelloWorld.xlsx"};

message ItemConf {
  option (tableau.worksheet) = {name:"ItemConf" namerow:1 typerow:2 noterow:3 datarow:4};

  repeated protoconf.Item item_list = 1 [(tableau.field) = {name:"Item" layout:LAYOUT_HORIZONTAL}];
}
ItemConf.json
{
    "ItemList": [
        {
            "id": 1,
            "num": 100
        },
        {
            "id": 2,
            "num": 200
        },
        {
            "id": 3,
            "num": 300
        }
    ]
}

Horizontal incell-struct list

A worksheet ItemConf in HelloWorld.xlsx:

Item1Item2Item3
[]{int32 ID, string Name}ItemItemItem
Item1’s infoItem2’s infoItem3’s info
1,Apple2,Orange3,Banana

Generated:

hello_world.proto
// --snip--
option (tableau.workbook) = {name:"HelloWorld.xlsx"};

message ItemConf {
  option (tableau.worksheet) = {name:"ItemConf" namerow:1 typerow:2 noterow:3 datarow:4};

  repeated Item item_list = 1 [(tableau.field) = {name:"Item" layout:LAYOUT_HORIZONTAL span:SPAN_INNER_CELL}];
  message Item {
    int32 id = 1 [(tableau.field) = {name:"ID"}];
    string name = 2 [(tableau.field) = {name:"Name"}];
  }
}
ItemConf.json
{
    "itemList": [
        {
            "id": 1,
            "name": "Apple"
        },
        {
            "id": 2,
            "name": "Orange"
        },
        {
            "id": 3,
            "name": "Banana"
        }
    ]
}

Horizontal incell-predefined-struct list

Item in common.proto is predefined as:

message Item {
    int32 id = 1 [(tableau.field) = {name:"ID"}];
    int32 num = 2 [(tableau.field) = {name:"Num"}];
}

A worksheet ItemConf in HelloWorld.xlsx:

Item1Item2Item3
[]{.Item}.Item.Item
Item1’s infoItem2’s infoItem3’s info
1,1002,2003,300

Generated:

hello_world.proto
// --snip--
option (tableau.workbook) = {name:"HelloWorld.xlsx"};

message ItemConf {
  option (tableau.worksheet) = {name:"ItemConf" namerow:1 typerow:2 noterow:3 datarow:4};

  repeated protoconf.Item item_list = 1 [(tableau.field) = {name:"Item" layout:LAYOUT_HORIZONTAL span:SPAN_INNER_CELL}];
}
ItemConf.json
{
    "itemList": [
        {
            "id": 1,
            "num": 100
        },
        {
            "id": 2,
            "num": 200
        },
        {
            "id": 3,
            "num": 300
        }
    ]
}

Vertical list

There are two kinds of vertical list:

  1. Vertical scalar list, as list element type is scalar. E.g: []int32.
  2. Vertical struct list, as list element type is struct. E.g: [Item]int32.

Vertical scalar list

No need to support, use [Item]SCALAR instead:

  • [Item]int32
  • [Item]enum<.FruitType>

Vertical struct list

A worksheet ItemConf in HelloWorld.xlsx:

IDNameDesc
[Item]uint32stringstring
Item’s IDItem’s nameItem’s desc
1AppleA kind of delicious fruit.
2OrangeA kind of sour fruit.
3BananaA kind of calorie-rich fruit.

Generated:

hello_world.proto
// --snip--
option (tableau.workbook) = {name:"HelloWorld.xlsx"};

message ItemConf {
  option (tableau.worksheet) = {name:"ItemConf" namerow:1 typerow:2 noterow:3 datarow:4};

  repeated Item item_list = 1 [(tableau.field) = {layout:LAYOUT_VERTICAL}];
  message Item {
    uint32 id = 1 [(tableau.field) = {name:"ID"}];
    string name = 2 [(tableau.field) = {name:"Name"}];
    string desc = 3 [(tableau.field) = {name:"Desc"}];
  }
}
ItemConf.json
{
    "itemList": [
        {
            "id": 1,
            "name": "Apple",
            "desc": "A kind of delicious fruit."
        },
        {
            "id": 2,
            "name": "Orange",
            "desc": "A kind of sour fruit."
        },
        {
            "id": 3,
            "name": "Banana",
            "desc": "A kind of calorie-rich fruit."
        }
    ]
}

Vertical predefined-struct list

Item in common.proto is predefined as:

message Item {
    int32 id = 1 [(tableau.field) = {name:"ID"}];
    int32 num = 2 [(tableau.field) = {name:"Num"}];
}

A worksheet ItemConf in HelloWorld.xlsx:

IDNum
[.Item]int32int32
Item’s IDItem’s num
1100
2200
3300

Generated:

hello_world.proto
// --snip--
option (tableau.workbook) = {name:"HelloWorld.xlsx"};

message ItemConf {
  option (tableau.worksheet) = {name:"ItemConf" namerow:1 typerow:2 noterow:3 datarow:4};

  repeated protoconf.Item _item_list = 1 [(tableau.field) = {layout:LAYOUT_VERTICAL}];
}
ItemConf.json
{
    "ItemList": [
        {
            "id": 1,
            "num": 100
        },
        {
            "id": 2,
            "num": 200
        },
        {
            "id": 3,
            "num": 300
        }
    ]
}

Vertical incell-struct list

A worksheet ItemConf in HelloWorld.xlsx:

Item
[]{int32 ID,int32 Num}Item
Item’s info
1,100
2,200
3,300

Generated:

hello_world.proto
// --snip--
option (tableau.workbook) = {name:"HelloWorld.xlsx"};

message ItemConf {
  option (tableau.worksheet) = {name:"ItemConf" namerow:1 typerow:2 noterow:3 datarow:4};

  repeated Item item_list = 1 [(tableau.field) = {name:"Item" layout:LAYOUT_VERTICAL span:SPAN_INNER_CELL}];
  message Item {
    int32 id = 1 [(tableau.field) = {name:"ID"}];
    int32 num = 2 [(tableau.field) = {name:"Num"}];
  }
}
ItemConf.json
{
    "itemList": [
        {
            "id": 1,
            "num": 100
        },
        {
            "id": 2,
            "num": 200
        },
        {
            "id": 3,
            "num": 300
        }
    ]
}

Vertical incell-predefined-struct list

Item in common.proto is predefined as:

message Item {
    int32 id = 1 [(tableau.field) = {name:"ID"}];
    int32 num = 2 [(tableau.field) = {name:"Num"}];
}

A worksheet ItemConf in HelloWorld.xlsx:

Item
[]{.Item}
Item’s info
1,100
2,200
3,300

Generated:

hello_world.proto
// --snip--
option (tableau.workbook) = {name:"HelloWorld.xlsx"};

message ItemConf {
  option (tableau.worksheet) = {name:"ItemConf" namerow:1 typerow:2 noterow:3 datarow:4};

  repeated protoconf.Item item_list = 1 [(tableau.field) = {name:"Item" layout:LAYOUT_VERTICAL span:SPAN_INNER_CELL}];
}
ItemConf.json
{
    "itemList": [
        {
            "id": 1,
            "num": 100
        },
        {
            "id": 2,
            "num": 200
        },
        {
            "id": 3,
            "num": 300
        }
    ]
}

Incell list

There are two kinds of in-cell list:

  1. Incell scalar list, as list value type is scalar. E.g: []int32.
  2. Incell struct list, as list value type is struct. E.g: [Item]int32.

Incell scalar list

A worksheet ItemConf in HelloWorld.xlsx:

Param
[]int32
Param list
1,2,3
4,5
6

The Param column’s type is incell list []int32, as the list element is scalar type int32.

Generated:

hello_world.proto
// --snip--
option (tableau.workbook) = {name:"HelloWorld.xlsx"};

message ItemConf {
  option (tableau.worksheet) = {name:"ItemConf" namerow:1 typerow:2 noterow:3 datarow:4};

  repeated int32 param_list = 1 [(tableau.field) = {name:"Param" layout:LAYOUT_INCELL}];
}
ItemConf.json
{
    "paramList": [
        1,
        2,
        3,
        4,
        5,
        6
    ]
}

Incell struct list

No need to support.

Horizontal list size

Dynamic size

By default, all lists are Dynamically Sized Types. List elements should be present continuously, otherwise an error is reported if an empty element is existed in between.

Fixed size

Implicit fixed size

The list size is auto resolved by the max present list elements in name row.

In this example below, though the second element Item2 is empty, it is legal as the field property fixed is set true. Besides, Item2 will also be generated as an empty element. You can see it in the generated file ItemConf.json.

A worksheet ItemConf in HelloWorld.xlsx.

Item1IDItem1NameItem2IDItem2NameItem3IDItem3Name
[Item]uint32|{fixed:true}stringuint32stringuint32string
Item1’s IDItem1’s nameItem2’s IDItem2’s nameItem3’s IDItem3’s name
1Apple3Banana

Generated:

hello_world.proto
// --snip--
option (tableau.workbook) = {name:"HelloWorld.xlsx"};

message ItemConf {
  option (tableau.worksheet) = {name:"ItemConf" namerow:1 typerow:2 noterow:3 datarow:4};

  repeated Item item_list = 1 [(tableau.field) = {name:"Item" layout:LAYOUT_HORIZONTAL prop:{fixed:true}}];
  message Item {
    uint32 id = 1 [(tableau.field) = {name:"ID"}];
    string name = 2 [(tableau.field) = {name:"Name"}];
  }
}
ItemConf.json
{
    "itemList":  [
        {
            "id":  1,
            "name":  "Apple"
        },
        {
            "id":  0,
            "name":  ""
        },
        {
            "id":  3,
            "name":  "Banana"
        }
    ]
}

Explicit fixed size

The list size is explicitly set by field property size.

In this example below, field property size is set as 2, then list elements after the second element Item2 will all be truncated. Besides, Item2 will also be generated as an empty element. You can see it in the generated file ItemConf.json.

A worksheet ItemConf in HelloWorld.xlsx:

Item1IDItem1NameItem2IDItem2NameItem3IDItem3Name
[Item]uint32|{size:2}stringuint32stringuint32string
Item1’s IDItem1’s nameItem2’s IDItem2’s nameItem3’s IDItem3’s name
1Apple3Banana

Generated:

hello_world.proto
// --snip--
option (tableau.workbook) = {name:"HelloWorld.xlsx"};

message ItemConf {
  option (tableau.worksheet) = {name:"ItemConf" namerow:1 typerow:2 noterow:3 datarow:4};

  repeated Item item_list = 1 [(tableau.field) = {name:"Item" layout:LAYOUT_HORIZONTAL prop:{size:2}}];
  message Item {
    uint32 id = 1 [(tableau.field) = {name:"ID"}];
    string name = 2 [(tableau.field) = {name:"Name"}];
  }
}
ItemConf.json
{
    "itemList":  [
        {
            "id":  1,
            "name":  "Apple"
        },
        {
            "id":  0,
            "name":  ""
        }
    ]
}

Advanced features

Horizontal column-skipped list

A worksheet ItemConf in HelloWorld.xlsx:

DProp1IDProp1ValueProp2IDProp2Value
map<uint32, Item>[Prop]int32int32int32int32
Item’s IDProp1’s IDProp1’s nameProp1’s valueProp2’s IDProp2’s nameProp2’s value
11Apple1002Orange200
23Banana3004Pomelo400
35Watermelon500

Generated:

hello_world.proto
// --snip--
option (tableau.workbook) = {name:"HelloWorld.xlsx"};

message ItemConf {
  option (tableau.worksheet) = {name:"ItemConf" namerow:1 typerow:2 noterow:3 datarow:4};

  map<uint32, Item> item_map = 1 [(tableau.field) = {key:"ID" layout:LAYOUT_VERTICAL}];
  message Item {
    uint32 id = 1 [(tableau.field) = {name:"ID"}];
    repeated Prop prop_list = 2 [(tableau.field) = {name:"Prop" layout:LAYOUT_HORIZONTAL}];
    message Prop {
      int32 id = 1 [(tableau.field) = {name:"ID"}];
      int32 value = 2 [(tableau.field) = {name:"Value"}];
    }
  }
}
HeroConf.json
{
    "itemMap": {
        "1": {
            "id": 1,
            "propList": [
                {
                    "id": 1,
                    "value": 100
                },
                {
                    "id": 2,
                    "value": 200
                }
            ]
        },
        "2": {
            "id": 2,
            "propList": [
                {
                    "id": 3,
                    "value": 300
                },
                {
                    "id": 4,
                    "value": 400
                }
            ]
        },
        "3": {
            "id": 3,
            "propList": [
                {
                    "id": 5,
                    "value": 500
                }
            ]
        }
    }
}

Keyed list

Keyed list is same as normal list, except that ColumnType (first field type) is surrounded by angle brackets <>, and is treated as map key.

Syntax: [ElemType]<ColumnType>

Vertical struct keyed-list

For example, a worksheet ItemConf in HelloWorld.xlsx:

IDPropIDPropName
[Item]<uint32>map<int32, Prop>string
Item’s IDProp’s IDProp’s name
11sweet
21sweet
22delicious

Generated:

hello_world.proto
// --snip--
option (tableau.workbook) = {name:"HelloWorld.xlsx"};

message ItemConf {
  option (tableau.worksheet) = {name:"ItemConf" namerow:1 typerow:2 noterow:3 datarow:4};

  repeated Item item_list = 1 [(tableau.field) = {key:"ID" layout:LAYOUT_VERTICAL}];
  message Item {
    uint32 id = 1 [(tableau.field) = {name:"ID"}];
    map<int32, Prop> prop_map = 2 [(tableau.field) = {key:"PropID" layout:LAYOUT_VERTICAL}];
    message Prop {
      int32 prop_id = 1 [(tableau.field) = {name:"PropID"}];
      string prop_name = 2 [(tableau.field) = {name:"PropName"}];
    }
  }
}
ItemConf.json
{
    "itemList": [
        {
            "id": 1,
            "propMap": {
                "1": {
                    "propId": 1,
                    "propName": "sweet"
                }
            }
        },
        {
            "id": 2,
            "propMap": {
                "1": {
                    "propId": 1,
                    "propName": "sweet"
                },
                "2": {
                    "propId": 2,
                    "propName": "delicious"
                }
            }
        }
    ]
}

Scalar keyed-list

A worksheet ItemConf in HelloWorld.xlsx:

Param
[]<int32>
Param list
1,2,2,3

Generated:

hello_world.proto
// --snip--
option (tableau.workbook) = {name:"HelloWorld.xlsx"};

message ItemConf {
  option (tableau.worksheet) = {name:"ItemConf" namerow:1 typerow:2 noterow:3 datarow:4};

  repeated int32 param_list = 1 [(tableau.field) = {name:"Param" key:"Param" layout:LAYOUT_INCELL}];
}
ItemConf.json
{
    "paramList": [
        1,
        2,
        3
    ]
}