您的位置:首页 > 编程语言 > PHP开发

tp5导出csv

2020-02-12 16:53 706 查看

前言:在列表页,根据搜索结果,导出数据;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,速度还可以
  • 点赞
  • 收藏
  • 分享
  • 文章举报
X练习生178 发布了5 篇原创文章 · 获赞 1 · 访问量 1784 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: