Thinkphp6 excel导入导出
发布时间:2022-07-26, 09:02:13 分类:PHP | 编辑 off 网址 | 辅助
正文 4132字数 339,120阅读
composer下载phpspreadsheet
composer require phpoffice/phpspreadsheet
Run code
Cut to clipboard
二次封装
<?php
namespace app\index\lib;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use think\exception\ValidateException;
use think\facade\Filesystem;
class Excel
{
// excel导入
public static function importExcel($filename = "")
{
$file[] = $filename;
try {
// 验证文件大小,名称等是否正确
validate(['file' => 'filesize:51200|fileExt:xls,xlsx'])
->check($file);
// 将文件保存到本地
$savename = Filesystem::putFile('topic', $file[0]);
// 截取后缀
$fileExtendName = substr(strrchr($savename, '.'), 1);
// 有Xls和Xlsx格式两种
if ($fileExtendName == 'xlsx') {
$objReader = IOFactory::createReader('Xlsx');
} else {
$objReader = IOFactory::createReader('Xls');
}
// 设置文件为只读
$objReader->setReadDataOnly(TRUE);
// 读取文件,tp6默认上传的文件,在runtime的相应目录下,可根据实际情况自己更改
$objPHPExcel = $objReader->load(public_path() . 'storage/' . $savename);
//excel中的第一张sheet
$sheet = $objPHPExcel->getSheet(0);
// 取得总行数
$highestRow = $sheet->getHighestRow();
// 取得总列数
$highestColumn = $sheet->getHighestColumn();
Coordinate::columnIndexFromString($highestColumn);
$lines = $highestRow - 1;
if ($lines <= 0) {
echo('数据不能为空!');
exit();
}
// 直接取出excle中的数据
$data = $objPHPExcel->getActiveSheet()->toArray();
// 删除第一个元素(表头)
array_shift($data);
// 返回结果
return $data;
} catch (ValidateException $e) {
return $e->getMessage();
}
}
// 导出
public static function export($header = [], $type = true, $data = [], $fileName = "")
{
// 实例化类
$preadsheet = new Spreadsheet();
// 创建sheet
$sheet = $preadsheet->getActiveSheet();
// 循环设置表头数据
foreach ($header as $k => $v) {
$sheet->setCellValue($k, $v);
}
// 生成数据
$sheet->fromArray($data, null, "A2");
// 样式设置
$sheet->getDefaultColumnDimension()->setWidth(12);
// 设置下载与后缀
if ($type) {
header("Content-Type:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
$type = "Xlsx";
$suffix = "xlsx";
} else {
header("Content-Type:application/vnd.ms-excel");
$type = "Xls";
$suffix = "xls";
}
// 激活浏览器窗口
header("Content-Disposition:attachment;filename=$fileName.$suffix");
//缓存控制
header("Cache-Control:max-age=0");
// 调用方法执行下载
$writer = IOFactory::createWriter($preadsheet, $type);
// 数据流
$writer->save("php://output");
}
}
Run code
Cut to clipboard
控制器层调用
excel的导入
public function index(Request $request)
{
// 接收文件上传信息
$files = $request->file("myfile");
// 调用类库,读取excel中的内容
$data = Excel::importExcel($files);
dd($data); // 二维数组
}
Run code
Cut to clipboard
excel的导出
public function get()
{
// 设置表格的表头数据
$header = ["A1" => "编号", "B1" => "姓名", "C1" => "年龄"];
// 假设下面这个数组从数据库查询出的二维数组
$data = [
[1,'李朋',18],
[2,'常师太',19],
[3,'宋一个',22],
[4,'朱贝贝',19],
[5,'胡燕东',29]
];
// 保存文件的类型
$type= true;
// 设置下载文件保存的名称
$fileName = '1909A班违纪信息导出'.time();
// 调用方法导出excel
Excel::export($header,$type,$data,$fileName);
}
Run code
Cut to clipboard
(支付宝)给作者钱财以资鼓励 (微信)→
有过 5 条评论 »
在网上查了很多资料知道解决办法大概有两个:一是在身份证字段前加个英文单引号,二是设置Excel的格式为文本格式。 我试用过第一种确实可以显示,但是有个“'”号在那里感觉确实不是很好,虽然听说不影响,但是需要用户点击那个单元格那个单引号才消失,并且在该格的左上角中显示绿色的三角形。 客户要求我继续改进。 于是考虑第二种办法,发现网上的资料是有一些,但是都是关于Delphi,asp.net,asp等设置格式的方法。 而关于php的也有,但是大多都是用phpExcel导出的方法或者spreadsheet等类或者控件之类的导出方法,而我所在维护的系统却用很简单的方法,如下,网上很少有讲如何设置要导出数据的EXcel格式。 我导出EXcel的主要代码的前面部分: <? if(count($data)>40000){ $filename_type='csv'; }else{ $filename_type='xls'; } header("Content-Type: application/vnd.ms-excel"); Header("Accept-Ranges:bytes"); Header("Content-Disposition:attachment;filename=".$filename.".".$filename_type); //$filename导出的文件名 header("Pragma: no-cache"); header("Expires: 0"); if($filename_type=='xls'){ echo '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"> <head> <meta http-equiv="expires" content="Mon, 06 Jan 1999 00:00:01 GMT"> <meta http-equiv=Content-Type content="text/html; charset=gb2312"> <!--[if gte mso 9]><xml> <x:ExcelWorkbook> <x:ExcelWorksheets> <x:ExcelWorksheet> <x:Name></x:Name> <x:WorksheetOptions> <x:DisplayGridlines/> </x:WorksheetOptions> </x:ExcelWorksheet> </x:ExcelWorksheets> </x:ExcelWorkbook> </xml><![endif]--> </head>'; } 后面就是以<table><tr><td></td></tr></table>的格式输出数据 查了大半天终于查到了一点有用的资料,现在摘抄如下: “首先,我们了解一下excel从web页面上导出的原理。当我们把这些数据发送到客户端时,我们想让客户端程序(浏览器)以excel的格式读取它,所以把mime类型设为:application/vnd.ms-excel,当excel读取文件时会以每个cell的格式呈现数据,如果cell没有规定的格式,则excel会以默认的格式去呈现该cell的数据。这样就给我们提供了自定义数据格式的空间,当然我们必须使用excel支持的格式。下面就列出常用的一些格式: 1) 文本:vnd.ms-excel.numberformat:@ 2) 日期:vnd.ms-excel.numberformat:yyyy/mm/dd 3) 数字:vnd.ms-excel.numberformat:#,##0.00 4) 货币:vnd.ms-excel.numberformat:¥#,##0.00 5) 百分比:vnd.ms-excel.numberformat: #0.00% 这些格式你也可以自定义,比如年月你可以定义为:yy-mm等等。那么知道了这些格式,怎么去把这些格式添加到cell中呢?很简单,我们只需要把样式添加到对应的标签对(即闭合标签)即可。如<td></td>,给标签对<td></td>添加样式,如下: <td style="vnd.ms-excel.numberformat:@">410522198402161833</td> 同样,我们也可以给<div></div>添加样式,也可以给<tr></tr>,<table></table>添加样式;当我们在父标签对和子标签对都添加样式时,数据会以哪一个样式呈现呢?经过测试,会以离数据最近的样式呈现. ” 于是按照他说的方法设置了导出数据时对应的身份证列的<td>的样式: echo "<td style='vnd.ms-excel.numberformat:@'>".$printable."</td>\n"; 果然成功了,没有枉费了查半天的资料。
而关于php的也有,但是大多都是用phpExcel导出的方法或者spreadsheet等类或者控件之类的导出方法,而我所在维护的系统却用很简单的方法,如下,网上很少有讲如何设置要导出数据的EXcel格式。 我导出EXcel的主要代码的前面部分: if(count($data)>40000){ $filename_type='csv'; }else{ $filename_type='xls'; } header("Content-Type: application/vnd.ms-excel"); Header("Accept-Ranges:bytes"); Header("Content-Disposition:attachment;filename=".$filename.".".$filename_type); //$filename导出的文件名 header("Pragma: no-cache"); header("Expires: 0"); if($filename_type=='xls'){ echo ' xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"> '; } 后面就是以 的格式输出数据 查了大半天终于查到了一点有用的资料,现在摘抄如下: “首先,我们了解一下excel从web页面上导出的原理。当我们把这些数据发送到客户端时,我们想让客户端程序(浏览器)以excel的格式读取 它,所以把mime类型设为:application/vnd.ms-excel,当excel读取文件时会以每个cell的格式呈现数据,如果cell 没有规定的格式,则excel会以默认的格式去呈现该cell的数据。这样就给我们提供了自定义数据格式的空间,当然我们必须使用excel支持的格式。 下面就列出常用的一些格式: 1) 文本:vnd.ms-excel.numberformat:@ 2) 日期:vnd.ms-excel.numberformat:yyyy/mm/dd 3) 数字:vnd.ms-excel.numberformat:#,##0.00 4) 货币:vnd.ms-excel.numberformat:¥#,##0.00 5) 百分比:vnd.ms-excel.numberformat: #0.00% 这些格式你也可以自定义,比如年月你可以定义为:yy-mm等等。那么知道了这些格式,怎么去把这些格式添加到cell中呢?很简单,我们只需要把样式添 加到对应的标签对(即闭合标签)即可。如 ,给标签对添加样式,如 下: 410522198402161833 同样,我们也可以给 < /tr>,添加样式;当我们在父标签对和子标签对都添加样式时,数据会以哪一个样式呈现 呢?经过测试,会以离数据最近的样式呈现. ” 于是按照他说的方法设置了导出数据时对应的身份证列的 的样式: echo " ".$printable."\n";
setCellValue 是不支持设置数据格式的 下面是方法可有看处
setCellValue($pCoordinate = 'A1', $pValue = null, $returnCell = false)
setCellValueExplicit 是可以设置数据格式 同时支持连贯操作
/** * Set a cell value * * @param string $pCoordinate Coordinate of the cell * @param mixed $pValue Value of the cell * @param string $pDataType Explicit data type * @param bool $returnCell Return the worksheet (false, default) or the cell (true) * @return PHPExcel_Worksheet|PHPExcel_Cell Depending on the last parameter being specified */ public function setCellValueExplicit($pCoordinate = 'A1', $pValue = null, $pDataType = PHPExcel_Cell_DataType::TYPE_STRING, $returnCell = false) { // Set value $cell = $this->getCell($pCoordinate)->setValueExplicit($pValue, $pDataType); return ($returnCell) ? $cell : $this; }
setCellValueExplicit 支持以下数据格式 目前只发现这些
TYPE_STRING TYPE_STRING2 TYPE_NULL TYPE_NUMERIC TYPE_FORMULA TYPE_BOOL TYPE_ERROR
解决 PHPExcel 长数字串显示为科学计数
在excel中如果在一个默认的格中输入或复制超长数字字符串,它会显示为科学计算法,例如身份证号码,解决方法是把表格设置文本格式或在输入前加一个单引号。
对于下面这种修改数据类型未字符串 超长数字依然不能正常显示
->setCellValueExplicit('D1',123456789033,PHPExcel_Cell_DataType::TYPE_STRING);
百分之百可以解决超长数字的办法 就是在值前面加空格
->setCellValue('D1', ' ' . 123456789033);
Hi can somebody tell me how to set phpexcel cell format to datetime if I have datatime in php variable? I use it this way but it is only string: $list->setCellValueByColumnAndRow( ++$column, $row, $survey->task->closed->format(DateTimeUtils::DATE_FORMAT_NO_SPACES) ); EDIT: Now I have this code: $list->setCellValueByColumnAndRow( ++$column, $row, \PHPExcel_Shared_Date::PHPToExcel( $survey->task->closed ) ) ->getStyle()->getNumberFormat()->setFormatCode(\PHPExcel_Style_NumberFormat::FORMAT_DATE_DDMMYYYY); but it sets the cell format to number and date seems in result like float number 43098.4755671296 解决方案 It seems the fluent call getStyle() does not work and should be called getStyleByColumnAndRow() instead on excel sheet object. $activeSheet->getStyleByColumnAndRow( $column, $row, $survey)->getNumberFormat()->setFormatCode( \PHPExcel_Style_NumberFormat::FORMAT_DATE_DDMMYYYY ); I am confused and don't understand what is the difference between getStyle() and getStyleByColumnAndRow(). If somebody knows let me know. EDIT: There is fourth parameter in setCellValueByColumnAndRow() method which determines return value. Fluent getStyle() needs to set it to TRUE.
工作中比较多地遇到导出excel的需求,我通常是用phpspread完成,然而有时候像导出身份证号,银行卡号,订单号这些比较长而且格式为纯数字的数据时往往会出现变成科学计数法的情况,设置为默认文本格式又会出现末尾数字变成0的情况
经过搜索和测试后总算是有了解决办法,我将其封装成了一个函数
function CreateExcel($Data, $Header, $Path, $FileName,$LongNumberField=null) { $SpreadSheet = new \PhpOffice\PhpSpreadsheet\Spreadsheet(); $Sheet = $SpreadSheet->getActiveSheet(); if($LongNumberField===null){ array_unshift($Data, $Header); $SpreadSheet->getDefaultStyle()->getNumberFormat()->setFormatCode(\PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_NUMBER); $Sheet->fromArray($Data); } else{ $HeaderCount=count($Header); for($i=0;$i<$HeaderCount;$i++){ $Sheet->setCellValueByColumnAndRow($i+1,1,$Header[$i]); } $RowIndex=2; $DataCount=count($Data); for($i=0;$i<$DataCount;$i++){ $ColumnIndex=1; foreach ($Data[$i] as $Key=>$Value){ if(in_array($Key,$LongNumberField)){ $Sheet->setCellValueExplicitByColumnAndRow($ColumnIndex,$RowIndex,$Value,\PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING); } else{ $Sheet->setCellValueByColumnAndRow($ColumnIndex,$RowIndex,$Value); } $ColumnIndex++; } $RowIndex++; } } $Xlsx = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($SpreadSheet); $Xlsx->save($Path . $FileName); }
示例
$Data=[ ['id'=>1,'name'=>'张三','bank_card'=>'123456789123456789'], ['id'=>2,'name'=>'李四','bank_card'=>'123456123456789789'], ]; $Header=['id','姓名','银行卡号']; $Path='D:/www/test/'; $FileName='Export.xlsx'; $LongNumberField=['bank_card']; CreateExcel($Data,$Header,$Path,$FileName,$LongNumberField);