Enum(枚举)

本文说明 Excel enum 类型的各种特性。

使用预定义枚举类型

[!NOTE] 枚举基础知识请参考 Enum(枚举)

例如,common.proto 中定义的枚举类型 FruitType

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

HelloWorld.xlsx 中的 worksheet ItemConf

IDType
map<uint32, Item>enum<.FruitType>
Item’s IDFruit’s type
11
2Orange
3FRUIT_TYPE_BANANA

生成结果:

hello_world.proto
// --snip--
import "common.proto";
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"}];
    FruitType type = 2 [(tableau.field) = {name:"Type"}];
  }
}
ItemConf.json
{
    "itemMap":  {
        "1":  {
            "id":  1,
            "type":  "FRUIT_TYPE_APPLE"
        },
        "2":  {
            "id":  3,
            "type":  "FRUIT_TYPE_ORANGE"
        }
        "3":  {
            "id":  2,
            "type":  "FRUIT_TYPE_BANANA"
        },
    }
}

在 sheet 中定义枚举类型

在 metasheet @TABLEAU 中有两种 Mode 可用于在 sheet 中定义枚举类型:

  • MODE_ENUM_TYPE:在一个 sheet 中定义单个枚举类型。
  • MODE_ENUM_TYPE_MULTI:在一个 sheet 中定义多个枚举类型。

单个枚举类型

[!Note]

  1. Number 列是可选的,用于指定枚举值编号。省略时从 1 开始自动递增。
  2. 如果未显式定义默认枚举值 0,则会自动生成,命名模式为 {ENUM_TYPE}_INVALID

需要在 metasheet @TABLEAU 中将 Mode 选项设置为 MODE_ENUM_TYPE

例如,HelloWorld.xlsx 中的 worksheet ItemType

NumberNameAlias
1ITEM_TYPE_FRUIT水果
2ITEM_TYPE_EQUIP装备
3ITEM_TYPE_BOX箱子
SheetMode
ItemTypeMODE_ENUM_TYPE

生成结果:

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

// Generated from sheet: ItemType.
enum ItemType {
  ITEM_TYPE_INVALID = 0;
  ITEM_TYPE_FRUIT = 1 [(tableau.evalue).name = "水果"]; // 水果
  ITEM_TYPE_EQUIP = 2 [(tableau.evalue).name = "装备"]; // 装备
  ITEM_TYPE_BOX = 3 [(tableau.evalue).name = "箱子"]; // 箱子
}

多个枚举类型

[!IMPORTANT] 每个枚举类型由一个 block 定义,即一系列连续的非空行。不同的 block 之间由一行或多行空行分隔。

需要在 metasheet @TABLEAU 中将 Mode 选项设置为 MODE_ENUM_TYPE_MULTI

例如,HelloWorld.xlsx 中的 worksheet Enum

CatType猫类
NumberNameAlias
1CAT_TYPE_RAGDOLL布偶猫
2CAT_TYPE_PERSIAN波斯猫
3CAT_TYPE_SPHYNX无毛猫
DogType犬类
NumberNameAlias
1DOG_TYPE_POODLE贵宾犬
2DOG_TYPE_BULLDOG牛头犬
3DOG_TYPE_DACHSHUND腊肠犬
BirdType鸟类
NumberNameAlias
1BIRD_TYPE_CANARY金丝雀
2BIRD_TYPE_WOODPECKER啄木鸟
3BIRD_TYPE_OWL猫头鹰
SheetMode
EnumMODE_ENUM_TYPE_MULTI

生成结果:

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

// 猫类
enum CatType {
  option (tableau.etype) = {name:"EnumType" note:"猫类"};

  CAT_TYPE_INVALID = 0;
  CAT_TYPE_RAGDOLL = 1 [(tableau.evalue).name = "Ragdoll"]; // 布偶猫
  CAT_TYPE_PERSIAN = 2 [(tableau.evalue).name = "Persian"]; // 波斯猫
  CAT_TYPE_SPHYNX = 3 [(tableau.evalue).name = "Sphynx"]; // 无毛猫
}

// 犬类
enum DogType {
  option (tableau.etype) = {name:"EnumType" note:"犬类"};

  DOG_TYPE_INVALID = 0;
  DOG_TYPE_POODLE = 1 [(tableau.evalue).name = "Poodle"]; // 贵宾犬
  DOG_TYPE_BULLDOG = 2 [(tableau.evalue).name = "Bulldog"]; // 牛头犬
  DOG_TYPE_DACHSHUND = 3 [(tableau.evalue).name = "Dachshund"]; // 腊肠犬
}

// 鸟类
enum BirdType {
  option (tableau.etype) = {name:"EnumType" note:"鸟类"};

  BIRD_TYPE_INVALID = 0;
  BIRD_TYPE_CANARY = 1 [(tableau.evalue).name = "Canary"]; // 金丝雀
  BIRD_TYPE_WOODPECKER = 2 [(tableau.evalue).name = "Woodpecker"]; // 啄木鸟
  BIRD_TYPE_OWL = 3 [(tableau.evalue).name = "Owl"]; // 猫头鹰
}

在 sheet 中定义并使用枚举类型

例如,HelloWorld.xlsx 中的两个 worksheet ItemTypeItemConf

NumberNameAlias
1ITEM_TYPE_FRUITFruit
2ITEM_TYPE_EQUIPEquip
3ITEM_TYPE_BOXBox
IDTypeNamePrice
map<int32, Item>enum<.ItemType>stringint32
Item’s IDItem’s typeItem’s nameItem’s price
1FruitApple40
2FruitOrange20
3EquipSword10
SheetMode
ItemTypeMODE_ENUM_TYPE
ItemConf

生成结果:

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

// Generated from sheet: ItemType.
enum ItemType {
  ITEM_TYPE_INVALID = 0;
  ITEM_TYPE_FRUIT = 1 [(tableau.evalue).name = "Fruit"];
  ITEM_TYPE_EQUIP = 2 [(tableau.evalue).name = "Equip"];
  ITEM_TYPE_BOX = 3 [(tableau.evalue).name = "Box"];
}

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

  map<int32, Item> item_map = 1 [(tableau.field) = {key:"ID" layout:LAYOUT_VERTICAL}];
  message Item {
    int32 id = 1 [(tableau.field) = {name:"ID"}];
    protoconf.ItemType type = 2 [(tableau.field) = {name:"Type"}];
    string name = 3 [(tableau.field) = {name:"Name"}];
    int32 price = 4 [(tableau.field) = {name:"Price"}];
  }
}
ItemConf.json
{
    "itemMap": {
        "1": {
            "id": 1,
            "type": "ITEM_TYPE_FRUIT",
            "name": "Apple",
            "price": 40
        },
        "2": {
            "id": 2,
            "type": "ITEM_TYPE_FRUIT",
            "name": "Orange",
            "price": 20
        },
        "3": {
            "id": 3,
            "type": "ITEM_TYPE_EQUIP",
            "name": "Sword",
            "price": 10
        }
    }
}