excel转xml
2016-08-17 11:12
399 查看
python把excel文件转成xml文件。
策划用excel配置各种数据,程序在使用前,用python把该excel文件转换成xml文件,再在程序里面加载读取xml文件。
首先定好规则,我们是这样的,一个excel文件只允许第一个表格存放有效配置数字,列名字以c_开头表示此列只有客户端需要,以s_开头表示此列只有客户端需要,以_开头表示为无效配置数据(策划解释说明用),这样定好规则后,就能更清晰的知道哪些需要写入xml文件中,还有,规定每一个表格的第二行为对每一列名字的说明。 也就是说 第二行的数据是不要写入xml文件的。比如如下表格:
其中单元格为空的表示该行数据没有该列的属性,如表格中钻石道具没有颜色这一属性。
我们用python来实现转换,其实用java c c++ 都可以,但是做些小工具嘛,最好是用轻便而简单的语言实现,因为对效率不是那么的高,转换的时候,多花费个几秒钟也是可以接受的。所以就用python来写咯,对了最近node.js很火,也可以用js来写,原理都是一样的。
因为要读取excel文件,那么首先就要导入xlrd模块, 以下是我写的py代码:
具体就是 读取excel的第一个表格,然后遍历每一行,分情况,把要写入文件字段累加,最后写入xml文件,代码很简单,但是里面包括了一些和工程涉及的东西,不过很容易看懂,也不影响。
那么上面的表格经过转换之后,就会得到两个文件,一个是给服务器的,一个是给客户端的。其中服务器xml如下:
客服端xml文件如下:
注意这两个文件内容的区别 和excel之前的区别。
这样就实现了策划按照规定来填写表格,我们程序负责转化就是了。
改进和优化:有个时候,表格行数很多,就会有一个问题,什么问题,相同的字符串太多,因为每一行的属性名字就是每一列的名字,比如上面的表格,如果有1000行,那么这个xml中就会有1000 个 字符串 “itemId”,并且其余的属性也基本那么多,这样一来就会想到,压缩了,其实zip文件压缩的最基本的原理就是重复多次出现的字符串,用一个标识代替。 我们可以首先给每一列的名字,用较短的字符串来表示,比如第一列用c0代替,如上xml可以这么写:
如果表格中行数较少,影响不大,但是表格行数多了,效果就显示出来了,无论是xml文件的大小,还有在内存中解析所占的内存,都是一份不小的优化了。 至于具体怎么实现,这里就不贴代码了,首先写入xml的原理无非新建一个列的索引,把第一列名写到column。 再以后写内容的时候,不写列名,而写列的索引。 至于解析也一样,读到某一行数据 再把属性索引对应到colum 得到真正的属性名字,就ok了。
策划用excel配置各种数据,程序在使用前,用python把该excel文件转换成xml文件,再在程序里面加载读取xml文件。
首先定好规则,我们是这样的,一个excel文件只允许第一个表格存放有效配置数字,列名字以c_开头表示此列只有客户端需要,以s_开头表示此列只有客户端需要,以_开头表示为无效配置数据(策划解释说明用),这样定好规则后,就能更清晰的知道哪些需要写入xml文件中,还有,规定每一个表格的第二行为对每一列名字的说明。 也就是说 第二行的数据是不要写入xml文件的。比如如下表格:
itemId | itemNameId | c_itemColor | s_itemPrice | _comment |
---|---|---|---|---|
物品id | 物品名字id | 物品颜色 | 物品价格 | 补充说明 |
0001 | 10001 | 10 | 钻石道具 | |
0002 | 10002 | red | 50 | 帽子道具 |
0003 | 10003 | red | 50 | 鞋子道具 |
我们用python来实现转换,其实用java c c++ 都可以,但是做些小工具嘛,最好是用轻便而简单的语言实现,因为对效率不是那么的高,转换的时候,多花费个几秒钟也是可以接受的。所以就用python来写咯,对了最近node.js很火,也可以用js来写,原理都是一样的。
因为要读取excel文件,那么首先就要导入xlrd模块, 以下是我写的py代码:
# -*- coding: utf-8 -*- import os import sys import types import xlrd import inspect import shutil from time import localtime, strftime EXL_PATH = '' XML_PATH = '' TEMP_EXL_PATH = './xls' TEMP_XML_PATH = './xml' LOG_PATH = './log' reload(sys) sys.setdefaultencoding('utf8') def getExlList(): exl_list = [] for (dirpath, dirnames, filenames) in os.walk(EXL_PATH): for filename in filenames: if os.path.splitext(filename)[1] == '.xls': exl_list.append(filename) return exl_list def isChinese(stringCode): for ch in stringCode.decode('utf-8'): if u'\u4e00' <= ch <= u'\u9fff': return True return False def makeDir(dirPath): if not os.path.exists(dirPath): os.mkdir(dirPath) def copyDir(sourceDir, destDir): if os.path.exists(destDir): shutil.rmtree(destDir) shutil.copytree(sourceDir,destDir) def copyAllFile(sourceDir, destDir): for(dirpath, dirnames, filenames) in os.walk(sourceDir): for filename in filenames: desFileName = destDir + '/' + filename shutil.copy(sourceDir + '/' + filename,desFileName) class enumColType: clientOnly = 0 #客户端专用 serverOnly = 1 #服务器专用 cleAndSer = 2 #cs都用 comment = 3 #cs都无需用 def getColType(sourceString): if sourceString[0] == '_': return enumColType.comment elif sourceString[0:2] == 'c_': return enumColType.clientOnly elif sourceString[0:2] == 's_': return enumColType.serverOnly else: return enumColType.cleAndSer def writeToXml(exlName): prefixFileName = exlName.split('.')[0] xmlFileName = prefixFileName + '.xml' xmlServerFileFullName = TEMP_XML_PATH + '/server/' + xmlFileName xmlClientFileFullName = TEMP_XML_PATH + '/client/' + xmlFileName fileClient = open(xmlClientFileFullName,'wb') fileClient.write('<?xml version="1.0" encoding="utf-8" ?>\n') fileClient.write('<root>\n') fileServer = open(xmlServerFileFullName,'wb') fileServer.write('<?xml version="1.0" encoding="utf-8" ?>\n') fileServer.write('<root>\n') exlFileFullName = TEMP_EXL_PATH + '/' + exlName exlData = xlrd.open_workbook(exlFileFullName,formatting_info = True,encoding_override="utf-8") table = exlData.sheets()[0] nrows = table.nrows ncols = table.ncols print 'nrows:' + str(nrows) + ' ncols:' + str(ncols) fileLog.write('xlsName:%s, nrows:%s, ncols:%s\n' %(exlName,str(nrows),str(ncols))) firstRows = table.row_values(0) for rownum in range(2,nrows): stringClient = '<element' stringServer = '<element' row = table.row_values(rownum) for colnum in range(ncols): if row[colnum] != '' and firstRows[colnum] != '': #单元格不为空 且列名不为空 if type(row[colnum]) is types.FloatType: row[colnum] = int(row[colnum]) colType = getColType(firstRows[colnum]) if colType == enumColType.cleAndSer: #cs 都用 tempString = ' %s="%s"' %( str(firstRows[colnum]), str(row[colnum]) ) stringClient += tempString stringServer += tempString elif colType == enumColType.clientOnly: #只客户端用 ss = str(firstRows[colnum])[2:] tempString = ' %s="%s"' %( ss, str(row[colnum]) ) stringClient += tempString elif colType == enumColType.serverOnly: #服务器专用 ss = str(firstRows[colnum])[2:] tempString = ' %s="%s"' %( ss, str(row[colnum]) ) stringServer += tempString stringClient += '/>\n' fileClient.write(stringClient) stringServer += '/>\n' fileServer.write(stringServer) fileClient.write('</root>') fileClient.close() fileServer.write('</root>') fileServer.close() fileLog.write('xlsName:%s transform success\n' %(exlName)) if __name__ == "__main__": EXL_PATH = sys.argv[1] XML_PATH = sys.argv[2] print 'EXL_PATH = ' + EXL_PATH print 'XML_PATH = ' + XML_PATH makeDir(LOG_PATH) copyDir(EXL_PATH,TEMP_EXL_PATH) makeDir(TEMP_XML_PATH) makeDir(TEMP_XML_PATH + '/client') makeDir(TEMP_XML_PATH + '/server') fileLog = open(LOG_PATH + '/' + strftime("%Y%m%d%H%M%S", localtime()) + '.txt', "wb") fileLog.write('from %s to %s\n' %(EXL_PATH,XML_PATH)) allExlFiles = getExlList() for(exlFile) in allExlFiles: print 'exchange file : ' + exlFile writeToXml(exlFile) copyAllFile(TEMP_XML_PATH + '/client',XML_PATH) fileLog.close()
具体就是 读取excel的第一个表格,然后遍历每一行,分情况,把要写入文件字段累加,最后写入xml文件,代码很简单,但是里面包括了一些和工程涉及的东西,不过很容易看懂,也不影响。
那么上面的表格经过转换之后,就会得到两个文件,一个是给服务器的,一个是给客户端的。其中服务器xml如下:
<?xml version="1.0" encoding="utf-8" ?> <root> <element itemId="0001" itemNameId="10001" itemPrice="10"/> <element itemId="0002" itemNameId="10002" itemPrice="50"/> <element itemId="0003" itemNameId="10003" itemPrice="50"/> </root>
客服端xml文件如下:
<?xml version="1.0" encoding="utf-8" ?> <root> <element itemId="0001" itemNameId="10001"/> <element itemId="0002" itemNameId="10002" itemColor="red"/> <element itemId="0003" itemNameId="10003" itemColor="red"/> </root>
注意这两个文件内容的区别 和excel之前的区别。
这样就实现了策划按照规定来填写表格,我们程序负责转化就是了。
改进和优化:有个时候,表格行数很多,就会有一个问题,什么问题,相同的字符串太多,因为每一行的属性名字就是每一列的名字,比如上面的表格,如果有1000行,那么这个xml中就会有1000 个 字符串 “itemId”,并且其余的属性也基本那么多,这样一来就会想到,压缩了,其实zip文件压缩的最基本的原理就是重复多次出现的字符串,用一个标识代替。 我们可以首先给每一列的名字,用较短的字符串来表示,比如第一列用c0代替,如上xml可以这么写:
<?xml version="1.0" encoding="utf-8" ?> <root> <column c0="itemId" c1="itemNameId" c2="itemPrice" c3="itemColor"/> <element c0="0001" c1="10001"/> <element c0="0002" c1="10002" c3="red"/> <element c0="0003" c1="10003" c3="red"/> </root>
如果表格中行数较少,影响不大,但是表格行数多了,效果就显示出来了,无论是xml文件的大小,还有在内存中解析所占的内存,都是一份不小的优化了。 至于具体怎么实现,这里就不贴代码了,首先写入xml的原理无非新建一个列的索引,把第一列名写到column。 再以后写内容的时候,不写列名,而写列的索引。 至于解析也一样,读到某一行数据 再把属性索引对应到colum 得到真正的属性名字,就ok了。
相关文章推荐
- 使用Python生成Excel格式的图片
- Excel 曝出 Power Query 安全漏洞,1.2 亿用户易受远程 DDE 攻击
- VBA将excel数据表生成JSON文件
- excel vba 限制工作表的滚动区域代码
- excel vba 高亮显示当前行代码
- C#控制Excel Sheet使其自适应页宽与列宽的方法
- SQL 导入导出Excel数据的语句
- 文本、Excel、Access数据导入SQL Server2000的方法
- C#实现Excel动态生成PivotTable
- C#基于COM方式读取Excel表格的方法
- C#导出数据到Excel文件的方法
- Vbscript生成Excel报表的常用操作总结
- C#开发教程之利用特性自定义数据导出到Excel
- C#实现导入CSV文件到Excel工作簿的方法
- C#基于NPOI生成具有精确列宽行高的Excel文件的方法
- 总提示[Microsoft][ODBC Excel Driver] 数值字段溢出官方解决方法
- C#实现DataSet内数据转化为Excel和Word文件的通用类完整实例
- C#将Sql数据保存到Excel文件中的方法
- VC6.0实现读取Excel数据的方法
- C#定制Excel界面并实现与数据库交互的方法