### Change to quick start example directory Source: https://tableauio.github.io/docs/api/tableau/guide Changes to the helloworld example directory. ```bash cd demo/examples/helloworld ``` -------------------------------- ### Install Go protocol compiler plugins Source: https://tableauio.github.io/docs/api/tableau/guide Installs the protoc-gen-go plugin version v1.26 using go install. ```bash go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26 ``` -------------------------------- ### Generated proto file for transpose example Source: https://tableauio.github.io/docs/excel/metasheet The generated proto file hello_world.proto for the transpose example. It defines the HeroConf message with transposed fields and a repeated skill list. ```protobuf // --snip-- option (tableau.workbook) = {name:"HelloWorld.xlsx" namerow:1 typerow:2 noterow:3 datarow:4}; message HeroConf { option (tableau.worksheet) = {name:"HeroConf" transpose:true}; int32 id = 1 [(tableau.field) = {name:"ID"}]; string name = 2 [(tableau.field) = {name:"Name"}]; string desc = 3 [(tableau.field) = {name:"Desc"}]; repeated int32 skill_list = 4 [(tableau.field) = {name:"Skill" layout:LAYOUT_INCELL}]; } ``` -------------------------------- ### Run excel2proto example Source: https://tableauio.github.io/docs/api/tableau/guide Compiles and executes the excel2proto tool, generating proto files to examples/helloworld/proto. ```bash go run main.go ``` -------------------------------- ### Clone the tableau/demo repository Source: https://tableauio.github.io/docs/api/tableau/guide Clones the example code repository from GitHub. ```bash git clone https://github.com/tableauio/demo ``` -------------------------------- ### Run excel2conf example Source: https://tableauio.github.io/docs/api/tableau/guide Generates *.pb.go files and then compiles and executes the excel2conf tool, generating JSON files to examples/helloworld/excel2conf/_out. ```bash bash gen.sh go run main.go ``` -------------------------------- ### Generated JSON for transpose example Source: https://tableauio.github.io/docs/excel/metasheet The generated JSON output for the transpose example, showing the data from the HeroConf sheet. ```json { "id": 123, "name": "Robin", "desc": "A big hero!", "skillList": [ 100, 101, 102 ] } ``` -------------------------------- ### Generated proto file for workbook alias example Source: https://tableauio.github.io/docs/excel/metasheet The generated proto file custom_conf.proto for the workbook alias example. It defines the ItemConf message with a map field and nested Item message. ```protobuf // --snip-- option (tableau.workbook) = {name:"HelloWorld.xlsx" namerow:1 typerow:2 noterow:3 datarow:4}; message ItemConf { option (tableau.worksheet) = {name:"ItemConf"}; map 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"}]; } } ``` -------------------------------- ### Generated proto for predefined struct Source: https://tableauio.github.io/docs/yaml/struct Generated hello_world.proto for the predefined struct example. It imports common.proto and defines the ItemConf message with a field of type protoconf.Item. ```protobuf // --snip-- import "common.proto"; option (tableau.workbook) = {name:"HelloWorld.yaml"}; message ItemConf { option (tableau.worksheet) = {name:"ItemConf"}; protoconf.Item item = 1 [(tableau.field) = {name:"Item"}]; } ``` -------------------------------- ### Generated protobuf for general struct Source: https://tableauio.github.io/docs/yaml/struct Generated hello_world.proto for the general struct example. Shows the message ItemConf with a nested Item message and field options. ```proto // --snip-- option (tableau.workbook) = {name:"HelloWorld.yaml"}; message ItemConf { option (tableau.worksheet) = {name:"ItemConf"}; Item item = 1 [(tableau.field) = {name:"Item"}]; message Item { uint32 id = 1 [(tableau.field) = {name:"ID"}]; google.protobuf.Timestamp start_time = 2 [(tableau.field) = {name:"StartTime"}]; google.protobuf.Duration expiry = 3 [(tableau.field) = {name:"Expiry"}]; } } ``` -------------------------------- ### Generated protobuf for reuse same-level struct Source: https://tableauio.github.io/docs/yaml/struct Generated hello_world.proto for the reuse example. Shows the ItemConf message with an additional field new_item of type Item. ```proto // --snip-- option (tableau.workbook) = {name:"HelloWorld.yaml"}; message ItemConf { option (tableau.worksheet) = {name:"ItemConf"}; Item item = 1 [(tableau.field) = {name:"Item"}]; message Item { uint32 id = 1 [(tableau.field) = {name:"ID"}]; google.protobuf.Timestamp start_time = 2 [(tableau.field) = {name:"StartTime"}]; google.protobuf.Duration expiry = 3 [(tableau.field) = {name:"Expiry"}]; } Item new_item = 2 [(tableau.field) = {name:"NewItem"}]; } ``` -------------------------------- ### Enum Naming Convention Example Source: https://tableauio.github.io/docs/basics/naming-convention Shows the required naming style for enums: PascalCase for the enum type name and CAPITALS_WITH_UNDERSCORES for value names, as per the Protobuf style guide. ```protobuf enum FooBar { FOO_BAR_UNSPECIFIED = 0; FOO_BAR_FIRST_VALUE = 1; FOO_BAR_SECOND_VALUE = 2; } ``` -------------------------------- ### hello_world.proto - Tableau workbook mapping example Source: https://tableauio.github.io/docs/basics/concepts Protoconf file defining two top-level messages (ItemConf and ActivityConf) that map to worksheets in HelloWorld.xlsx. Uses tableau.proto options to specify workbook and worksheet settings, with fields annotated using tableau.field options. ```protobuf syntax = "proto3"; package protoconf; option go_package = "github.com/tableauio/demo/examples/helloworld/protoconf"; import "tableau/protobuf/tableau.proto"; option (tableau.workbook) = {name:"HelloWorld.xlsx" namerow:1 typerow:2 noterow:3 datarow:4}; message ItemConf { option (tableau.worksheet) = {name:"ItemConf"}; map 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"}]; int32 type = 3 [(tableau.field) = {name:"Type"}]; } } message ActivityConf { option (tableau.worksheet) = {name:"ActivityConf"}; map activity_map = 1 [(tableau.field) = {key:"ID" layout:LAYOUT_VERTICAL}]; message Activity { uint32 id = 1 [(tableau.field) = {name:"ID"}]; string name = 2 [(tableau.field) = {name:"Name"}]; bool open = 3 [(tableau.field) = {name:"Open"}]; } } ``` -------------------------------- ### GetOrderedMap() Source: https://tableauio.github.io/docs/api/loader/cpp Gets the whole ordered map. ```APIDOC ## GetOrderedMap() ### Description Gets the whole ordered map. ### Prerequisite You need to set metasheet option `OrderedMap` to `true`. See metasheet option: OrderedMap. ### Method GetOrderedMap ### Signature `const OrderedMapMap* GetOrderedMap() const` ### Returns - **OrderedMapMap*** - The whole ordered map. ``` -------------------------------- ### Data() Source: https://tableauio.github.io/docs/api/loader/csharp Gets the internal protobuf message data. ```APIDOC ## Data() ### Description Gets the internal protobuf message data. ### Method Data() ### Signature `public ref readonly ProtobufMessage Data()` ### Returns - **ProtobufMessage** - The internal protobuf message data. ``` -------------------------------- ### Vertical incell-predefined-struct list: generated hello_world.proto Source: https://tableauio.github.io/docs/excel/list Generated proto file for the vertical incell-predefined-struct list example. It imports common.proto and defines ItemConf with a repeated protoconf.Item field using layout:LAYOUT_INCELL, span:SPAN_INNER_CELL, and prop:{aggregate:true}. ```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"}; repeated protoconf.Item item_list = 1 [(tableau.field) = {name:"Item" layout:LAYOUT_INCELL span:SPAN_INNER_CELL prop:{aggregate:true}}]; } ``` -------------------------------- ### FindChapterMap() Source: https://tableauio.github.io/docs/api/loader/cpp Gets the whole hash map for the index named Chapter. ```APIDOC ## FindChapterMap() ### Description Gets the whole hash map for the index named Chapter. ### Prerequisite You need to set metasheet option `Index` appropriately. See metasheet option: Index. ### Method FindChapterMap ### Signature `const Index_ChapterMap& FindChapterMap() const` ### Returns - **Index_ChapterMap&** - The whole hash map. ``` -------------------------------- ### Generated Proto for Incell Scalar List Source: https://tableauio.github.io/docs/yaml/list Generated proto file 'hello_world.proto' for the incell scalar list example. Shows the workbook option and the ItemConf message with a repeated int32 field using LAYOUT_INCELL. ```proto // --snip-- option (tableau.workbook) = {name:"HelloWorld.yaml"}; message ItemConf { option (tableau.worksheet) = {name:"ItemConf"}; repeated int32 items = 1 [(tableau.field) = {name:"Items" layout:LAYOUT_INCELL}]; } ``` -------------------------------- ### FindChapterMap() (OrderedIndex) Source: https://tableauio.github.io/docs/api/loader/cpp Gets the whole ordered map for the ordered index named Chapter. ```APIDOC ## FindChapterMap() (OrderedIndex) ### Description Gets the whole ordered map for the ordered index named Chapter. ### Prerequisite You need to set metasheet option `OrderedIndex` appropriately. See metasheet option: OrderedIndex. ### Method FindChapterMap ### Signature `const OrderedIndex_ChapterMap& FindChapterMap() const` ### Returns - **OrderedIndex_ChapterMap&** - The whole ordered map. ``` -------------------------------- ### Horizontal-list in horizontal-map: Generated JSON (ItemConf.json) Source: https://tableauio.github.io/docs/excel/list-in-map Generated JSON output for the horizontal-list in horizontal-map example. ```json { "rewardMap": { "1": { "id": 1, "itemList": [ { "id": 1, "num": 10 }, { "id": 2, "num": 20 } ] }, "2": { "id": 2, "itemList": [ { "id": 3, "num": 30 } ] } } } ``` -------------------------------- ### Time: Generated hello_world.proto Source: https://tableauio.github.io/docs/excel/wellknown-types Shows the protobuf message for the Time worksheet, using google.protobuf.Duration for begin_time and end_time, and a repeated Duration for time_list with LAYOUT_INCELL. ```protobuf // --snip-- option (tableau.workbook) = {name:"HelloWorld.xlsx" namerow:1 typerow:2 noterow:3 datarow:4}; message ItemConf { option (tableau.worksheet) = {name:"ItemConf"}; google.protobuf.Duration begin_time = 1 [(tableau.field) = {name:"BeginTime"}]; google.protobuf.Duration end_time = 2 [(tableau.field) = {name:"EndTime"}]; repeated google.protobuf.Duration time_list = 3 [(tableau.field) = {name:"Time" layout:LAYOUT_INCELL}]; } ``` -------------------------------- ### Generated proto for predefined union Source: https://tableauio.github.io/docs/yaml/union Generated hello_world.proto for the predefined union example. Shows the workbook option and the ItemConf message with a target field of type protoconf.Target. ```proto // --snip-- option (tableau.workbook) = {name:"HelloWorld.yaml"}; message ItemConf { option (tableau.worksheet) = {name:"ItemConf"}; protoconf.Target target = 1 [(tableau.field) = {name:"Target"}]; } ``` -------------------------------- ### GetOrderedMap(KEY1 k1) Source: https://tableauio.github.io/docs/api/loader/cpp Gets the 2nd-level ordered map value by key. Returns nullptr if the key is not found. ```APIDOC ## GetOrderedMap(KEY1 k1) ### Description Get the 2nd-level ordered map value. Returns `nullptr` if the key is not found. Be aware that only applies to each level message’s **first map field**. ### Prerequisite You need to set metasheet option `OrderedMap` to `true`. See metasheet option: OrderedMap. ### Method GetOrderedMap ### Signature `const OrderedMapValueType* GetOrderedMap(KEY1 k1) const` ### Parameters - **k1** (KEY1) - Required - First-level key. ### Returns - **OrderedMapValueType*** - The 2nd-level ordered map value, or `nullptr` if the key is not found. ``` -------------------------------- ### Date: Generated hello_world.proto Source: https://tableauio.github.io/docs/excel/wellknown-types Shows the protobuf message for the Date worksheet, using google.protobuf.Timestamp for begin_date and end_date, and a repeated Timestamp for date_list with LAYOUT_INCELL. ```protobuf // --snip-- option (tableau.workbook) = {name:"HelloWorld.xlsx" namerow:1 typerow:2 noterow:3 datarow:4}; message ItemConf { option (tableau.worksheet) = {name:"ItemConf"}; google.protobuf.Timestamp begin_date = 1 [(tableau.field) = {name:"BeginDate"}]; google.protobuf.Timestamp end_date = 2 [(tableau.field) = {name:"EndDate"}]; repeated google.protobuf.Timestamp date_list = 3 [(tableau.field) = {name:"Date" layout:LAYOUT_INCELL}]; } ``` -------------------------------- ### OrderedMap Accessors Source: https://tableauio.github.io/docs/api/loader/csharp Methods to get ordered map values. Requires the metasheet option 'OrderedMap' to be set to true. ```APIDOC ## OrderedMap Accessors ### Description Get the Nth-level ordered map value. Be aware that only applies to each level message's **first map field**. ### Prerequisite You need to set metasheet option `OrderedMap` to `true`. ### Methods - `public ref readonly OrderedMapMap GetOrderedMap()`: Gets the whole ordered map. - `public OrderedMapValueType? GetOrderedMap1(KEY1 k1)`: Gets the 1st-level ordered map value. Returns `null` if the key is not found. - ... ### Parameters - **k1** (KEY1) - Required - The first-level key. ### Returns - **OrderedMapMap** - The whole ordered map (for GetOrderedMap). - **OrderedMapValueType?** - The ordered map value, or `null` if the key is not found. ``` -------------------------------- ### Generated JSON for reuse same-level struct Source: https://tableauio.github.io/docs/yaml/struct Generated ItemConf.json for the reuse example. Shows the JSON with both item and newItem objects. ```json { "item": { "id": 1, "startTime": "2024-10-01T02:10:10Z", "expiry": "3600s" }, "newItem": { "id": 2, "startTime": "2026-10-01T02:10:10Z", "expiry": "7200s" } } ``` -------------------------------- ### Datetime: Generated hello_world.proto Source: https://tableauio.github.io/docs/excel/wellknown-types Shows the protobuf message for the Datetime worksheet, using google.protobuf.Timestamp for begin_datetime and end_datetime, and a repeated Timestamp for datetime_list with LAYOUT_INCELL. ```protobuf // --snip-- option (tableau.workbook) = {name:"HelloWorld.xlsx" namerow:1 typerow:2 noterow:3 datarow:4}; message ItemConf { option (tableau.worksheet) = {name:"ItemConf"}; google.protobuf.Timestamp begin_datetime = 1 [(tableau.field) = {name:"BeginDatetime"}]; google.protobuf.Timestamp end_datetime = 2 [(tableau.field) = {name:"EndDatetime"}]; repeated google.protobuf.Timestamp datetime_list = 3 [(tableau.field) = {name:"Datetime" layout:LAYOUT_INCELL}]; } ``` -------------------------------- ### Generated JSON for scalar map Source: https://tableauio.github.io/docs/xml/map Generated ItemConf.json for the scalar map example, showing the map data as key-value pairs. ```json { "itemMap": { "1": "dog", "2": "bird", "3": "cat" } } ``` -------------------------------- ### Tableauc _config.yaml_ Configuration Source: https://tableauio.github.io/docs/prologue/config Create a file named _config.yaml_ and copy this configuration. It sets the locale (lang), timezone (locationName), custom acronyms, log options, and proto generation input/output settings. Defaults are shown for each option. ```yaml # locale BCP 47 language tags: en, zh. # # Default: "en". lang: en # Location represents the collection of time offsets in use in a geographical area. # - If the name is "" or "UTC", LoadLocation returns UTC. # - If the name is "Local", LoadLocation returns Local. # - Otherwise, the name is taken to be a location name corresponding to a file in the # IANA Time Zone database, such as "America/New_York", "Asia/Shanghai", and so on. # # See https://go.dev/src/time/zoneinfo_abbrs_windows.go. # # Default: "Local". locationName: Local # Configure your custom acronyms (regexp supported). Out of the box, # "ID" -> "id" is auto configured. # For example, if you configure K8s -> k8s, then the field name in PascalCase "InK8s" # will be converted to snake_case "in_k8s" but not "in_k_8_s". acronyms: {} # Log options. log: # Log mode: SIMPLE, FULL. mode: SIMPLE # Log level: DEBUG, INFO, WARN, ERROR. level: INFO # Log filename: set this if you want to write log messages to files. filename: "" # Log sink: CONSOLE, FILE, and MULTI. sink: CONSOLE # Options for generating proto files. Only for protogen. proto: input: # Header options of worksheet. header: # Exact row number of column name definition at a worksheet. # # Default: 1. namerow: 1 # Exact row number of column type definition at a worksheet. # # Default: 2. typerow: 2 # Exact row number of column note at a worksheet. # # Default: 3. noterow: 3 # Start row number of data at a worksheet. # # Default: 4. datarow: 4 # The line number of column name definition in a cell. # Value 0 means the whole cell. # # Default: 0. nameline: 0 # The line number of column type definition in a cell. # Value 0 means the whole cell. # # Default: 0. typeline: 0 # The line number of column note definition in a cell. # Value 0 means the whole cell. # # Default: 0. noteline: 0 # Separator for separating: # - incell list elements (scalar or struct). # - incell map items. # # Default: ",". sep: "" # Subseparator for separating: # - key-value pair of each incell map item. # - struct fields of each incell struct list element. # # Default: ":". subsep: "" # The proto paths are used to search for dependencies that are referenced in import # statements in proto source files. If no import paths are provided then # "." (current directory) is assumed to be the only import path. # # Default: nil. protoPaths: [.] # The enums and messages in protoFiles can be used in Excel/CSV/XML/YAML # as common types. # # NOTE: Glob patterns are supported, which can specify sets # of filenames with wildcard characters. # # Default: nil. protoFiles: [] # Specify input file formats. # Note: recognize all formats (Excel/CSV/XML/YAML) if not set # (value is nil). # Available formats: "xlsx", "csv", "xml", and "yaml". # # Default: nil. formats: [xlsx] # Specify only these subdirs (relative to input dir) to be processed. # # Default: nil. subdirs: [] # Specify rewrite subdir path (relative to input dir). # # Default: nil. subdirRewrites: {} # Follow the symbolic links when traversing directories recursively. # WARN: be careful to use this option, it may lead to infinite loop. # # Default: false. followSymlink: false # Specify metasheet name. Metasheet is "@TABLEAU" if not set. # NOTE: metasheet name must start with '@'. # # Default: "". metasheetName: "@TABLEAU" # Specify the first-pass mode to parse predefined types when generate # specified config files. Under the hood, the parsed predefined types will # be recognized and used in the second-pass. # # The first-pass mode can be: # # - "": default mode, parse based on specified config files. # - "normal": parse based on all config files. # - "advanced": parse based on all previous generated proto files. # # Default: "". firstPassMode: "" # Specify the name pattern for messager (regexp supported). If the generated # messager name does not match this pattern, an error will be reported. # Example: "Conf$" # # Default: "". messagerPattern: "" output: # Specify subdir (relative to output dir) for generated proto files. # # Default: "". subdir: "" # Dir separator `/` or `\` in filename is replaced by "__". # # Default: false. filenameWithSubdirPrefix: false # Append suffix to each generated proto filename. # # Default: "". filenameSuffix: "" # Specify the generated protobuf file's edition. ``` -------------------------------- ### Horizontal-list in vertical-map: generated ItemConf.json Source: https://tableauio.github.io/docs/excel/list-in-map Generated JSON output for the horizontal-list in vertical-map example. Shows the itemMap with propList arrays. ```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": [] } } } ``` -------------------------------- ### Update PATH for protoc plugins Source: https://tableauio.github.io/docs/api/tableau/guide Adds the Go bin directory to PATH so protoc can find the plugins. ```bash export PATH="$PATH:$(go env GOPATH)/bin" ``` -------------------------------- ### Predefined types in common.proto Source: https://tableauio.github.io/docs/excel/infinite-nesting Defines enum types ConfType and ServerType with tableau.evalue names. Used for nested naming in the example. ```proto // --snip-- enum ConfType { CONF_TYPE_UNKNOWN = 0 [(tableau.evalue).name = "Unknown"]; CONF_TYPE_CLOUD = 1 [(tableau.evalue).name = "Cloud"]; CONF_TYPE_LOCAL = 2 [(tableau.evalue).name = "Local"]; CONF_TYPE_REMOTE = 3 [(tableau.evalue).name = "Remote"]; } enum ServerType { SERVER_TYPE_UNKNOWN = 0 [(tableau.evalue).name = "Unknown"]; SERVER_TYPE_GAME = 1 [(tableau.evalue).name = "GameServer"]; SERVER_TYPE_ACTIVITY = 2 [(tableau.evalue).name = "ActivityServer"]; SERVER_TYPE_MATCH = 3 [(tableau.evalue).name = "MatchServer"]; } ``` -------------------------------- ### Generated proto for predefined incell union Source: https://tableauio.github.io/docs/yaml/union Generated hello_world.proto for the predefined incell union example. Shows the workbook option and the ItemConf message with a target field that has span SPAN_INNER_CELL and prop form:FORM_TEXT. ```proto // --snip-- option (tableau.workbook) = {name:"HelloWorld.yaml"}; message ItemConf { option (tableau.worksheet) = {name:"ItemConf"}; protoconf.Target target = 1 [(tableau.field) = {name:"Target" span:SPAN_INNER_CELL prop:{form:FORM_TEXT}}]; } ``` -------------------------------- ### Generated proto for struct list ItemConf Source: https://tableauio.github.io/docs/yaml/list Generated hello_world.proto for the struct list example, defining message ItemConf with repeated Item items and nested message Item. ```proto // --snip-- option (tableau.workbook) = {name:"HelloWorld.yaml"}; message ItemConf { option (tableau.worksheet) = {name:"ItemConf"}; repeated Item items = 1 [(tableau.field) = {name:"Items"}]; message Item { uint32 id = 1 [(tableau.field) = {name:"ID"}]; int32 num = 2 [(tableau.field) = {name:"Num"}]; } } ``` -------------------------------- ### Empty key map: generated protobuf (hello_world.proto) Source: https://tableauio.github.io/docs/excel/map Generated protobuf for a worksheet with an empty key map. The map key is not configured, so it defaults to the map key type's default value (0 for uint32). ```protobuf // --snip-- option (tableau.workbook) = {name:"HelloWorld.xlsx" namerow:1 typerow:2 noterow:3 datarow:4}; message ItemConf { option (tableau.worksheet) = {name:"ItemConf"}; map item_map = 1 [(tableau.field) = {key:"ID" layout:LAYOUT_VERTICAL}]; message Item { uint32 id = 1 [(tableau.field) = {name:"ID"}]; string desc = 2 [(tableau.field) = {name:"Desc"}]; } } ``` -------------------------------- ### Generated JSON for reused struct Source: https://tableauio.github.io/docs/xml/struct Generated JSON output for the reused struct example, showing the data for item, newItem, and otherItem. ```json { "item": { "id": 1, "startTime": "2024-10-01T02:10:10Z", "expiry": "3600s" }, "newItem": { "id": 2, "startTime": "2026-10-01T02:10:10Z", "expiry": "7200s" }, "otherItem": { "id": 3, "startTime": "2028-10-01T02:10:10Z", "expiry": "10800s" } } ``` -------------------------------- ### Predefined FruitType enum (common.proto) Source: https://tableauio.github.io/docs/excel/keyedlist Predefined enum used for the vertical enum keyed list example. Includes tableau.evalue names. ```protobuf 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"]; } ``` -------------------------------- ### Generated hello_world.proto for enum incell KeyedList Source: https://tableauio.github.io/docs/excel/keyedlist Proto definition for ItemConf with a repeated protoconf.FruitType field type_list using LAYOUT_INCELL. It imports common.proto and uses the predefined FruitType enum. ```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"}; repeated protoconf.FruitType type_list = 1 [(tableau.field) = {name:"Type" key:"Type" layout:LAYOUT_INCELL}]; } ```