PHPExcel内存溢出解决方案

                                                                  PHPExcel内存溢出解决方案

一、当PHPEXCEL导出大数据时,PHP内存溢出时,可使用Table把数据分页追加到Excel文件

存在的问题:这种方法最多只能写入 65536 条数据,解决方案 请移步 >>> ThinkPhp 使用 PHP_XLSXWriter 代替 PHPExcel 百万级数据单次导出

1、代码

<?php

namespace app\index\controller;

class Ablog extends Base
{
    /**
     * 入口方法
     * 当PHPEXCEL导出大数据时,PHP内存溢出时,可使用该方法把数据分页追加到Excel文件
     */
    public function run(){
        $title = self::getTitle();  //获取字段与标题的对应关系
        $data = self::randData();   //生成所有数据
        $count = count($data);      //总记录数
        $filePath = self::copyTableToExcel($title, $data, $count);
        echo '文件保存路径为:[ ' . $filePath . ' ]';
        exit();
    }

    /**
     * 分页把table追加存入excel中
     * @param $title 字段与标题的对应关系
     * @param $data  所有数据
     * @param $count 数据的总量
     * @param int $limit 分页数量
     * @return string 结果路径
     */
    public function copyTableToExcel($title, $data, $count, $limit = 10){
        $path = 'download';         //设置文件保存的路径
        if(!file_exists($path)){    //如果目录不存在,则创建
            mkdir($path, 0777, true);
        }
        $fileName = '数据分页导出:' . time() . '_' . mt_rand(1000, 9999) . '.xlsx';   //文件名
        $filePath = $path . '/' . $fileName;    //文件保存目录

        $number = ceil($count / $limit);
        for($i = 1; $i <= $number; $i++) {  //处理分页数据
            $tableHtml = '<table border="1" cellspacing="0">';
            if($i == 1){    //第一次分页才需要设置标题,其他分页只需设置table-body即可
                $tableHtml .= '<tr>';
                foreach ($title as $value) {
                    $tableHtml .= "<th>{$value}</th>";
                }
                $tableHtml .= '</tr>';
            }

            //array_slice函数模拟分页数据
            $start = $limit * ($i-1);
            $pageSize = $limit;
            $pageData = array_slice($data, $start, $pageSize);

            $tableHtml .= self::getTableBody($pageData, $title);

            file_put_contents($filePath, $tableHtml, FILE_APPEND);
        }

        //unlink(str_replace('\\','/', $filePath));   //删除本地文件
        return $filePath;
    }

    /**
     * 处理表格Body数据
     * @param $data 当前页的数据
     * @param $title 字段与标题的对应关系
     * @return string html字符串
     */
    public function getTableBody($data, $title){
        $bodyHtml = '';    // 拼接表格body数据
        foreach ($data as $value){   //一行数据
            $bodyHtml .= '<tr>';
            foreach ($title as $field => $name){ //一行中的一列数据
                $bodyHtml .= "<td>{$value[$field]}</td>";
                //$bodyHtml .= "<td style='vnd.ms-excel.numberformat:@'>{$value[$field]}</td>";
            }
            $bodyHtml .= '</tr>';
        }

        return $bodyHtml . '</table>';
    }

    /**
     * 设置表格第一列数据
     * @return array
     */
    public function getTitle(){
        $title = [
            'id' => 'ID',
            'order_sn' => '订单号',
            'amount' => '订单金额',
            'payed_name' => '下单人',
            'create_time' => '创建时间'
        ];

        return $title;
    }

    /**
     * 生成$number条随机数据
     * @param int $number 数据的数量
     * @return array
     */
    public function randData($number = 100){
        $data = [];
        for ($x = 0; $x < $number; $x++){
            //订单号随机生成
            $prefix = '';
            if ($x%2 == 0){
                $prefix = 'HELLO';
            }
            $orderSn = $prefix . 123456 . mt_rand(1000, 9999) . mt_rand(100, 999) . 999;

            //创建时间随机生成
            $createTime = 1572 . mt_rand(100, 999) . mt_rand(100, 999);

            $data[] = [
                'id' => ($x+1),
                'order_sn' => $orderSn,
                'amount' => mt_rand(100, 999),
                'payed_name' => '下单人',
                'create_time' => date('Y-m-d H:i:s', $createTime)
            ];
        }
        return $data;
    }
}

2、【情况1】执行的结果:订单号为十几位数字时,被转成了科学计数法;创建时间也不整齐。

3、【情况2】修改

注释这一行

$bodyHtml .= "<td>{$value[$field]}</td>";

打开这一行

$bodyHtml .= "<td style='vnd.ms-excel.numberformat:@'>{$value[$field]}</td>";

结果为:

4、【情况1】11KB 和【情况2】29KB 的文件大小对比,

二、php导出数据到excel,防止身份证等数字字符格式变成科学计数的方法

#以下内容来自 https://www.cnblogs.com/jcz1206/p/3837723.html
1、首先,我们了解一下excel从web页面上导出的原理。
    当我们把这些数据发送到客户端时,我们想让客户端程序(浏览器)以excel的格式读取它,所以把mime类型设为:application/vnd.ms-excel,
    当excel读取文件时会以每个cell的格式呈现数据,如果cell没有规定的格式,则excel会以默认的格式去呈现该cell的数据。
    这样就给我们提供了自定义数据格式的空间,当然我们必须使用excel支持的格式。

2、下面就列出常用的一些格式:

    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等等。

3、那么知道了这些格式,怎么去把这些格式添加到cell中呢?
    很简单,我们只需要把样式添加到对应的标签对(即闭合标签)即可。
    如<td></td>,给标签对<td></td>添加样式,如下:

<td style="vnd.ms-excel.numberformat:@">410522198402161833</td>

    同样,我们也可以给<div></div>添加样式,也可以给<tr></tr>,<table></table>添加样式;
当我们在父标签对和子标签对都添加样式时,数据会以哪一个样式呈现呢?经过测试,会以离数据最近的样式呈现.

4、转文本使用案例如下:
1)、直接在浏览器弹出框下载

echo "<td style='vnd.ms-excel.numberformat:@'>{$orderSn}</td>";

2)、拼接字符串,直接下载到项目中

$table = "<td style='vnd.ms-excel.numberformat:@'>{$orderSn}</td>";

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值