2019-05-31 16:33:30 gu_wen_jie 阅读数 724

我在去年写过一篇关于laravel的Excel导出文章:Laravel Excel 实现 Excel/CSV 文件导入导出功能,使用的是Laravel Excel实现的。
该扩展包含Excel导入导出功能,功能点是比较完善的,但是有一个地方,当实现大量数据导出到Excel的时候,会发现侠侣很慢,然后如果开启任务管理器查看的时候会发现CPU使用率飙升,内存使用率飙升,功能是没问题,但是总体导出效果不尽如人意。
我们再来说一下另一个扩展:PHPExcel

PHPExcel & PhpSpreadsheet

PHPExcel 是一个处理Excel,CVS文件的开源框架,它基于微软的OpenXML标准和PHP语言。可以使用它来读取、写入不同格式的电子表格,这也是PHP至今最通用的Excel处理工具,但是它有一个非常致命的缺点: 特别占内存,对大批量的表格数据几乎会让人累觉不爱,处理速度非常慢,但是它功能非常丰富,API非常多,所以在导出复杂格式的Excel表格时,它又非常方便。所以,纠结啊~~~
不过,PHPExcel上一版本1.8.1于2015年发布。该项目于2017年正式弃用,并于2019年永久存档。现在如果你依旧想要使用PHPExcel的话建议使用它的进阶版PhpSpreadsheet,它打破了兼容性,大大提高了代码库质量(名称空间,PSR合规性,最新PHP语言功能的使用等)。
不过,还是文章开头所说的,这个扩展,功能性非常丰富,导出复杂的Excel表格很方便,但是内存的消耗很夸张,如果你导出的是一个简单的Excel的话,建议使用一下下面这个扩展。

PHP_XLSXWriter

PHP_XLSXWriter设计为轻量级,并且具有最小的内存使用量。
它旨在输出(Office 2007+)xlsx格式的Excel兼容电子表格,仅支持基本功能:

  • 支持PHP 5.2.1+
  • 采用UTF-8编码输入
  • 多个工作表
  • 支持货币/日期/数字单元格格式,简单公式
  • 支持基本的单元格样式
  • 支持编写巨大的100K +行电子表格
    总体来说:它并没有PhpSpreadsheet功能丰富,很多高级操作并不具备,但是它导出速度非常快,非常适合于数据量特别大,报表格式不是很复杂的导出需求。

基础使用

首先你需要安装它(建议使用composer安装):
如果你对composer的使用不太了解,建议看下我写的另一篇文章:
Composer详细使用及利用Composer在Github和Packagist库中发布项目

composer require phpoffice/phpspreadsheet

我贴一个官方的demo:

$data = array(
    array('year','month','amount'),
    array('2003','1','220'),
    array('2003','2','153.5'),
);

$writer = new XLSXWriter();
$writer->writeSheet($data);
$writer->writeToFile('output.xlsx');

在Laravel中使用

我这里其实并没有很规则的使用Laravel的方法来进行服务注册等等,只是在Laravel框架中进行了安装,然后直接使用类的方法,你如果使用这个库,可以到时候进行注册然后使用,更加方便一点。
安装步骤在基础使用中已经说明了,也可以查看github的文档。看一下代码吧

<?php

namespace App\Http\Controllers;
use Illuminate\Http\Request;
class TestController extends Controller
{
	/**
     * 导出列表
     */
     public function xlsxWriter()
    {
        $search = [];
        $title = [
	        '姓名',
	        '年龄',
	        '性别',
	        '时间'
        ];
        $data = [
            [
              'name' => '小明',
              'age' => 18,
              'sex' => '男',
              'time' => '2019-05-30 13:20:45'
            ],
            [
               'name' => '小红',
               'age' => 20,
               'sex' => '女',
               'time' => '2019-05-31 13:20:45'
            ]
        ];
        $writer = new \XLSXWriter();
        $filename = 'Excel导出-'.date('Ymd') . ".xlsx";             //文件名
        header('Content-disposition: attachment; filename="' . \XLSXWriter::sanitize_filename($filename) . '"');
        header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        header('Content-Transfer-Encoding: binary');
        header('Cache-Control: must-revalidate');
        header('Pragma: public');
        $colnum = count($title) - 1;                              //查询条件合并列数
        $sheet1 = 'sheet1';                                     //工作簿名称
        if($search){//此处是如果在有筛选条件的情况下,将第一行合并,展示筛选条件
            $where = '筛选条件:'.$search['start_time'].'--'.$search['end_time'];
            $writer->writeSheetRow(                                 //写入第一行的数据,顺便指定样式
                $sheet1,
                [$where],
                ['height' => 33, 'font-size' => 10, 'font-style' => 'bold',
                    'halign' => 'center', 'valign' => 'center', 'wrap_text' => true]
            );
            //合并单元格,第一行的搜索条件需要合并单元格
            $writer->markMergedCell($sheet1, $start_row = 0, $start_col = 0, $end_row = 0, $end_col = $colnum);
        }
        //设置标题头,指定样式
        $styles1 = array('font' => '宋体', 'font-size' => 10, 'font-style' => 'bold', 'fill' => '#8DEEEE',
            'halign' => 'center', 'border' => 'left,right,top,bottom');
        $writer->writeSheetRow($sheet1, $title, $styles1);
        $styles2 = ['height' => 25];//设置单元格的高度
        foreach ($data as $row) {
            $writer->writeSheetRow($sheet1, $row, $styles2);
        }
        $writer->writeToStdOut();exit();
    }
}

运行后,我们看下导出的效果:
在这里插入图片描述
这时候你会发现并没有筛选条件,那是因为上面的$search为空,如果我把条件加上看下效果

 public function xlsxWriter()
 {
 		$search = [
            'start_time' => '2019-05-30 00:00:00',
            'end_time' => '2019-05-31 23:59:59',
        ];
        ...
        ...
        ...
        if($search){//此处是如果在有筛选条件的情况下,将第一行合并,展示筛选条件
            $where = '筛选条件:'.$search['start_time'].'--'.$search['end_time'];
            $writer->writeSheetRow(                                 //写入第一行的数据,顺便指定样式
                $sheet1,
                [$where],
                ['height' => 33, 'font-size' => 10, 'font-style' => 'bold',
                    'halign' => 'center', 'valign' => 'center', 'wrap_text' => true]
            );
            //合并单元格,第一行的搜索条件需要合并单元格
            $writer->markMergedCell($sheet1, $start_row = 0, $start_col = 0, $end_row = 0, $end_col = $colnum);
        }
       ...
       ...
    }

看下效果:
在这里插入图片描述
对于一些并不是很复杂的Excel整体展示上还是可以的,并且可以指定样式

指定列的数据类型

注意:如果你需要指定某一列单元格的数据类型,你可以添加以下代码对列数据类型进行指定。

 public function xlsxWriter()
 {
		$search = [
            'start_time' => '2019-05-30 00:00:00',
            'end_time' => '2019-05-31 23:59:59',
        ];
 		$title = [
 			'编号',
	        '姓名',
	        '年龄',
	        '性别',
	        '时间'
        ];
        $data = [
            [
              'number' => '123456789101112',
              'name' => '小明',
              'age' => 18,
              'sex' => '男',
              'time' => '2019-05-30 13:20:45'
            ],
            [
               'number' => '123456789101113',
               'name' => '小红',
               'age' => 20,
               'sex' => '女',
               'time' => '2019-05-31 13:20:45'
            ]
        ];
        ...
        ...
        ...
       
    }

如果暂时按照这样的话,看下效果:
在这里插入图片描述
由于编号被Excel识别成数字,长度过长直接采用科学计数法将长串的数值进行记录,这显然不符合我们的要求。可以这样做

 public function xlsxWriter()
 {
		$search = [
            'start_time' => '2019-05-30 00:00:00',
            'end_time' => '2019-05-31 23:59:59',
        ];
 		$title = [
 			'编号',
	        '姓名',
	        '年龄',
	        '性别',
	        '时间'
        ];
        $data = [
            [
              'number' => '123456789101112',
              'name' => '小明',
              'age' => 18,
              'sex' => '男',
              'time' => '2019-05-30 13:20:45'
            ],
            [
               'number' => '123456789101113',
               'name' => '小红',
               'age' => 20,
               'sex' => '女',
               'time' => '2019-05-31 13:20:45'
            ]
        ];
        ...
        ...
        $sheet1 = 'sheet1';
         //指定列的数据类型
        foreach ($title as $key => $item){
            if($key == 0){//如果是编号的话,指定数据类型为string,excel中则为文本类型
                $col_style[] = 'string';
            }
        }
        //设置列格式,suppress_row: 去掉会多出一行数据;widths: 指定每列宽度,看自己需求是否需要指定
        $writer->writeSheetHeader($sheet1, $col_style, ['suppress_row'=>true,'widths'=>[30,30,30,30,30]] );
        ...
        ...
       
    }

再来看下效果:
在这里插入图片描述
如果你需要其他类型,请参照:https://github.com/mk-j/PHP_XLSXWriter
在这里插入图片描述
因为测试数据比较少,所以也无法展示导出耗时及内存的使用情况,如果你自己使用的时候,上百条数据,你就会明显发现 PHP_XLSXWriter 速度非常快,并且消耗内存很少,不过当下这个扩展已经没有人维护了,不过使用起来没有影响,只是你在使用的时候遇到问题可能需要自己去解决,没有相关社区,也很久没有更新维护,但是也不失为一个轻量级的大数据量Excel导出扩展

2017-10-20 08:11:11 gyen_ki 阅读数 798
<?php  
    //导出数据
    public function exportData(){
        $ary_lottery_list = D('DrawUser')->userLucky('5');
        $fileExcel  =  $_SERVER['DOCUMENT_ROOT'].'/Public/Uploads/excel/';                                       //文件存放目录
        if(!is_dir($fileExcel)) @mkdir($fileExcel,0777,1);
        $excel_file = 'exportStatData'. date('Y-m-d-H-i-s', time()).'.csv';
        $header     = $this->setExcelHeader($ary_lottery_list);
        $contents = $this->setExcelContents($ary_lottery_list);
        $this->export_csv($contents, $header, $excel_file,$fileExcel);
        //Excel显示列
        header("Content-type:application/force-download;charset=utf-8");
        header("Content-Disposition:attachment;filename=" .$excel_file);
        readfile($fileExcel.$excel_file);
        exit;
    }
    /* *
    * 报表字段
    */
    private function setExcelHeader($ary_data){
        $heards = array(
            'ID','姓名','手机号','详细地址','奖品'
        );
        return $heards;
    }
    /* *
     * 处理获取的数据库数据
     */
    private function setExcelContents($ary_data){
        $contents = array();
        foreach($ary_data as $key=>$val){
            $tmp_contents = array(
                $val['id'],
                $val['name'],
                $val['tel'],
                $val['province']." ".$val['city']." ".$val['county']." ".$val['address'],
                $val['p_name']
            );
            $contents[] = $tmp_contents;
        }
        return $contents;
    }
    function export_csv($data, $title_arr, $file_name = '',$filexcel) {
        $csv_data = '';
        /** 标题 */
        $nums = count($title_arr);
        for ($i = 0; $i < $nums - 1; ++$i) {
            $csv_data .= '"' . $title_arr[$i] . '",';
        }
        if ($nums > 0) {
            $csv_data .= '"' . $title_arr[$nums - 1] . "\"\r\n";
        }
        $csv_data = iconv('utf-8', 'GB2312',$csv_data);
        $file_name = empty($file_name) ? date('Y-m-d-H-i-s', time()) : $file_name;
        if(count($data)>300){
            file_put_contents($filexcel.$file_name,  $csv_data) ;
            foreach ($data as $k => $row) {
                $csv_data = "";
                for ($i = 0; $i < $nums - 1; ++$i) {
                    if($i == 0){
                        $row[$i] = str_replace("\"", "\"\"", $row[$i]);
                        //$csv_data .= '`'.trim($row[$i]). '`,';
                        $csv_data .= trim($row[$i]). ',';
                    }else{
                        $row[$i] = str_replace("\"", "\"\"", trim($row[$i]));
                        $csv_data .= '"' . $row[$i] . '",';
                    }
                }
                $csv_data .= '"' . $row[$nums - 1] . "\"\r\n";
                unset($data[$k]);
                file_put_contents($filexcel.$file_name, iconv('utf-8', 'GB2312', $csv_data),FILE_APPEND) ;
            }
        }
        else{
            foreach ($data as $k => $row) {
                $csv_line='';
                for ($i = 0; $i < $nums - 1; ++$i) {
                    if($i == 0){
                        $row[$i] = str_replace("\"", "\"\"", $row[$i]);
                        //$csv_line .= '`'.trim($row[$i]). '`,';
                        $csv_line .= trim($row[$i]). ',';
                    }else{
                        $row[$i] = str_replace("\"", "\"\"", trim($row[$i]));
                        $csv_line .= '"' . $row[$i] . '",';
                    }
                }
                $csv_line .= '"' . $row[$nums - 1] . "\"\r\n";
                $csv_line = iconv('utf-8', 'GB2312',$csv_line);
                $csv_data .= $csv_line;
                //unset($data[$k]);
            }
            file_put_contents($filexcel.$file_name,  $csv_data) ;
//            file_put_contents($filexcel.$file_name, $csv_data) ;
        }
        return true;
    }
?>

2018-10-17 15:49:57 T_Struggle 阅读数 1154
  1. MySQL筛选出要导出数据的列表,字段就是excel中要显示的列,比如id、name、address等
  2. 设置导出excel的表名,一般是名称加时间的格式,php代码如下:
    $field    = 'a.`did`,a.addtime,a.`phone`,a.`system`,a.msg_status,a.`author`';
    $result   = "select $field from table where 1=1";
    
    //导出excel核心
    $file_name   = "-下载地址预约表".date("Y-m-d",time());
    $file_suffix = "xls";
    header("Content-Type: application/vnd.ms-excel");
    header("Content-Disposition: attachment; filename=$file_name.$file_suffix");
    
    $this->smarty->assign('list',  	$result);
    $this->smarty->display("export.html");

     

  3.  输入到html模板,html示例代码:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <table border=1 cellpadding=0 cellspacing=0>
        <tr><th colspan="5" style="height: 50px;line-height: 50px;background: #505050;color: #fff;font-size: 22px;">{$dname}-下载地址预约表</th></tr>
        <tr class="t1">
            <td width="8%">预约游戏名称</td>
            <td width="3%">手机号码</td>
            <td width="5%">预约时间</td>
            <td width="5%">系统类型</td>
        </tr>
            {foreach from=$list key=key item=val}
            <tr>
                <td><strong>{if $downid}{$dname}{else}{$val.dname}{/if}</strong></td>
                <td>{$val.phone}</td>
                <td >{$val.addtime|date_format:"%Y-%m-%d %H:%M:%S"}</td>
                <td >{if $val.system eq 1}安卓{elseif $val.system eq 2}IOS{else}全部{/if}</td>
            </tr>
            {/foreach}
    </table>
    </body>
    </html>

    注:并不是所有浏览器都支持这种方式,推荐使用chrome浏览器 

     

2019-04-19 15:23:38 qq_42217190 阅读数 33

下载功能请使用 a 标签  下载, 
public function show()

{

$excel = $this->excelExport();

}

/**
 * excel表格导出

 * @param string $fileName 文件名称

 * @param array $headArr 表头名称

 * @param array $data 要导出的数据

 * @author static7  */
public function excelExport($fileName = '', $headArr = [], $data = []) {
    $fileName .= "_" . date("Y_m_d", Request::instance()->time()) . '.xls';
    引入PHPEXCEL的路劲
    $objPHPExcel = new \PHPExcel();
    $objPHPExcel->getProperties();
    $key = ord("A"); // 设置表头
    foreach ($headArr as $v) {
        $colum = chr($key);
        $objPHPExcel->setActiveSheetIndex(0)->setCellValue($colum . '1', $v);
        $objPHPExcel->setActiveSheetIndex(0)->setCellValue($colum . '1', $v);
        $key += 1;
    }
    $column = 2;
    $objActSheet = $objPHPExcel->getActiveSheet();
    foreach ($data as $key => $rows) { // 行写入
        $span = ord("A");
        foreach ($rows as $keyName => $value) { // 列写入
            $objActSheet->setCellValue(chr($span) . $column, $value);
            $span++;
        }
        $column++;
    }
    $fileName = iconv("utf-8", "gb2312", $fileName); // 重命名表
    $objPHPExcel->setActiveSheetIndex(0); // 设置活动单指数到第一个表,所以Excel打开这是第一个表
    header('Content-Type: application/vnd.ms-excel');
    header("Content-Disposition: attachment;filename=$fileName");
    header('Cache-Control: max-age=0');
    $objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
    $objWriter->save('php://output'); // 文件通过浏览器下载
    exit();
}
2015-03-21 20:57:28 u012162220 阅读数 1119

PHP导出数据到Excel

在Web开发中经常需要将一些数据导入到Excel表格中,比如需要导出符合条件的用户数据,导出项包括姓名性别身份证号联系方式等等。那么问题来了,在导出的数据中如果出现比较长的数值类型的项时,默认按科学计数法表示,比如身份证号这显然不是我们需要的,那么我们怎么做才能让数据按我们要求的格式显示呢?


查到一些相关资料,摘抄如下:

首先,我们了解一下excel从web页面上导出的原理。当我们把这些数据发送到客户端时,我们想让客户端程序(浏览器)以excel的格式读取它,所以把mime类型设为:application/vnd.ms-excel,当excel读取文件时会以每个cell的格式呈现数据,如果cell 没有规定的格式,则excel会以默认的格式去呈现该cell的数据。这样就给我们提供了自定义数据格式的空间,当然我们必须使用excel支持的格式。 下面就列出常用的一些格式:
- 文本:vnd.ms-excel.numberformat:@
- 日期:vnd.ms-excel.numberformat:yyyy/mm/dd
- 数字:vnd.ms-excel.numberformat:#,##0.00
- 货币:vnd.ms-excel.numberformat:¥#,##0.00
- 百分比:vnd.ms-excel.numberformat: #0.00%
这些格式你也可以自定义,比如年月你可以定义为:yy-mm等等。那么知道了这些格式,怎么去把这些格式添加到cell中呢?很简单,我们只需要把样式添加到对应的标签对(即闭合标签)即可。如<td></td>,给标签对<td></td>添加样式,如下:<td style="vnd.ms-excel.numberformat:@">410522198402161833</td>同样,我们也可以给div添加样式,也可以给tr,table添加样式;当我们在父标签对和子标签对都添加样式时,数据会以哪一个样式呈现呢?经过测试,会以离数据最近的样式呈现。 —— 原文链接


以下分别给出自定义格式输出和默认格式输出两种示例代码

自定义格式

    /**
     * 用户信息导出为Excel(方法一)
     * 优点:输出的数据列格式可以自定义,如数值、字符串等
     * 缺点:需要将二维表数据组装成html表格代码,代码简洁较繁杂
     */
    public function exportDo() {
        set_time_limit(0);
        $groupid = $_REQUEST['groupid'];
        $field = $_REQUEST['field'];
        $head = $_REQUEST['head'];

        //查询数据
        $model = new GroupUserModel();
        $data = $model->field(field )
                      ->where("groupid = '".$groupid."'")
                      ->order('id')
                      ->select();

        array_unshift($data, $head);  //添加表头
        $file_name = '用户详细信息';         //excel文件名

        //将用户信息组装成表格导出到excel中
        $str = ''; //初始化
        //输出表头
        $str .= '<table border="1">
                    <tr>
                        <td colspan="'.count($data[0]).'" align="center" style="font-size:16px; height:32px; font-weight:bold">'.$file_name.'</td>
                    </tr>';
        //循环输出行     
        foreach($data as $v1) {
            $str .= '<tr>';
            //循环输出列
            foreach($v1 as $v2) {
                $str .= '<td style="vnd.ms-excel.numberformat:@">'.$v2.'</td>';
            }
            $str .= '</tr>';
        }
        $str .=    '</table>';

        //转换为GBK编码
        $str = iconv("UTF-8","GBK",$str);

        //输出
        header('Content-Length: '.strlen($str));
        header("Content-type:application/vnd.ms-excel");
        header("Content-Disposition:filename={$file_name}.xls");
        echo $str;
    }

默认格式

    /**
     * 用户信息导出为Excel(方法二)
     * 优点:不需要将二维表数据组装成html表格代码,代码简洁
     * 缺点:输出的数据列格式不可控制,如身份证号用科学计数法表示
     */
    public function exportDo() {
        set_time_limit(0);
        $groupid = $_REQUEST['groupid'];
        $field = $_REQUEST['field'];
        $head = $_REQUEST['head'];

        header("Content-type:application/vnd.ms-excel;charset=UTF-8;"); 
        header("Content-Disposition:filename=".iconv("utf-8", "gb2312", "用户详细信息.xls");

        //组装查询表头
        $head_field = array();
        foreach ($head as $key => $row) {
            if(isset($field[$key])) array_push($head_field, $row);
        }
        //查询数据
        $model = new GroupUserModel();
        $data = $model->field($select_field)
                      ->where("groupid = '".$groupid."'")
                      ->order('id')
                      ->select();

        array_unshift($data, $head_field);  //添加表头
        foreach ($data as $key => $row) {
            $out_string = '';
            foreach($row as $h_key => $h_row) {
                $out_string .= iconv("utf-8", "gb2312", $h_row)."\t";
            }
            echo $out_string;
            echo "\n";
        }
    }

php数据导出excel

阅读数 39

//使用PHP将Mysql数据表导出到Excel中

博文 来自: qq_23488347

php导出excel数据

阅读数 183

没有更多推荐了,返回首页