Gratis update & dukungan instalasi

Tutorial Website 15 Oct 2026

Cara Export Data ke Excel di Laravel: Laporan Transaksi Rapi dengan Styling (2026)

R Oleh renz mobellgnd
Cara Export Data ke Excel di Laravel: Laporan Transaksi Rapi dengan Styling (2026)

Cara Export Data ke Excel di Laravel: Laporan Transaksi Rapi dengan Styling (2026)

Fitur export Excel di Laravel paling mudah dibuat dengan package maatwebsite/excel (Laravel Excel): install via Composer, buat Export class yang mengimplementasikan FromCollection + WithHeadings, lalu panggil Excel::download(new TransactionsExport, 'laporan.xlsx') dari controller — file .xlsx langsung terunduh. Panduan ini membawa satu langkah lebih jauh: laporan transaksi dengan header Bahasa Indonesia, format rupiah, styling header profesional, dan multiple sheet, plus strategi untuk data besar.

Apa Itu Laravel Excel (maatwebsite/excel)?

Laravel Excel adalah package open-source dari Maatwebsite yang dibangun di atas PhpSpreadsheet. Ia menyediakan concern-concern siap pakai untuk mengubah data Eloquent, collection, atau Blade view menjadi file .xlsx, .csv, bahkan .pdf.

Fitur ini hampir wajib ada di source code produk seperti toko online, aplikasi kasir, atau sistem informasi: pemilik bisnis butuh tombol "Unduh Laporan" untuk rekap transaksi, daftar produk, atau data member. Kalau kamu menjual source code, laporan Excel yang rapi (bukan tabel polos) adalah nilai jual yang nyata — dan ini melengkapi fitur cetak invoice PDF otomatis yang sudah kita bahas sebelumnya.

Batasan yang perlu kamu tahu: export berjalan sinkron di request HTTP. Untuk puluhan ribu baris, proses bisa memakan memori besar dan timeout. Nanti di bagian akhir kita bahas solusinya (FromQuery + queue). Cara ini juga kurang cocok kalau kamu butuh file dengan rumus Excel kompleks yang interaktif — untuk itu PhpSpreadsheet mentah lebih tepat.

Langkah 1: Install Package

composer require maatwebsite/excel

Setelah terinstall, publish file konfigurasinya (opsional tapi disarankan agar bisa mengatur default disk dan chunk size):

php artisan vendor:publish --provider="Maatwebsite\Excel\ExcelServiceProvider" --tag=config

Perintah di atas membuat config/excel.php. Untuk Laravel 8–11, package versi 3.1.x adalah rilis stabil yang umum dipakai; selalu cocokkan versi package dengan versi Laravel di project-mu lewat dokumentasi resmi di docs.laravel-excel.com.

Langkah 2: Buat Export Class untuk Laporan Transaksi

Generate class export dengan artisan:

php artisan make:export TransactionsExport

File app/Exports/TransactionsExport.php terbuat. Sekarang isi dengan concern yang kita butuhkan: FromCollection (sumber data), WithHeadings (baris judul kolom), dan WithMapping (mengubah tiap baris sebelum ditulis — di sinilah kita format rupiah dan relasi):

<?php

namespace App\Exports;

use App\Models\Transaction;
use Maatwebsite\Excel\Concerns\FromCollection;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;

class TransactionsExport implements FromCollection, WithHeadings, WithMapping
{
public function __construct(
protected string $startDate,
protected string $endDate,
) {}

public function collection()
{
return Transaction::with('customer')
->whereBetween('created_at', [$this->startDate, $this->endDate])
->orderBy('created_at')
->get();
}

public function headings(): array
{
return [
'No. Invoice',
'Tanggal',
'Pelanggan',
'Total (Rp)',
'Status',
];
}

public function map($transaction): array
{
return [
$transaction->invoice_number,
$transaction->created_at->format('d/m/Y H:i'),
$transaction->customer->name,
$transaction->total, // biarkan angka mentah, diformat di WithColumnFormatting
ucfirst($transaction->status),
];
}
}

Trik penting di map(): kolom total dibiarkan sebagai angka mentah, bukan string "Rp 150.000". Kenapa? Karena angka mentah bisa dijumlahkan (SUM) di Excel dan diformat sebagai mata uang lewat WithColumnFormatting — jauh lebih profesional daripada teks.

Langkah 3: Styling Profesional — Header Bold, AutoSize, Format Rupiah

Export polos terlihat murahan. Tambahkan tiga concern ini agar laporan terlihat seperti dibuat aplikasi berbayar:

use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Maatwebsite\Excel\Concerns\WithColumnFormatting;
use Maatwebsite\Excel\Concerns\WithStyles;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;

class TransactionsExport implements
FromCollection, WithHeadings, WithMapping,
ShouldAutoSize, WithColumnFormatting, WithStyles
{
// ... collection(), headings(), map() seperti di atas

public function styles(Worksheet $sheet)
{
return [
1 => [
'font' => ['bold' => true, 'color' => ['argb' => 'FFFFFFFF']],
'fill' => [
'fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID,
'startColor' => ['argb' => 'FF1F4E79'],
],
],
];
}

public function columnFormats(): array
{
return [
'D' => '#,##0', // format rupiah: 150000 -> 150.000
];
}
}

Hasilnya: baris pertama (header) tampil bold dengan background biru navy, lebar kolom menyesuaikan isi otomatis (ShouldAutoSize), dan kolom Total tampil sebagai angka ribuan ala Indonesia. Concern WithStyles tersedia sejak versi 3.1.21 — kalau project-mu memakai versi lebih lama, update dulu dengan composer update maatwebsite/excel.

Langkah 4: Multiple Sheet — Rekap + Detail dalam Satu File

Laporan yang bagus biasanya punya sheet ringkasan di depan dan data mentah di belakang. Gunakan WithMultipleSheets:

<?php

namespace App\Exports;

use Maatwebsite\Excel\Concerns\WithMultipleSheets;

class FullReportExport implements WithMultipleSheets
{
public function __construct(
protected string $startDate,
protected string $endDate,
) {}

public function sheets(): array
{
return [
'Rekap' => new SummaryExport($this->startDate, $this->endDate),
'Detail' => new TransactionsExport($this->startDate, $this->endDate),
];
}
}

SummaryExport bisa berupa class sederhana berbasis FromArray yang berisi total omzet, jumlah transaksi, dan rata-rata per hari. Satu file, dua sheet — persis seperti laporan yang diminta akuntan.

Langkah 5: Controller, Route, dan Tombol Unduh

Di controller, terima parameter rentang tanggal lalu trigger download:

<?php

namespace App\Http\Controllers;

use App\Exports\FullReportExport;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Facades\Excel;

class ReportController extends Controller
{
public function exportTransactions(Request $request)
{
$request->validate([
'start_date' => 'required|date',
'end_date' => 'required|date|after_or_equal:start_date',
]);

$filename = 'laporan-transaksi-'
. $request->start_date . '-sd-' . $request->end_date . '.xlsx';

return Excel::download(
new FullReportExport($request->start_date, $request->end_date),
$filename
);
}
}

Daftarkan route-nya:

Route::get('/laporan/transaksi/export', [ReportController::class, 'exportTransactions'])
->name('laporan.transaksi.export')
->middleware('auth');

Dan tombol di Blade (misalnya di halaman laporan admin):

<form action="{{ route('laporan.transaksi.export') }}" method="GET" class="d-inline">
<input type="date" name="start_date" required>
<input type="date" name="end_date" required>
<button type="submit" class="btn btn-success">Unduh Excel</button>
</form>

Catatan keamanan: route export wajib di belakang auth (dan idealnya middleware role admin). Jangan pernah membiarkan URL export bisa diakses publik — itu sama saja membocorkan seluruh data transaksimu. Prinsip yang sama berlaku untuk proteksi umum website, seperti yang dibahas di panduan mengamankan website setelah beli source code.

Langkah 6: Menangani Data Besar — FromQuery + Queue

FromCollection memuat semua data ke memori sekaligus. Untuk laporan di atas ~10.000 baris, ganti dengan FromQuery yang otomatis men-chunk query:

use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\Exportable;
use Illuminate\Contracts\Queue\ShouldQueue;

class BigTransactionsExport implements FromQuery, WithHeadings, WithMapping, ShouldQueue
{
use Exportable;

public function query()
{
return Transaction::query()->orderBy('id'); // dijalankan per chunk 1000 baris
}
}

Dengan ShouldQueue, export berjalan di background. Polanya: simpan ke disk dengan Excel::store() (bukan download), lalu kirim link unduhan ke user lewat notifikasi — misalnya notifikasi WhatsApp otomatis atau email. Pastikan queue worker berjalan; kalau belum paham konsepnya, baca dulu panduan kirim email dengan queue di Laravel.

Perbandingan: FromCollection vs FromQuery vs FromView

Pendekatan Cocok untuk Kelebihan Kekurangan
FromCollectionData < 10rb barisPaling sederhana, cepat ditulisSeluruh data di memori
FromQueryData besarChunk otomatis, hemat memoriMapping sedikit lebih rumit
FromViewLayout custom (kop laporan, logo)Full kontrol HTML/BladeStyling terbatas, lebih lambat

Untuk laporan transaksi standar, FromCollection + styling seperti di artikel ini adalah sweet spot. Naik ke FromQuery + queue hanya saat datamu benar-benar besar.

FAQ

1. Apa bedanya export Excel dengan export CSV biasa? CSV hanya teks polos tanpa formatting, satu sheet, dan sering bermasalah dengan karakter koma/titik-koma di Excel Indonesia. XLSX mendukung multiple sheet, styling, format angka/tanggal, dan rumus — jauh lebih cocok untuk laporan resmi.

2. Apakah maatwebsite/excel gratis? Ya, 100% open-source (lisensi MIT). Cocok dipakai di source code komersial yang kamu jual — tidak ada kewajiban bagi hasil. Kalau kamu menjual source code, pastikan juga memahami model lisensi software agar produkmu terlindungi.

3. Berapa baris maksimal yang bisa di-export? Tidak ada batas baku — batasnya memori PHP dan max_execution_time. Praktik amannya: di bawah 10.000 baris pakai FromCollection sinkron; di atas itu pakai FromQuery + queue.

4. Bagaimana cara menampilkan format rupiah yang benar (Rp 150.000)? Jangan simpan sebagai string "Rp ...". Simpan angka mentah lalu format kolomnya dengan WithColumnFormatting ('#,##0'), atau format custom "Rp "#,##0. Angka tetap bisa di-SUM di Excel.

5. Bisakah export langsung ke PDF, bukan Excel? Bisa — Laravel Excel mendukung writer Dompdf/Tcpdf/Mpdf, cukup ganti ekstensi file menjadi .pdf. Tapi untuk invoice yang butuh desain kop surat penuh, library PDF khusus seperti Dompdf langsung memberi kontrol layout lebih baik.

6. Export saya timeout / memory exhausted, kenapa? Kemungkinan besar FromCollection memuat ratusan ribu baris sekaligus. Migrasi ke FromQuery + ShouldQueue, naikkan memory_limit secukupnya, dan simpan hasilnya ke storage alih-alih download langsung.

7. Apakah bisa export data relasi (misal nama pelanggan dari tabel lain)? Bisa dan disarankan: eager-load relasinya (with('customer')) di collection()/query(), lalu akses di map() seperti contoh di artikel ini. Tanpa eager loading, export 5.000 baris bisa memicu 5.000 query tambahan (masalah N+1).

Laporan Excel yang rapi bukan sekadar fitur tambahan — di mata pembeli source code, ini sinyal bahwa aplikasimu "siap dipakai bisnis beneran". Implementasikan pola di atas sekali, lalu pakai ulang Export class-nya untuk setiap modul: produk, member, kupon voucher diskon, hingga mutasi stok.