工作需要,也因为之前编写的一个导出CSV文件,竟然不支持生僻字(可能是编码问题),算是一个升级版吧。
函数优点:
- 参数简洁明了,基本一看就懂;
- 支持无限列,看了一些别人的代码没看到支持的;
- 满足基本导出需求,花式的还是得自行编写。
函数缺点:
- 不支持合并,样式调整等等;
- IO开销较大,foreach层级较多。其实吧,还是CSV快,但它也就只是快。
函数代码:
<?php
/**
* 导出Excel文件,支持列数无限大(20220111编写,推荐使用)
* @param array $headArr 数据头
* @param array $datas 导出数据
* @param string $fileName 导出的文件名
* @param null|int|string|array $untransNumCols 针对数字字符串(如订单号、身份证号)不转化科学计数设置,字段必须为$datas索引,包括:数字索引、文字索引。多个请设置为数组
*/
function exportExcel($headArr, $datas, $fileName = 'info', $untransNumCols = null)
{
set_time_limit(60);
ini_set('memory_limit', -1);
Yii::import('application.extensions.phpexcel.PHPExcel');
$date = date("YmdHis");
$fileName .= "_{$date}.xls";
$objPHPExcel = new \PHPExcel();
$headArr = array_chunk($headArr, 26);
$headKey = ord("A");
if (!is_null($untransNumCols) && in_array(gettype($untransNumCols), [
'string',
'integer',
])) {
$untransNumCols = [$untransNumCols];
}
$untransNumCols = is_null($untransNumCols) ? [] : $untransNumCols;
foreach ($headArr as $headkeys => $headvals) {
$key = ord("A");
if ($headkeys)
$headChr = chr($headKey);
foreach ($headvals as $v) {
$colum = (isset($headChr) ? $headChr : '') . chr($key);
$objPHPExcel->setActiveSheetIndex(0)->setCellValue($colum . '1', $v);
$key++;
}
if ($headkeys)
$headKey++;
unset($headArr[$headkeys]);
}
unset($key);
$column = 2;
$objActSheet = $objPHPExcel->getActiveSheet();
foreach ($datas as $key => $rows) {
$datasArr = array_chunk($rows, 26, true);
$headSpan = ord("A");
foreach ($datasArr as $datakeys => $datavals) {
$span = ord("A");
if ($datakeys)
$spanChr = chr($headSpan);
foreach ($datavals as $vcolumn => $value) {
$j = (isset($spanChr) ? $spanChr : '') . chr($span);
if (is_numeric($value) && !in_array($vcolumn, $untransNumCols)) {
$valtype = \PHPExcel_Cell_DataType::TYPE_NUMERIC;
} else {
$valtype = \PHPExcel_Cell_DataType::TYPE_STRING;
}
$objActSheet->setCellValueExplicit($j . $column, $value, $valtype);
$span++;
}
if ($datakeys)
$headSpan++;
}
unset($headSpan, $span, $spanChr, $datas[$key]);
$column++;
}
$fileName = iconv("utf-8", "gbk", $fileName);
$objPHPExcel->setActiveSheetIndex(0);
ob_end_clean();
ob_start();
header('Content-Type: application/vnd.ms-excel'); //定义输出的文件类型为excel文件
header("Content-Disposition: attachment;filename=\"$fileName\""); //定义输出的文件名
header('Cache-Control: max-age=0'); //强制每次请求直接发送给源服务器,而不经过本地缓存版本的校验。
$objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
$objWriter->save('php://output'); //文件通过浏览器下载
}
调用示例:
<?php
$headArr = [
'座次',
'星宿名',
'绰号',
'姓名',
'字',
'原职业/出身',
'职位',
];
$datas = [
0 => ['ID' => '1', 'name' => '天魁星', 'name2' => '及时雨', 'name3' => '宋江', 'name4' => '公明', 'org_post' => '济州郓城县押司', 'ls_post' => '总兵都头领'],
1 => ['ID' => '2', 'name' => '天罡星', 'name2' => '玉麒麟', 'name3' => '卢俊义', 'name4' => '-', 'org_post' => '大名府员外', 'ls_post' => '总兵都头领'],
2 => ['ID' => '3', 'name' => '天机星', 'name2' => '智多星', 'name3' => '吴用', 'name4' => '学究', 'org_post' => '门馆教授', 'ls_post' => '掌管机密军师'],
3 => ['ID' => '4', 'name' => '天闲星', 'name2' => '入云龙', 'name3' => '公孙胜', 'name4' => '一清', 'org_post' => '蓟州道士', 'ls_post' => '掌管机密军师'],
4 => ['ID' => '5', 'name' => '天勇星', 'name2' => '大刀', 'name3' => '关胜', 'name4' => '-', 'org_post' => '凌州蒲东县巡检', 'ls_post' => '马军五虎将-左军大将'],
5 => ['ID' => '6', 'name' => '天雄星', 'name2' => '豹子头', 'name3' => '林冲', 'name4' => '-', 'org_post' => '八十万禁军教头', 'ls_post' => '马军五虎将-右军大将'],
6 => ['ID' => '7', 'name' => '天猛星', 'name2' => '霹雳火', 'name3' => '秦明', 'name4' => '-', 'org_post' => '青州指挥司统制', 'ls_post' => '马军五虎将-先锋大将'],
7 => ['ID' => '8', 'name' => '天威星', 'name2' => '双鞭', 'name3' => '呼延灼', 'name4' => '-', 'org_post' => '汝宁州都统制', 'ls_post' => '马军五虎将-合后大将'],
8 => ['ID' => '9', 'name' => '天英星', 'name2' => '小李广', 'name3' => '花荣', 'name4' => '-', 'org_post' => '青州清风寨武知寨', 'ls_post' => '马军八虎骑兼先锋使'],
9 => ['ID' => '10', 'name' => '天贵星', 'name2' => '小旋风', 'name3' => '柴进', 'name4' => '-', 'org_post' => '沧州横海郡地主', 'ls_post' => '掌管钱粮头领'],
];
exportExcel($headArr, $datas, '人员清单');
说明下,$datas可以有key(如直接数据库查询出来的Query),也可以无key(自行组装)。
PHPExcel下载链接:https://pan.baidu.com/s/1Jr6EBtwLr5zb4s7VZ6eQVA 提取码: 4dsg