获取数据库数据生成excel文件方法

1.使用插件的方式

https://docs.laravel-excel.com/3.1/imports/batch-inserts.html

   1.安装插件

composer require maatwebsite/excel
2.创建一个操作导出表的类
php artisan make:export UsersExport   在app/Exports文件夹中生成UsersExport.php
<?php

namespace App\Exports;

use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\WithHeadings;
class SellExport implements FromCollection, WithMapping, WithHeadings
{
    public function __construct(){
        //传参数时可以在构造函数中初始化
    }
    /**
    * @return \Illuminate\Support\Collection
    */
    public function collection()
    {
        //跨数据库操作表
        $db = \DB::connection('old_mysql');
            $result = $db->table('student as s')->select([
                \DB::raw("sum(s.score) as total"),
                's.number',
                's.name',
                'g.phone',
            ])->leftJoin('gift as g', 'g.sid', '=', 's.gid')
                ->groupBy('s.number')
                ->orderBy('total')->get();
        return $result;
//同时也可以用模型操作比如:return User::all();
    }
    //生成excel表的字段名
    public function headings(): array
    {
        return [
            'total',
            'sales',
            'goods_code',
            'goods_barcode',
            'store_code',
            'date',
            'cn_name',
            'retail_price',
            'cost_price',
            'package_qty',
            'price',
        ];
    }
//返回每个字段的值,$sell是collection中return 后遍历的值
    public function map($sell): array
    {
        return [
            $sell->total,
            $sell->sales,
            is_numeric($sell->goods_code) ? $sell->goods_code . "\t" : $sell->goods_code,
            is_numeric($sell->goods_barcode) ? $sell->goods_barcode . "\t" : $sell->goods_barcode,
            $sell->store_code,
            $sell->date,
            $sell->cn_name,
            $sell->retail_price,
            $sell->cost_price,
            $sell->package_qty,
            $sell->price,
        ];
    }
}
          //这里只是一个例子,其它的操作可以查看文档   
在控制器中调用下载
use Maatwebsite\Excel\Facades\Excel;
$file = 'public/sell/'.$year.'-'.$month.'.xlsx';//默认是根目录下的storage/app
Excel::store(new SellExport(), $file);//store有多个参数,详细可以子在文档中找

 

 
 

2.使用php的csv方式,结合php生成器(yield),减少内存的占用,(生成csv文件后,可以在桌面保存为excel文件),原生操作数据库

private function generateCsv(){
        $file = storage_path().'/app/public/sell/'.date('Y-m',strtotime('-1 month')).'.csv'; //生成的csv文件路径
    //链接数据库参数
$url='localhost';//主机 $username='root';//用户名 $pwd='root';//用户密码 $database='database_name';//数据库名 $charset='utf8';//字符集 $name='user';//数据表名 $fp = fopen($file, 'a+');//存在打开文件资源,不存在就创建(追加方式)
      //csv文件内容头部
        $csv_header = ['id','name','age'];
        fputcsv($fp,$csv_header);//使用fputcsv写入csv文件
        foreach($this->select($url,$username,$pwd,$database,$charset,$name) as $value){
            fputcsv($fp,$value);//使用yield每次获取一条数据写入到csv文件
        }
        fclose($fp);
    }
    
    private function select($url='',$username='',$pwd='',$database='',$charset='',$name=''){
        $link = mysqli_connect($url,$username,$pwd);
        if(mysqli_connect_errno($link)>0){
            die(mysqli_connect_error($link));
        }
        mysqli_set_charset($link,$charset);
        mysqli_select_db($link,$database);
        $sql = "select id,name,age from user";$res = mysqli_query($link,trim($sql));//成功返回true否则false
    //
mysqli_fetch_assoc($res)逐条获取,每次都是一条关联数组数据
    while($result = mysqli_fetch_assoc($res)){ 
      yield
$result;
    }
    mysqli_close($link);
}

 3.laravelDB类操作数据库

使用DB类获取数据生成csv
//生成指定时间段表数据的csv文件
private function select()
    {
        $start_date = date('Y-m', strtotime('-1 month'));
        $end_date = date('Y-m');
        $file = storage_path().'/app/public/sell/'.date('Y-m', strtotime('-1 month')).'.csv';
        $fp = fopen($file, 'a+');//打开csv文件,没有就自动创建
        $csv_header = ['total','sales','goods_code','goods_barcode','store_code','date','cn_name','retail_price','cost_price','package_qty','price'];
        fputcsv($fp, $csv_header);//插入字段名
    //获取某时间段的所有数据,使用生成器yield返回单条数据
function getData($start_date, $end_date) {
        //$dataname是数据库名,也可以在/config/database.php设置
$db = DB::connection($dataname); $result = $db->table('user as s')->select([ DB::raw("sum(s.count) as total"), DB::raw("sum(s.price) as sales"), 's.name', 'p.cn_name', ])->leftJoin('phone as p', 'g.user_id', '=', 's.id') ->where('s.date', '>=', $start_date) ->where('s.date', '<', $end_date) ->groupBy('s.goods_code', 's.store_code', 's.date') ->orderBy('total')->get()->map(function ($item) { return (array)$item;//通过get()获取到的是集合对象,将内存对象通过map返回数组,内层对象就转为数组, }); foreach ($result as $item) {
            //如果在csv表中字段值以科学计数法显示加上这个"\t"
          $item['goods_barcode'] = is_numeric($item['goods_barcode']) ? $item['goods_barcode'] . "\t" : $item['goods_barcode'];

                yield $item;//生成器返回的是一维数组
            }
        };
    //调用函数,获取生成器的数据,通过遍历获取
foreach (getData($start_date, $end_date) as $data) { fputcsv($fp, $data);//$data要是一维数组才行 } fclose($fp); }

 

posted @ 2020-11-10 17:53  小林不会飞  阅读(722)  评论(0编辑  收藏  举报