关于前台使用ajax后台使用PhpSpreadsheet从数据库导出excel

作者:二三   2019-03-30 22:41:05   1259
因为本人毕业设计中需要用到excel表的导入导出,后台使用的ThinkPHP5框架,所以使用PhpSpreadsheet来完成该功能,此处记录导出功能遇到的问题。
先画个重点:PhpSpreadsheet中$writer -> save('php://output');虽然可以不保存直接下载excel文件,但如果我们是使用ajax和后台交互的话,excel文件是不会下载的。

这种时候,我想到的解决方式有三种:

1.不使用ajax。因为我之前的项目必须使用ajax,所以这种方式我就不介绍了,不使用ajax的话百度有大把方案可行;

2.$writer -> save('php://output')改为$writer -> save('filename.xlsx'),即不下载保存在服务器中,然后我们把文件路径返回,在ajax的成功回调函数中拉起下载。这个方法是我一开始的思路,但是想到下载之后还有清除服务器上的文件,好像搞得麻烦很多,所以我也没采用此方案;

3.在一番面向百度编程后,我发现了一个好东西——jquery.fileDownload.js,该js可以让我们使用ajax也能调起excel文件下载,刚好解决了我们的问题。


步骤:

1.页面中导入该js:



2.后台的excel导出功能的封装函数:

<?php
/*
*excel导入导出操作封装类
*/

namespace app\admin\controller;


//使用Spreadsheet类
use PhpOffice\PhpSpreadsheet\Spreadsheet;
//xlsx格式类
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
//可以生成多种格式类
use PhpOffice\PhpSpreadsheet\IOFactory;



class Office
{

/**
* 导出excel表
* $data:要导出excel表的数据,接受一个二维数组
* $name:excel表的表名
* $head:excel表的表头,接受一个一维数组
* $key:$data中对应表头的键的数组,接受一个一维数组
* 备注:此函数缺点是,表头(对应列数)不能超过26;
*循环不够灵活,一个单元格中不方便存放两个数据库字段的值
*/
public function outdata($name='默认表名', $data=[], $head=[], $keys=[])
{
$count = count($head); //计算表头数量

$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();

for ($i = 65; $i < $count + 65; $i++) { //数字转字母从65开始,循环设置表头:
$sheet->setCellValue(strtoupper(chr($i)) . '1', $head[$i - 65]);
}

/*--------------开始从数据库提取信息插入Excel表中------------------*/
foreach ($data as $key => $item) { //循环设置单元格:
//$key+2,因为第一行是表头,所以写到表格时 从第二行开始写
for ($i = 65; $i < $count + 65; $i++) { //数字转字母从65开始:
$sheet->setCellValue(strtoupper(chr($i)) . ($key + 2), $item[$keys[$i - 65]]);
$spreadsheet->getActiveSheet()->getColumnDimension(strtoupper(chr($i)))->setWidth(20); //固定列宽
}

}
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');//告诉浏览器输出07Excel文件
header('Content-Disposition: attachment;filename="' . $name . '.xlsx"');
header('Cache-Control: max-age=0');//禁止缓存
header('Set-Cookie: fileDownload=true; path=/');
$writer = new Xlsx($spreadsheet);
$writer -> save('php://output');

//释放内存,防止内存泄露:
$spreadsheet->disconnectWorksheets();
unset($spreadsheet);
exit;
}
}


3.使用jquery.fileDownload.js传输数据下载excel:

function excelOutputStuList(res) {
    //res为我需要导出到excel表中的数据,因为我是先读取数据在页面上展示,展示页面有导出excel按钮,此变量为该按钮传来的页面上展示的所有数据。
    var index = layer.confirm('确定导出课程学生列表?', {
btn: ['确定','取消']
}, function(){
$.fileDownload('/admin.php/course/outputStuList', {
httpMethod: 'POST', /*我在调试时报错发现后台接收到的数据是[object object],[object object]形式的,无法解析; *所有在这里我用JSON.stringify(res)把传去后台的数据转换为json字符串,后台再使用json_decode($data,TRUE)转换为数组。
*/ data: 'data=' + JSON.stringify(res),
successCallback: function() {
layer.close(index);
},
failCallback: function() {
layer.msg('加载中..');
}
});
});
}


4.course控制器中的outputStuList()方法:

//excel导出课程学生列表
public function outputStuList(){
$data = request()->param('data');//json字符串 /*将json字符串转换为数组需要加第二个参数'TRUE',因为默认json_decode()函数第二个参数为FALSE,会将json字符串转换为对象*/ $res = json_decode($data,TRUE);
$excel = new Office();
//设置表头:
$head = ['学号','英文名','中文姓名','班级','国籍'];
//数据中对应的字段,用于读取相应数据:
$keys = ['stu_id', 'en_name', 'cn_name', 'class', 'nationality']; //调用封装的excel导出方法outdata($name='默认表名', $data=[], $head=[], $keys=[]);

$excel->outdata($data[0]['course_name'].'学生列表', $res, $head, $keys);
}
注:json_encode() 对变量进行JSON编码;json_decode() 对JSON数据进行解码,转换为PHP变量。


至此,excel成功导出!



热门文章 关于前台使用ajax后台使用PhpSpreadsheet从数据库导出excel 对于Laravel Blade模板转义html标签的记录 PHP-文件上传 去除隐藏字符—— PHP-验证码制作
评论成功!
评论内容不能为空

tips:仅支持jpg,jpeg,png格式图片。