Struct
This guide demonstrates different features of excel struct type.
Cross-cell struct
Syntax: <StructType>ColumnType
.
Each column name should be prefixed with the same struct variable name, which is just the same as struct type name by default.
For example, a worksheet ItemConf
in HelloWorld.xlsx
:
PropertyID | PropertyName | PropertyDesc |
---|---|---|
{Property}int32 | string | string |
Property’s ID | Property’s Name | Property’s Description |
1 | Orange | A kind of sour fruit. |
Note that each column name in ItemConf
is prefixed with struct variable name Property which is same as struct type name.
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};
Property property = 1 [(tableau.field) = {name:"Property"}];
message Property {
int32 id = 1 [(tableau.field) = {name:"ID"}];
string name = 2 [(tableau.field) = {name:"Name"}];
string desc = 3 [(tableau.field) = {name:"Desc"}];
}
}
ItemConf.json
{
"property": {
"id": 1,
"name": "Orange",
"desc": "A kind of sour fruit."
}
}
Note
Cross-cell struct is usually used together with:
- cross-cell horizontal/vertical map, as map value type. Map â
- cross-cell horizontal/vertical list, as list element type. List â
Incell struct
Each field type of the struct should be scalar type.
For example, a worksheet ItemConf
in HelloWorld.xlsx
:
ID | Prop |
---|---|
map<int32, Item> | {int32 ID,string Name,string Desc}Property |
Item’s ID | Item’s property. |
1 | 1,Orange,A good fruit. |
2 | 2,Apple |
3 | 3 |
The Property
column’s type is in-cell struct {int32 ID,string Name,string Desc}Property
.
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"}];
Property prop = 2 [(tableau.field) = {name:"Prop" span:SPAN_INNER_CELL}];
message Property {
int32 id = 1 [(tableau.field) = {name:"ID"}];
string name = 2 [(tableau.field) = {name:"Name"}];
string desc = 3 [(tableau.field) = {name:"Desc"}];
}
}
}
ItemConf.json
{
"itemMap": {
"1": {
"id": 1,
"prop": {
"id": 1,
"name": "Apple",
"desc": "A kind of delicious fruit."
}
},
"2": {
"id": 2,
"prop": {
"id": 2,
"name": "Orange",
"desc": ""
}
},
"3": {
"id": 3,
"prop": {
"id": 3,
"name": "",
"desc": ""
}
}
}
}
Predefined incell struct
Each field type of the predefined struct should be scalar type.
For example, Property
in common.proto is predefined as:
message Property {
int32 id = 1 [(tableau.field) = {name:"ID"}];
string name = 2 [(tableau.field) = {name:"Name"}];
string desc = 3 [(tableau.field) = {name:"Desc"}];
}
A worksheet ItemConf
in HelloWorld.xlsx:
ID | Prop |
---|---|
map<uint32, Item> | {.Property} |
Item’s ID | Item’s property. |
1 | 1,Orange,A good fruit. |
2 | 2,Apple |
3 | 3 |
The Prop
column’s type is a predefined struct Property
.
Generated:
hello_world.proto
// --snip--
import "common.proto";
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"}];
protoconf.Property prop = 2 [(tableau.field) = {name:"Prop" span:SPAN_INNER_CELL}];
}
}
ItemConf.json
{
"itemMap": {
"1": {
"id": 1,
"prop": {
"id": 1,
"name": "Apple",
"desc": "A kind of delicious fruit."
}
},
"2": {
"id": 2,
"prop": {
"id": 2,
"name": "Orange",
"desc": ""
}
},
"3": {
"id": 3,
"prop": {
"id": 3,
"name": "",
"desc": ""
}
}
}
}
Custom named struct
By default, struct variable name is same as struct type name, but you can specify a different struct variable name. Custom named struct is mainly used to identify name prefix of continuous cells in name row, when the tableau (protogen) can’t auto-recognize the variable name.
Syntax: just after struct type name, use parentheses ()
to specify struct variable name: VariableType(VariableName)
.
For example, Item
is predefined:
message Item {
int32 id = 1 [(tableau.field).name = "ID"];
int32 num = 2 [(tableau.field).name = "Num"];
}
A worksheet ItemConf
in HelloWorld.xlsx:
RewardItemID | RewardItemNum | CostItemID | CostItemNum | PredefinedItemID | PredefinedItemNum |
---|---|---|---|---|---|
{Item(RewardItem)}int32 | int32 | {Item(CostItem)}int32 | int32 | {.Item(PredefinedItem)}int32 | int32 |
Item’s ID | Item’s ID | Cost’s ID | Cost’s ID | Predefined item’s ID | Predefined item’s ID |
1 | 100 | 2 | 200 | 10 | 20 |
Details:
In type cell {Item(RewardItem)}int32
, RewardItem
is the custom variable name of new defined struct Item
. And in type cell {Item(CostItem)}int32
, CostItem
is the custom variable name of just already defined struct Item
in the same scope. Finally, in type cell {.Item(PredefinedItem)}int32
, PredefinedItem
is the custom variable name of predefined struct Item
at global (at the same protobuf package).
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};
Item reward_item = 1 [(tableau.field) = {name:"RewardItem"}];
message Item {
int32 id = 1 [(tableau.field) = {name:"ID"}];
int32 num = 2 [(tableau.field) = {name:"Num"}];
}
Item cost_item = 2 [(tableau.field) = {name:"CostItem"}];
protoconf.Item predefined_item = 3 [(tableau.field) = {name:"PredefinedItem"}];
}
ItemConf.json
{
"rewardItem": {
"id": 1,
"num": 100
},
"costItem": {
"id": 2,
"num": 200
},
"predefinedItem": {
"id": 10,
"num": 20
}
}
Advanced predefined incell struct
In some situations, you may want to configure any complex struct in a cell, so tableau support two kinds of protobuf serialized formats: text format, and JSON format.
Syntax: in field prop, specify form
option as FORM_TEXT
or FORM_JSON
.
For example, Transform
is predefined as:
message Transform {
Vector3 position = 1;
Vector3 rotation = 2;
Vector3 scale = 3;
}
message Vector3 {
float x = 1;
float y = 2;
float z = 3;
}
A worksheet ItemConf
in HelloWorld.xlsx:
Transform1 | Transform2 |
---|---|
{.Transform}|{form:FORM_TEXT} | {.Transform}|{form:FORM_JSON} |
Box’s transform1 | Box’s transform2 |
position:{x:1 y:2 z:3} rotation:{x:4 y:5 z:6} scale:{x:7 y:8 z:9} | {“position”:{“x”:1, “y”:2, “z”:3}, “rotation”:{“x”:4, “y”:5, “z”:6}, “scale”:{“x”:7, “y”:8, “z”:9}} |
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};
protoconf.Transform transform_1 = 1 [(tableau.field) = {name:"Transform1" span:SPAN_INNER_CELL prop{form:FORM_TEXT}}];
protoconf.Transform transform_2 = 2 [(tableau.field) = {name:"Transform2" span:SPAN_INNER_CELL prop:{form:FORM_JSON}}];
}
ItemConf.json
{
"transform1": {
"position": {
"x": 1,
"y": 2,
"z": 3
},
"rotation": {
"x": 4,
"y": 5,
"z": 6
},
"scale": {
"x": 7,
"y": 8,
"z": 9
}
},
"transform2": {
"position": {
"x": 1,
"y": 2,
"z": 3
},
"rotation": {
"x": 4,
"y": 5,
"z": 6
},
"scale": {
"x": 7,
"y": 8,
"z": 9
}
}
}
Define struct type in sheet
In order to generate struct type definition, you should specify Mode
option to MODE_STRUCT_TYPE
in metasheet @TABLEAU
.
For example, a worksheet Item
in HelloWorld.xlsx:
Name | Type |
---|---|
ID | uint32 |
Num | int32 |
FruitType | enum<.FruitType> |
Feature | []int32 |
Prop | map<int32, string> |
Detail | {enum<.ItemType> Type, string Name, string Desc}Detail |
Sheet | Mode |
---|---|
Item | MODE_STRUCT_TYPE |
Generated:
hello_world.proto
// --snip--
option (tableau.workbook) = {name:"HelloWorld.xlsx"};
// Generated from sheet: Item.
message Item {
uint32 id = 1 [(tableau.field) = {name:"ID"}];
int32 num = 2 [(tableau.field) = {name:"Num"}];
protoconf.FruitType fruit_type = 3 [(tableau.field) = {name:"FruitType"}];
repeated int32 feature_list = 4 [(tableau.field) = {name:"Feature" layout:LAYOUT_INCELL}];
map<int32, string> prop_map = 5 [(tableau.field) = {name:"Prop" layout:LAYOUT_INCELL}];
Detail detail = 6 [(tableau.field) = {name:"Detail" span:SPAN_INNER_CELL}];
message Detail {
protoconf.ItemType type = 1 [(tableau.field) = {name:"Type"}];
string name = 2 [(tableau.field) = {name:"Name"}];
string desc = 3 [(tableau.field) = {name:"Desc"}];
}
}