php 导出excel问题

蜗牛奔跑 发布于 2015/08/24 15:11
阅读 846
收藏 0
PHP

//导出类

<?php 


class DownExcel
{
 
private $limit = 10000;


public function setHeader($fileName,$title){
$fileName = $this->_charset($fileName);
header("Content-Type: application/vnd.ms-excel; charset=gbk");
            header("Content-Disposition: inline; filename=\"" . $fileName . ".xls\"");
            echo "<?xml version=\"1.0\" encoding=\"gbk\"?>\n
                <Workbook xmlns=\"urn:schemas-microsoft-com🏢spreadsheet\"
                xmlns:x=\"urn:schemas-microsoft-com🏢excel\"
                xmlns:ss=\"urn:schemas-microsoft-com🏢spreadsheet\"
                xmlns:html=\"http://www.w3.org/TR/REC-html40\">";
            echo "\n<Worksheet ss:Name=\"" . $fileName . "\">\n<Table>\n";
echo $this->_addRow($this->_charset($title));
}
 
public function download($data)
{
$guard = 0;
foreach($data as $v)
{
$guard++;
if($guard==$this->limit)
{
ob_flush();
flush();
$guard = 0;
}
echo $this->_addRow($this->_charset($v));
}
}
 
    public function setFooter(){
      echo "</Table>\n</Worksheet>\n</Workbook>";
     }


private function _addRow($row)
{
$cells = "";
foreach ($row as $k => $v)
{
$cells .= "<Cell><Data ss:Type=\"String\">" . $v . "</Data></Cell>\n";
}
return "<Row>\n" . $cells . "</Row>\n";
}
 
private function _charset($data)
{
if(!$data)
{
return false;
}
if(is_array($data))
{
foreach($data as $k=>$v)
{
$data[$k] = $this->_charset($v);
}
return $data;
}
return iconv('utf-8', 'gbk', $data);
}
 
}

?>


//处理导出数据

<?php
class List  extends Controller
{
private $size =1000; //每次导出1000条
private $nums ; //导出的次数
private $data = array(); //保存导出的数据
     public function __construct() 
     {
        parent::__construct();
     }
  
     /**
* 导出数据
*/
public function export(){
set_time_limit(0);
ini_set('memory_limit','-1');
//获取对应的中文名
$lotterys = M('lotterym')->select();
$lnames = array();
if($lotterys){
foreach($lotterys as $k=>$v){
$lnames[$v['level']] = $v['lname'];
}
}
//获取配置文件信息
$level = C('level');
//获取要导出数据的总记录数
$total = M('recordm')->getExportTotal();

$this->nums = ceil($total/$this->size); //要分几次导出

for($i=0;$i<$this->nums;$i++){
$page = $i * $this->size;
$result = M('recordm')->getExportData($page,$this->size); //取出数据
$this->processList($result,$lnames,$level); //处理要导出的玩家数据数据
}

$title = array('xx', 'xx','xx', 'xx','xx','xx','xx','xx','xx','xx');
include_once APP.'/lib/DownExcel.php';
$excel = new DownExcel();
$excel->setHeader('xxx',$title);
foreach($this->data as $k=>$list){
$excel->download($list);
}
$excel->setFooter();
}


/**
* 处理要操作的数据
*/
private function  processList($result,$lnames,$level){
if($result){
foreach($result as $k=>$v){
$list = array();
$list['account'] =  $v['account'];
$list['group'] = !empty($v['group']) ? $lnames[$v['group']] :'没中奖';
$list['level'] = !empty($v['group']) ? $level[$v['group']] :'';
$list['atype'] =  $v['atype'] == 1 ? "虚拟奖" : ($v['atype'] == 2 ? '实物奖' : '');
$list['date'] =  !empty($v['date']) ? date('Y-m-d H:i:s',$v['date']) : '';
$list['name'] = ($v['atype'] == 2) ?  $v['name'] : '';
$list['card'] = ($v['atype'] == 2)  ?  $v['card'] : '';
$list['tel'] = ($v['atype'] == 2) ?  $v['tel'] : '' ;
$list['address'] = ($v['atype'] == 2) ? $v['address'] : '';
$list['addtime'] = ($v['atype'] == 2) && !empty($v['addtime']) ? date('Y-m-d H:i:s',$v['addtime']) : '' ;
$data[] = $list;
}
$this->data[] = $data;
}

}
       
}



现在的问题是导出数据在测试环境导出数据正常,在线上环境不正常,打印数组,数组只有部分打印处理,其余的数据被截断了,数组显示和什么有关系!导出的数据只有几百条就没有了,测试环境数组没有被截断,都被打印出来了。


对应大数据导出excel有什么好的解决办法,






加载中
0
~\(≧▽≦)/~
~\(≧▽≦)/~

大数据导出还是用 csv吧

配合 flush()

轻松几十万

亦可塞艇
亦可塞艇
回复 @~\(≧▽≦)/~ : 那这样的话不是会生成多个文件吗
OSC首席键客
OSC首席键客
我也感觉还不如用csv,不用库了,简单!一样excel打开!
~\(≧▽≦)/~
~\(≧▽≦)/~
回复 @还没名字 : 我是一次拿1w,处理完flush到客户端。然后继续1W,直到取完数据
亦可塞艇
亦可塞艇
数据库受的鸟吗
0
西南茂
西南茂
我用过PHP EXCEL 导出数据,但是用的时候数据量都很小,具体情况我也不清楚
0
南湖船老大
南湖船老大

PHP也有OOM(out of memory)错误,需要启动时设置最大内存。

也就是 php.ini 里的memory_limit 参数。因为导出excel 特别耗内存。

南湖船老大
南湖船老大
回复 @OSC首席键客 : phpexcel 这个类库特别费内存,简单的excel还是建议直接导出XML格式的excel,这样稍微好点,但是仍然需要加大内存
OSC首席键客
OSC首席键客
这哥说的对,我有一次也是导出excel,会截断,看一下是内存不够,我看了下128M内存不够使,我就几万条数据,也是分段刷出,试几次加大内存不够,直接给1g,够了!
0
蜗牛奔跑

引用来自“~\(≧▽≦)/~”的评论

大数据导出还是用 csv吧

配合 flush()

轻松几十万

这样也试过了,     set_time_limit(0);
    //set_time_limit(20000); 
            ini_set("memory_limit","2000M");   设置这个也不管用,在线上服务器,数组输出到几百条就被截断了,数组中每一行的内容比较多一点,导致,导出来的数据也就几百行


貌似导出csv格式也不行


public function export(){

    set_time_limit(0);
    //set_time_limit(20000); 
            ini_set("memory_limit","2000M"); 
            // 输出Excel文件头,可把user.csv换成你要的文件名
           header('Content-Type: application/vnd.ms-excel');
           header('Content-Disposition: attachment;filename="user.csv"');
           header('Cache-Control: max-age=0');
            // 从数据库中获取数据,为了节省内存,不要把数据一次性读到内存,从句柄中一行一行读即可
            // 打开PHP文件句柄,php://output 表示直接输出到浏览器
            $fp = fopen('php://output', 'a');
            $head = array('xx', 'xx','xx', 'xx','xx','xx','xx','xx','xx','xx','xx','xx','xx','xx','xx');
           /* foreach ($head as $i => $v) {         
            // CSV的Excel支持GBK编码,一定要转换,否则乱码
            $head[$i] = iconv('utf-8', 'gbk', $v);
            }*/
            // 将数据通过fputcsv写到文件句柄
            fputcsv($fp, $head);
            //数据库连接  
            $link = mysql_connect("localhost", "root", "111111");  
            mysql_select_db("test",$link);  //选择数据库,这里为"ywcl"。  
            mysql_query("SET NAMES UTF8",$link); //设定编码方式为UTF8  
            $dbname = 'test_'.date('Y');
            $sql = "SELECT * FROM {$dbname} WHERE  (status =1 OR status=3)  ORDER BY click DESC,id ASC ";
            $result=mysql_query($sql,$link); 
            // 计数器
            $cnt = 0;
            // 每隔$limit行,刷新一下输出buffer,不要太大,也不要太小
            $limit = 100;
            // 逐行取出数据,不浪费内存
             while($row=mysql_fetch_assoc($result)){ 
                    $cnt ++;
                    if ($limit == $cnt) { //刷新一下输出buffer,防止由于数据过多造成问题
                        ob_flush();
                        flush();
                        $cnt = 0;
                    }
                    $account = $row['account'];
                    $gameid = $row['gameid'];
                    $nickname = $row['nickname'];
                    $zone_server = $row['zone_server'];
                    $star = $row['star'];
                    $address = $row['address'];
                    $click = $row['click'];
                    $order = $orders[$row['id']]['order'];
                    $status = $types[$row['status']];
                    $addtime = date('Y-m-d H:i:s',$row['addtime']);


                   $data = array($account,$gameid,$nickname,$zone_server,$star,$address,$click,$order,$status,$addtime);


                   fputcsv($fp, $data); 
                } 
    }
~\(≧▽≦)/~
~\(≧▽≦)/~
你这个本地没问题的话,看看线上的nginx 配置。是不是控制了输出大小限制
返回顶部
顶部