jxTMS:低成本快速定制的业务系统个人开发平台。
操作Excel
目前,jxTMS对excel的使用有两个场景:
- 数据准备环节的数据导入
- 业务表单的格式化导出
本文首先介绍使用excel文件进行数据导入的处理。
jxTMS部署后的第一件事就是数据准备。这时就出现了一个问题,即jxTMS属于B/S模式,服务器一般又部署在互联网的云上,加之jxTMS自身由于动态定制的特点,所以其页面显示过程较为复杂,所以耗时也较长。这对于其它需要查看、思考、分析、判断的业务操作都没有太大的问题,但对于就是简单的录入大量数据的数据准备环节就有些问题了:效率太低。
不过呢,由于业务管理系统都是针对当前的业务所展开,所以一般都已经存在了业务数据,而这些数据目前大量的都是用excel文件来存储的,或是可以导出为excel文件。
所以经过实践,jxTMS的数据准备工作基本都是通过导入excel文件来进行的【如demo中的导入销售权限和产品分类码】。
上传Excel文件
开发人员首先应定义一个文件上传界面,其中要有一个fileInput控件【下为demo中的导入产品分类码】:
web importStoreClassCode type div;
web importStoreClassCodet1 parent importStoreClassCode type table title="导入分类码",width=900;
with importStoreClassCodet1 row 0 col c0 web n type text text='上传excel:',width=200;
with importStoreClassCodet1 row 0 col c1 web n type fileInput width=700;
with importStoreClassCodet1 row 1 col c0 web n type button width=80,text='导入',motion=cmd,demand=importStoreClassCode,confirm='确认导入产品分类码?之前的产品分类码将被清除!!';
fileInput控件默认支持的就是只能导入xls格式的excel文件,如果需要支持其它格式的文件,可定义其fileExts属性,如以下的定义就是只能导入c和python语言的源文件:
with importStoreClassCodet1 row 0 col c1 web n type fileInput width=700,fileExts='c,py';
如果是不是指定格式的文件,fileInput会拒绝上传并提示错误。此外为避免上传大文件所带来的种种问题,目前fileInput控件限制了最大上传文件的大小为10M字节。
当用户将文件拖到上传框中时,该框会变色,代表已经感知到了用户的拖入操作,这时用户松开鼠标,则该文件即自动上传到服务器上。
打开Excel文件
在上面的例子中,当用户点击【导入】按钮,首先会弹出一个提示框,显示【确认导入产品分类码?之前的产品分类码将被清除!!】请求用户确认,当用户点击【确定】按钮后,即会执行importStoreClassCode事件函数。
用户上传的文件,会被保存到tmp目录中【根据系统配置,tmp目录中的文件在存活一定时间后即会被自动清除以确保服务器硬盘不会因各种临时文件被耗尽】。然后会将该文件的文件名【含相对目录名】放到self.importFilepath中。导入excel中数据的一般性操作示例如下:
#打开上传文件中名为storeClassCode的sheet
with jxExcel(self.importFilepath,'storeClassCode') as e:
#导入使用的是poi,其行是从0开始计数的,所以行号是excel中的行号减一
#head函数即将列名行设为指定的那一行,即此行中的各格文字即可作为后面各行的列名
e.head()
#从行号是1的行开始直到最后一行
rs=e.rows(1)
for r in rs:
#将分类编码作为字符串读取
code=e.getCellStringValue(r,'分类编码'.decode('utf-8'))
if code is None:
continue
#读到分类存储码后的其它业务操作,可直接阅读demo中的相关py文件
注1:excel的格子是有格式定义的,因为分类码是数值格式,excel可能会默认将其作为数值,那么这里读入的可能就不是我们直接在excel中看到的形式 注2:强烈建议在导入任何excel文件前,将整个sheet全选,然后将格子的格式全部设为文本,以避免读到的数据不是我们看到的数据
笔者曾在开发某系统时需要导入用户手机号作为登录名,但因为手机号位数较多,excel会将其转换为浮点数的e格式,这样我们读到的就是1.2345678987e11这样的字符串【但在excel文件中看到还是12345678987】,而用户在web登录时自然输入的12345678987,这就出现了用户不存在的错误。所以强烈建议在导入时取消所有格式设置,统一设为文本格式。在导入后,再根据业务逻辑将数据转换为相应的类型。
注:需要说明的是,数据库中的数据格式是和java相对应的,即jxTMS可自动完成java数据和数据库中数据的转换,而java是强类型语言,但python是动态类型语言,所以一定要用jxTMS提供的转换函数将字符串转换成需要的格式:
#转换为32位整数
Trans.TransToInteger(str)
#转换为64位浮点数
Trans.TransToDouble(str)
#转换为64位整数
Trans.TransToLong(str)
#转换为日期【字符串应形如:yyyy:mm:dd hh:MM:ss、或yyyy:mm:dd hh:MM、或python utc格式yyyy:mm:ddThh:MM:ss.SSSZ】
Trans.TransToDate(str)
#转换为32位浮点数
Trans.TransToFloat(str)
#转换为布尔量
Trans.TransToBoolean(str)
#转换为精确数值
Trans.TransToBigDecimal(str)
而为了避免用户就这些简单的调用大量重复执行反导致bug,所以jxTMS提供了从excel中直接读取相关类型的函数:
getCellStringValue(row,colName)
getCellBooleanValue(row,colName)
getCellDoubleValue(row,colName)
getCellIntegerValue(row,colName)
getCellLongValue(row,colName)
getCellBigDecimalValue(row,colName)
上述函数是用打开的excel文件的对象来读取的,大家可以看到这是逐行读取该行中的某一列。如果用户的excel表是类似用户报价表这样的表格,其开始是如用户名、联系方式这样的零散信息,下面才是报价明细这样重复行的格式,那么该如何读取用户名、联系方式这样的零散信息呢?
jxTMS提供了用excel中格子编号【A1、M15】的方式直接读取这些零散数据的函数:
getCellStringValue(cellName)
getCellBooleanValue(cellName)
getCellDoubleValue(cellName)
getCellLongValue(cellName)
getCellIntegerValue(cellName)
getCellBigDecimalValue(cellName)
最后,请仔细看一下导入代码,可以看到jxTMS打开excel文件时使用的是with方式,即jxTMS已经实现了相关的接口,可以确保使用完毕后自动关闭该excel文件。
目前,jxTMS已经打包为云服务器镜像,开发者开箱即用:
jxTMS-腾讯云市场market.cloud.tencent.comexc