当前位置: 首页 > 后端技术 > PHP

PHP如何更新Excel30W+数据导入数据表

时间:2023-03-30 04:48:15 PHP

最近产品有一个需求,要求:在后台管理系统导入10~50w左右的数据到系统中,通过excel上传,这样可以是非实时的。模板就是下面的图片作为一个程序各位,脑子里第一反应应该会出现下面的关键字PHPExcel异步,消息队列mysql更新很好,其实主要解决的确实是围绕这些问题,其实还有实际问题的解决方案很多,比如Canyouguide,loaddata,通过csv,naviecat写一个sql文件,然后用mysql源执行等等,那么我们应该按照What-Why-How来对应选型方案,但是在实际场景中,我们应该把要求说得更具体一些,比如导入的excel中是否有错误的数据?(是否过滤每一行),数据是否会重复,单元格是否可以为空(判断跳过)非实时是允许的,但是多久导入一次?(我这里一个月导入1、2次)导入完成后如何通知用户?(后台站内信)解决方案一PHPExcel+MysqlUpdate,简单粗暴的解决方案,读一行(excel)写一行(update),但是必须在后台常驻内存中执行,否则会超时,严重影响生意。这里我使用thinkphp5+定时任务执行的命令行,innodb是行锁,注意更新内容的范围解决方案2PHP高性能Excel扩展VtifulKernelExcel+Mysql更新(casewhen),使用游标方式来逐行读取excel单元格,但是,我在这里循环遍历excel,然后更新大约1000个条目。拼接后的sql语句类似如下:UPDATE`mytable`SET`name`=CASEWHEN`title`='我的标题'THEN'我的名字2'WHEN`title`='另一个标题'THEN'另一个名字2'ELSE`name`END,`date`=CASEWHEN`title`='Mytitle'THEN'Mydate2'WHEN`title`='Anothertitle'THEN'Anotherdate2'ELSE`date`ENDWHERE`title`IN('我的标题','另一个标题')直接输入业务代码//先用phpexcel获取总行数,Vtiful没找到这个函数$objReader=\PHPExcel_IOFactory::createReader('Excel2007');$objReader->setReadDataOnly(true);try{//加载文件$objPHPExcel=$objReader->load('tutorial.xlsx');}catch(\Exception$e){thrownew\Exception("加载文件失败");}//获取表格中的第一个工作表$currentSheet=$objPHPExcel->getSheet(0);//获取总行数$allRow=(int)$currentSheet->getHighestRow();$excel=new\Vtiful\Kernel\Excel($config);$data=$excel->openFile('tutorial.xlsx')->openSheet();$data->nextRow();//手动跳过第一行//每次更新计算$commit_every=1000;$commit_k=ceil($allRow/$commit_every);$arr_commit=[];对于($i=1;$i<=$commit_k;$i++){$arr_commit[]=$i*$commit_every;}if(end($arr_commit)<$allRow){$arr_commit[]=$allRow-1;//因为第一项被跳过了}//while($rowData=$excel->nextRow()){//todonon-number设置为0//todoscorethreealso//todo导入的数量对行进行评分if(!is_numeric($rowData[0])){continue;}如果(!is_numeric($rowData[1])){$rowData[1]=0;}如果(!is_numeric($rowData[2])){$rowData[2]=0;}if(!is_numeric($rowData[3])){$rowData[3]=0;}$upd[]=['id'=>$rowData[0],//主键'a'=>(int)$rowData[1],'b'=>(int)$rowData[2],'c'=>(int)$rowData[3],];如果(in_array($line,$arr_commit)){$this->updateBatch('table',$upd);取消设置($upd);}}公共赋nctionupdateBatch($tableName="",$multipleData=array()){if($tableName&&!empty($multipleData)){//要更新的列或字段$updateColumn=array_keys($multipleData[0]);$referenceColumn=$updateColumn[0];//例如idunset($updateColumn[0]);$whereIn="";$q=“更新”。$表名。“放”;foreach($updateColumnas$uColumn){$q.=$uColumn.“=案例”;foreach($multipleDataas$data){$q.="WHEN".$referenceColumn。“=”。$数据[$referenceColumn]。“然后'”。$数据[$u列]。“'”;$q.="其他".$u列。“结尾,”;}foreach($multipleDataas$data){$whereIn.="'".$数据[$referenceColumn]。"',";}$q=rtrim($q,",")。“在哪里”。$referenceColumn。"IN(".rtrim($whereIn,',')。")";//更新返回Db::execute(Db::raw($q));}else{返回错误;}}到这里基本就结束了,文中引用的mysqlupdate和xlxsextensions(如果项目不允许或者麻烦的就不适用)https://stackoverflow.com/que...https://github.com/viest/php-...