En este post de programación con PHP y MySQL vamos a ver cómo exportar los resultados de una consulta SQL como CSV (valores separados por coma) y como archivo Excel, además de mostrarlos como HTML.
A partir de las filas que sean devueltas por una consulta vamos a crear un archivo CSV y un archivo de Excel.
Estructura de la tabla
En este ejemplo vamos a trabajar con una tabla llamada personas
, cuyas columnas están descritas a continuación. En el script que se muestra a continuación también vas a encontrar algunos datos de prueba.
Funciones
Comencemos viendo el código PHP que va a tener una función para obtener la base de datos y una que realiza la consulta SQL y devuelve las filas de la tabla:
Tenemos a la función que obtiene la base de datos. Debes configurar las credenciales de acceso y el nombre de la base de datos. En mi caso específico la base de datos se llama personas
, y he creado una tabla con el mismo nombre dentro de esa base de datos. Puede que en tu caso el usuario, contraseña o nombre de la base de datos sea distinto.
Por otro lado, la segunda función devuelve la lista de personas haciendo la consulta SQL e invocando a la función que obtiene la base de datos. Esta función será usada en los 3 casos: al mostrar los datos como HTML, como CSV y como Excel. La única diferencia radica en el formato de los datos.
Generar reporte como HTML
En el primer caso vamos a ver cómo mostrar los resultados de la consulta en el navegador web para que el usuario pueda revisarlos. Simplemente invocamos a la función y dibujamos una tabla HTML recorriendo el arreglo de personas.
Para lograr esto, estoy incluyendo el archivo funciones.php
que contiene las 2 funciones necesarias:
Luego, estoy dibujando la tabla:
Estoy recorriendo todas las filas devueltas por la consulta en el foreach
. Después, en cada paso, dibujo una nueva celda con la etiqueta td
y accedo a cada propiedad usando la notación []
, por ejemplo, para acceder a la edad de la persona acceso con $persona["edad"]

Fíjate en que ahí mismo tengo los botones para descargar el reporte de MySQL como CSV o como Excel. Lo importante es que sepas que voy a usar la misma función para generar esos 2 archivos.
Generando CSV a partir de consulta SQL
Veamos el siguiente apartado en donde simplemente concatenamos una cadena y vamos agregando los valores separados por coma. Estamos usando un foreach
al igual que en la ocasión anterior, pero ahora en cada paso agregamos contenido a la cadena.
En este caso estoy usando sprintf
para evitar concatenaciones confusas y para tener un código más limpio.
Después, simplemente muestro la cadena como respuesta a la petición del cliente, pero antes de ello establezco los encabezados para que el navegador sepa que no debe mostrar el contenido, sino forzar su descarga como archivo CSV:
Cuando alguien visite el archivo csv.php
se le va a descargar un archivo CSV con todos los datos de la tabla SQL.

Ya lo dije anteriormente pero lo repito: seguimos usando la misma función, por lo que el reporte HTML, CSV y Excel van a tener los mismos datos.
Excel a partir de consulta con MySQL
Pasemos al último caso: la generación de un archivo de Excel usando MySQL. En este caso vamos a necesitar la librería PHPSpreadSheet que se instala con:
composer require phpoffice/phpspreadsheet
Cuando descargues el código completo simplemente ejecuta: composer install
en la ubicación raíz del proyecto, eso va a crear una carpeta llamada vendor
en donde estarán todas las dependencias.
Luego incluimos esas clases en el archivo que se encarga de generar el reporte, así como nuestras propias funciones:
Después creamos un nuevo documento y accedemos a la primer hoja, aprovechando también para colocar el título de la misma:
Explicando setCellValue
Es necesario hacer una explicación adicional para el caso de setCellValue. En este caso la vamos a invocar con la siguiente sintaxis:
setCellValue([$indiceColumna, $indiceFila], "valor");
El índice de columna es el equivalente a las letras en Excel, de modo que la A es la columna 1. El índice de fila es el número de fila de Excel, de modo que el 1 es la primer fila. Así que si invocamos a:
setCellValue([3,5], "Luis");
Sería el equivalente a colocar el valor Luis
en la celda C5
usando Excel.
En este caso voy a usar algunas banderas de índices para llevar un seguimiento de la columna y fila actual, ya sea al momento de escribir los encabezados de la tabla o al momento de agregar cada persona al documento.
Recorrer filas de SQL y escribirlas en Excel
Comenzamos iniciando las variables ayudantes para los índices de filas y columnas. Después, escribimos el encabezado:
Después recorremos el arreglo de personas, mismo que será devuelto por la función que vimos desde el principio.
Fíjate en que estoy accediendo a $persona[$columna]
, esto es una manera simple de dibujar todas las columnas. Podría hacerse con $persona["id"]
, después con $persona["nombre"]
y así sucesivamente, pero es más fácil definir un arreglo de las propiedades que tiene cada fila devuelta por MySQL y usar dicho valor como clave.
En algunos casos estoy definiendo el formato, ya que los números y flotantes deben ser definidos como lo que son. Para ello, reviso el índice de la columna de personas en el que estoy, y si es el 3 (que corresponde a la edad) o el 4 (altura) agrego el formato con setFormatCode
.
Descargar Excel
Cuando terminemos de recorrer la lista de personas vamos a tener el documento con todos los datos, pero resta enviarlo como respuesta al cliente. Para ello veamos el siguiente código:
Cuando el usuario visite el enlace, se le va a descargar el archivo de Excel de manera automática:

Poniendo todo junto
Te he mostrado las partes más importantes, pero el código completo está en GitHub. Ahí vas a encontrar la definición de la tabla, el archivo composer.json
y los archivos completos para generar HTML, CSV y Excel usando PHP y MySQL: https://github.com/parzibyte/mysql-csv-excel-php
Cuando lo descargues, instala las dependencias con composer install
, configura la base de datos en funciones.php
y asegúrate de crear la tabla como se indica en esquema.sql
.
Recuerda: si hay algún error, el mensaje de error contendrá los detalles necesarios para arreglarlo. El código está probado y funciona perfectamente, solo que en ocasiones es necesario habilitar extensiones o actualizar la versión de PHP.