Skip to content
 
 

Repository files navigation

xresloader

快速实现一个简单暴力功能强大的导表工具

构建环境 Linux (Oracle JDK 8)
当前构建状态 Build Status

Gitter

License

MIT License

GET START

使用步骤

  1. 定义protobuf的协议文件(.proto)
  2. 使用protobuf官方工具protoc把.proto文件转换成pb
  3. 编写Excel,并且字段名和protobuf协议字段名和层级关系对应
  4. 执行命令 java -jar XRESLOADER.jar [参数...],传入excel文件名、表名和其他规则。(参数和选项见 工具命令行参数
  5. 使用对应的语言或者工具库加载导出的数据。(编码规则和解析工具见 关于加载导出的数据
  • sample目录下有所有功能的示例excel、配置、协议和对sample数据的几种读取方式代码

工具命令行参数

执行方式 java -jar xresloader.jar [参数...]

比如:(生成源和结果在sample目录下, xresloader的路径为 ../target/xresloader-1.3.3.0.jar)

cd sample;

# Excel=>二进制(按协议) 
java -client -jar ../target/xresloader-1.3.3.0.jar -t bin -p protobuf -f proto_v3/kind.pb -s 资源转换示例.xlsx -m scheme_kind -o proto_v3

# Excel=>Lua,并重命名输出文件 
java -client -jar ../target/xresloader-1.3.3.0.jar -t lua -p protobuf -f proto_v3/kind.pb --pretty 4 -s 资源转换示例.xlsx -m scheme_kind -n "/(?i)\.bin$/\.lua/" -o proto_v3

# Excel=>Javascript,并重命名输出文件, 并把数据都导入到全局变量sample
java -client -jar ../target/xresloader-1.3.3.0.jar -t js -p protobuf -f proto_v3/kind.pb --pretty 2 -s 资源转换示例.xlsx -m scheme_kind -n "/(?i)\.bin$/\.js/" --javascript-global sample -o proto_v3

# Excel=>MsgPack二进制,并重命名输出文件 
java -client -jar ../target/xresloader-1.3.3.0.jar -t msgpack -p protobuf -f proto_v3/kind.pb -s 资源转换示例.xlsx -m scheme_kind -n "/(?i)\.bin$/\.msgpack.bin/" -o proto_v3

# 输出文件重命名+输出json格式+多次转表(多个-m参数)
java -client -jar ../target/xresloader-1.3.3.0.jar -t json -p protobuf -f proto_v3/kind.pb -n "/(?i)\.bin$/\.json/" -s 资源转换示例.xlsx -m scheme_kind -m scheme_upgrade -o proto_v3

# Excel=>Xml,并重命名输出文件 
# Excel=>Xml,数据源是ini文件, 并重命名输出文件 
# Excel=>Xml,数据源是json文件, 并重命名输出文件
# Protobuf=>lua代码,输出所有的枚举类型  
echo "
-t xml -p protobuf -f proto_v3/kind.pb -s 资源转换示例.xlsx -m scheme_kind -n \"/(?i)\.bin$/\.xml/\" -o proto_v3
-t xml -p protobuf -f proto_v3/kind.pb --pretty 2 -s 资源转换示例.scheme.ini -m scheme_kind -n \"/(?i)\.bin$/\.xml/\" -o proto_v3
-t xml -p protobuf -f proto_v3/kind.pb -s 资源转换示例.scheme.json -m scheme_kind -n \"/(?i)\.bin$/\.xml/\" -o proto_v3
-t lua -p protobuf -f proto_v3/kind.pb --pretty 2 -c kind_const.lua --lua-global -o proto_v3
" | java -Dfile.encoding=UTF-8 -client -jar ../target/xresloader-1.3.3.0.jar --stdin

# 注意这个命令必须使用bash或sh
# 如果bash的编码是UTF-8在Windows下会因为编码错误而找不到文件,所以需要加-Dfile.encoding=UTF-8
# 如果bash的编码和系统编码一致(一般是GBK),则不用加这个选项

# Excel => 二进制(按协议,内嵌数组)+命令行输入meta
# Excel => Lua(按协议,内嵌数组)+命令行输入meta
echo "
-t lua -p protobuf -f proto_v3/kind.pb --pretty 2 -m \"DataSource=资源转换示例.xlsx|arr_in_arr|3,1\" -m \"MacroSource=资源转换示例.xlsx|macro|2,1\" -m \"ProtoName=arr_in_arr_cfg\" -m \"OutputFile=arr_in_arr_cfg.lua\" -m \"KeyRow=2\" -o proto_v3
-t bin -p protobuf -f proto_v3/kind.pb -m \"DataSource=资源转换示例.xlsx|arr_in_arr|3,1\" -m \"MacroSource=资源转换示例.xlsx|macro|2,1\" -m \"ProtoName=arr_in_arr_cfg\" -m \"OutputFile=arr_in_arr_cfg.bin\" -m \"KeyRow=2\" -o proto_v3
" | java -Dfile.encoding=UTF-8 -client -jar ../target/xresloader-1.3.3.0.jar --stdin

可用参数列表

参数选项 描述 说明
-h --help 帮助信息 显示帮助和支持的参数列表
-t --output-type 输出类型 bin(默认值),lua,msgpack,json,xml,javascript,js
-p --proto 协议描述类型 protobuf(默认值),capnproto(暂未实现),flatbuffer(暂未实现)
-f --proto-file 协议描述文件
-o --output-dir 输出目录 默认为当前目录
-d --data-src-dir 数据源根目录 默认为当前目录
-s --src-file 数据源描述文件 后缀可以是 .xls, .xlsx, .cvs, .xlsm, .ods, .ini, .cfg, .conf, .json
-m --src-meta 数据源描述表 可多个
-v --version 打印版本号
-n --rename 重命名输出文件名 正则表达式 (如:/(?i)\.bin$/\.lua/)
-c --const-print 输出协议描述中的常量 参数为字符串,表示输出的文件名
--pretty 格式化输出 参数为整数,0代表关闭美化输出功能,大于0表示格式化时的缩进量
--enable-excel-formular 开启Excel公式支持 默认开启,使用公式会大幅减慢转表速度
--disable-excel-formular 关闭Excel公式支持 关闭公式会大幅加快转表速度
--disable-empty-list 禁止空列表项 默认开启,禁止空列表项,自动删除Excel中的未填充数据,不会转出到输出文件中
--enable-empty-list 开启空列表项 开启空列表项,未填充数据将使用默认的空值来填充,并转出到输出文件中
--stdin 通过标准输入批量转表 通过标准输入批量转表,参数可上面的一样,每行一项,字符串参数可以用单引号或双引号包裹,但是都不支持转义
--lua-global lua输出写到全局表 输出协议描述中的常量到Lua脚本时,同时导入符号到全局表_G中(仅对常量导出有效)
--xml-root xml输出的根节点tag 输出格式为xml时的根节点的TagName
--javascript-export 导出javascript数据的模式 可选项(nodejs: 使用兼容nodejs的exports, amd: 使用兼容amd的define, 其他: 写入全局(window或global))
--javascript-global 导出javascript全局空间 导出数据到全局时,可以指定写入的名字空间

协议类型

  1. protobuf (已实现)
  2. capnproto (暂未支持:目前capnproto还没有提供java下通过反射打解包数据的方法,暂时放弃支持)
  3. flatbuffer (暂未支持:目前flatbuffers还没有提供java下通过反射打解包数据的方法,暂时放弃支持)

数据源描述文件说明(根据后缀判断类型有不同读取方式)

数据源描述文件后缀 数据源描述表 说明
.xls,.xlsx 视作Excel文件,数据源描述表为Excel内的Sheet名称 已实现, 非微软格式尚未测试
.ini,.conf,.cfg 视作ini文件,数据源描述表为ini内的Section名称 已实现(不支持自动合表)
.json 视作json文件,数据源描述表为json内的第一层子节点名称 已实现(必须是UTF-8编码,不支持自动合表)
.xml 视作xml文件,数据源描述表为xml内的根节点下的子节点TagName,并且只取第一个 (暂未支持)

数据源描述表配置项及示例

字段 简介 主配置 次配置 补充配置 说明
DataSource 配置数据源(主配置:文件路径,次配置:表名,补充配置:起始行号,列号) ./资源转换示例.xlsx kind 3,1 必须,可多个。多个则表示把多个Excel表数据合并再生成配置输出,这意味着这多个Excel表的描述Key的顺序和个数必须相同
MacroSource 元数据数据源(主配置:文件路径,次配置:表名,补充配置:起始行号,列号) ./资源转换示例.xlsx macro 2,1 可选
编程接口配置
ProtoName 协议描述名称 role_cfg 必须, 这个名字可以直接是类型名称[MessageName],也可以是[PackageName].[MessageName]
OutputFile 输出文件 role_cfg.bin 必须
KeyRow 字段名描述行 2 必须
KeyCase 字段名大小写 不变 大写/小写/不变(大小写转换,如果不需要则留空或小写)
KeyWordSplit 字段名分词字符 _ 可选,字段名映射时单词之间填充的字符串,不需要请留空
KeyPrefix 字段名固定前缀 可选,字段名映射时附加的前缀,不需要请留空
KeySuffix 字段名固定后缀 可选,字段名映射时附加的后缀,不需要请留空
KeyWordRegex 分词规则(判断规则,移除分词符号规则,前缀过滤规则) [A-Z_$ \t\r\n] [_$ \t\r\n] [a-zA-Z_$] (可选),字段名映射时单词的分词规则,正则表达式,不需要请留空
Encoding 编码转换 UTF-8 注:Google的protobuf库的代码里写死了UTF-8,故而该选项对Protobuf的二进制输出无效

数据源描述的特别说明

比如在资源转换示例.xlsx中:

  1. DataSource指明配置从文件:资源转换示例.xlsx,表:kind,第3行第1列开始读数据
  2. MacroSource指明配置从文件:资源转换示例.xlsx,表:macro,第2行第1列开始读数据文本替换的搜索串,并第2列读替换目标
  3. ProtoName指明协议中的数据结构名称为role_cfg
  4. OutputFile指明输出的文件名
  5. KeyRow指明从文件:资源转换示例.xlsx,表:kind(DataSource指定)第2行找字段名称,并转换成协议中的字段名。填充数据到该字段。
  6. KeyCase指明从第2行的字段名称转换成协议中的字段名时要转换成小写(如果字段名和第2行的内容一致则填不变即可)
  7. KeyWordSplit指明从第2行的字段名称转换成协议中的字段名时分词符号是*_*。(如果字段名和第2行的内容一致则留空)
  8. KeyPrefix指明从第2行的字段名称转换成协议中的字段名后,字段名加固定前缀
  9. KeySuffix指明从第2行的字段名称转换成协议中的字段名后,字段名加固定后缀
  10. KeyWordRegex指明分词的判定规则,全部是正则表达式
  • 主配置(分词匹配符):[A-Z_$ \t\r\n]是指,碰到大写字母、下划线、$符号、空格和打印符、换行符都认为是新单词
  • 次配置(过滤匹配符):[_$ \t\r\n]是指,碰到分词符号后下划线、$符号、空格和打印符、换行符时都要移除
  • 补充配置(起始匹配符):[a-zA-Z_$]是指,第一次碰到字母、下划线、$符号后才开始认为是字段名,前面的都视为无效字符
  1. Encoding指明输出的字符串内容都是UTF-8编码。(目前最好只用UTF-8,因为protobuf里写死了UTF-8编码,其他编码不保证完全正常)

上面的配置中,数据从第3行读取,Key从第2行读取。那么第一行可以用来写一些说明或描述性数据。

以上6-10是都为了兼容某些情况下的名称和规范的适配问题。

比如:资源转换示例.xlsx的kind表中,0CostType这一项

  1. KeyWordRegex的补充配置会过滤掉前缀0(不匹配[a-zA-Z_$]),即CostType
  2. KeyWordRegex的主配置会在大写字母处做分词,次配置指明保留字母,即分割成Cost Type
  3. KeyCase指明转换成小写,即cost type
  4. KeyWordSplit指明分词符号是*_*,即cost_type
  5. 最后匹配到kind.protorole_cfgcost_type字段.

如果不需要字段名转换,直接把KeyWordRegex的配置全部配成空即可。(注意这样大小写转换也不会执行)

输出格式说明

输出格式参数 输出格式说明 说明
bin 基于协议的二进制文件,不同的协议类型(-p参数)输出的二进制不一样,一般是header+body,body中有转出的数据列表, 协议格式见header文件夹 示例见 sample (protobuf)
lua 转出为格式化的lua文件(易读), 一般格式为 return {[1] = 转表头信息, [协议结构名称] = {数据列表} } 示例见sample
msgpack 转出为使用MsgPack打包的二进制文件,内含的第一个message是转表头信息,后面紧跟数据,可以用任何支持得客户端解包 示例见sample
json 转出为json文件,一般格式为 [ {转表头信息}, {协议结构名称 : [ 转出的数据 ] } ] 示例见sample
xml 转出为xml文件,一般格式为<root><header>转表头信息</header><body><协议结构名称>数据内容</协议结构名称></body></root> 示例见sample

注意: Xml输出格式中,列表元素的结构是*<配置名称 for="0">数据1</配置名称><配置名称 for="1">数据2...</配置名称>* 属性字段for表示数组索引,目的是方便通过xpath查找。

关于加载导出的数据

转出的数据都采用header+data_block的形式。本工具并不规定怎么读取转表导出的数据,开发者可以按照转出的数据规则自由操作。

建议项目中使用导出的协议二进制或者msgpack。协议二进制可以用任意语言加载protobuf或者其他类似工具(如:pbc)加载。

而其他导出类型可以用于一些外部工具的集成,比如基于Web的GM工具,基于Lua的远程调试工具等等。

但是为了使用方便,在loader-binding里提供了几种基本的读表方式。

protobuf协议

  • protobuf的协议数据解包主要流程:
  1. 二进制文件使用header/pb_header.proto中的xresloader_datablocks结构解包
  2. xresloader_datablocks.data_block内保存的二进制使用指定的配置协议解包
  3. xresloader_datablocks.data_block的个数就是Excel转出的数据行数,注意包含空行
  • 如果你使用官方的protobuf或protobuf-lite,可以使用loader-binding/cxx来加载配置

sample 参见: sample/cxx/read_kind_sample.cpp

这个加载器会依赖 https://github.com/owent-utils/lua/tree/master/src 里的部分内容。

需要使用pbc先加载header/pb_header.pb文件

proto v3请注意: pbc不支持[packed=true]属性。在proto v3中,所有的repeated整数都默认是[packed=true],要使用pbc解码请注意这些field要显示申明为[packed=false]

或者使用我修改过的pbc的proto_v3分支

pbc_config_manager:load_buffer_kv(协议名, 二进制, function(序号, 转出的lua table) return key的值 end) -- 读取key-value型数据接口

pbc_config_manager:load_buffer_kl(协议名, 二进制, function(序号, 转出的lua table) return key的值 end) -- 读取key-list型数据接口

其他输出格式

注意:所有导出非二进制的数据都是不带包名的(package),但是使用-c --const-print选项导出协议常量除外。因为数据加载一般有manager统一管理,而协议常量一般直接用于代码中。

导出的常量都很简单易懂,直接看生成的文件很容易理解,这里不再额外作说明了。

  1. lua格式输出可以按loader-binding/lua的说明读取。

这个加载器会依赖 https://github.com/owent-utils/lua/tree/master/src 里的部分内容。

conf_manager:load_kv(require的路径, function(序号, 转出的lua table) return key的值 end) -- 读取key-value型数据接口

conf_manager:load_kl(require的路径, function(序号, 转出的lua table) return key的值 end) -- 读取key-list型数据接口

  1. MsgPack的读取的语言和工具很多,任意工具都能比较简单地读出数据,loader-binding/msgpack里有一些读取示例(Python和Node.js)
  2. Json的读取的语言和工具很多,任意工具都能比较简单地读出数据,故而不再提供读取工具
  3. Xml的读取的语言和工具很多,任意工具都能比较简单地读出数据,故而不再提供读取工具
  4. Javascript的读取的语言和工具很多,任意工具都能比较简单地读出数据,loader-binding/javascript里有相关说明

高级功能

验证器

Excel里的Key使用@后缀的字段名,@后面的部分都属于验证器。如果一个字段使用了验证器,那么可以直接填写验证器类型的内部名字或者ID

详见 sample/资源转换示例.xlsx 的upgrade_10001和upgrade_10002表

编译和打包(For developer)

  • 本项目使用apache maven管理包依赖和打包构建流程。
  • JDK 需要1.8或以上版本
# 编译
mvn compile
# 打包
mvn package

以上命令会自动下载依赖文件、包和插件。

编译完成后,输出的结果默认会放在 target 目录下。

更新依赖包

编译和打包见 安装说明

FAQ

  1. 为什么会读到很多空数据?

Ans: Excel里编辑过的单元格即便删除了也会留下不可见的样式配置,这时候会导致转出的数据有空行。可以通过在Excel里删除行解决

  1. 为什么Excel里填的时间,但是转出来是一个负数?

Ans: Excel里的日期时间类型转成协议里整数时会转为Unix时间戳,但是Excel的时间是以1900年1月0号为基准的,这意味着如果时间格式是hh:mm:dd的话,49:30:01会被转为1900-1-2 1:31:01。时间戳会是一个很大的负数

介于这个原因,不建议在Excel中使用时间类型

  1. Windows下控制台里执行执行会报文件编码错误?(java.nio.charset.UnsupportedCharsetException: cp65001)

Ans: 这个问题涉及的几个Exception是

ERROR StatusLogger Unable to inject fields into builder class for plugin type class org.apache.logging.log4j.core.appender.ConsoleAppender, element Console.
 java.nio.charset.UnsupportedCharsetException: cp65001
        at java.nio.charset.Charset.forName(Unknown Source)
        at org.apache.logging.log4j.util.PropertiesUtil.getCharsetProperty(PropertiesUtil.java:146)
        at org.apache.logging.log4j.util.PropertiesUtil.getCharsetProperty(PropertiesUtil.java:134)
        at org.apache.logging.log4j.core.appender.ConsoleAppender$Target.getCharset(ConsoleAppender.java:85)
        at org.apache.logging.log4j.core.appender.ConsoleAppender$Target$1.getDefaultCharset(ConsoleAppender.java:71)
        at org.apache.logging.log4j.core.appender.ConsoleAppender$Builder.build(ConsoleAppender.java:218)
        at org.apache.logging.log4j.core.appender.ConsoleAppender$Builder.build(ConsoleAppender.java:185)
        at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.build(PluginBuilder.java:122)
...

ERROR StatusLogger Unable to invoke factory method in class class org.apache.logging.log4j.core.appender.ConsoleAppender for element Console.
 java.lang.IllegalStateException: No factory method found for class org.apache.logging.log4j.core.appender.ConsoleAppender
        at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.findFactoryMethod(PluginBuilder.java:224)
        at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.build(PluginBuilder.java:130)
        at org.apache.logging.log4j.core.config.AbstractConfiguration.createPluginObject(AbstractConfiguration.java:952)
        at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:892)
        at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:884)
        at org.apache.logging.log4j.core.config.AbstractConfiguration.doConfigure(AbstractConfiguration.java:508)
        at org.apache.logging.log4j.core.config.AbstractConfiguration.initialize(AbstractConfiguration.java:232)
        at org.apache.logging.log4j.core.config.AbstractConfiguration.start(AbstractConfiguration.java:244)
        at org.apache.logging.log4j.core.LoggerContext.setConfiguration(LoggerContext.java:545)
        at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:617)
        at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:634)
        at org.apache.logging.log4j.core.LoggerContext.start(LoggerContext.java:229)
...

这是因为在Windows控制台中,如果编码是UTF-8,java获取编码时会获取到cp65001,而这个编码java本身是不识别的。这种情况可以按下面的方法解决:

  • 第一种: 执行xresloader之前先执行 chcp 936,切换到GBK编码
  • 第二种: 在powershell里执行

About

跨平台、易于适配和集成的Excel导表工具

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages