Generar excel con Codeigniter

Es muy común que en una aplicación web que trabaja con reportes, nos permita descargar una archivo excel con dichos registros. Porque es útil para los usuarios, por costumbre trabajar con este formato. En la siguiente publicación vamos a ver cómo convertir una consulta con MySQL y Codeigniter en un archivo Excel.

En primer lugar vamos a ir al respositorio de PHPOffice, que son varias librerías que nos permiten desarrollar, no sólo Excel, sino el resto de las herramientas de Office, como Word por ejemplo. Pero en esta ocasión vamos a descargar la de excel:

https://github.com/PHPOffice/PHPExcel

De ahí copiamos el contenido de la carpeta ‘Classes’, y la movemos dentro de ‘application/libraries’ de nuestro proyecto Codeigniter.

En esa misma carpeta creamos un nuevo archivo con el nombre: ‘Excel.php’ con el siguiente código:

<?php 
if (!defined('BASEPATH')) exit('No direct script access allowed'); 
require_once APPPATH."/libraries/PHPExcel.php"; 
class Excel extends PHPExcel {
 public function __construct() {
    parent::__construct();
 }
}

Base de datos

Para este ejemplo vamos a hacer algo sencillo, vamos a tener una tabla con clientes y otra con llamadas con reclamos de estos clientes:

CREATE TABLE clientes( 
   id_cliente int(10) unsigned not null primary key,
   nombre varchar(50) not null,
   apellido varchar(50) not null
);
CREATE TABLE llamadas( 
   id_llamada int(10) unsigned not null auto_increment primary key, 
   telefono varchar(20) not null, 
   mensaje text not null, 
   fecha datetime not null, 
   id_cliente int(10) unsigned, 
   foreign key(id_cliente) references clientes(id_cliente)
);

Y le insertamos registros de prueba:

INSERT INTO clientes(id_cliente, nombre, apellido)
VALUES
(665, 'Mauricio', 'Kedi'),
(31773, 'Mercedes', 'Corta'),
(552553, 'Patricia', 'Criollo');
INSERT INTO llamadas(telefono, mensaje, fecha, id_cliente)
VALUES
('66555669', 'No funciona mi conexión a internet', now(), 665),
('66555669', 'No funciona mi conexión a internet', now(), 665),
('66555669', 'No funciona el teléfono', now(), 665),
('66554669', 'Hace tres días que no tengo internet', now(), 665),
('66554669', 'Quiero dar de baja todos los servicios', now(), 665),
('33332223232', 'No funciona mi conexión a internet', now(), 31773),
('33332243232', 'No funciona el teléfono', now(), 31773),
('33332223232', 'Quiero dar de baja todos los servicios', now(), 31773),
('0303456', 'No funciona mi conexión a internet', now(), 552553),
('0303456', 'No funciona mi conexión a internet', now(), 552553),
('0303456', 'No funciona el teléfono', now(), 552553),
('0303456', 'Hace tres días que no tengo internet', now(), 552553);

Modelo

Agregamos un modelo, llamado ‘Llamada_model.php’ con un sólo método para recuperar las llamadas por el id del cliente:

<?php
class Llamada_model extends CI_Model {
 public function __construct()  {
    parent::__construct();
 }
 public function listarPorCliente($id_cliente)  {
    return $this->db
      ->select('c.nombre, c.apellido, l.telefono, l.mensaje, l.fecha')
      ->from('llamadas l')
      ->join('clientes c', 'c.id_cliente = l.id_cliente')
      ->where('c.id_cliente', $id_cliente)
      ->get()
      ->result();
  }
}

Vista

Mostramos con HTML una tabla con la consulta de las llamadas ‘llamadas/buscar_llamadas.php’:

<!DOCTYPE html>
<html>
<head>
 <meta charset="utf-8">
 <title> Buscar llamadas </title>
 <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous" />
</head>
<body>
 <div class="container">
    <h1> Llamadas </h1>
    <form method="post" action="llamadas">
       <div class="form-group">
          <label for="id_cliente"> Código del cliente </label>
          <input type="number" name="id_cliente" id="id_cliente" class="form-control" min="0" value="<?php echo $id_cliente ?>" />
       </div> 
       <button type="submit" class="btn btn-primary"> Buscar </button>
    </form> 
    <?php if($buscando): ?>
       <?php if(count($llamadas) > 0): ?>
          <h2> <?php echo $llamadas[0]->nombre ?> <?php echo $llamadas[0]->apellido ?> </h2> 
          <a href="llamadas/generar_excel/<?php echo $id_cliente ?>" target="_blank"> Generar excel </a> 
       <?php endif; ?> 
       <table class="table">
          <thead>
             <tr>
                <th> Número de teléfono </th>
                <th> Fecha </th>
                <th> Mensaje </th>
             </tr> 
          </thead>
          <tbody>
             <?php if(count($llamadas) > 0): ?> 
                <?php foreach($llamadas as $item): ?>
                   <tr> 
                      <td> <?php echo $item->telefono ?> </td> 
                      <td> <?php echo $item->fecha ?> </td> 
                      <td> <?php echo $item->mensaje ?> </td> 
                   </tr> 
                <?php endforeach; ?> 
             <?php else: ?> 
                <tr>
                   <td colspan="3"> No se han encontrado registros </td> 
                </tr> 
             <?php endif; ?> 
          </tbody> 
       </table> 
    <?php endif; ?> 
 </div>
</body>
</html>

La vista tendrá un aspecto como éste:

Notar que tendrá un botón para generar el excel, una vez que busquemos a un cliente por su código:

<a href="llamadas/generar_excel/<?php echo $id_cliente ?>" target="_blank"> Generar excel </a>

El cuál, más tarde, veremos cómo generar un excel con este aspecto:

Controlador

Ahora que ya tenemos nuestro modelo y nuestra vista, vamos a crear las acciones para buscar las llamadas y generar el excel. Creamos un controlador con el nombre: ‘Llamadas.php’, con el siguiente código:

defined('BASEPATH') OR exit('No direct script access allowed');
class Llamadas extends CI_Controller {
 public function __construct(){
    parent::__construct();
    $this->load->model('llamada_model'); 
 }
 public function buscar_llamadas_get(){
    $this->load->view('llamadas/buscar_llamadas',
       array('buscando' => false, 'id_cliente' => null 
    ));
 }
 public function buscar_llamadas_post(){
    $id_cliente = $this->input->post('id_cliente');
    $llamadas = $this->llamada_model->listarPorCliente($id_cliente);
    $this->load->view('llamadas/buscar_llamadas',
       array('buscando' => true, 'id_cliente' => $id_cliente, 'llamadas' => $llamadas )); 
 }
 public function generar_excel($id_cliente=null){
    $llamadas = $this->llamada_model->listarPorCliente($id_cliente);
    if(count($llamadas) > 0){
        //Cargamos la librería de excel.
        $this->load->library('excel'); $this->excel->setActiveSheetIndex(0);
        $this->excel->getActiveSheet()->setTitle('Llamadas');
        //Contador de filas
        $contador = 1;
        //Le aplicamos ancho las columnas.
        $this->excel->getActiveSheet()->getColumnDimension('A')->setWidth(20);
        $this->excel->getActiveSheet()->getColumnDimension('B')->setWidth(20);
        $this->excel->getActiveSheet()->getColumnDimension('C')->setWidth(100);
        //Le aplicamos negrita a los títulos de la cabecera.
        $this->excel->getActiveSheet()->getStyle("A{$contador}")->getFont()->setBold(true);
        $this->excel->getActiveSheet()->getStyle("B{$contador}")->getFont()->setBold(true);
        $this->excel->getActiveSheet()->getStyle("C{$contador}")->getFont()->setBold(true);
        //Definimos los títulos de la cabecera.
        $this->excel->getActiveSheet()->setCellValue("A{$contador}", 'Número de teléfono');
        $this->excel->getActiveSheet()->setCellValue("B{$contador}", 'Fecha');
        $this->excel->getActiveSheet()->setCellValue("C{$contador}", 'Mensaje');
        //Definimos la data del cuerpo.        
        foreach($llamadas as $l){
           //Incrementamos una fila más, para ir a la siguiente.
           $contador++;
           //Informacion de las filas de la consulta.
           $this->excel->getActiveSheet()->setCellValue("A{$contador}", $l->telefono);
           $this->excel->getActiveSheet()->setCellValue("B{$contador}", $l->fecha);
           $this->excel->getActiveSheet()->setCellValue("C{$contador}", $l->mensaje);
        }
        //Le ponemos un nombre al archivo que se va a generar.
        $archivo = "llamadas_cliente_{$id_cliente}.xls";
        header('Content-Type: application/vnd.ms-excel');
        header('Content-Disposition: attachment;filename="'.$archivo.'"');
        header('Cache-Control: max-age=0');
        $objWriter = PHPExcel_IOFactory::createWriter($this->excel, 'Excel5');
        //Hacemos una salida al navegador con el archivo Excel.
        $objWriter->save('php://output');
     }else{
        echo 'No se han encontrado llamadas';
        exit;        
     }
  }
}

Notar el método ‘generar_excel()’, el cual recibe como parámetro el id del cliente y con la consulta, es el que va armando el libro de cálculos.

Ruteador

Finalmente para definir las url de nuestra aplicación vamos a ‘application/config/routes.php’ y agregamos las siguientes líneas:

$route['llamadas']['get'] = 'llamadas/buscar_llamadas_get';
$route['llamadas']['post'] = 'llamadas/buscar_llamadas_post';
$route['llamadas_excel/(:num)']['get'] = 'llamadas/generar_excel/$1';

 

No olvidar los siguientes configuraciones:

Dentro de ‘application/config/autoload.php’:

$autoload['libraries'] = array('database');

Dentro de ‘application/config/config.php’:

$config['base_url'] = 'http://tu_url';

Dentro de ‘application/config/database.php’:

'hostname' => 'tu_host', 
'username' => 'tu_usuario', 
'password' => 'tu_contrasena', 
'database' => 'nombre_de_tu_base_de_datos',

Descargar ejemplo

 

 

 

 

 

 

 

 

 

 


4 Respuestas a “Generar excel con Codeigniter”

  1. al hacer el ejemplo me da error al abrir el archivo en excel. y en la hoja aparece caracteres extraños

  2. excelente funciona muy bien, por casualidad tendras el de importar de excel a base de datos mysql