看了这篇,EXCEL 导出 JSON 再也不用求人啦

实际开发过程中,策划习惯使用 Excel 填写游戏数据,而程序使用的配置数据一般是 xml,json,lua 或者某种自定义的 DSL (Domain Specific Language) 等,或是 scriptable 等二进制文件,所以产生了一个把 Excel 里的数据转换成程序所需要的 "导表" 的过程.

一般团队的导表工具都是程序写的,有好的方面,也有坏的方面.好的方面是: 程序会对比 MD5 码来确定文件一致.坏的方面是: 要规定文件路径,只能一次性转换所有表格,或者选择所需转换表格时难用的 UI, 表格 sheet 名和表的某一行必须有特殊规定等.最大的问题还是这个工具对策划并不开源,加上导表工具里还有上传 SVN, 重启服务器等一系列自动化操作,出了错误之后无法确定是配置数据问题,还是工具问题,网络问题,在这条管线里面,就有了巨大的甩锅空间.

所以策划要牢牢把握住这口锅,出了错就是你配置的错,谁让你离开了 Excel 连游戏都不会做了呢? 下面以 json 格式举例,讲几种策划也能学会的方法,制作自己的导表工具.

题外话,非常不推荐直接把 Excel 导入进数据库的操作.

方法一: 手动转换

最简单的就是复制粘贴手动存成 json, 对,就这样干,因为程序要的就是个 json 文件而已.沙塔斯城里的商人说过一句话:

"你要战争,我就给你战争,水果贩."

我们先分析下 json 格式一般是什么样的,以下面这段为例:

可以看出,整个文件是用大括号 {} 包裹起来,左边引号里的是 key, 右边是对应的 value. Value 有多种类型: 是个数字的 / 用引号圈起来的 / 用大括号圈起来的 / 和用中括号圈起来的,那么我们只要弄成这样就好了.

下面看 excel 表格里面的格式一般是这样的:

第一行是字段名,下面是字段的值,一般用 id 作为数据库里面的 key, 或者还有自动生成的 uid, 增加一行用作标记改字段的类型等,大差不差的内容.我们需要的就是把每一行都通过 "字段: 值,字段: 值..." 的形式连接起来,然后用个大括号来包裹即可.

我们后面加一列,通过 Excel 的函数,来获取我们需要的数据.给策划新人们一个建议,就是函数要一步一步地写,哪怕一共有十几步,每一步的结果都放在一列里,确认结果正确后,再拼接到一起,写一个超长的函数 (不能超过 255 个字符), 然后删掉中间的步骤,云淡风轻地对旁边的人说:"不就是这样简单吗?"

第一步:

=INDEX($A$1:$F$1,COLUMN(A2))

index 函数用来获得字段名,第一个参数 $A$1:$F$1 是第一行需要的字段范围,注意加上 $ 符号,快捷键是 F4...(自己搜索吧,有一种教人 ' 这是冰箱 ' 的感觉), 第二个参数是当前值所在的列号,如果前面还有空行的话,这里要减去相应的数量.

横着一拖,竖着一拖,看到了需要的内容是我们要的 key.

接着连接冒号和每一行的值:

=INDEX($A$1:$F$1,COLUMN(A2))&":"&A2

然后使用 textJoin 函数,连接在一起,外面接上大括号就好了.

="{"&TEXTJOIN(",",TRUE,G2:L2)&"}"

有人问了,所需要的 json 的 key 有引号的啊,要怎么办?

最简单的就是字段名字就给他加上引号!

到这里主体部分就完成了,每一条 {} 大括号里面的,都是个 json 的对象.对象之间用 [] 包裹起来,就是一个 json 的列表,或者还有 {} 包裹组成 kv 对,那么就只需要在把拼接的内容再次按照要求拼接就好了.

有人可能会问了,最重要的云淡风轻,怎么还没讲? 这么多辅助列,明明是手忙脚乱啊? 怎么能写到一个函数里面啊?

别急,这里我们要用到数组公式.直接上公式:

{="{"&TEXTJOIN(",",TRUE,INDEX($A$1:$F$1,COLUMN(A2:F2))&":"&A2:F2)&"}"}

只要把值从一个格子 A2, 变成一个范围 A2:F2, 然后按 CTRL+SHITF+ENTER 输入数组公式就好了.(数组公式最外面的大括号不是打字打上去的...)

至此,终于可以云淡风轻了,因为一般程序猿也不太会用 Excel, 这样就显得你很专业了.

方法二: 自定义函数加载项

上面的例子中,有的字段的值是数组,用 [] 中括号引起来,例如

"keywords":["小猪","小肚","小鸡"]

或者自定义的类似 lambda 表达式的东西

scripts:(Count(Unit))=100&Count(Wonder)=3IsDead(Bob)

这个时候为了策划填表方便,可能每一列都有特殊的拼接方法,我们在第二行里面写上值的类型,示例如下:

这种会有很多特殊的,定制的内容,例如看到 lambda 的时候,赋值给一个临时变量名,例如

lambda1=(Count(Unit))=100&Count(Wonder)=3IsDead(Bob)

array 字段为了策划填写方便,用逗号分割起来,生成的时候还是要分别加上引号,并用中括号括起来

"keyword":["小猪","小肚","小鸡"]

面对这些定制化的需求,直接用 Excel 里的函数,就捉襟见肘了.那么我们来自己写一个,高度定制化的函数。

打开 Visual Basic 的 IDE,如果你的 Excel 不显示开发工具选项卡,则需要在自定义功能区里勾选一下。

插入一个模块,写入下列代码:

Function textToJson(ByVal s As Variant)Dim myKey,myValueDim valueTypeDim output'将单元格范围作为选中范围Dim mr As RangeSet mr = s'读取第一行的key,和当前的value组成一对For Each i In mr         If Not IsEmpty(i) And i <> 0 Then                       '通过第二行的类型来处理对应的值                valueType = Cells(2, i.Column)                myKey = Cells(1, i.Column)                myValue = i.value                                Select Case valueType                        'lambda把key特殊处理,加一个用行号作为序列号的变量                Case "lambda"                     myKey = "lambda" & i.Row - 2                       output = output & myKey & "=" & myValue & ","                                  'array把值特殊处理,将逗号分隔的字符串放在一个数组里               Case "array"                    temp = ""                       tempString = Split(i.value, ",")                       For Each k In tempString                            temp = temp & Chr(34) & k & Chr(34) & ","                       Next k                       temp = Left(temp, Len(temp) - 1)                       temp = "[" & temp & "]"                       myValue = temp                       output = output & myKey & ":" & myValue & ","                                 '情况不做处理              Case Else                  output = output & myKey & ":" & myValue & ","                      End Select      End IfNext i'最后拼接一下If IsError(output) Or Len(output) <= 1 Then    textToJson = ""Else    output = Left(output, Len(output) - 1)       textToJson = "{" & output & "}"  End IfEnd Function

这样我们定义了 textToJson()这个函数,在最后一列里面输入 = textToJson (A3:F3) 即可转换。

如果其他表格也想使用该函数,但是不想转换成 xlsm 这带宏的格式,怎么办?

我们可以把这个文件另存为 xlam,作为加载宏,给其他表格使用。

其他表格使用时,通过开发工具》Excel 加载项》浏览 找到该文件,即可使用 textToJson 这个自定义函数。

方法三:VBA

上面既然已经用了自定义函数,还要另存为等手动操作,那么不如使用 VBA 直接导出。写法基本一样,只不过创建了一个 json 文件作为 object 来承载导出的内容。注意,如果报出找不到对象的错误的话,那么可以去人民公园试试。

Sub toJson()Dim i, j, k As IntegerDim myString, output As StringDim myRange As RangeDim myArr()Dim myTitle()Dim WriteStream As ObjectSet MyFile = CreateObject("Scripting.FileSystemObject").OpenTextFile("D:\testjson.json", 8, True)myString = ""output = ""i = 0j = 0k = 0Set myRange = SelectionmyArr = myRangeReDim myTitle(20)For k = 0 To myRange.Columns.Count - 1    myTitle(k) = myArr(1, k + 1)    Next kFor i = 2 To myRange.Rows.Count      output = output & "{"                      For j = 1 To myRange.Columns.Count                                       If myTitle(j - 1) = "truth" Then                                myString = Trim(myArr(i, j))                                                          output = output & Chr(34) & myTitle(j - 1) & Chr(34) & ":" & LCase(myString) & ","                                    ElseIf myTitle(j - 1) = "tag" Or myTitle(j - 1) = "falseWord" Then                                            myString = Trim(myArr(i, j))                                              output = output & Chr(34) & myTitle(j - 1) & Chr(34) & ":[" & mySubString(myString) & "],"                                    ElseIf myTitle(j - 1) = "difficulty" Then                                        myString = Trim(myArr(i, j))                                           output = output & Chr(34) & myTitle(j - 1) & Chr(34) & ":" & myString & ","                                      Else                            myString = Trim(myArr(i, j))                                                          output = output & Chr(34) & myTitle(j - 1) & Chr(34) & ":" & Chr(34) & myString & Chr(34) & ","                             End If                                Next j                    output = Mid(output, 1, Len(output) - 1)           output = output & "}," & Chr(10)               Next i     output = Mid(output, 1, Len(output) - 2)    '    Set WriteStream = CreateObject("ADODB.Stream")''    With WriteString'         .Type = 2'                 .Charset = "UTF-8"''    End With              MyFile.WriteLine (output)                  MyFile.Close         Set MyFile = Nothing                  MsgBox "成功!!"         'UserForm1.TextBox1.Text = output         'UserForm1.Show              End Sub

以上代码是我们做过的一个答题游戏的例子,超过几万条有趣的问题。配置表可以稍微露一下:

方法四:其他

大家可能会问了,这一个一个表格的导出,太麻烦了,能不能一起导出多张?很多公司用 VBA 写过导出多张表格的工具,我也写过,但因为 VBA 先天的弱势,速度极慢,还容易卡死。

这里推荐用 python 去写,速度快 100 倍。可以用 openpyxl 库,至于如何写,可以参考上一篇文章:世界杯到了,写个爬虫获取球员数据吧

因为很简单,在此不再赘述了,可以作为初学 python 的某种练习。还可以通过 pandas 模块把 excel 读成字典对象,然后直接存进 mySQL 或者 mongodb,根本不需要导表这个中间过程了。

本文来自微信公众号:千猴马的游戏设计之道 (ID:baima21th),作者:千两

广告声明:文内含有的对外跳转链接(包括不限于超链接、二维码、口令等形式),用于传递更多信息,节省甄选时间,结果仅供参考,IT之家所有文章均包含本声明。

文章价值:
人打分
有价值还可以无价值
置顶评论
    热门评论
      全部评论
      一大波评论正在路上
        取消发送
        软媒旗下人气应用

        如点击保存海报无效,请长按图片进行保存分享