در اولین مثال برای کار با این پکیج قصد داریم از اطلاعات مربوط به کارمندان چند شرکت که برروی دیتابیس وبسایت ما ذخیره شده است گزارشی را در قالب فایل اکسل تهیه کنیم. شمای دیتابیس مثال ما به صورت زیر خواهد بود.
همانطور که در این شِما مشاهده میکنید جدول employees با جدول companies رابطه یک به چند دارد. یعنی هر شرکت میتواند چندین کارمند داشته باشد.
فایل model مربوط به جدول employees را بصورت زیر بنویسید:
class Employee extends Model
{
protected $table = 'employees';
public $timestamps = false;
protected $dates = ['birthday'];
public function company()
{
return $this->belongsTo(Company::class);
}
}
توجه : قسمت dates برای فرمت کردن تاریخ در فایل excel ضروری است.
و فایل model مربوط به جدول companies را به این صورت بنویسید:
class Company extends Model
{
protected $table = 'companies';
public $timestamps = false;
protected $dates = ['established_at'];
public function employees()
{
return $this->hasMany(Employee::class);
}
}
توجه : قسمت dates برای فرمت کردن تاریخ در فایل excel ضروری است.
بعد از نصب پکیج laravel excel دستور make:export به لیست دستور های artisan اضافه میشود. و میتوانید از آن برای ساخت کلاسهای مربوط به خروجی هایی که میخواهید از دادههای تجمیع شده در سایت بگیرید استفاده کنید. در این دوره با این دستور خیلی کار خواهیم کرد.
برای ساخت کلاس export دستور زیر را وارد کنید. این کلاس به منظور تعیین نحوه ساخته شدن فایل excel ایجاد میشود. و تنظیمات مربوط به فایل excel تولید شده در این کلاس تعیین میشود.
$ php artisan make:export EmployeeExport
با اجرای این دستور در مسیر app/Exports یک کلاس به اسم EmployeeExport.php ایجاد میشود که به شکل زیر میباشد:
<?php
namespace App\Exports;
use Maatwebsite\Excel\Concerns\FromCollection;
class EmployeeExport implements FromCollection
{
public function collection()
{
//
}
}
حال تغییرات زیر را در فایل ایجاد کنید:
● به دلیل حجیم بودن اطلاعات جدول employees بجای استفاده از اینترفیس FromCollection از اینترفیس FromQuery استفاده میکنیم. پس بجای متد collection هم باید متد query را پیاده سازی کنیم.
به صورت کلی، اگر اطلاعاتی که میخواهیم از آنها خروجی بگیریم حجیم است، بهتر است از FromQuery استفاده شود زیرا لاراول با این دستور در پشت صحنه از chunk استفاده میکند. و سرعت پردازش دادهها بسیار بالاتر میرود.
public function query();
توجه داشته باشید که این متد باید یک شی از کلاس Builder را برگرداند.
● همچنین از اینترفیس WithHeading برای تعیین کردن سر ستون ها استفاده و متد زیر را نیز اضافه میکنیم.
public function heading(): array;
● از اینترفیس WithMapping برای تعیین اطلاعات ستون ها استفاده کرده و متد زیر را به کلاس EmployeeExport اضافه میکنیم.
public function map($row): array;
● از اینترفیس WithColumnFormatting برای اِعمال برخی تغییرات بر روی اطلاعات ستون ها استفاده میکنیم. برای مثال تغییر نحوه نمایش تاریخ ها در این متد صورت میگیرد.
public function columnFormats(): array;
● از اینترفیس ShouldAutoSize برای تعیین عرض مناسب برای هر ستون (با توجه به حجم اطلاعات هر ستون) استفاده خواهد شد.
● از اینترفیس WithEvents برای اِعمال برخی تنظیمات بر روی سلول ها با استفاده از event ها استفاده میکنیم. برای مثال bold کردن سر ستون ها در این متد مدیریت میشود.
Public function registerEvents(): array;
در نهایت انتظار میرود کلاس EmployeeExport بصورت زیر تبدیل شود:
<?php
namespace App\Exports;
use App\Employee;
use PhpOffice\PhpSpreadsheet\Shared\Date;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Events\AfterSheet;
use Maatwebsite\Excel\Concerns\WithColumnFormatting;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
class EmployeeExport implements FromQuery, WithMapping, WithHeadings, ShouldAutoSize, WithEvents, WithColumnFormatting
{
protected $employeesCount;
/**
* EmployeeExport constructor
*/
public function __construct()
{
$this->employeesCount = Employee::query()->count();
}
/**
* @return Builder
*/
public function query()
{
return Employee::query()->with('company');
}
/**
* @return array
*/
public function headings(): array
{
return [
'نام', 'شغل', 'تاریخ تولد', 'نام شرکت', 'تعداد کارمندان شرکت', 'تاریخ تاسیس شرکت'
];
}
/**
* @return array
*/
public function columnFormats(): array
{
return [
'C' => NumberFormat::FORMAT_DATE_YYYYMMDD,
'F' => NumberFormat::FORMAT_DATE_YYYYMMDD,
];
}
/**
* @param mixed $row
*
* @return array
*/
public function map($employee): array
{
return [
$employee->first_name . ' ' . $employee->last_name,
$employee->job,
Date::dateTimeToExcel($employee->birthday),
$employee->company->name,
$employee->company->employee_count,
Date::dateTimeToExcel($employee->company->established_at)
];
}
/**
* @return array
*/
public function registerEvents(): array
{
$styleArray = ['font' => ['bold' => true]];
return [
AfterSheet::class =>
function (AfterSheet $event) use ($styleArray) {
// bold heading
$event->sheet->getStyle('A1:F1')
->applyFromArray($styleArray);
// change direction to rtl
$event->sheet->setRightToLeft(true);
// center all text
$event->sheet
->getStyle("A1:F{$this->employeesCount}")
->getAlignment()->setHorizontal('center');
},
];
}
}
حالا کافیست تا یک route بسازیم تا به کمک آن فایل excel را دانلود کنیم:
Route::get('/download', function() {
return Excel::download(new EmployeeExport(), 'employees.xlsx');
});