PHP

PHP导出Excel、CSV

字号+ 编辑: 秦朝 修订: 秦朝 来源: 利志分享 2015-02-07 11:40:55 我要说两句(0)

PHP导出大量数据应该使用ob_flush(),flush()来强制卸载旧的缓存。而其中CSV较各类Excel版本的好处就是在于没有限制, 可以用CSV做导入导出的业务。

要点一:

对于导出大量数据不能使用Excel,会导致输出数据不全。

Excel2003限制为65536行就Excel2007限制为1048576行

对于CSV目前对数据量没有限制,所以大量数据导出选用。


要点二:

PHP处理大数据导出时,要强行刷出缓存在服务器和WEB浏览器中的缓存,避免爆内存。

使用的函数:ob_flush()  flush()同时使用才会奏效。


生成EXCEL的三张方法:

  1. excel:[\t \n]

  2. csv: [, \n]

  3. csv: [fputcsv] PHP函数

1.导出EXCEL:

主要使用声明头文件、输出格式使用[\t \n]

//导出Excel:单元格'\t'分隔,换行\n
header("Content-type:application/vnd.ms-excel");
header("Content-Disposition:filename=excel.xls");
echo "A1\t B1\t C1\n";
echo "A2\t B2\t C2\n";
echo "A3\t B3\t c3\n";

2.导出CSV:

主要使用声明头文件、输出格式使用[ , \n]

//导出CSV:单元格','分隔,换行\n
header('Content-Type: application/vnd.ms-excel');
header('Content-Disposition: attachment;filename=csv.csv');
header('Cache-Control: max-age=0');
echo "A1, B1, C1\n";
echo "A2, B2, C2\n";
echo "A3, B3, c3\n";

3.导出大量数据:

百万以上的实现如下(注意不要一次获取mysql大量数据,可以去ID再去生成CSV,在循环去库中拿数据)fputcsv

set_time_limit(0);
error_reporting(0);
// 输出Excel文件头,可把user.csv换成你要的文件名
header('Content-Type: application/vnd.ms-excel');
header('Content-Disposition: attachment;filename="user.csv"');
header('Cache-Control: max-age=0');
$fp = fopen('/tmp/export/data.csv', 'a');
$head = array('UID', 'EMAIL', '注册时间', '第一次登陆时间');
foreach ($head as $i => $v) {
    // CSV的Excel支持GBK编码,一定要转换,否则乱码
    $head[$i] = iconv('utf-8', 'gbk', $v);
}
fputcsv($fp, $head);
$result = array(.................................);
foreach($resutl as $val){
    ob_flush();
    flush();
     // 从数据库中获取数据,为了节省内存,不要把数据一次性读到内存,从句柄中一行一行读即可
    $sql = "SELECT uid,email,regdate,lastlogintime FROM reg_members WHERE email in ($val) ORDER BY uid ASC, regdate ASC";
    $query = $db_reg_read -> query($sql);
    while ($res = $db_reg_read -> fetch_array($query)) {
        $email = strtolower($res['email']);
        $list[] = $res;
    }
    //对数据进行整理
    //输入到CSV中
    foreach($list as $key => $val){
        $row[0] = iconv('utf-8', 'gbk', $val['uid']);
        $row[1] = iconv('utf-8', 'gbk', $val['email']);
        $row[2] = iconv('utf-8', 'gbk', $val['regdate']);
        $row[3] = iconv('utf-8', 'gbk', $val['lastlogintime']);
        fputcsv($fp, $row);
    }
}

PHP导入导出csv文件的案例

以下列举一些实际项目中的代码来说明csv的导入导出:

导入Excel

/**
 * 导入目标数据
 * @param  string  $tmp_filename  临时文件地址
 */
public function importTargetData()
{
    ignore_user_abort();
    @ini_set('max_execution_time', '300');
    try {
        $fileName   = $this->checkCsvFile();
        $common     = new Common();
        $totalLines = $common->getFileLineNumber($fileName);
        if ($totalLines < 2) {
            throw new \Exception('文件是空的');
        }
        if ($totalLines >= 10000) {
            throw new \Exception('行数太多,不能接受');
        }
        // 清理中间库
        MmAchievementShop::onWriteConnection()->whereIn('availability', [0, 1, 2, 3])->delete();
        // 步长
        $num = 150;
        // 行数
        $s = 2;
        for ($i = 2; $i <= $totalLines; $i += $num) {
            // 完善字段
            $data    = [];
            $csvData = $common->getCsvLines($fileName, $i, $i + $num - 1);
            // 处理数据
            foreach ($csvData as $line => $v) {
                // 处理字段进行操作
                if (empty($v[0]) || empty($v[1]) || empty($v[2]) || empty($v[3])) {
                    if (empty($v[0]) && empty($v[1]) && empty($v[2]) && empty($v[3])) {
                        // 完全就是个空行
                        continue;
                    } else {
                        throw new \Exception('存在残缺表数据[' . $s . ']');
                    }
                }
            }
            unset($csvData);
            $s++;
        }
        return true;
    } catch (\Exception $e) {
        return $e->getMessage();
    }
}

导出Excel

一个下载csv文件模板的程序例子


public function makeCsvTemplate()
{
    @ini_set('memory_limit', '400M');
    @ini_set('max_execution_time', '0');
    $filename = '目标与完成度' . date('YmdHis') . '.csv';
    header("Content-type:text/csv");
    header("Content-Disposition:attachment;filename=" . $filename);
    header('Cache-Control: max-age=0');
    $fp = fopen('php://output', 'a');
    // csv的列名
    $i          = 0;
    $contentArr = [];
    $headerList = Config('c2bData.targetColumnName');
    foreach ($headerList as $v) {
        $v = str_replace(array(
            "\r\n",
            "\r",
            "\n",
        ), '', $v);
        $contentArr[$i] = iconv('utf-8', 'gbk//IGNORE', $v);
        $i++;
    }
    fputcsv($fp, $contentArr);
    $contentList = [];
    // 查询对象
    $contentList[] = $this->formatExportStr('全国');
    // 月份
    $contentList[] = $this->formatExportStr('2017#01');
    // 线索转化率目标值
    $contentList[] = $this->formatExportStr('0.10%');
    // 门店-单车利润目标值
    $contentList[] = $this->formatExportStr('2000');
    fputcsv($fp, $contentList);
    $currentDate = date('Ym', time());
    $sampleList = BiC2bTarget::whereIn('query_type', [2, 3, 4])
        ->where('date_month', $currentDate)
        ->orderBy('query_type', 'asc')
        ->lists('object_name')->toArray();
    $countOfList = count($sampleList);
    for ($i = 0; $i < $countOfList; ++$i) {
        $contentList = [];
        // 查询对象
        $contentList[] = $this->formatExportStr($sampleList[$i]);
        // 月份
        $contentList[] = '';
        // 线索转化率目标值
        $contentList[] = '';
        // 门店-单车利润目标值
        $contentList[] = '';
        fputcsv($fp, $contentList);
    }
}

导出的例子

/**
 * 导出
 * 鬼知道数据库里都是什么格式的数据,为了防止导出乱码,一律使用了formatExportStr进行转码
 */
public function exportAchievementData($request)
{
    @ini_set('memory_limit', '400M');
    @ini_set('max_execution_time', '0');
    $filename = '目标与完成度' . date('YmdHis') . '.csv';
    header("Content-type:text/csv");
    header("Content-Disposition:attachment;filename=" . $filename);
    header('Cache-Control: max-age=0');
    $fp = fopen('php://output', 'a');
    // csv的列名
    $i          = 0;
    $contentArr = [];
    $headerList = Config('c2bData.exportAchiList');
    foreach ($headerList as $v) {
        $v = str_replace(array(
            "\r\n",
            "\r",
            "\n",
        ), '', $v);
        $contentArr[$i] = iconv('utf-8', 'gbk//IGNORE', $v);
        $i++;
    }
    fputcsv($fp, $contentArr);
    unset($contentArr, $headerList);
    $objArr = $this->getDataBySearcher($request);
    foreach ($objArr as $v) {
        $contentList = [];
        // 查询对象
        $contentList[]   = $this->formatExportStr($v['object_name']);
        $v['date_month'] = $this->formatMonthData((string) $v['date_month']);
        // 月份
        $contentList[] = $this->formatExportStr($v['date_month']);
        // 线索转化率目标值
        $contentList[] = $this->formatExportStr($v['target_clue']);
        // 线索实际值
        $contentList[] = $this->formatExportStr($v['actual_clue']);
        // 线索完成度
        $contentList[] = $this->formatExportStr($v['complete_clue']);
        // 门店-单车利润目标值
        $contentList[] = $this->formatExportStr($v['target_profit']);
        // 门店实际值
        $contentList[] = $this->formatExportStr($v['actual_profit']);
        // 门店完成度
        $contentList[] = $this->formatExportStr($v['complete_profit']);
        // 线索量(条)
        $contentList[] = $this->formatExportStr($v['clue']);
        // 计划收购量
        $contentList[] = $this->formatExportStr($v['target_buy']);
        // 实际收购量
        $contentList[] = $this->formatExportStr($v['buy']);
        // 收购差异(台)
        $contentList[] = $this->formatExportStr($v['diff_buy']);
        fputcsv($fp, $contentList);
    }
}

过滤并转码的例子

/**
 * 过滤并转码导出至csv的数据
 * @param  string $str
 * @return string $str
 */
public function formatExportStr($str)
{
    if (!empty($str)) {
        $str = iconv('utf-8', 'gbk//IGNORE', str_replace(array(
            "\r\n",
            "\r",
            "\n",
        ), '', $str));
    }
    return $str;
}
阅完此文,您的感想如何?
  • 鼓掌

    1

  • 鄙视

    0

  • 开心

    0

  • 愤怒

    0

  • 可怜

    0

1.转来的文章都会标好来源,如对来源资料存疑,请邮件声明;
2.本站标注原创的文章,转发时烦请注明来源;
3.如文章侵犯了您的版权,请通知本站,该文章将在24小时内移除。

相关课文
  • pecl安装swoole报错 error

  • php针对mysql的orm: 一个轻量级的pdo操作类

  • shell_exec() has been disabled for security reasons 解决方法

  • PHP框架全部显得多余的4种原因

我要说说
网上宾友点评