Suppose that a client has an employees table that he wants to export into a PDF file with table-formatted like this:
Employees table |
Step 1 : Add an "Export to PDF" Button
The first thing that we should do, of course, is to add an "Export to PDF" button somewhere on the page. In this case, I put it below the pagination buttons. Open the view file and add these html lines:<div class="text-center">
<a href="{{ url('/employees/export-to-pdf') }}" class="btn btn-primary">
Export to PDF
</a>
</div>
Notice that the
href
attribute of the anchor tag (the button) is leading to /employees/export-to-pdf. So later we need to make a route for it. For now, let's just save the view file, and refresh the page in the browser. It should look like this:An "Export to PDF" button has been added |
Step 2 : Install a PDF Library
Next we need to install a tcpdf library that works well with laravel. I'm not recommending any specific package, but since use it in most of my projects, I will be using tcpdf-laravel from elibyy throughout this article.Open the terminal, enter your laravel project directory, and run this artisan command:
composer require elibyy/tcpdf-laravel
After composer is done installing the package, open up the config/app.php file, and add this line somewhere inside the providers array
Elibyy\TCPDF\ServiceProvider::class,
Also, add this line somewhere inside the aliases array:
'PDF' => Elibyy\TCPDF\Facades\TCPDF::class,
Now save the file and open the routes/web.php file.
Step 3 : Add a Route
Add this line to make a route for our /employees/export-to-pdf url:Route::get('/employees/export-to-pdf', 'EmployeeController@exportToPdf');
Note that if you don't have the controller, create it before you add the route. This is how you create a controller from the terminal:php artisan make:controller EmployeeController
Now save the file, and get ready put some code in the controller.
Step 4 : Add a Method in The Controller
Next, open up the app/Http/Controllers/EmployeeController.php file, and add a public method as we defined previously in the route.public function exportToPdf()
{
$employees = \App\User::all();
$html = view('employees-pdf', compact('employees'));
PDF::SetTitle('Employees Table');
PDF::SetPrintHeader(false);
PDF::SetPrintFooter(false);
PDF::SetMargins(20, 10, 15);
PDF::AddPage('P','LEGAL');
PDF::writeHTML($html, true, false, true, false, '');
$filename = public_path() . '/files/employees.pdf';
PDF::output($filename,'I');
}
Here is how it works:
- The first two lines of the method, are to gather all of the employees data, and load it into a view file named resources/views/employees-pdf.blade.php. Then store the view to a variable $html.
- The next five lines are the PDF settings.
- The last three lines are to save the view to a pdf file named /files/employees.pdf, relative to the public directory (also relative to the domain name of the application).
- Note that on the last line, the second parameter
'I'
is to directly stream the pdf to the browser. So you will be able to instantly see the PDF as a response of the /employee/esport-to-pdf url.
Step 5 : Create a View File
According to the
exportToPdf
method on the EmployeeController
, There is supposed to be a view file named resource/views/employees-pdf.blade.php. so create the file if it hasn't been created yet. Open the file and put these html code:<!DOCTYPE html>
<html>
<head>
<title>Employees</title>
</head>
<body>
<h1>Employees Table</h1>
<table class="table table-bordered" cellpadding="5" width:"100%">
<tr>
<th><div>ID</div></th>
<th><div>Name</div></th>
<th><div>Age</div></th>
<th><div>Division</div></th>
<th><div>Salary</div></th>
<th><div>Performance</div></th>
</tr>
@foreach($employees as $employee)
<tr nobr="true">
<td>{{ $employee->id }}</td>
<td>{{ $employee->name }}</td>
<td>{{ $employee->age }}</td>
<td>{{ $employee->division }}</td>
<td>{{ $employee->salary }}</td>
<td>{{ $employee->performance }}</td>
</tr>
@endforeach
</table>
</body>
</html>
Save it and test the "Export to PDF" button from the browser. It should look something like this:
Messy Employees Table |
Okay it works.. But.. It is sooo ugly..
We need to tweak the HTML mockup to beautify the table. Back to the employees-pdf.blade.php file.
Add some styling just above the closing
</head>
tag...
<style>
.text-center{text-align:center;}
.text-right{text-align:right;}
td,th{border:1px solid #000000;}
</style>
...
Add a pair of
<thead></thead>
tag after the first closing </tr>
tag, and fill it with these:...
<thead>
<tr>
<th width="50"><div class="text-center">1</div></th>
<th width="200"><div class="text-center">2</div></th>
<th width="50"><div class="text-center">3</div></th>
<th><div class="text-center">4</div></th>
<th width="70"><div class="text-center">5</div></th>
<th><div class="text-center">6</div></th>
</tr>
</thead>
...
The thead pairs will allow anything it contained to be displayed on each and every page.
Next, add an opening
<tbody>
tag before the @foreach
statement, and also a closing </tbody>
tag after the @endforeach
statement....
<tbody>
@foreach($employees as $employee)
<tr>
...
</tr>
@endforeach
</tbody>
...
Next, adjust the width of the column titles, by following the width we defined in thead above
...
<tr>
<th width="50">ID</th>
<th width="200">Name</th>
<th width="50">Age</th>
<th>Division</th>
<th width="70">Salary</th>
<th>Performance</th>
</tr>
...
Lastly, center some columns by applying a corresponding class that we defined in the
style
tag above. Overall, the final version of the employees-pdf.blade.php file will be like this:<!DOCTYPE html> <html> <head> <title>Employees</title> <style> .text-center{text-align:center;} .text-right{text-align:right;} td,th{border:1px solid #000000;} </style> </head> <body> <h1>Employees Table</h1> <table class="table table-bordered" cellpadding="5" width:"100%"> <tr> <th width="50"><div class="text-center">ID</div></th> <th width="200"><div class="text-center">Name</div></th> <th width="50"><div class="text-center">Age</div></th> <th><div class="text-center">Division</div></th> <th width="70"><div class="text-center">Salary</div></th> <th><div class="text-center">Performance</div></th> </tr> <thead> <tr> <th width="50"><div class="text-center">1</div></th> <th width="200"><div class="text-center">2</div></th> <th width="50"><div class="text-center">3</div></th> <th><div class="text-center">4</div></th> <th width="70"><div class="text-center">5</div></th> <th><div class="text-center">6</div></th> </tr> </thead> <tbody> @foreach($employees as $employee) <tr> <td><div class="text-center">{{ $employee->id }}</div></td> <td>{{ $employee->name }}</td> <td><div class="text-center">{{ $employee->age }}</div></td> <td>{{ $employee->division }}</td> <td> <div class="text-right"> $ {{ number_format($employee->salary,0,',','.') }} </div> </td> <td> <div class="text-center"> {{ $employee->performance }} </div> </td> </tr> @endforeach </tbody> </table> </body> </html>
Save the file and test it out in the browser. It will look something like this:
Good Looking Table |
Better.. But hey, if you look at the bottom at each page, there will be an ugly breaking.
Static Column Title, But Ugly Breaks |
Well.. That is eazy.. Just add a
nobr="true"
attribute on the tr tag under the @foreach
statement line...
<tbody>
@foreach($employees as $employee)
<tr nobr="true">
...
</tr>
@endforeach
</tbody>
...
Save the file again, and test it in the browser. It will look something like this:
Nice Break |
Amazing.. We just got ourselves a nice and neat table. Why don't you give it a try and leave a comment below.
Happy coding ^_^
No comments:
Post a Comment