昨天和两个做开发的朋友聊天,对于我还在使用layui感到奇怪,我也没有多解释,毕竟layui对于做一些中小型的开发还是不错的,前端的框架中,熟悉了一个其他的也差之不多。但layui的资料不细致是个很大的缺憾。
用户提出有一个excel表的记录要导入,这个是基本要求,肯定要满足。
2006年,我用powerbuilder写过一个通用的导入程序,程序上也不难。
用前端框架来完成会有一点麻烦,主要在于
1、数据回显
如果是让用户选择一个excel文件然后就直接入库,那程序就太简单了,问题是要先让用户看到结果,可能的话还可以修改,然后再保存到数据库中。
2、数据保存
因为以前c/s开发使用的是强连接,操作数据后直接提交即可;但现在前端和后端是弱连接,一次交互就需要配置相应参数才可能保存数据,动态的表格保存就有一点小麻烦。
作为一般性的要求,这个程序肯定是要应对数据库中的所有表。
那么只能先将数据表的字段设置传到php中,然后php提取excel记录,按照layui对表记录的要求封装数据,传回到前端。
具体做法:
1、在数据库中创建表,记录要导入的表信息;
2、在前端列出表,让用户选择要导入的表;
3、根据选择的表,确定字段参数即对应的excel列;
4、将前端选择传入到php中,提取excel记录,传回前端;
5、用户确定要保存数据,点击保存,数据入库。
一天完成,功能全部正常,后面需要加入一些错误检测,还有文件名应该使用用户名加随机数来存储,这样可以防止多用户冲突,读取完删除。
这个程序主要涉及的就是动态对象、动态属性的创建与赋值。
完成的界面:
程序前端代码:
<!doctype html> <html> <head> <meta charset="utf-8"> <title>〖通用excel数据表导入〗</title> <meta name="renderer" content="webkit"> <meta http-equiv="x-ua-compatible" content="ie=edge,chrome=1"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <link rel="stylesheet" href="../lib/layui-v2.6.3/css/layui.css" rel="external nofollow" media="all"> <link rel="stylesheet" href="../css/public.css" rel="external nofollow" media="all"> <script src="../lib/layui-v2.6.3/layui.js" charset="utf-8"></script> <style> body { background-color: #ffffff; } </style> </head> <body> <div class="layui-form layuimini-form"> <form class="layui-form login-bottom" lay-fiter="ztbuseredit"> <div class="layui-tab"> <ul class="layui-tab-title"> <li class="layui-this">导入设置</li> <li>导入的数据表记录</li> </ul> <div class="layui-tab-content"> <div class="layui-tab-item layui-show"> <div style="width: 1000px;"> <div class="layuimini-container"> <div class="layuimini-main"> <div class="layui-form layuimini-form" style="white-space:nowrap!important;"> <div class="layui-form-item"> <label class="layui-form-label">选择要导入的表</label> <div class="layui-input-block"> <select id="tablelist" lay-filter="tablelistfilter"> <option value=""></option> </select> </div> </div> <div class="layui-form-item"> <label class="layui-form-label">excel文件</label> <div class="layui-input-inline" style="width: 400px;"> <input type="text" name="dc05" id="dc05" value="" style="width: 400px;" class="layui-input" disabled="disabled"> </div> <div class="layui-input-inline"> <button type="button" class="layui-btn layui-btn-sm layui-btn-normal" style="width: 100px;height: 39px;" id="selectexcel">选择excel文件</button> <input type='file' id='readfile' style="opacity: 0;border: 0px solid #1e9fff;"> </div> </div> <div class="layui-form-item" style="padding-left: 41px;"> <div class="layui-input-inline"> <label class="layui-form-label">工作簿序号</label> <input type="number" id="excelsetsheet" value="1" class="layui-input" style="width: 50px;"> </div> <div class="layui-input-inline"> <label class="layui-form-label">起始行号</label> <input type="number" id="excelsetstartrow" value="4" class="layui-input" style="width: 50px;"> </div> <div class="layui-input-inline"> <label class="layui-form-label">结束行号</label> <input type="number" id="excelsetendrow" value="33" class="layui-input" style="width: 50px;"> </div> <button class="layui-btn layui-btn-normal" lay-submit lay-filter="getdata" style="width: 100px;height: 39px;">提取数据</button> </div> </div> <table class="layui-hide" id="currenttableidset" lay-filter="currenttablefilterset"></table> </div> </div> </div> </div> <div class="layui-tab-item"> <button class="layui-btn layui-btn-normal" lay-submit lay-filter="savebtn">保存数据</button> <table class="layui-hide" id="currenttableidtwo" lay-filter="currenttablefiltertwo"></table> </div> </div> </div> </form> </div> <script> let tablenamelist; let selecttablename; let tabletotalcount; let submitdata=[];//准备一个空数组 let fieldset=[];//字段设置 let dbrows={};//excel记录的行对象 let colset=[]; let colsetchild=[]; let dbdatarecordcount; layui.use(['layer','form','table'], function () { var form = layui.form; var layer = layui.layer; var $ = layui.$; var table = layui.table; document.getelementbyid('selectexcel').addeventlistener('click',function(){ $("#readfile").trigger("click"); }); document.getelementbyid('readfile').addeventlistener('change',function(){ if(this.files.length===0){ layer.msg('没有选择文件!',{time:3000,icon:5}); return; } if(this.files[0].name.split('.')[1]!='xls'){ layer.msg('请选择excel文件!',{time:3000,icon:5}); return; } let reader=new filereader(); reader.onload=function (){ console.log(reader.result); } document.getelementbyid('dc05').value=this.files[0].name; }) //得到数据表的名称列表 $.ajax({ url:'ztbexceldatain.php', data:{"op":"gettablelist"}, type:'post', async:false, success:function (data) { tablenamelist = data['data']; //在数组中找到对应的编码 for(var i=0;i<tablenamelist.length;i++){ $('#tablelist').append(new option(tablenamelist[i].c02, tablenamelist[i].c02)); } },error:function(data){ console.log(data); } }); form.render(); form.on('submit(getdata)', function (data) { data = data.field; let tempdata=new object();//准备一个空对象 tempdata.excelsheet=document.getelementbyid("excelsetsheet").value; tempdata.excelsetstartrow=document.getelementbyid("excelsetstartrow").value; tempdata.excelsetendrow=document.getelementbyid("excelsetendrow").value; let adddata=new object(); adddata.excelset=tempdata; submitdata.push(adddata); for(let i=0;i<=tabletotalcount-1;i++){ tempdata=new object(); tempdata.c02=$("#currenttableidset").next().find("tbody tr[data-index='" +i +"'] td[data-field='c02'] div").html();//字段英文名 tempdata.c03=$("#currenttableidset").next().find("tbody tr[data-index='" +i +"'] td[data-field='c03'] div").html();//字段汉字名称 tempdata.c09=$("#currenttableidset").next().find("tbody tr[data-index='" +i +"'] td[data-field='c09'] div").html();//字段对应的excel列 fieldset.push(tempdata); dbrows[tempdata.c02]=''; colsetchild={}; colsetchild['field']=tempdata.c02; colsetchild['title']=tempdata.c03; colsetchild['width']=100; colset.push(colsetchild); } submitdata.push(fieldset); //准备提取数据 let excelfile = document.getelementbyid('readfile'); //用formdata对象对表单数据进行封装 const fd = new formdata();//formdata构造器接收的是一个form的dom对象 fd.append("excelfile",excelfile.files[0]);//excel文件数据 fd.append("excelset",json.stringify(submitdata));//设置 fd.append("dbrows",json.stringify(dbrows));//行对象 fd.append("op",'getset'); $.ajax({ url: 'ztbexceldatain.php', type: "post", data: fd, datatype: "json", async: true, processdata: false,//设置为false,jquery则不对数据进行序列化 contenttype: false,//设置为false,jquery则不设content-type请求头 beforesend: function(xhr){}, complete: function(xhr,status){}, error: function(xhr,status,error){}, success: function(result){ //刷新数据记录表 table.render({ elem: '#currenttableidtwo', data:result['data'], cols: [colset], done: function (res, curr, count) { dbdatarecordcount=res.data.length; } }); } }); return false; }) //监听下拉列表的点击事件 form.on('select(tablelistfilter)', function(data){ let selectitemname = data.value; //选择的单位名称 //选择的具体表 selecttablename=tablenamelist.find(element=>element.c02==selectitemname ).c01; //提取具体的设置信息 table.render({ elem: '#currenttableidset', url: 'ztbexceldatain.php', method:'post', where:{ "op":"getsetlist", "selecttable":selecttablename}, cols: [[ {field: 'c01', width: 80, title: '表的名字', hide: true}, {field: 'c02', width: 120, title: '字段英文名称'}, {field: 'c03', width: 150, title: '字段汉字名称'}, {field: 'c09', width: 120, title: '对应的excel列号',edit: 'number'}, {field: 'c04', width: 100, title: '数据类型'}, {field: 'c05', width: 100, title: '长度'}, {field: 'c06', width: 120, title: '能否为空'} ]], done: function (res, curr, count) { tabletotalcount=res.data.length; } }); }); form.on('submit(savebtn)', function (data) { for(let k=0;k<dbdatarecordcount;k++){ let insertsql=''; let assignsql=''; for(let i=0;i<tabletotalcount;i++){ let tempfieldname=''; let tempfieddata; let tempfieldtype=''; tempfieldname=$("#currenttableidset").next().find("tbody tr[data-index='" +i +"'] td[data-field='c02'] div").html(); tempfieldtype=$("#currenttableidset").next().find("tbody tr[data-index='" +i +"'] td[data-field='c04'] div").html(); if(insertsql==''){ insertsql=tempfieldname; }else{ insertsql=insertsql +"," +tempfieldname; } tempfieddata=$("#currenttableidtwo").next().find("tbody tr[data-index='" + k +"'] td[data-field='"+tempfieldname+"'] div").html() if(tempfieddata=='undefined' || tempfieddata==null){ if(tempfieldtype=='integer' || tempfieldtype=='decimal'){ tempfieddata=0; }else{ tempfieddata=''; } } if(assignsql==''){ if(tempfieldtype=='integer' || tempfieldtype=='decimal'){ assignsql=tempfieddata; }else{ assignsql="'"+tempfieddata+"'"; } }else{ if(tempfieldtype=='integer' || tempfieldtype=='decimal'){ assignsql=assignsql+","+tempfieddata; }else{ assignsql=assignsql+",'"+tempfieddata+"'"; } } } //提交数据 $.ajax({ url:'ztbexceldatain.php', data:{ "op":"savedata", "insertsql":insertsql, "assignsql":assignsql, "tablename":selecttablename }, type:'post', async:false, success:function (data) { },error:function(data){} }); } return false; }); }); </script> </body> </html>
后端php代码:
<?php require_once 'reader.php';//加载reader require 'ztblinkconfig.php'; $ztbconn->setattribute(pdo::attr_errmode, pdo::errmode_exception); $strfalse=""; $continue=true; $srcaddr="http://xx.xx.xx.xx"; $returnarr=[];//准备返回的数组 if (array_key_exists('http_origin',$_server)) { $origin = $_server['http_origin']; }else if (array_key_exists('http_referer',$_server)) { $origin = $_server['http_referer']; }else { $origin = $_server['remote_addr']; } if(substr($origin,0,15)!=substr($srcaddr,0,15)){ $continue=false; $strfalse="拒绝访问".substr($origin,0,15)."!"; } if(!$_session[xxxyyyy']){ $continue=false; $strfalse="请登录!"; } if($continue){ $op=!empty($_post['op']) ? $_post['op'] : '';//得到操作类型 switch($op){ case 'gettablelist'://数据表列表 $sql="select c01,c02 from dawntable"; $result=$ztbconn->query($sql); $rows=$result->fetchall(pdo::fetch_assoc); $returnarr['data']=$rows; break; case 'getsetlist'://具体表的字段设置项目 $selecttable=$_post['selecttable']; $sql1 = "select count(*) from dawnfield where c01='$selecttable'"; $res = $ztbconn->query($sql1); $rows = $res->fetch(); $rowcount = $rows[0]; $returnarr['code']=0; $returnarr['msg']=""; $returnarr['count']=$rowcount; $sql="select c01,c02,c03,c04,c05,c06,c07,c08,c09 from dawnfield where c01='$selecttable'"; $result=$ztbconn->query($sql); $rows=$result->fetchall(pdo::fetch_assoc); $returnarr['data']=$rows; break; case 'getset': $uploadfile = $_files["excelfile"];//得到上传的文件 $excelblob=file_get_contents($uploadfile['tmp_name']); file_put_contents("./tempfile/123.xls",$excelblob, file_append);//将文件内容写到磁盘上 $exceldata = new spreadsheet_excel_reader();//创建 reader $exceldata->setoutputencoding('utf-8');//设置文本输出编码 $exceldata->read("./tempfile/123.xls");//读取excel文件 //准备提取数据 $excelset=json_decode($_post['excelset'],true);//gettype($excelset[0]) $dbrows =json_decode($_post['dbrows'],true); $excelsetstartrow=$excelset[0]['excelset']['excelsetstartrow'];//起始行 $excelsetendrow =$excelset[0]['excelset']['excelsetendrow'];//结束行 $excelsheet=$excelset[0]['excelset']['excelsheet']-1;//工作簿序号 $returnarr['code']=0; $returnarr['msg']=""; $returnarr['count']=$excelsetendrow - $excelsetstartrow +1; $data=[]; try{ for ($i = $excelsetstartrow; $i <= $excelsetendrow; $i++) { for($k=0;$k<sizeof($excelset[1]);$k++){ $fieldname=$excelset[1][$k]['c02'];//字段名称 $fieldexcelcol=$excelset[1][$k]['c09'];//字段对应的列 $fieldtype=$excelset[1][$k]['c03'];//字段数据类型 if ( isset( $exceldata->sheets[$excelsheet]['cells'][$i][$fieldexcelcol] )){ $fielddata=$exceldata->sheets[$excelsheet]['cells'][$i][$fieldexcelcol]; }else{ $fielddata=''; } //装入数组 $dbrows[$fieldname]=$fielddata; } array_push($data,$dbrows); } }catch(pdoexception $e){ $returnarr['data']=$e.getmessage(); } $returnarr['data']=$data; break; case 'savedata': $insertsql=$_post['insertsql']; $assignsql=$_post['assignsql']; $tablename=$_post['tablename']; try{ $sql = "insert into $tablename($insertsql) values($assignsql)"; $result =$ztbconn->exec($sql); if ( $result>0 ) { $returnarr['data']='ok'; }else{ $returnarr['data']="数据插入错误!"; } }catch(exception $exception){ $returnarr['data']=$exception->getmessage(); } break; default: $returnarr['data']="不支持的操作!"; break; } }else{ $returnarr=$strfalse; } header('content-type:text/json'); echo json_encode($returnarr,json_unescaped_unicode);//返回json格式的数据 ?>
这个程序虽然简单,但是应用的地方还是挺多的,有必要后面再对这个程序进行完善。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。