昨天和两个做开发的朋友聊天,对于我还在使用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格式的数据 ?>
这个程序虽然简单,但是应用的地方还是挺多的,有必要后面再对这个程序进行完善。
以上就是基于PHP制作通用的Excel导入程序的详细内容,更多关于PHP Excel导入的资料请关注其它相关文章!
暂无评论内容