ThinkPHP利用phpOffice/Spreadsheet实现Excel导出(加粗、背景色、文字颜色、合并行列)

  • A+
所属分类:PHP ThinkPHP5

首先我们使用composer安装:

composer require phpoffice/phpspreadsheet

然后建立一个抽象的工具类Export并为其创建单例类:

namespace app\common\tool;

abstract class Export
{
   private static $instance = [];
    /**
         * @return static
         */
      public static function getInstance()
      {
            $class = get_called_class();
            if(!isset(self::$instance[$class]) || !self::$instance[$class] instanceof $class){
                self::$instance[$class] = new static();
            }
            return self::$instance[$class];
      }  
}

然后我们定义3个方法,分别定义文件的标题(sheet)名,文件的后缀格式以及表头是否加粗显示:

定义标题:

public function setFileTitle() : string
{
    return 'sheet';
}

定义文件后缀格式:

public function setFileFormat() : string
{
    return 'Xlsx';
}

定义表头是否加粗:

public function setFileHeaderBold(): bool
{
    return true;
}

定义两个抽象方法要求子类必须实现:

定义表头的内容:

abstract public function setFileHeader(): array ;

定义文件的名称:

abstract public function setFileName(): string ;

我们来实现导出的功能:

public function export($datas)
{
    $spreadsheet = new Spreadsheet();
    //设置当前的sheet对象 并获取 sheet
    $worksheet = $spreadsheet->setActiveSheetIndex(0);
    $startRow = 1;
    $nextRow = 0;
    $fields = [];
    foreach ($this->setFileHeader() as $key => $headers){
        //设置起始的单元格
        $startCell = 0;
        foreach ($headers as $column => $header){
            //表头中设置text的属性
            if(isset($header['text'])){
                //获取当前要做成的单元格对象
                $nowColumn = \PHPExcel_Cell::stringFromColumnIndex($startCell).$startRow;
                //设置单元格值
                $worksheet->setCellValue($nowColumn, $header['text']);
                //设置单元格的宽度
                if(isset($header['width'])){
                    $worksheet->getColumnDimension(\PHPExcel_Cell::stringFromColumnIndex($startCell))->setWidth($header['width']);
                }
                //设置表头加粗
                $worksheet->getStyle($nowColumn)->getFont()->setBold($this->setFileHeaderBold());
                //设置水平居中
                $worksheet->getStyle($nowColumn)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
                //设置垂直居中
                $worksheet->getStyle($nowColumn)->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER);
                //设置背景颜色
                if(isset($header['bgColor'])){
                    $worksheet->getStyle($nowColumn)->getFill()->setFillType(\PHPExcel_Style_Fill::FILL_SOLID)
                        ->getStartColor()->setARGB($header['bgColor']);
                }
                //设置文字颜色
                if(isset($header['fontColor'])){
                    $worksheet->getStyle($nowColumn)->getFont()->getColor()->setARGB($header['fontColor']);
                }
                //合并列
                if(isset($header['colspan']) && $header['colspan'] >= 2){
                    $mergeCells = $nowColumn.':'.\PHPExcel_Cell::stringFromColumnIndex($startCell + $header['colspan'] - 1).$startRow;
                    $worksheet->mergeCells($mergeCells);
                    $startCell += $startCell + $header['colspan'] - 1;
                }
                //合并行
                if(isset($header['rowspan']) && $header['rowspan'] >= 2){
                    $mergeCells = $nowColumn.':'.\PHPExcel_Cell::stringFromColumnIndex($startCell).($startRow + $header['rowspan'] - 1);
                    $worksheet->mergeCells($mergeCells);
                    $nextRow = $startRow + $header['rowspan'] - 1;
                }
            }
            //field在datas中存在,用于取数据
            if(isset($header['field'])){
                $fields[] = $header['field'];
            }
            $startCell++;
        }
        //设置操作行
        $startRow = $nextRow > 0 ? $startRow + $nextRow : $startRow + 1;
    }
    //设置sheet标题
    $worksheet->setTitle($this->setFileTitle());
    //输出内容到sheet
    foreach ($datas as $key => $data){
        $row = $startRow + $key;
        foreach ($fields as $index => $field){
            //如果存在getFieldNameAttr()则调用,实现字段的判断
            $method = 'get'.ucfirst(Loader::parseName($field, 1)).'Attr';
            if(method_exists($this, $method)){
                $value = $this->$method(...[$field, $data]);
            }else if(isset($data[$field])){
                //存在取值
                $value = $data[$field];
            }else{
                //不存在留空
                $value = '';
            }
            //设置单元格值
            $worksheet->setCellValue(\PHPExcel_Cell::stringFromColumnIndex($index).$row, $value);
            $worksheet->getStyle(\PHPExcel_Cell::stringFromColumnIndex($index).$row)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
        }
    }
    //下载Excel
    $this->downloadExcel($spreadsheet, $this->setFileName(), $this->setFileFormat());

}

下载文件的方法:

private function downloadExcel($spreadsheet, $fileName, $format)
{
    header("Content-Type:application/octet-stream");
    if ($format == 'Xlsx') {
        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
    } elseif ($format == 'Xls') {
        header('Content-Type: application/vnd.ms-excel');
    }
    header("Content-Disposition: attachment;filename="
        . $fileName. '.' . strtolower($format));
    header('Cache-Control: max-age=0');
    $writer = IOFactory::createWriter($spreadsheet, $format);
    $writer->save('php://output');
    exit;
}

我们来实现一个具体的导出,如用户导出:

首先建立UserExport:

namespace app\common\tool\export;

use app\common\tool\Export;

class UserExport extends Export
{
    public function setFileHeader(): array
    {
       return [
           [
               ['field' => 'user_name', 'text' => '用户名', 'width' => 60, 'bgColor' => '67834B', 'fontColor' => 'FFFFFF']
           ]
       ];
    }

    public function setFileName(): string
    {
        return 'userData'.date("Ymd");
    }

}

高级用法:

    public function setFileHeader(): array
    {
       return [
            [
                ['text' => '用户信息', 'width' => 20, 'rowspan' => 2],
                ['text' => '其他信息', 'colspan' => 5, 'bgColor' => '0589FA'],
            ],
            [
                ['field' => 'mem_name','text' => '姓名'],
                ['field' => 'telephone', 'text' => '电话', 'width' => 25],
                ['field' => 'city', 'text' => '城市'],
            ]
        ];
    }

设置字段的值:

public function getTelephoneAttr($key, $data)
{
    return $data['telephone']; //手机号隐藏中间的四位处理
}

avatar

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: