Laravel Import and Export Excel/CSV
Hello artisans, today I’ll talk about how you can import and export excel file in our Laravel Application. We will use an package which was very easy to use and comes with a lot of features called maatwebsite/excel So, let’s see how we can implement this in our application.
Note: Tested on Laravel 8.65.
Table of Contents
- Installation of Maatwebsite Package
- Create Import Class for Import
- Create Export Class for Export
- Setup Import and Export function
- Output
Installation of Maatwebsite Package
To install the latest version of maatwebsite package simply run the below command
composer require maatwebsite/excel
And that’s it your package is now ready to use.
Create Import Class for Import
Maatwebsite provide way to build import classes which reduces our work. So, to create the class fire the below command
php artisan make:import UsersImport --model=User
We will use this class to import our users of our application. So, paste the following code into our UsersImport class.
<?php
namespace App\Imports;
use App\Models\User;
use Maatwebsite\Excel\Concerns\ToModel;
class UsersImport implements ToModel
{
public function model(array $row)
{
return new User([
'name' => $row[1], //remember excel sheet cells start with 0
'email' => $row[2],
'password' => bcrypt('password'),
]);
}
}
Create Export Class for Export
To create the Export class simply run the following command.
php artisan make:export UsersExport --model=User
And that’s it you don’t have to do anything. The file looks like below
<?php
namespace App\Exports;
use App\Models\User;
use Maatwebsite\Excel\Concerns\FromCollection;
class UsersExport implements FromCollection
{
public function collection()
{
return User::all(); //use your own logic here.
}
}
Setup Import and Export function
Here, first we are going to create some dummy records using Tinker. If you are not familiar with tinker, I strongly recommend you to see one of my short article on Tinker. So, at first migrate your migration using the following command.
php artisan migrate
Then in the command line fire below commands to create some dummy records.
php artisan tinker
App\Models\User::factory()->count(50)->create()
Now, we need to create our controller which can handle the requests. So , at first create a controller using the below command
php artisan make:controller ExcelController
Now paste the following code into the controller
<?php
namespace App\Http\Controllers;
use App\Exports\UsersExport;
use App\Imports\UsersImport;
use App\Models\User;
use Maatwebsite\Excel\Facades\Excel;
class ExcelController extends Controller
{
public function index()
{
$users = User::paginate(15);
return view('welcome',compact('users'));
}
public function export()
{
return Excel::download(new UsersExport, 'users.xlsx');
}
public function import()
{
Excel::import(new UsersImport,request()->file('file'));
return back();
}
}
Now, we have to create routes for that paste the following code into web.php file.
<?php
use Illuminate\Support\Facades\Route;
Route::get('/', [\App\Http\Controllers\ExcelController::class,'index']);
Route::get('export', [\App\Http\Controllers\ExcelController::class,'export'])->name('export');
Route::post('import', [\App\Http\Controllers\ExcelController::class,'import'])->name('import');
No replace your default welcome.blade.php with the following code
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel</title>
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css"/>
<!-- Styles -->
<style>
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
html {
line-height: 1.15;
-webkit-text-size-adjust: 100%
}
body {
margin: 0
}
a {
background-color: transparent
}
[hidden] {
display: none
}
html {
font-family: system-ui, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
line-height: 1.5
}
*, :after, :before {
box-sizing: border-box;
border: 0 solid #e2e8f0
}
a {
color: inherit;
text-decoration: inherit
}
svg, video {
display: block;
vertical-align: middle
}
video {
max-width: 100%;
height: auto
}
.bg-white {
--bg-opacity: 1;
background-color: #fff;
background-color: rgba(255, 255, 255, var(--bg-opacity))
}
.bg-gray-100 {
--bg-opacity: 1;
background-color: #f7fafc;
background-color: rgba(247, 250, 252, var(--bg-opacity))
}
.border-gray-200 {
--border-opacity: 1;
border-color: #edf2f7;
border-color: rgba(237, 242, 247, var(--border-opacity))
}
.border-t {
border-top-width: 1px
}
.flex {
display: flex
}
.grid {
display: grid
}
.hidden {
display: none
}
.items-center {
align-items: center
}
.justify-center {
justify-content: center
}
.font-semibold {
font-weight: 600
}
.h-5 {
height: 1.25rem
}
.h-8 {
height: 2rem
}
.h-16 {
height: 4rem
}
.text-sm {
font-size: .875rem
}
.text-lg {
font-size: 1.125rem
}
.leading-7 {
line-height: 1.75rem
}
.mx-auto {
margin-left: auto;
margin-right: auto
}
.ml-1 {
margin-left: .25rem
}
.mt-2 {
margin-top: .5rem
}
.mr-2 {
margin-right: .5rem
}
.ml-2 {
margin-left: .5rem
}
.mt-4 {
margin-top: 1rem
}
.ml-4 {
margin-left: 1rem
}
.mt-8 {
margin-top: 2rem
}
.ml-12 {
margin-left: 3rem
}
.-mt-px {
margin-top: -1px
}
.max-w-6xl {
max-width: 72rem
}
.min-h-screen {
min-height: 100vh
}
.overflow-hidden {
overflow: hidden
}
.p-6 {
padding: 1.5rem
}
.py-4 {
padding-top: 1rem;
padding-bottom: 1rem
}
.px-6 {
padding-left: 1.5rem;
padding-right: 1.5rem
}
.pt-8 {
padding-top: 2rem
}
.fixed {
position: fixed
}
.relative {
position: relative
}
.top-0 {
top: 0
}
.right-0 {
right: 0
}
.shadow {
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .1), 0 1px 2px 0 rgba(0, 0, 0, .06)
}
.text-center {
text-align: center
}
.text-gray-200 {
--text-opacity: 1;
color: #edf2f7;
color: rgba(237, 242, 247, var(--text-opacity))
}
.text-gray-300 {
--text-opacity: 1;
color: #e2e8f0;
color: rgba(226, 232, 240, var(--text-opacity))
}
.text-gray-400 {
--text-opacity: 1;
color: #cbd5e0;
color: rgba(203, 213, 224, var(--text-opacity))
}
.text-gray-500 {
--text-opacity: 1;
color: #a0aec0;
color: rgba(160, 174, 192, var(--text-opacity))
}
.text-gray-600 {
--text-opacity: 1;
color: #718096;
color: rgba(113, 128, 150, var(--text-opacity))
}
.text-gray-700 {
--text-opacity: 1;
color: #4a5568;
color: rgba(74, 85, 104, var(--text-opacity))
}
.text-gray-900 {
--text-opacity: 1;
color: #1a202c;
color: rgba(26, 32, 44, var(--text-opacity))
}
.underline {
text-decoration: underline
}
.antialiased {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale
}
.w-5 {
width: 1.25rem
}
.w-8 {
width: 2rem
}
.w-auto {
width: auto
}
.grid-cols-1 {
grid-template-columns:repeat(1, minmax(0, 1fr))
}
@media (min-width: 640px) {
.sm\:rounded-lg {
border-radius: .5rem
}
.sm\:block {
display: block
}
.sm\:items-center {
align-items: center
}
.sm\:justify-start {
justify-content: flex-start
}
.sm\:justify-between {
justify-content: space-between
}
.sm\:h-20 {
height: 5rem
}
.sm\:ml-0 {
margin-left: 0
}
.sm\:px-6 {
padding-left: 1.5rem;
padding-right: 1.5rem
}
.sm\:pt-0 {
padding-top: 0
}
.sm\:text-left {
text-align: left
}
.sm\:text-right {
text-align: right
}
}
@media (min-width: 768px) {
.md\:border-t-0 {
border-top-width: 0
}
.md\:border-l {
border-left-width: 1px
}
.md\:grid-cols-2 {
grid-template-columns:repeat(2, minmax(0, 1fr))
}
}
@media (min-width: 1024px) {
.lg\:px-8 {
padding-left: 2rem;
padding-right: 2rem
}
}
@media (prefers-color-scheme: dark) {
.dark\:bg-gray-800 {
--bg-opacity: 1;
background-color: #2d3748;
background-color: rgba(45, 55, 72, var(--bg-opacity))
}
.dark\:bg-gray-900 {
--bg-opacity: 1;
background-color: #1a202c;
background-color: rgba(26, 32, 44, var(--bg-opacity))
}
.dark\:border-gray-700 {
--border-opacity: 1;
border-color: #4a5568;
border-color: rgba(74, 85, 104, var(--border-opacity))
}
.dark\:text-white {
--text-opacity: 1;
color: #fff;
color: rgba(255, 255, 255, var(--text-opacity))
}
.dark\:text-gray-400 {
--text-opacity: 1;
color: #cbd5e0;
color: rgba(203, 213, 224, var(--text-opacity))
}
.dark\:text-gray-500 {
--tw-text-opacity: 1;
color: #6b7280;
color: rgba(107, 114, 128, var(--tw-text-opacity))
}
}
</style>
<style>
body {
font-family: 'Nunito', sans-serif;
}
</style>
</head>
<body class="antialiased">
<div class="container">
<div class="card bg-light mt-3">
<div class="card-header">
Import Export Excel to database Example
</div>
<div class="card-body">
<form action="{{ route('import') }}" method="POST" enctype="multipart/form-data">
@csrf
<input type="file" name="file" class="form-control" required>
<br>
<button type="submit" class="btn btn-success">Import User Data</button>
</form>
</div>
</div>
<div class="text-right mt-2 mb-2"><a class="btn btn-warning" href="{{ route('export') }}">Export User Data</a></div>
<table class="table table-bordered">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Email</th>
</tr>
</thead>
<tbody>
@foreach($users as $key=> $user)
<tr>
<td>{{ $key+1 }}</td>
<td>{{ $user->name }}</td>
<td>{{ $user->email }}</td>
</tr>
@endforeach
</tbody>
</table>
{{ $users->links() }}
<div class="mt-5"></div>
</div>
</body>
</html>
Output
Finally you can see the following output if you successfully follow the all steps
That’s all for today. For download this project checkout this repo in GitHub. Thanks for reading.