Thực hiện chức năng xuất Excel danh sách Sản phẩm (excel)

Cài đặt thư viện xuất Excel
composer require maatwebsite/excel

Mô hình hoạt động của excel:

Step 1: tạo route xuất Excel Danh mục sản phẩm

  • Hiệu chỉnh file routes/web.php
Route::get('/admin/sanpham/excel', 'Backend\SanPhamController@excel')->name('admin.sanpham.excel');

Step 2: tạo nút nhấn Xuất Excel trên giao diện index:

  • Hiệu chỉnh file resources/views/sanpham/index.blade.php
<!-- Tạo nút Xuất Excel danh sách sản phẩm
- Theo quy ước, các route đã được đăng ký trong file `web.php` đều phải được đặt tên để dễ dàng bảo trì code sau này.
- Đường dẫn URL là đường dẫn được tạo ra bằng route có tên `admin.sanpham.excel`
- Sẽ có dạng http://tenmiencuaban.com/admin/sanpham/excel
-->
<a href="{{ route('admin.sanpham.excel') }}" class="btn btn-primary">Xuất Excel</a>

Step 3: thực hiện tạo class Quản lý việc xuất dữ liệu ra Excel SanPhamExport

  • Tạo class SanPhamExport bằng câu lệnh
php artisan make:export SanPhamExport
  • Laravel Framework sẽ tạo cho bạn file export ở app\Exports\SanPhamExport.php
Viết code quản lý việc xuất Excel:
<?php

namespace App\Exports;

use App\SanPham;
use App\Loai;
use Illuminate\Contracts\View\View;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\RegistersEventListeners;
use Maatwebsite\Excel\Concerns\FromView;
use Maatwebsite\Excel\Concerns\WithDrawings;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Maatwebsite\Excel\Events\AfterSheet;
use Maatwebsite\Excel\Events\AfterImport;
use Maatwebsite\Excel\Events\BeforeSheet;
use Maatwebsite\Excel\Events\BeforeExport;
use Maatwebsite\Excel\Events\BeforeImport;
use Maatwebsite\Excel\Events\BeforeWriting;

class SanPhamExport implements FromView, WithDrawings, WithEvents, ShouldAutoSize
{
    use Exportable, RegistersEventListeners;

    public function view(): View
    {
        return view('backend.sanpham.excel', [
            'danhsachsanpham' => SanPham::all(),
            'danhsachloai' => Loai::all(),
        ]);
    }

    /**
     * @return BaseDrawing|BaseDrawing[]
     */
    public function drawings()
    {
        $arrDrawings = [];

        // Hình logo
        $drawingLogo = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing();
        $drawingLogo->setName('Logo');
        $drawingLogo->setDescription('Logo');
        $drawingLogo->setPath(public_path('img/logo-nentang.jpg'));
        $drawingLogo->setHeight(90);
        $drawingLogo->setCoordinates('C4');
        $offsetX = 40; //pixels
        $drawingLogo->setOffsetX($offsetX); //pixels
        $arrDrawings[] = $drawingLogo;

        // Dòng bắt đầu xuất Excel danh sách sản phẩm
        $startRow = 7;

        // Lấy danh sách Sản Phẩm
        $ds_sanpham = SanPham::all();
        foreach($ds_sanpham as $index=>$sp)
        {
            $drawing = new \PhpOffice\PhpSpreadsheet\Worksheet\Drawing();
            $drawing->setName($sp->sp_ten);
            $drawing->setDescription($sp->sp_thongTin);
            $drawing->setPath(public_path('storage/photos/' . $sp->sp_hinh));
            $drawing->setHeight(40);
            $drawing->setWidth(40);
            $drawing->setCoordinates('B' . ($startRow + $index));
            $arrDrawings[] = $drawing;
        }

        return $arrDrawings;
    }

    /* Event beforeExport
    */
    public static function beforeExport(BeforeExport $event)
    {
        //
    }

    /* Event beforeWriting
    */
    public static function beforeWriting(BeforeWriting $event)
    {
        //
    }

    /* Event beforeSheet
    */
    public static function beforeSheet(BeforeSheet $event)
    {
        //
    }

    /* Event afterSheet
    */
    public static function afterSheet(AfterSheet $event)
    {
        // Set khổ giấy in ngang
        $event->sheet->getDelegate()->getPageSetup()
            ->setOrientation(\PhpOffice\PhpSpreadsheet\Worksheet\PageSetup::ORIENTATION_LANDSCAPE);

        // Set dòng 4 (dùng chứ ảnh logo) có chiều cao 100
        $event->sheet->getDelegate()->getRowDimension('4')->setRowHeight(100);

        // Format dòng tiêu đề giới thiệ "Công ty"
        $event->sheet->getDelegate()->getStyle('A1:C5')->applyFromArray(
            [
                'font' => [
                    'bold' => true,
                ],
                'alignment' => [
                    'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
                ]
            ]
        );

        // Format dòng tiêu đề "Danh sách sản phẩm"
        $event->sheet->getDelegate()->getStyle('A5:F5')->applyFromArray(
            [
                'font' => [
                    'bold' => true,
                ],
                'alignment' => [
                    'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
                ]
            ]
        );

        // Format dòng tiêu đề "Tiêu đề cột"
        $event->sheet->getDelegate()->getStyle('A6:F6')->applyFromArray(
            [
                'font' => [
                    'bold' => true,
                ],
                'alignment' => [
                    'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
                ],
                'borders' => [
                    'outline' => [
                        'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,
                        'color' => ['argb' => '00000000'],
                    ],
                ]
            ]
        );

        // Dòng bắt đầu xuất Excel danh sách sản phẩm
        $startRow = 7;

        // Lấy danh sách Sản Phẩm, set độ cao của dòng là 50
        $ds_sanpham = SanPham::all();
        foreach($ds_sanpham as $index=>$sp)
        {
            $currentRow = $startRow + $index;
            $event->sheet->getDelegate()->getRowDimension($currentRow)->setRowHeight(50);

            $coordinate = "A${currentRow}:F${currentRow}";
            $event->sheet->getDelegate()->getStyle($coordinate)->applyFromArray(
                [
                    'alignment' => [
                        'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_LEFT,
                    ],
                    'borders' => [
                        'outline' => [
                            'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,
                            'color' => ['argb' => '00000000'],
                        ],
                    ]
                ]
            );
        }
    }
}

Step 4: viết code action

Viết code cho action excel():

  • Action excel() dùng để lấy danh sách sản phẩm có trong table sanphamvà xuất thành file EXCEL "xlsx" cho người dùng download về.
Hiệu chỉnh file app\Http\Controllers\SanphamController.php
use App\Exports\SanPhamExport;
use Maatwebsite\Excel\Facades\Excel as Excel;

/**
 * Action xuất Excel
 */
public function excel() 
{
    /* Code dành cho việc debug
    - Khi debug cần hiển thị view để xem trước khi Export Excel
    */
    // $ds_sanpham = Sanpham::all();
    // $ds_loai    = Loai::all();
    // return view('backend.sanpham.excel')
    //     ->with('danhsachsanpham', $ds_sanpham)
    //     ->with('danhsachloai', $ds_loai);

    return Excel::download(new SanPhamExport, 'danhsachsanpham.xlsx');
}
Tạo view excel.blade.php
  • Để dễ dàng quản lý các view, ta sẽ tạo 1 thư mục tương ứng với tên Controller, mỗi action sẽ tương ứng với tên view.
  • Tạo folder resources/views/backend/sanpham
  • Tạo file resources/views/backend/sanpham/excel.blade.php
<!DOCTYPE html>
<html>

<head>
    <title>Danh sách sản phẩm</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <style type="text/css">
        * {
            font-family: DejaVu Sans, sans-serif;
        }
    </style>
</head>

<body style="font-size: 10px">
    <div class="row">
        <table border="0" align="center" cellpadding="5" style="border-collapse: collapse;">
            <tr>
                <td colspan="6" align="center" style="font-size: 13px;" width="100">
                    <b>Công ty TNHH Sunshine</b></td>
            </tr>
            <tr>
                <td colspan="6" align="center" style="font-size: 13px">
                    <b>http://sunshine.com/</b></td>
            </tr>
            <tr>
                <td colspan="6" align="center" style="font-size: 13px">
                    <b>(0292)3.888.999 # 01.222.888.999</b></td>
            </tr>
            <tr>
                <td colspan="6" align="center">
                    {{-- Đây là khoảng trống dùng để chèn ảnh LOGO bằng Laravel Excel --}}
                    {{-- Khi hiển thị ảnh để xem trên WEB -> sử dụng đường dẫn URL bằng hàm asset() --}}
                    {{-- Khi xuất file Excel, muốn chèn hình ảnh phải sử dụng đường dẫn PATH bằng hàm public_path() --}}
                    
                    {{-- Nếu muốn debug để xem mẫu in, bỏ comment dòng dưới đây --}}
                    {{-- <img src="{{ asset('img/logo-nentang.jpg') }}" /> --}}
                </td>
            </tr>
            <tr>
                <td colspan="6" class="caption" align="center" style="text-align: center; font-size: 20px">
                    <b>Danh sách sản phẩm</b>
                </td>
            </tr>
            <tr style="border: 1px thin #000">
                <th style="text-align: center">STT</th>
                <th style="text-align: center">Hình sản phẩm</th>
                <th style="text-align: center">Tên sản phẩm</th>
                <th style="text-align: center">Giá gốc</th>
                <th style="text-align: center">Giá bán</th>
                <th style="text-align: center">Loại sản phẩm</th>
            </tr>
            @foreach ($danhsachsanpham as $sp)
            <tr style="border: 1px thin #000">
                <td align="center" valign="middle" width="5">
                    {{ $loop->index + 1 }}
                </td>
                <td align="center" valign="middle" width="20" height="110">
                    {{-- Đây là khoảng trống dùng để chèn ảnh LOGO bằng Laravel Excel --}}
                    {{-- Khi hiển thị ảnh để xem trên WEB -> sử dụng đường dẫn URL bằng hàm asset() --}}
                    {{-- Khi xuất file Excel, muốn chèn hình ảnh phải sử dụng đường dẫn PATH bằng hàm public_path() --}}
                    
                    {{-- Nếu muốn debug để xem mẫu in, bỏ comment dòng dưới đây --}}
                    {{-- <img class="hinhSanPham" src="{{ asset('storage/photos/' . $sp->sp_hinh) }}" width="100" height="100" /> --}}
                </td>
                <td align="left" valign="middle" width="30">{{ $sp->sp_ten }}</td>
                <td align="right" valign="middle" width="15">{{ $sp->sp_giaGoc }}</td>
                <td align="right" valign="middle" width="15">{{ $sp->sp_giaBan }}</td>
                @foreach ($danhsachloai as $l)
                    @if ($sp->l_ma == $l->l_ma)
                    <td align="left" width="15" valign="middle">{{ $l->l_ten }}</td>
                    @endif
                @endforeach
            </tr>
            @endforeach
        </table>
    </div>
</body>

</html>