映射嵌套列表(List in map)

Excel 映射中嵌套列表的规范说明。

垂直映射中的嵌套

垂直映射嵌套水平列表(Horizontal-list in vertical-map)

HelloWorld.xlsx 中的工作表 ItemConf

IDNameProp1IDProp1ValueProp2IDProp2Value
map<uint32, Item>string[Prop]int32int64int32int64
Item’s IDItem’s nameProp1’s IDProp1’s valueProp2’s IDProp2’s value
1Apple110220
2Orange330
3Banana

生成结果:

hello_world.proto
// --snip--
option (tableau.workbook) = {name:"HelloWorld.xlsx" namerow:1 typerow:2 noterow:3 datarow:4};

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"}];
    string name = 2 [(tableau.field) = {name:"Name"}];
    repeated Prop prop_list = 3 [(tableau.field) = {name:"Prop" layout:LAYOUT_HORIZONTAL}];
    message Prop {
      int32 id = 1 [(tableau.field) = {name:"ID"}];
      int64 value = 2 [(tableau.field) = {name:"Value"}];
    }
  }
}
ItemConf.json
{
    "itemMap": {
        "1": {"id": 1, "name": "Apple", "propList": [{"id": 1, "value": "10"}, {"id": 2, "value": "20"}]},
        "2": {"id": 2, "name": "Orange", "propList": [{"id": 3, "value": "30"}]},
        "3": {"id": 3, "name": "Banana", "propList": []}
    }
}

垂直映射嵌套水平聚合列表(Horizontal-aggregate-list in vertical-map)

[!NOTE] 当键相同的多行需要把水平展开的键控列表元素跨行追加到同一个父记录时, 在水平列表字段上设置 prop:{aggregate:true}, 父映射的键字段同时设置 prop:{unique:false} 允许重复键。

重复键控列表素会触发 E2028

HelloWorld.xlsx 中的工作表 ItemConf

IDNameParam1IDParam1NumParam2IDParam2Num
map<uint32, Item>|{unique:false}string[Param]uint32|{aggregate:true}int32uint32int32
Item’s IDItem’s nameParam1’s IDParam1’s numParam2’s IDParam2’s num
1Apple10110
110220
2Orange2013020240
3Banana30150

生成结果:

hello_world.proto
// --snip--
option (tableau.workbook) = {name:"HelloWorld.xlsx" namerow:1 typerow:2 noterow:3 datarow:4};

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" prop:{unique:false}}];
    string name = 2 [(tableau.field) = {name:"Name"}];
    repeated Param param_list = 3 [(tableau.field) = {name:"Param" layout:LAYOUT_HORIZONTAL prop:{aggregate:true}}];
    message Param {
      uint32 id = 1 [(tableau.field) = {name:"ID"}];
      int32 num = 2 [(tableau.field) = {name:"Num"}];
    }
  }
}
ItemConf.json
{
    "itemMap": {
        "1": {"id": 1, "name": "Apple", "paramList": [{"id": 101, "num": 10}, {"id": 102, "num": 20}]},
        "2": {"id": 2, "name": "Orange", "paramList": [{"id": 201, "num": 30}, {"id": 202, "num": 40}]},
        "3": {"id": 3, "name": "Banana", "paramList": [{"id": 301, "num": 50}]}
    }
}

垂直映射嵌套垂直列表(Vertical-list in vertical-map)

HelloWorld.xlsx 中的工作表 ItemConf

IDNamePropIDPropValue
map<uint32, Item>string[Prop]int32int64
Item’s IDItem’s nameProp’s IDProp’s value
1Apple110
2Orange120
2Banana230

生成结果:

hello_world.proto
// --snip--
option (tableau.workbook) = {name:"HelloWorld.xlsx" namerow:1 typerow:2 noterow:3 datarow:4};

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"}];
    string name = 2 [(tableau.field) = {name:"Name"}];
    repeated Prop prop_list = 3 [(tableau.field) = {layout:LAYOUT_VERTICAL}];
    message Prop {
      int32 prop_id = 1 [(tableau.field) = {name:"PropID"}];
      int64 prop_value = 2 [(tableau.field) = {name:"PropValue"}];
    }
  }
}
ItemConf.json
{
    "itemMap": {
        "1": {"id": 1, "name": "Apple", "propList": [{"propId": 1, "propValue": "10"}]},
        "2": {"id": 2, "name": "Orange", "propList": [{"propId": 1, "propValue": "20"}, {"propId": 2, "propValue": "30"}]}
    }
}

垂直映射嵌套单元格内列表(Incell-list in vertical-map)

HelloWorld.xlsx 中的工作表 ItemConf

IDProp
map<uint32, Item>[]int32
Item’s IDItem’s props
110,20,30
210,20
310

生成结果:

hello_world.proto
// --snip--
option (tableau.workbook) = {name:"HelloWorld.xlsx" namerow:1 typerow:2 noterow:3 datarow:4};

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"}];
    repeated int32 prop_list = 2 [(tableau.field) = {name:"Prop" layout:LAYOUT_INCELL}];
  }
}
ItemConf.json
{
    "itemMap": {
        "1": {"id": 1, "propList": [10, 20, 30]},
        "2": {"id": 2, "propList": [10, 20]},
        "3": {"id": 3, "propList": [10]}
    }
}

垂直映射嵌套单元格内结构体列表(Incell-struct-list in vertical-map)

HelloWorld.xlsx 中的工作表 ItemConf

IDItem
map<uint32, Reward>[]{uint32 ID,int32 Num}Item
Reward’s IDReward’s items
11001:10,1002:20,1003:30
22001:10,2002:20

生成结果:

hello_world.proto
// --snip--
option (tableau.workbook) = {name:"HelloWorld.xlsx" namerow:1 typerow:2 noterow:3 datarow:4};

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

  map<uint32, Reward> reward_map = 1 [(tableau.field) = {key:"ID" layout:LAYOUT_VERTICAL}];
  message Reward {
    uint32 id = 1 [(tableau.field) = {name:"ID"}];
    repeated Item item_list = 2 [(tableau.field) = {name:"Item" layout:LAYOUT_INCELL span:SPAN_INNER_CELL}];
    message Item {
      uint32 id = 1 [(tableau.field) = {name:"ID"}];
      int32 num = 2 [(tableau.field) = {name:"Num"}];
    }
  }
}
ItemConf.json
{
    "rewardMap": {
        "1": {"id": 1, "itemList": [{"id": 1001, "num": 10}, {"id": 1002, "num": 20}, {"id": 1003, "num": 30}]},
        "2": {"id": 2, "itemList": [{"id": 2001, "num": 10}, {"id": 2002, "num": 20}]}
    }
}

水平映射中的嵌套

水平映射嵌套水平列表(Horizontal-list in horizontal-map)

HelloWorld.xlsx 中的工作表 ItemConf

Reward1IDReward1Item1IDReward1Item1NumReward1Item2IDReward1Item2NumReward2IDReward2Item1IDReward2Item1Num
map<uint32, Reward>[Item]uint32int32uint32int32uint32uint32int32
Reward1 IDReward1 item1 IDReward1 item1 numReward1 item2 IDReward1 item2 numReward2 IDReward2 item1 IDReward2 item1 num
11102202330

生成结果:

hello_world.proto
// --snip--
option (tableau.workbook) = {name:"HelloWorld.xlsx" namerow:1 typerow:2 noterow:3 datarow:4};

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

  map<uint32, Reward> reward_map = 1 [(tableau.field) = {name:"Reward" key:"ID" layout:LAYOUT_HORIZONTAL}];
  message Reward {
    uint32 id = 1 [(tableau.field) = {name:"ID"}];
    repeated Item item_list = 2 [(tableau.field) = {name:"Item" layout:LAYOUT_HORIZONTAL}];
    message Item {
      uint32 id = 1 [(tableau.field) = {name:"ID"}];
      int32 num = 2 [(tableau.field) = {name:"Num"}];
    }
  }
}
ItemConf.json
{
    "rewardMap": {
        "1": {"id": 1, "itemList": [{"id": 1, "num": 10}, {"id": 2, "num": 20}]},
        "2": {"id": 2, "itemList": [{"id": 3, "num": 30}]}
    }
}

水平映射嵌套单元格内列表(Incell-list in horizontal-map)

HelloWorld.xlsx 中的工作表 ItemConf

Reward1IDReward1ItemReward2IDReward2Item
map<uint32, Reward>[]{uint32 ID,int32 Num}Itemuint32[]Item
Reward1 IDReward1 itemsReward2 IDReward2 items
11:10,2:2023:30

对于 predefined struct list,可以使用 []{.Item} 代替 []{uint32 ID,int32 Num}Item

生成结果:

hello_world.proto
// --snip--
option (tableau.workbook) = {name:"HelloWorld.xlsx" namerow:1 typerow:2 noterow:3 datarow:4};

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

  map<uint32, Reward> reward_map = 1 [(tableau.field) = {name:"Reward" key:"ID" layout:LAYOUT_HORIZONTAL}];
  message Reward {
    uint32 id = 1 [(tableau.field) = {name:"ID"}];
    repeated Item item_list = 2 [(tableau.field) = {name:"Item" layout:LAYOUT_INCELL span:SPAN_INNER_CELL}];
    message Item {
      uint32 id = 1 [(tableau.field) = {name:"ID"}];
      int32 num = 2 [(tableau.field) = {name:"Num"}];
    }
  }
}
ItemConf.json
{
    "rewardMap": {
        "1": {"id": 1, "itemList": [{"id": 1, "num": 10}, {"id": 2, "num": 20}]},
        "2": {"id": 2, "itemList": [{"id": 3, "num": 30}]}
    }
}