設(shè)置
  • 日夜間
    隨系統(tǒng)
    淺色
    深色
  • 主題色

看了這篇,EXCEL 導(dǎo)出 JSON 再也不用求人啦

千猴馬的游戲設(shè)計(jì)之道 2022/11/29 13:09:14 責(zé)編:遠(yuǎn)生

實(shí)際開(kāi)發(fā)過(guò)程中,策劃習(xí)慣使用 Excel 填寫(xiě)游戲數(shù)據(jù),而程序使用的配置數(shù)據(jù)一般是 xml,json,lua 或者某種自定義的 DSL (Domain Specific Language) 等,或是 scriptable 等二進(jìn)制文件,所以產(chǎn)生了一個(gè)把 Excel 里的數(shù)據(jù)轉(zhuǎn)換成程序所需要的 "導(dǎo)表" 的過(guò)程.

一般團(tuán)隊(duì)的導(dǎo)表工具都是程序?qū)懙?,有好的方面,也有壞的方?好的方面是: 程序會(huì)對(duì)比 MD5 碼來(lái)確定文件一致.壞的方面是: 要規(guī)定文件路徑,只能一次性轉(zhuǎn)換所有表格,或者選擇所需轉(zhuǎn)換表格時(shí)難用的 UI, 表格 sheet 名和表的某一行必須有特殊規(guī)定等.最大的問(wèn)題還是這個(gè)工具對(duì)策劃并不開(kāi)源,加上導(dǎo)表工具里還有上傳 SVN, 重啟服務(wù)器等一系列自動(dòng)化操作,出了錯(cuò)誤之后無(wú)法確定是配置數(shù)據(jù)問(wèn)題,還是工具問(wèn)題,網(wǎng)絡(luò)問(wèn)題,在這條管線里面,就有了巨大的甩鍋空間.

所以策劃要牢牢把握住這口鍋,出了錯(cuò)就是你配置的錯(cuò),誰(shuí)讓你離開(kāi)了 Excel 連游戲都不會(huì)做了呢? 下面以 json 格式舉例,講幾種策劃也能學(xué)會(huì)的方法,制作自己的導(dǎo)表工具.

題外話,非常不推薦直接把 Excel 導(dǎo)入進(jìn)數(shù)據(jù)庫(kù)的操作.

方法一: 手動(dòng)轉(zhuǎn)換

最簡(jiǎn)單的就是復(fù)制粘貼手動(dòng)存成 json, 對(duì),就這樣干,因?yàn)槌绦蛞木褪莻€(gè) json 文件而已.沙塔斯城里的商人說(shuō)過(guò)一句話:

"你要戰(zhàn)爭(zhēng),我就給你戰(zhàn)爭(zhēng),水果販."

我們先分析下 json 格式一般是什么樣的,以下面這段為例:

可以看出,整個(gè)文件是用大括號(hào) {} 包裹起來(lái),左邊引號(hào)里的是 key, 右邊是對(duì)應(yīng)的 value. Value 有多種類(lèi)型: 是個(gè)數(shù)字的 / 用引號(hào)圈起來(lái)的 / 用大括號(hào)圈起來(lái)的 / 和用中括號(hào)圈起來(lái)的,那么我們只要弄成這樣就好了.

下面看 excel 表格里面的格式一般是這樣的:

第一行是字段名,下面是字段的值,一般用 id 作為數(shù)據(jù)庫(kù)里面的 key, 或者還有自動(dòng)生成的 uid, 增加一行用作標(biāo)記改字段的類(lèi)型等,大差不差的內(nèi)容.我們需要的就是把每一行都通過(guò) "字段: 值,字段: 值..." 的形式連接起來(lái),然后用個(gè)大括號(hào)來(lái)包裹即可.

我們后面加一列,通過(guò) Excel 的函數(shù),來(lái)獲取我們需要的數(shù)據(jù).給策劃新人們一個(gè)建議,就是函數(shù)要一步一步地寫(xiě),哪怕一共有十幾步,每一步的結(jié)果都放在一列里,確認(rèn)結(jié)果正確后,再拼接到一起,寫(xiě)一個(gè)超長(zhǎng)的函數(shù) (不能超過(guò) 255 個(gè)字符), 然后刪掉中間的步驟,云淡風(fēng)輕地對(duì)旁邊的人說(shuō):"不就是這樣簡(jiǎn)單嗎?"

第一步:

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

index 函數(shù)用來(lái)獲得字段名,第一個(gè)參數(shù) $A$1:$F$1 是第一行需要的字段范圍,注意加上 $ 符號(hào),快捷鍵是 F4...(自己搜索吧,有一種教人 ' 這是冰箱 ' 的感覺(jué)), 第二個(gè)參數(shù)是當(dāng)前值所在的列號(hào),如果前面還有空行的話,這里要減去相應(yīng)的數(shù)量.

橫著一拖,豎著一拖,看到了需要的內(nèi)容是我們要的 key.

接著連接冒號(hào)和每一行的值:

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

然后使用 textJoin 函數(shù),連接在一起,外面接上大括號(hào)就好了.

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

有人問(wèn)了,所需要的 json 的 key 有引號(hào)的啊,要怎么辦?

最簡(jiǎn)單的就是字段名字就給他加上引號(hào)!

到這里主體部分就完成了,每一條 {} 大括號(hào)里面的,都是個(gè) json 的對(duì)象.對(duì)象之間用 [] 包裹起來(lái),就是一個(gè) json 的列表,或者還有 {} 包裹組成 kv 對(duì),那么就只需要在把拼接的內(nèi)容再次按照要求拼接就好了.

有人可能會(huì)問(wèn)了,最重要的云淡風(fēng)輕,怎么還沒(méi)講? 這么多輔助列,明明是手忙腳亂啊? 怎么能寫(xiě)到一個(gè)函數(shù)里面啊?

別急,這里我們要用到數(shù)組公式.直接上公式:

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

只要把值從一個(gè)格子 A2, 變成一個(gè)范圍 A2:F2, 然后按 CTRL+SHITF+ENTER 輸入數(shù)組公式就好了.(數(shù)組公式最外面的大括號(hào)不是打字打上去的...)

至此,終于可以云淡風(fēng)輕了,因?yàn)橐话愠绦蛟骋膊惶珪?huì)用 Excel, 這樣就顯得你很專(zhuān)業(yè)了.

方法二: 自定義函數(shù)加載項(xiàng)

上面的例子中,有的字段的值是數(shù)組,用 [] 中括號(hào)引起來(lái),例如

"keywords":["小豬","小肚","小雞"]

或者自定義的類(lèi)似 lambda 表達(dá)式的東西

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

這個(gè)時(shí)候?yàn)榱瞬邉澨畋矸奖?,可能每一列都有特殊的拼接方法,我們?cè)诘诙欣锩鎸?xiě)上值的類(lèi)型,示例如下:

這種會(huì)有很多特殊的,定制的內(nèi)容,例如看到 lambda 的時(shí)候,賦值給一個(gè)臨時(shí)變量名,例如

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

array 字段為了策劃填寫(xiě)方便,用逗號(hào)分割起來(lái),生成的時(shí)候還是要分別加上引號(hào),并用中括號(hào)括起來(lái)

"keyword":["小豬","小肚","小雞"]

面對(duì)這些定制化的需求,直接用 Excel 里的函數(shù),就捉襟見(jiàn)肘了.那么我們來(lái)自己寫(xiě)一個(gè),高度定制化的函數(shù)。

打開(kāi) Visual Basic 的 IDE,如果你的 Excel 不顯示開(kāi)發(fā)工具選項(xiàng)卡,則需要在自定義功能區(qū)里勾選一下。

插入一個(gè)模塊,寫(xiě)入下列代碼:

Function textToJson(ByVal s As Variant)

Dim myKey,myValue
Dim valueType
Dim output
'將單元格范圍作為選中范圍
Dim mr As Range
Set mr = s

'讀取第一行的key,和當(dāng)前的value組成一對(duì)
For Each i In mr     

    If Not IsEmpty(i) And i <> 0 Then               
        '通過(guò)第二行的類(lèi)型來(lái)處理對(duì)應(yīng)的值        
        valueType = Cells(2, i.Column)        
        myKey = Cells(1, i.Column)        
        myValue = i.value                
        
        Select Case valueType                
        'lambda把key特殊處理,加一個(gè)用行號(hào)作為序列號(hào)的變量        
        Case "lambda"          
           myKey = "lambda" & i.Row - 2            
           output = output & myKey & "=" & myValue & ","                
           
       'array把值特殊處理,將逗號(hào)分隔的字符串放在一個(gè)數(shù)組里        
       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 If
Next i

'最后拼接一下
If IsError(output) Or Len(output) <= 1 Then
    textToJson = ""
Else
    output = Left(output, Len(output) - 1)   
    textToJson = "{" & output & "}"  
End If
End Function

這樣我們定義了 textToJson()這個(gè)函數(shù),在最后一列里面輸入 = textToJson (A3:F3) 即可轉(zhuǎn)換。

如果其他表格也想使用該函數(shù),但是不想轉(zhuǎn)換成 xlsm 這帶宏的格式,怎么辦?

我們可以把這個(gè)文件另存為 xlam,作為加載宏,給其他表格使用。

其他表格使用時(shí),通過(guò)開(kāi)發(fā)工具》Excel 加載項(xiàng)》瀏覽 找到該文件,即可使用 textToJson 這個(gè)自定義函數(shù)。

方法三:VBA

上面既然已經(jīng)用了自定義函數(shù),還要另存為等手動(dòng)操作,那么不如使用 VBA 直接導(dǎo)出。寫(xiě)法基本一樣,只不過(guò)創(chuàng)建了一個(gè) json 文件作為 object 來(lái)承載導(dǎo)出的內(nèi)容。注意,如果報(bào)出找不到對(duì)象的錯(cuò)誤的話,那么可以去人民公園試試。

Sub toJson()

Dim i, j, k As Integer
Dim myString, output As String
Dim myRange As Range
Dim myArr()
Dim myTitle()
Dim WriteStream As Object


Set MyFile = CreateObject("Scripting.FileSystemObject").OpenTextFile("D:\testjson.json", 8, True)

myString = ""
output = ""

i = 0
j = 0
k = 0

Set myRange = Selection
myArr = myRange

ReDim myTitle(20)

For k = 0 To myRange.Columns.Count - 1

    myTitle(k) = myArr(1, k + 1)
    
Next k


For 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

以上代碼是我們做過(guò)的一個(gè)答題游戲的例子,超過(guò)幾萬(wàn)條有趣的問(wèn)題。配置表可以稍微露一下:

方法四:其他

大家可能會(huì)問(wèn)了,這一個(gè)一個(gè)表格的導(dǎo)出,太麻煩了,能不能一起導(dǎo)出多張?很多公司用 VBA 寫(xiě)過(guò)導(dǎo)出多張表格的工具,我也寫(xiě)過(guò),但因?yàn)?VBA 先天的弱勢(shì),速度極慢,還容易卡死。

這里推薦用 python 去寫(xiě),速度快 100 倍??梢杂?openpyxl 庫(kù),至于如何寫(xiě),可以參考上一篇文章:世界杯到了,寫(xiě)個(gè)爬蟲(chóng)獲取球員數(shù)據(jù)吧

因?yàn)楹芎?jiǎn)單,在此不再贅述了,可以作為初學(xué) python 的某種練習(xí)。還可以通過(guò) pandas 模塊把 excel 讀成字典對(duì)象,然后直接存進(jìn) mySQL 或者 mongodb,根本不需要導(dǎo)表這個(gè)中間過(guò)程了。

本文來(lái)自微信公眾號(hào):千猴馬的游戲設(shè)計(jì)之道 (ID:baima21th),作者:千兩

廣告聲明:文內(nèi)含有的對(duì)外跳轉(zhuǎn)鏈接(包括不限于超鏈接、二維碼、口令等形式),用于傳遞更多信息,節(jié)省甄選時(shí)間,結(jié)果僅供參考,IT之家所有文章均包含本聲明。

相關(guān)文章

關(guān)鍵詞:代碼Excel,編程,函數(shù)

軟媒旗下網(wǎng)站: IT之家 最會(huì)買(mǎi) - 返利返現(xiàn)優(yōu)惠券 iPhone之家 Win7之家 Win10之家 Win11之家

軟媒旗下軟件: 軟媒手機(jī)APP應(yīng)用 魔方 最會(huì)買(mǎi) 要知