tp5导出csv

前言:在列表页,根据搜索结果,导出数据;csv相对于excel的优点是数据量大,速度快;有些具体细节不多说了,自己打印调试;

1.在html部分:使用一个简单的a标签,按钮应该也可以,这里可以自己尝试;
 <a href="javascript:;" onclick="export_csv()" dialog-title="导出csv" class="btn btn-primary btn-sm">导出csv</a>
2.在js部分:关于安全问题,目前我还没有相关经验,只能简单的不使用变量名;使用了jquery
 function export_csv() {
		var url = '/admin/some_model/export_csv.html';
		//获取搜索字段值,一般是selcet和input,(自行查询各个标签的获取方法)
		var param1 = $("select[name='area_1']").val();
		var param2 = $("select[name='area_2']").val();
		...
		var param5 = $("select[name='org_id']").val();
		var param6 = $("input[name='num']").val();
		var param7 = $("input[name='start_time']").val();
		var param8 = $("input[name='end_time']").val();
		//思考:有的时候搜索条件很多,不知道会不会超出get方法携带参数的大小
		url += "?param1"+param1+"&param2="+param2+...+"&param8="+param8;
		window.location.href = url;
}
3.控制器,后台处理,我这里用的thinkphp5框架

导出的代码要参考 列表的代码;这样就能保证导出的数据和列表的数据一样


public function export_csv(){
        set_time_limit(0);    //设置运行永不超时
        //下面这个是项目里封装的一些获取方法;
        //普通使用 $area_1 = $this->get('param1')即可;使用request()->param()也行;
 		$area_1 = $this->get('param1', !$this->_supe_admin && getter($this->_userInfo['area_permission'], 'area_1', 0) ? getter($this->_userInfo['area_permission'], 'area_1', 0) : 0);
        $area_2 = $this->get('param2', !$this->_supe_admin && getter($this->_userInfo['area_permission'], 'area_2', 0) ? getter($this->_userInfo['area_permission'], 'area_2', 0) : 0);
        $area_3 = $this->get('param3', !$this->_supe_admin && getter($this->_userInfo['area_permission'], 'area_3', 0) ? getter($this->_userInfo['area_permission'], 'area_3', 0) : 0);
        $area_4 = $this->get('param4', !$this->_supe_admin && getter($this->_userInfo['area_permission'], 'area_4', 0) ? getter($this->_userInfo['area_permission'], 'area_4', 0) : 0);
        $org_id = $this->get('param5', !$this->_supe_admin && getter($this->_userInfo['area_permission'], 'org_id', 0) ? getter($this->_userInfo['area_permission'], 'org_id', 0) : 0);
		
		$where = [];
		//这里加null 和 undefined完全是由于封装的组件的原因,默认会传null或者undefined,你们可以自己打印调试
		if (!empty($org_id) && $org_id != 'null' && $org_id != 'undefined'){
            $where['oabi.org_id'] = $org_id;
        }
        elseif(!empty($area_4) && $area_4 != 'null' && $area_4 != 'undefined'){
            $where['oabi.area_4'] = $area_4;
        }
        elseif(!empty($area_3) && $area_3 != 'null' && $area_3 !='undefined'){
            $where['oabi.area_3'] = $area_3;
        }
        elseif(!empty($area_2) && $area_2 != 'null' && $area_2 != 'undefined'){
            $where['oabi.area_2'] = $area_2;
        }elseif(!empty($area_1) && $area_1 != 'null' && $area_1 != 'undefined'){
            $where['oabi.area_1'] = $area_1;
        }
		//下面是获取查询条件
		 //评估编号
        $num = $this->get('param6','');
        if (!empty($num))   $where['oabi.num'] = ['like','%'.$num.'%'];
        //评估时间
        $start_time=$this->get('param7','');
        $end_time=$this->get('param8','');
        if (!empty($start_time)&&!empty($end_time)){
            $where['oabi.add_time'] = ['between',[strtotime($start_time.' 00:00:00'),strtotime($end_time.' 23:59:59')]];
        }elseif (!empty($start_time)){
            $where['oabi.add_time'] = ['>',strtotime($start_time.' 00:00:00')];
        }elseif (!empty($end_time)){
            $where['oabi.add_time'] = ['<',strtotime($end_time.' 23:59:59')];
        }
        //数据库 查询
         $dataList = $this->someModel->db() ->alias('oabi')
            ->join('__ASSESS_REPORT__ ar','ar.flag = oabi.flag','left')
            ->where($where)
            ->where('oabi.is_final_save',2)
            ->where('ar.flag','<>','')
            ->field('oabi.*,ar.initial_level,ar.final_level')
            ->order('oabi.add_time desc')
            ->fetchSql(true)->select();

		ini_set('default_charset','UTF-8');
        $dbusername=config("database.username");
        $dbpwd=config("database.password");
        $dbhost=config("database.hostname");
        $dbname=config("database.database");
        $dsn="mysql:host=$dbhost;dbname=$dbname";
        $dbh=new\PDO($dsn,$dbusername,$dbpwd);
        $dbh->setAttribute(\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY,false);
        $sth=$dbh->prepare($dataList);

        $sth->execute();
        $limit=100000;  //一次上限100000条记录
        if(ob_get_level()){  //输出缓冲机制的嵌套级别
            ob_end_clean();
        }

		 $filename = 'XXX列表.csv';
        header("Content-Type:text/csv;charset=utf-8");
        header("Content-Disposition:attachment;filename=".$filename);
        header("Pragma:no-cache");
        header("Expires:0");
        $fp=fopen('php://output','w');

		//$head表示csv打开时的标题栏
		 $head=array(
	            '所属区域','姓名','性别','评估编号','评估原因','信息提供者',
	             ...
	             等等,有时候字段会很多
	        );
			
			 foreach($head as $i=>$v){
		            //CSV的Excel支持GBK编码,一定要转换,否则乱码
		            $head[$i]=iconv('utf-8','gb2312',$v);
		        }

		        fputcsv($fp,$head);
		        $num=0;
				
				 foreach($sth as $k => $v) {
						//对一些字段的处理,比如数据表里性别字段存的只有 1和2;这时就把他转化成 男和女
						//除了if else;也可能用到switch
						$sex = '';
			           if (isset($v['sex'])){
			                if ($v['sex']==1){
			                    $sex='男';
			                }elseif ($v['sex']==2){
			                    $sex='女';
			                }else{
			                    $sex='保密';
			           }

						
					//处理完成字段后,输出到csv中
					 $row = [
					 	$v['areaaddress'],$v['name'],$sex,$v['num'],$v['reasons'],$provider_name
					 ];

					if ($num%$limit == 0){
						//清空缓存区
		               flush();
		                $num = 0;
		            }

		            foreach ($row as $key => $val) {
		                if (!empty($val)) {
		                    $val=is_numeric($val) ? $val . "\t" : $val;
		                    $row[$key] = iconv('utf-8', 'gb2312//IGNORE', $val);
		                }
		            }
		            fputcsv($fp, $row);
		            unset($row);
		       }
			
				die;
	}
	
小tips:
  • csv格式的文件,用excel打开数字会强制转换成科学记数法;想身份证号码可以前后端约定加个字母,将其转换成字符串,取用时切割去字母即可
  • 有些偏僻汉字,无法正常显示时,编码问题:gbk的字符数量 大于gb2312,将gb2312替换成gbk
  • Cannot modify header information - headers already sent by;这个报错很有可能是字段转换时,写错字段名,特别是导出字段非常多时,需要逐个排除;建议一边调试一边写代码
  • 目前一次性全部导出过13W的多字段csv,速度还可以
发布了5 篇原创文章 · 获赞 1 · 访问量 126

猜你喜欢

转载自blog.csdn.net/qq_37029718/article/details/103923220
tp5