非常好用的PHPExcel导入导出类 [ 2.0 版本 ]
<?php
namespace common\helpers;
use \PHPExcel;
use \PHPExcel_Reader_Excel2007;
use \PHPExcel_Reader_Excel5;
use \PHPExcel_IOFactory;
class Excel{
/**
* 读取excel表格中的数据
* @author xxx
* @dateTime 2017-06-12T09:39:01+0800
* @param string $filePath excel文件路径
* @param integer $startRow 开始的行数
* @return array
*/
public function getExcelData($filePath, $startRow = 1) {
$PHPExcel = new PHPExcel();
/**默认用excel2007读取excel,若格式不对,则用之前的版本进行读取*/
$PHPReader = new PHPExcel_Reader_Excel2007();
//setReadDataOnly Set read data only 只读单元格的数据,不格式化 e.g. 读时间会变成一个数据等
$PHPReader->setReadDataOnly(TRUE);
if (!$PHPReader->canRead($filePath)) {
$PHPReader = new PHPExcel_Reader_Excel5();
//setReadDataOnly Set read data only 只读单元格的数据,不格式化 e.g. 读时间会变成一个数据等
$PHPReader->setReadDataOnly(TRUE);
if (!$PHPReader->canRead($filePath)) {
echo 'can not read excel';
return;
}
}
$PHPExcel = $PHPReader->load($filePath);
//获取sheet的数量
$sheetCount = $PHPExcel->getSheetCount();
//获取sheet的名称
$sheetNames = $PHPExcel->getSheetNames();
//获取所有的sheet表格数据
$excleDatas = array();
$emptyRowNum = 0;
for ($i = 0; $i < $sheetCount; $i++) {
/**读取excel文件中的第一个工作表*/
$currentSheet = $PHPExcel->getSheet($i);
/**取得最大的列号*/
$allColumn = $currentSheet->getHighestColumn();
/**取得一共有多少行*/
$allRow = $currentSheet->getHighestRow();
$arr = array();
for ($currentRow = $startRow; $currentRow <= $allRow; $currentRow++) {
/**从第A列开始输出*/
for ($currentColumn = 'A'; $currentColumn <= $allColumn; $currentColumn++) {
$val = $currentSheet->getCellByColumnAndRow(ord($currentColumn) - 65, $currentRow)->getValue();
$arr[$currentRow][] = trim($val);
}
$arr[$currentRow] = array_filter($arr[$currentRow]);
//统计连续空行
if(empty($arr[$currentRow]) && $emptyRowNum <= 50) {
$emptyRowNum++ ;
} else {
$emptyRowNum = 0;
}
//防止坑队友的同事在excel里面弄出很多的空行,陷入很漫长的循环中,设置如果连续超过50个空行就退出循环,返回结果
//连续50行数据为空,不再读取后面行的数据,防止读满内存
if($emptyRowNum > 50) {
break;
}
}
$excleDatas[$i] = $arr; //多个sheet的数组的集合
}
//这里我只需要用到第一个sheet的数据,所以只返回了第一个sheet的数据
$returnData = $excleDatas ? array_shift($excleDatas) : [];
//第一行数据就是空的,为了保留其原始数据,第一行数据就不做array_fiter操作;
$returnData = $returnData && isset($returnData[$startRow]) && !empty($returnData[$startRow]) ? array_filter($returnData) : $returnData;
return $returnData;
//return $excleDatas ? array_filter(array_shift($excleDatas)) : [];
}
/**
* 生成excel数据表
* e.g.
* $fields = [
* ['key' => 'province', 'name' => '省', 'required' => false]
* ['key' => 'city', 'name' => '市', 'required' => true]
* ['key' => 'district', 'name' => '区/县', 'required' => true]
* ['key' => 'street', 'name' => '街道', 'required' => true]
* ];
*
* $dataList = [
* ['province' => 'xx省' , 'city'=>'xx市' , 'district' => 'xx县' ,'street' => 'xx街道'],
* ['province' => 'xx省' , 'city'=>'xx市' , 'district' => 'xx县' ,'street' => 'xx街道'],
* ['province' => 'xx省' , 'city'=>'xx市' , 'district' => 'xx县' ,'street' => 'xx街道'],
* ['province' => 'xx省' , 'city'=>'xx市' , 'district' => 'xx县' ,'street' => 'xx街道'],
* ]
*
* @author xxx
* @dateTime 2017-07-18T15:19:04+0800
* @param array $fileds 表头数据
* @param array $dataList 导出数据的数组
* @param string $fileName 生成的文件名
* @return mix
*/
public function createExcelFromData($fileds, $dataList = array(),$fileName = 'data') {
if(!count($fileds || !count($dataList))) {return false;}
$dataList = array_values($dataList);
$fieldConfig = array();
$objPHPExcel = new PHPExcel();
$objPHPExcel->setActiveSheetIndex(0);
$i = 0;
foreach ($fileds as $key => $value) {
$cloumStr = chr(ord("A") + $key);
$column = $cloumStr . "1";
//必填字段列表标红
$required = isset($value['required']) ? $value['required'] : false;
if ($required == true) {
//把必填字段标红
$objPHPExcel->getActiveSheet()->getStyle($column)->getFont()->getColor()->setARGB('FF0000');
}
$objPHPExcel->getActiveSheet()->setCellValue($column, $value['name']);
$i++;
}
$filedKeys = array_column($fileds, 'key');
$list = [];
ob_start();
foreach ($dataList as $key => $value) {
if ($key % 5000 == 0) {
ob_flush();
flush();
}
$num = $key + 2;
for ($j = 0; $j < $i; $j++) {
$cloumStr = chr(ord("A") + $j);
$column = $cloumStr . $num;
if(isset($value[$filedKeys[$j]])) {
$objPHPExcel->getActiveSheet()->setCellValue($column, $value[$filedKeys[$j]]);
} else {
$objPHPExcel->getActiveSheet()->setCellValue($column, '');
}
}
}
//设置必填字段字体颜色
$objPHPExcel->getActiveSheet()->setTitle('Simple');
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
if(php_sapi_name() != 'cli'){
$fileName = basename($fileName);
$fileName = iconv("utf-8", "gb2312", $fileName);
header('Content-Type: application/vnd.ms-excel');
header('Content-Disposition: attachment;filename='.$fileName);
header('Cache-Control: max-age=0');
$objWriter->save('php://output'); //文件通过浏览器下载
}else{
$dirname = dirname($fileName);
if ($dirname != '.') {
//文件路径如果不存在则递归创健
CommonFun::recursionMkDir($dirname);
}
$objWriter->save($fileName); //脚本方式运行,保存在指定目录
if(!file_exists($fileName)) {
return false;
}
return true;
}
}
}
bzzear
注册时间:2017-04-20
最后登录:2021-04-18
在线时长:42小时17分
最后登录:2021-04-18
在线时长:42小时17分
- 粉丝8
- 金钱3110
- 威望80
- 积分4330
热门源码
- 基于 Yii 2 + Bootstrap 3 搭建一套后台管理系统 CMF
- 整合完 yii2-rbac+yii2-admin+adminlte 等库的基础开发后台源码
- 适合初学者学习的一款通用的管理后台
- yii-goaop - 将 goaop 集成到 Yii,在 Yii 中优雅的面向切面编程
- yii-log-target - 监控系统异常且多渠道发送异常信息通知
- 店滴云1.3.0
- 面向对象的一小步:添加 ActiveRecord 的 Scope 功能
- Yii2 开源商城 FecShop
- 基于 Yii2 开发的多店铺商城系统,免费开源 + 适合二开
- leadshop - 基于 Yii2 开发的一款免费开源且支持商业使用的商城管理系统
共 5 条评论
弱弱的请教一下大神:$filePath,该怎么写?也就是在Yii2.0中,需要读取的excel文件的路径的具体写法。我想把excel放到根目录下的web目录下,可总是读取不到,提示文件不存在。
web下面直接读取就好了
如果在根目录下就用 dirname(Yii::$app->basePath) 拼接下你的路径
补充1:
在使用的过程中遇到了问题,①ord函数只能转义字符串首个字母的ASCII值,当excel表格的列超过Z列的时候(AA,AB,AC,...)的时候会出bug,
这个时候只能获取到第一列数据的二维数组;②读取单元格内内容为数字为0的数据被array_filter过滤了;③增加第三个参数,读取某个sheet的数据, 不需要读取所以sheet的数据。读取excel数据的方法作出如下修改:
public function getExcelData($filePath, $startRow = 1,$sheetIndex = 0) { $PHPExcel = new PHPExcel(); /**默认用excel2007读取excel,若格式不对,则用之前的版本进行读取*/ $PHPReader = new PHPExcel_Reader_Excel2007(); //setReadDataOnly Set read data only 只读单元格的数据,不格式化 e.g. 读时间会变成一个数据等 $PHPReader->setReadDataOnly(TRUE); if (!$PHPReader->canRead($filePath)) { $PHPReader = new PHPExcel_Reader_Excel5(); //setReadDataOnly Set read data only 只读单元格的数据,不格式化 e.g. 读时间会变成一个数据等 $PHPReader->setReadDataOnly(TRUE); if (!$PHPReader->canRead($filePath)) { echo 'can not read excel'; return; } } $PHPExcel = $PHPReader->load($filePath); //获取sheet的数量 $sheetCount = $PHPExcel->getSheetCount(); //获取sheet的名称 $sheetNames = $PHPExcel->getSheetNames(); //获取所有的sheet表格数据 $emptyRowNum = 0; $i = $sheetIndex ; //超过范围 if($i > ($sheetCount-1)) { echo 'count error'; return; } /**默认读取excel文件中的第一个工作表*/ $currentSheet = $PHPExcel->getSheet($i); /**取得最大的列号*/ $allColumn = $currentSheet->getHighestColumn(); $allColumnIndex = PHPExcel_Cell::columnIndexFromString($allColumn); /**取得一共有多少行*/ $allRow = $currentSheet->getHighestRow(); $arr = array(); for ($currentRow = $startRow; $currentRow <= $allRow; $currentRow++) { /**从第A列开始输出*/ $ifhasZero = false; for ($currentColumn = 0; $currentColumn <= $allColumnIndex; $currentColumn++) { $val = $currentSheet->getCellByColumnAndRow($currentColumn, $currentRow)->getValue(); if($val == '0') $ifhasZero = true; $arr[$currentRow][] = trim($val); } if ($ifhasZero == true) { foreach ($arr[$currentRow] as $key => $value) { if($value === '') { unset($arr[$currentRow][$key]); } } } $arr[$currentRow] = $ifhasZero ? $arr[$currentRow] : array_filter($arr[$currentRow]); //统计连续空行 if(empty($arr[$currentRow]) && $emptyRowNum <= 50) { $emptyRowNum++ ; } else { $emptyRowNum = 0; } //防止坑队友的同事在excel里面弄出很多的空行,陷入很漫长的循环中,设置如果连续超过50个空行就退出循环,返回结果 //连续50行数据为空,不再读取后面行的数据,防止读满内存 if($emptyRowNum > 50) { break; } } //只返回了第一个sheet的数据 $returnData = $arr; //第一行数据就是空的,为了保留其原始数据,第一行数据就不做array_fiter操作; $returnData = $returnData && isset($returnData[$startRow]) && !empty($returnData[$startRow]) ? array_filter($returnData) : $returnData; return $returnData; }
导出大批量的数据呢?
导出大批量数据看这个:https://www.yiichina.com/code/1863
添加单元格数据验证的方法
/** * e.g. * addCellDataValidation($objPHPExcel->getActiveSheet(),'M4:M1000','"选择题,组合题,判断题,填空题,连线题,排序题,应用题"'); * * 设置单元格公式(现在只用到数据验证) * @author **** * @dateTime 2018-09-27T14:06:27+0800 * @param PHPExcel_Worksheet $workSheet 工作表 * @param string $rangeCell e.g. B3 A1:A9 A1:C9 * @param string $formula 公式 * @param string $errorTitle 错误提示标题 * @param string $errorMsg 错误提示信息 * @param string $prompTitle 标题 */ public static function addCellDataValidation( PHPExcel_Worksheet $workSheet, $rangeCell, $formula, $errorTitle = '输入的值有误', $errorMsg = '您输入的值不在下拉框列表内', $prompTitle = '') { $cells = PHPExcel_Cell::extractAllCellReferencesInRange($rangeCell); if ($cells) { foreach ($cells as $key => $value) { $objValidation = $workSheet->getCell($value)->getDataValidation(); $objValidation->setType(PHPExcel_Cell_DataValidation::TYPE_LIST) ->setErrorStyle(PHPExcel_Cell_DataValidation::STYLE_INFORMATION) ->setAllowBlank(false) ->setShowInputMessage(true) ->setShowErrorMessage(true) ->setShowDropDown(true) ->setErrorTitle($errorTitle) //->setError($errorMsg) ->setPromptTitle($prompTitle) ->setFormula1($formula); } } } Excel::addCellDataValidation($objPHPExcel->getSheet(0),'G2:G1000','"故事类,非故事类"'); Excel::addCellDataValidation($objPHPExcel->getSheet(0),'G2:G1000','sheet1!$A$2:$A$10');