Lua工具:Excel数据转换成Lua文件


现在很多手游使用Cocos2dx + Lua 的开发模式,在这过程中,很多游戏的基础数据,放在哪里,什么格式,怎么做效率最高。 当然是你已经采用的开发模式了,

        基础数据做成Lua 文件,才是最好的,读取的效率是最高的。 本工具使用的 “luacom” 调用的 Windows api 读取的excel 。但他内部还有点问题,就是中文的识别的问题,

       虽然有很多修改的例子,但都是有问题的。转  luacom中文内容输出BUG及修正  (本人测试,会有Lua.exe 卡死现象。这块还在测试,只能去看 luacom 源码来改这个问题了,个人能力有限,还请大家帮助一下。)

               好了,不扯犊子了。 看文件。

某关卡数据表:


导出的文件格式


表的前三行是必有的,第一行是 该列的说明,第二行是 类型和是否比填,第三行是字段名字,(当然也有策划自己看的,而不需要导入程序的数据,那就第二行和第三行什么都不填写)

ExcelToLua.lua

	local xlsPath = [[D:/SVN/public/cehua/db_excel]]
	local luaPath = [[D:/SVN/lua]]

	local M = {}

    -- 分割字符串
	local split = function (str, split_char)
		-- 以下3行代码做数据校检(在底端设备上尽量去掉)
	    if type(str) ~= "string" or #str == 0 then
	        return {}
	    end
	    local nSepLen = string.len(split_char)
	    local sub_str_tab = {}
	    while (true) do
	        local pos = string.find(str, split_char)
	        if (not pos) then
	            sub_str_tab[#sub_str_tab + 1] = str
	            break
	        end
	        local sub_str = string.sub(str, 1, pos - 1)
	        sub_str_tab[#sub_str_tab + 1] = sub_str
	        str = string.sub(str, pos + nSepLen, #str)
	    end
	    return sub_str_tab
	end

	-- 从后面开始查找
	local findStrFromBehind = function ( str , findstr)
		local len = string.len(str)
		local  val = string.len(findstr) - 1
		for i = len , 1 , -1 do
			if i + val <= len then
				local temp = string.sub(str,i,i + val)
				if temp == findstr then
					return i,i + val
				end
			end
		end
		return "nil"
	end

	M.parsing_excel = function( filePath )
		 require('luacom')
		local excel = luacom.CreateObject("Excel.Application") --创建新的实例
		if excel == nil then error("Object is not create") end

		--excel.Visible = false
		--打开指定的文件
		local book =excel.Workbooks:Open(filePath)
		if not book then error("book is nil") end
		--读第一个工作表
		local sheet = book.Sheets(1)

		 local keys  = {}
		 local cols = {}
		 local type_yn = {}  -- { {"string","yes"}...} string类型,true = 必须填写数值

		 -- 获取相应的 key值和 列号
		for i = 1 ,30 do
			local key = sheet.Cells(3, i).Value2
			if key then
				table.insert(keys,key)
				table.insert(cols,i)
				local ty = sheet.Cells(2, i).Value2
				local slt = string.find(ty,"[%p]")
			    table.insert(type_yn,split(ty,string.sub(ty,slt,slt)))
			end
		end

		-- 获取数据内容 并检测
		local content = {}
		local row = 4
		local flag = true
		while flag do
			local tempRow = {}
			for k,col in pairs(cols) do
				if not sheet.Cells(row,cols[1]).Value2 then flag = false break end
				local value = sheet.Cells(row,col).Value2
				if M.checkValue(type_yn[k],value) then
					 -- 中文问题

					value = value == "nil" and "nil" or value
					table.insert(tempRow,value)
					--print("row:"..row,"col:"..col,"value:"..tostring(value))
				else
					print(string.format("%s : %d 行 %d列",filePath,row,col))
					error(string.format("%s : row = %d , col = %d列",filePath,row,col))
				end
			end
			if tempRow and #tempRow ~= 0 then table.insert(content,tempRow) end
			row = row + 1
		end
			row = 4

		book:Close()
		excel:Quit()
		excel = nil
	    collectgarbage()

	    return {keys = keys, type_yn = type_yn ,content = content}
	end


	-- 查找 xls 文件
	require "lfs"
	M.findInDir = function( path, wefind, r_table, intofolder )

		 for file in lfs.dir(path) do
        if file ~= "." and file ~= ".." then
            local f = path..'/'..file

            if string.find(f, wefind) ~= nil then

                table.insert(r_table, f)
            end
            local attr = lfs.attributes (f)
            assert (type(attr) == "table")
            if attr.mode == "directory" and intofolder then
                M.findInDir (f, wefind, r_table, intofolder)
            else
               -- for name, value in pairs(attr) do
               --    print (name, value)
               -- end
            end
        end
    end
	end


	-- 存为lua 文件
	M.saveLuaFile = function( path, data )

		path = string.gsub(path,xlsPath,luaPath)
		local b,e = findStrFromBehind(path, "/")
		local dotp = findStrFromBehind(path,".")
		local fileName = "DB_"..string.sub(path,b + 1,dotp - 1)
		path = string.sub(path,1,b)..fileName..".lua"

		local file = io.open(path,'w+')
        if not file then
			local dirPath = string.sub(path,1,b)
        	dirPath = string.gsub(dirPath,"/","\\\\")
        	os.execute("md "..dirPath )
			file = io.open(path,'w+')
        end



		M.setLuaContent( file , data , fileName)
		file:close()
	end

    -- lua 文件内容编写
    M.setLuaContent = function( file , data , fileName)
    	local keys,content,type_yn = data.keys,data.content,data.type_yn
    	local tab = "	"
    	local str = ""
    	-- 注释内容
    	str = str.."-- Filename: "..tostring(fileName)..".lua\n"
     	str = str.."-- Author: auto-created by kyn`s ParseExcel(to lua) tool.".."\n"
	    str = str.."-- methods: X.keys = {}, X.getDataById(id), X.getArrDataByField(fieldName, fieldValue)".."\n"
	    str = str.."-- Function: no description.".."\n\n"

    	-- key
    		str =  str.."local keys = {\n"..tab

    		for k,v in pairs (keys) do
    			str = str.."\""..tostring(v).."\""..","
			end
			str = str.."\n}\n\n"

    	-- data
    		str = str.."local data = {\n"

    		for row,v in pairs(content) do
    			str = str..tab.."id"..row.. " = {"
    			for col,val in pairs(v) do
    				str = str..M.buildString(type_yn[col],val)..","
				end

				str = str.."}\n"
			end

			str = str.."}\n\n"

    	-- return

    	str = str..tostring(fileName).." = DB_Template.new (keys, data)\n"
    	str = str.."return "..tostring(fileName)

		--print(str)
		file:write(str)
    end

    --检测 类型,数据是否存在
    M.checkValue = function( type_yn, value)
    	-- 判断是否存在
    	if type_yn[2] == "yes" then

    		if value == nil or value == "nil" then return false end
		else
			if value == nil or value == "nil" then return true end
		end


    	if type_yn[1] == "string" or type_yn[1] == "String" then

		end

		if type_yn[1] == "number" or type_yn[1] == "Number" then
			local b = string.find(value,"[^0-9]")
			if b and string.sub(value,b,b) ~= "." and string.sub(value,b,b) ~= "-" then
				return false
			end
		end

		if string.find(type_yn[1],"array") and value ~= "nil" then
			local t = split(value,",")
			if #t <= 1 then return false end
		end


		return true
    end

    -- 构造 字符串,用于写于lua脚本
    M.buildString = function ( type_yn, value)

    	local str = ""

		if value == "nil" then
    		str = value
    		return str
    	end

    	if type_yn[1] == "Number" or type_yn[1] == "number" then
			str = value
			return str
		end

    	if type_yn[1] == "string" or type_yn[1] == "String" then
    		str = "\""..value.."\""
    		return str
		end

		if string.find(type_yn[1],"array") then
			local t = split(tostring(value),",")
			local str = "{"
			for k,v in pairs(t) do
				str = str..v
				str = str..(k~=#t and "," or "")
			end
			str = str.."}"
			return str
		end


    end

------------------------------------------------------------------------------------------
	local xlsList = {}
	M.findInDir(xlsPath,"%.xls",xlsList,true)

	local lastClock = os.clock()
	for k,v  in pairs(xlsList) do
		local data = M.parsing_excel(v)
		M.saveLuaFile(v,data)

		local curClock = os.clock()
		print (k,v,curClock - lastClock)
		lastClock = curClock

	end

    print("total time:"..os.clock())

	-- 每个文件大概在 1-2秒之间,根据数据量,数据越多,时间越长
    -- 优化方案:对每个文件内容进行MD5,存起来,下次做对比,内容没有改变的,直接跳过。

以上的代码 文件,大家可以直接 复制下来运行,当然 一些相关的 数据测试文件,和ExcelToLua.lua 文件,我会上传到  这里 ,大家可以下载测试一下。当然,这个东西,更多的是给那些 没有头绪的朋友 一个思路,一个参考,这个东西还不完善,也希望大家多 提提建议,如果中文问题没有解决的话,我可能考虑用 python 来写这个工具了。

本人也是小菜,希望大家照顾一下。




  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值