开源一个Thinkphp5封装的EXCEL导出及分批导出的类库

开源一个Thinkphp5封装的EXCEL导出及分批导出的类库,当然,针对后台类搜索之后GET的数据进行保留到字符串的办法也进行封装。

如有不懂的可给作者留言

下载地址:Thinkphp5-excel-export

<?php

/****
* 封装类扩展
* 为更好的使用,建议使用BIT 64 PHP
* @author 陈奎宗 <kuizong_chen@139.com>
*/
namespace app\qingxinzui\admin;

use app\admin\controller\Admin;
use think\Db;
ini_set(“memory_limit”, “-1″);
set_time_limit(0);
define(‘CKZ_EXPORT_SERIAL_NUMBER_MAX’,100); //导出流水的单页最大记录数
define(‘ZIP_FILE_DIR_PATH’, RUNTIME_PATH);
//导出的文件默认放在runtime/ 即RUNTIME_PATH
//如果需要把导出的文件放在外部可连接访问的话,那么请修改成ROOT_PATH下的对应目录节点
#ROOT_PATH . ‘public’ . DS . ‘uploads’ . DS.’zip’.DS

class Ckz extends Admin
{

/*****
* @author 陈奎宗 <kuizong_chen@139.com>
* 页面需要呈现的数据进行数据的初始化动作,然后如果有GET数据的时候,优先使用GET数据替换
* $arr = array(‘a’=>”,b=>”); $get = array(‘a’=>’a’,’b’=>’b’,’c’=>’c’);
* return $arr = array(‘a’=>’a’,’b’=>’b’)
* @param unknown $arr 默认数组
* @param unknown $get 请求数组
* @return unknown 返回替换之后的数组
*/
public function getPageCode($arr,$get){
foreach ($arr as $key=>$value){
if (isset($get[$key])){
$arr[$key] = $get[$key];
}
}
return $arr;
}

/*****
* @author 陈奎宗 <kuizong_chen@139.com>
* 针对现系统的TP5使用,很多需要查看和导出的,因为可能存在筛选条件,所以进行参数化保留,以方便查看之后要执行导出的时候,还需要重新组合URL
* 利用该方法,可直接转换成对应的GET链接模式
* 参数效果如
* $get = array(
* ‘status’=>’1’,
* ‘price’ => ‘100’,
* ‘name’=>’名称’
* );
* 组合成status=1&price=100&name=名称
* 然后直接在TP5的框架视图里使用href=”{:url(‘controller/functionname’)}?{$export}”
* @param unknown $get //请求的GET参数的汇集,可以直接使用$_GET进行传参
* @return string
*/
public function getExportUrl($get){
$export = ”;
if(!empty($get) && is_array($get)){
$i=0;
foreach ($get as $key => $value){
if($i==0){
$export.=$key.’=’.$value;
} else {
$export.=’&’.$key.’=’.$value;
}
$i++;
}
}
return $export;
}

/*****
* @author 陈奎宗 <kuizong_chen@139.com>
* 实现公共导出,后续可封装到公有函数,考虑GIT模式 避免冲突覆盖
* @param unknown $letter 栏目占位列数组,如 $letter = array(‘A’,’B’,’C’);主要表示使用EXCEL的哪个列段
* @param unknown $width 栏目占用宽度数组,如 $width = array(20,15,20,20);主要使对应列的宽度设置为多少PX
* @param unknown $tableheader 栏目标签,如$tableheader = array(‘产品名称’,’产品价格’,’产品描述’);主要使用对应列的头部标签文字化呈现
* @param unknown $textcode 数组字段下标,该参数将进行多次循环内使用,主要写满一行的数据使用,如果 $textcode = array(‘name’,’price’,’description’);
* @param unknown $arr 需要进行多次转换的数据二维数组(注,必须二维数组,并且二维数组内的下标,必须是在textcode里面存在的)
* @param unknown $filename 生成的文件名,不包含后缀,如word,那么将导出的文件名为word.excel
* @param unknown $exportall =0的时候或者小于某个数量的时候表示不切割多文件,否则按数量切隔 ,该参数如果要切割,必传!
* @param unknown $texttype 文本类型,默认全部为文本
* @param unknown $title EXCEL表的名
*/
public function ExportExcel($letter,$width,$tableheader,$textcode,$arr,$filename=null,$exportall=0,$texttype =’@’,$title=’Sheet1′){
if($exportall==0 && count($arr)<CKZ_EXPORT_SERIAL_NUMBER_MAX){
$this->exportall($letter, $width, $tableheader, $textcode, $arr,$filename,$exportall,$texttype,$title);
} else {
//这里后续还需要做iconv等扩展是否存在的支持
$exportall = CKZ_EXPORT_SERIAL_NUMBER_MAX;
$this->exportrow($letter, $width, $tableheader, $textcode, $arr,$filename,$exportall,$texttype,$title);
}
exit;
}

private $zip_file_dir_path; //需要打包的文件所在目录,系统会自动创建对应的子目录然后实现打包

private $zip_file_dir_name; //如果调用了切割打包的方法,该参数名必须存在,因为在$zip_file_dir_path里面会在创建一个对应的目录,然后浏览器输出打包数据的时候,根据该名称实现out
//注,该参数没有目录中止符/,因为创建目录需要,还有压缩成ZIP的时候也需要

/***
* 多文件切割的话,需要打包成ZIP给予下载,所以进行压缩处理
* @param unknown $path 路径,需要设置777权限,该方法给予外部直接调用
*/
public function setExportInZipIsDirPath($path){
$this->zip_file_dir_path = ZIP_FILE_DIR_PATH.$path;
if (!is_dir($this->zip_file_dir_path)){
if(mkdir($this->zip_file_dir_path,0777)){
} else {
die(“创建ZIP压缩文件根”.$path.”目录失败,请把”.$this->zip_file_dir_path.”权限设置为777″);
}
}
$this->zip_file_dir_name = time().$this->getSeed();
/*
$file_dir = $this->zip_file_dir_path.’/’.$this->zip_file_dir_name;
if (!mkdir($file_dir,0777)){
die(“创建ZIP压缩文件”.$file_dir.”目录失败,请把”.$this->zip_file_dir_path.”权限设置为777″);
}*/
}

/*****
* 创建文件名组和后缀字符串,主要防止同一时间并发大了,创建的文件名冲突
* @return string
*/
private function getSeed(){
$arr = array(‘a’,’b’,’c’,’d’,’e’,’f’,’g’,’h’,’i’,’j’,’k’,’l’,’m’,’n’,’o’,’p’,’q’,’r’,’s’,’t’,’u’,’v’,’w’,’x’,’y’,’z’);
$str = ”;
for($i=0;$i<5;$i++){
$str.= $arr[rand(0,25)];
}
return $str;
}

/*****
* 导出全部
* @param unknown $letter
* @param unknown $width
* @param unknown $tableheader
* @param unknown $textcode
* @param unknown $arr
* @param unknown $filename
* @param number $exportall
* @param string $texttype
* @param string $title
*/
private function exportall($letter,$width,$tableheader,$textcode,$arr,$filename=null,$exportall=0,$texttype =’@’,$title=’Sheet1′){
if ($filename == null){
$filename = date(“y-m-d H:i:s”);
}
require_once VENDOR_PATH.’PHPExcel/PHPExcel.php’;
$excel = new \PHPExcel();
$excel->setActiveSheetIndex(0); //第一栏
$excel->getActiveSheet()->setTitle($title);
for($i = 0;$i < count($tableheader);$i++) {
$excel->getActiveSheet()->getColumnDimension($letter[$i])->setWidth($width[$i]); //getDefaultColumnDimension为默认,不能单一设置
$excel->getActiveSheet()->setCellValue($letter[$i].”1″,”$tableheader[$i]”,$texttype);
}
$i=2;
for($s=0;$s<count($arr);$s++){
for($t=0;$t<count($textcode);$t++){
$excel->getActiveSheet()->setCellValue($letter[$t].$i,$arr[$s][$textcode[$t]],$texttype);
}
$i++;
}
$this->exportwrite($excel,$filename);
}

/****
* 按需求数量导出
* @param unknown $letter
* @param unknown $width
* @param unknown $tableheader
* @param unknown $textcode
* @param unknown $arr
* @param unknown $filename
* @param number $exportall
* @param string $texttype
* @param string $title
*/
private function exportrow($letter,$width,$tableheader,$textcode,$arr,$filename=null,$exportall,$texttype =’@’,$title=’Sheet1′){
if ($filename == null){
$filename = date(“y-m-d H:i:s”);
}
require_once VENDOR_PATH.’PHPExcel/PHPExcel.php’;
$excel = new \PHPExcel();
$page = ceil(count($arr)/$exportall);
$row = 0; //记录的行数
$dir = $this->zip_file_dir_path; //存储,压缩及下载目录
$files = array();
//var_dump($arr);die();
for ($p=0;$p<$page;$p++){
$excel->setActiveSheetIndex(0); //第一栏
$excel->getActiveSheet()->setTitle($title);
for($i = 0;$i < count($tableheader);$i++) {
$excel->getActiveSheet()->getColumnDimension($letter[$i])->setWidth($width[$i]); //getDefaultColumnDimension为默认,不能单一设置
$excel->getActiveSheet()->setCellValue($letter[$i].”1″,”$tableheader[$i]”,$texttype);
}
$q=2; //除表头之后的循环
for($s=0;$s<$exportall;$s++){
if (isset($arr[$row]) && is_array($arr[$row]) && !empty($arr[$row]) && $row<=count($arr)){
for($t=0;$t<count($textcode);$t++){
$excel->getActiveSheet()->setCellValue($letter[$t].$q,$arr[$row][$textcode[$t]],$texttype);
}
$q++;
$row++;
}
}
$files[$p] = $this->zip_file_dir_path.’/’.$filename.’-‘.$p.’.xls’;
$this->exportwrite($excel, $filename.’-‘.$p,’server’,’.xls’,$dir);
$excel = null;
$excel = new \PHPExcel(); //必须重新实例化,否则导出数据集会有汇集点冲突
usleep(100); //0.1秒一个,避免磁盘瞬间I/O满了,主要考虑可能多个数据同步进行的时候
}
$zipname = $this->zip_file_dir_path.’/’.$this->zip_file_dir_name.’.zip’;
$zip = new \ZipArchive();
if ($zip->open($zipname,\ZIPARCHIVE::CREATE)!==TRUE){ //\ZIPARCHIVE::OVERWRITE |
die(“创建压缩文件失败”);
}

for($e=0;$e<count($files);$e++){
$zip->addFile($files[$e], basename($files[$e]));//第二个参数是放在压缩包中的文件名称,如果文件可能会有重复,就需要注意一下,同时包括过滤中文GB2312等过滤
}
$zip->close();
if(!file_exists($zipname)){
die(“无法找到文件”); //即使创建,仍有可能失败
}
header(“Cache-Control: public”);
header(“Content-Description: File Transfer”);
header(‘Content-disposition: attachment; filename=’.$filename.’.zip’); //文件名
header(“Content-Type: application/zip”); //zip格式的
header(“Content-Transfer-Encoding: binary”); //告诉浏览器,这是二进制文件
header(‘Content-Length: ‘. filesize($zipname)); //告诉浏览器,文件大小
readfile($zipname);
}

/***
* 导出输出
* //数据写出,考虑兼容性的问题,使用EXCEL2003,避免部分客户还使用OFFICE2003而导致无法打开的情况
* @param unknown $excel EXCEL对象数据集
* @param unknown $filename 文件名
* @param unknown $save 默认browser为直接输出,否则就存储到SERVER端,后续可能存储到FTP盘,或者通过邮件发送,可以通过该参数定义进行switch
* @param unknown $postfix 后缀
* @param unknown $dir 本地服务器路径,该参数只有save!=browser的时候才有效果
*/
private function exportwrite($excel,$filename,$save=’browser’,$postfix=’.xls’,$dir=null){
$write = new \PHPExcel_Writer_Excel5($excel);
if ($save==’browser’){
header(“Pragma: public”);
header(“Expires: 0”);
header(“Cache-Control:must-revalidate, post-check=0, pre-check=0”);
header(“Content-Type:application/force-download”);
header(“Content-Type:application/vnd.ms-execl”);
header(“Content-Type:application/octet-stream”);
header(“Content-Type:application/download”);;
header(‘Content-Disposition:attachment;filename=”‘.$filename.$postfix.'”‘);
header(“Content-Transfer-Encoding:binary”);
$write->save(‘php://output’);
} else {
if (is_dir($dir) && $dir!=null){
//iconv(‘UTF-8’, ‘GB2312′, $filename)
$file = $dir.’/’.$filename.$postfix;
$write->save($file);
} else {
die(“存储服务器失败,请确保目录(“.$dir.”)是否存在,如果为LINUX请确保权限为0777″);
}
}
}

}

发表评论

电子邮件地址不会被公开。 必填项已用*标注