Cargar 200 o 1500 datos en una tabla de nuestra base de datos, uno a uno, es una tarea un poco enredosa, si no aburrida, ya que pasamos mucho tiempo para hacerlo, pudiendo hacerlo en 2 o 3 minutos.
Aquí voy a explicar cómo insertar en la tabla de productos los productos que tengo en una hoja de Excel, y aprovechando, también insertaremos las categorías pertenecientes a los productos.
Entonces, el primer paso es preparar nuestro archivo para insertar nuestro Excel con sus datos.
Paso 1: Configuración de SweetAlert y Librerías Necesarias
Para generar una carga masiva, en este caso, de dos hojas Excel (Productos y categorías), procedemos de la siguiente forma:
1. Incluimos los CDN necesarios para la realización de nuestro proyecto, tanto los CSS como los SCRIPTS.
Aquí dejo el ejemplo de los mismos.
La cabecera
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>AdminTienda</title> <!-- Google Font: Source Sans Pro --> <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700&display=fallback"> <!-- Font Awesome Icons --> <link rel="stylesheet" href="plugins/fontawesome-free/css/all.min.css"> <!-- Theme style --> <link rel="stylesheet" href="dist/css/adminlte.min.css"> </head>Los scripts
<script src="plugins/jquery/jquery.min.js"></script> <!-- Bootstrap 4 --> <script src="plugins/bootstrap/js/bootstrap.bundle.min.js"></script> <!-- AdminLTE App --> <script src="dist/js/adminlte.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
Paso 2: Instalación de Composer y PhpSpreadsheet
- Descarga e instala en la computadora Composer desde getcomposer.org.
- ¿Cómo instalamos PhpSpreadsheet?
Pues copiamos este comando composer require phpoffice/phpspreadsheet
, luego vamos a nuestro proyecto, abrimos la terminal, nos ubicamos en nuestro proyecto y pegamos el trozo de código que hemos copiado anteriormente. Le damos "enter" y esperamos hasta que las dependencias de la librería PhpSpreadsheet se instalen completamente.
Si miramos nuestro proyecto, veremos que tenemos una nueva carpeta con el nombre "Vendor" y los archivos de Composer. Dentro de la carpeta "Vendor" están los archivos necesarios para hacer la carga de nuestros archivos a la base de datos.
...
Paso 3: Estructura del Proyecto
Asegúrate de que tu proyecto tenga la estructura adecuada, con la carpeta "vendor" generada por Composer.
Paso 4: Maquetación HTML
Crea la estructura HTML con un card de Bootstrap, un input de tipo file y un botón para iniciar la carga masiva:
<div class="content-header"> <div class="container-fluid"> <div class="row mb-2"> <div class="col-sm-6"> <h1 class="m-0">carga masiva de productos</h1> </div><!-- /.col --> <div class="col-sm-6"> <ol class="breadcrumb float-sm-right"> <li class="breadcrumb-item"><a href="#">Home</a></li> </ol> </div><!-- /.col --> </div><!-- /.row --> </div><!-- /.container-fluid --> </div> <!-- /.content-header --> <!-- Main content --> <div class="content"> <div class="container-fluid"> <div class="row"> <div class="col"> <div class="card card-info"> <div class="card-header"> <h3 class="card-title">Selecionar archivo de carga</h3> <div class="card-tools"> <button type="button" class="btn btn-tool" data-card-widget="collapse"> <i class="fas fa-minus"></i> </button> </div> <!-- ./ end card-tools --> </div> <!-- ./ end card-header --> <div class="card-body"> <form action="" method="POST" enctype="multipart/form-data" id="form_cargaProductos"> <div class="row"> <div class="col-10"> <input type="file" name="fileProductos" id="fileProductos" class="form-control" accept=".xls, .xlsx"> </div> <div class="col-2"> <input type="submit" value="cargar Productos" class="btn btn-primary" id="btnCargar"> </div> </div> <div class="row text-center "> <div class="col-12"> <img class="mx-auto" src="../img/loading.gif" id="img_carga" alt="" style="display: none;"> </div> </div> </form> </div> <!-- ./ end card-body --> </div> </div> </div> </div><!-- /.container-fluid --> </div>
Hay que recordar que estamos trabajando con un proyecto onde usamos un template, si lo vas a usar en codigo completo solo hay que aprovechar el formulario, que es la parque que va recoger nuestro excel
Paso 5: Script Ajax
Ahora creamos el script Ajax que va a servir para enviar los datos de la hoja al servidor y recibir la respuesta.
Aqui dejo el codigo del script
<script> $(document).ready(function() { $('#form_cargaProductos').on('submit', function(e) { e.preventDefault(); //Verificar que se seleciono un archivo if ($('#fileProductos').get(0).files.length == 0) { Swal.fire({ title: 'Error!', text: 'Debe selecionar un archivo excel', icon: 'warning', showConfirmButton: false, timer: 2500 }) } else { //Validar que el archivo sea xls o xlsx var extensiones_permitidas = ['.xls', 'xlsx']; var input_file_productos = $('#fileProductos'); var exp_reg = new RegExp("([a-zA-Z0-9\s_\\.\-:])+(" + extensiones_permitidas.join('|') + ")$"); if (!exp_reg.test(input_file_productos.val().toLowerCase())) { Swal.fire({ title: 'Error!', text: 'Debe selecionar un archivo excel', icon: 'warning', showConfirmButton: false, timer: 2500 }) return false; } var datos = new FormData($('#form_cargaProductos')[0]); $('#btnCargar').prop("disabled", true); $('#img_carga').attr('style', 'display:block'); $.ajax({ type: "POST", url: "ajax/producto_cargaMasiva.php", data: datos, cache: false, contentType: false, processData: false, dataType: 'json', success: function(response) { console.log(response); if (response['totalCategorias'] > 0 && response['totalProductos'] > 0) { Swal.fire({ position: 'center', icon: 'success', title: 'Se registraram ' + response['totalCategorias'] + ' categorias ' + 'y ' + response[ 'totalProductos'] + 'productos correctamente', showConfirmButton: false, timer: 2500 }) $('#btnCargar').prop("disabled", false); $('#img_carga').attr('style', 'display:none'); } else { Swal.fire({ position: 'center', icon: 'error', title: 'Hay un error en el registro de categorias y productos', showConfirmButton: false, timer: 2500 }) } } }); } }) }) </script>
Explicacion del script
Este script en jQuery está diseñado para manejar la carga masiva de productos desde un archivo Excel. Aquí está la explicación detallada:
Document Ready:
$(document).ready(function() {
Espera a que el documento HTML esté completamente cargado antes de ejecutar el script.
Evento de Envío del Formulario:
$('#form_cargaProductos').on('submit', function(e) {
Asocia la función a ejecutar cuando se envía el formulario con el id form_cargaProductos
. El evento de envío se cancela inicialmente (e.preventDefault()
) para controlar la carga a través de Ajax.
Verificación de Archivo Seleccionado:
if ($('#fileProductos').get(0).files.length == 0) {
Verifica si se ha seleccionado un archivo. Si no, muestra un mensaje de advertencia usando la librería SweetAlert (Swal).
Validación de Extensión del Archivo:
var extensiones_permitidas = ['.xls', 'xlsx']; var input_file_productos = $('#fileProductos'); var exp_reg = new RegExp("([a-zA-Z0-9\s_\\.\-:])+(" + extensiones_permitidas.join('|') + ")$"); if (!exp_reg.test(input_file_productos.val().toLowerCase())) {
Verifica que el archivo seleccionado tenga una extensión permitida (.xls o .xlsx). Muestra un mensaje de advertencia si la extensión no es válida.
Preparación de Datos para Ajax:
var datos = new FormData($('#form_cargaProductos')[0]);
Crea un objeto FormData con los datos del formulario para enviarlos mediante Ajax.
Deshabilitar Botón y Mostrar Indicador de Carga:
$('#btnCargar').prop("disabled", true); $('#img_carga').attr('style', 'display:block');
Deshabilita el botón de carga y muestra un indicador de carga mientras se procesa la petición Ajax.
Envío de Datos mediante Ajax:
$.ajax({ // configuración de Ajax });
Realiza una petición Ajax para enviar los datos al servidor.
Manejo de Respuesta del Servidor:
success: function(response) {
Maneja la respuesta del servidor.
Verificación y Mensajes de SweetAlert:
if (response['totalCategorias'] > 0 && response['totalProductos'] > 0) {
Verifica si se registraron categorías y productos correctamente. Muestra un mensaje de éxito si todo está bien.
} else { Swal.fire({ position: 'center', icon: 'error', title: 'Hay un error en el registro de categorías y productos', showConfirmButton: false, timer: 2500 }) }
Muestra un mensaje de error si hay algún problema en el registro.
Restaurar Estado del Botón e Indicador de Carga:
$('#btnCargar').prop("disabled", false); $('#img_carga').attr('style', 'display:none');
Habilita nuevamente el botón de carga y oculta el indicador de carga después de procesar la respuesta del servidor.
Paso 6: Recibimiento de los datos y envío a la base de datos
En el servidor vamos a recibir los datos de las hojas de Excel y enviar esos datos a la tabla o tablas de la base de datos.
<?php require_once('../../vendor/autoload.php'); require_once('../../conexion.php'); use PhpOffice\PhpSpreadsheet\IOFactory; if ($_SERVER['REQUEST_METHOD'] === 'POST') { // Verificar que se ha enviado un archivo if (!empty($_FILES['fileProductos']['tmp_name'])) { $nombreArchivo = $_FILES['fileProductos']['tmp_name']; // Cargar el documento Excel $documento = IOFactory::load($nombreArchivo); // Acceder a la hoja de categorías $hojaCategorias = $documento->getSheet(1); // Obtener el número de filas en la hoja de categorías $numeroFilasCategorias = $hojaCategorias->getHighestDataRow(); $categoriasRegistradas = 0; $hojaProductos = $documento->getSheetByName('Productos'); $numeroFilasProductos = $hojaProductos->getHighestDataRow(); $productosRegistrados = 0; for ($i = 2; $i <= $numeroFilasCategorias; $i++) { // Obtener valores de la hoja de categorías $categoria = $hojaCategorias->getCellByColumnAndRow(1, $i); $peso = $hojaCategorias->getCellByColumnAndRow(2, $i); $fechaActualizacion = date("Y-m-d"); if (!empty($categoria)) { $sql = "INSERT INTO categorias_productos (categoria, peso, fechaActualizacion) VALUES (:categoria, :peso, :fechaActualizacion)"; $stmt = $pdo->prepare($sql); $stmt->bindParam(':categoria', $categoria); $stmt->bindParam(':peso', $peso); $stmt->bindParam(':fechaActualizacion', $fechaActualizacion); if ($stmt->execute()) { $categoriasRegistradas = $categoriasRegistradas + 1; } else { $categoriasRegistradas = 0; } } } if ($categoriasRegistradas > 0) { for ($i = 2; $i <= $numeroFilasProductos; $i++) { // Obtener valores de la hoja de productos $codigoBarras = $hojaProductos->getCell("A" . $i); $categoria = BuscarIdCategoria($hojaProductos->getCell("B" . $i), $pdo); $producto = $hojaProductos->getCell("C" . $i); $precioCompra = $hojaProductos->getCell("D" . $i); $precioVenta = $hojaProductos->getCell("E" . $i); $beneficio = $hojaProductos->getCell("F" . $i)->getCalculatedValue(); $stock = $hojaProductos->getCell("G" . $i); $minimoStock = $hojaProductos->getCell("H" . $i); $ventas = $hojaProductos->getCell("I" . $i); $fechaActualizacion = date("Y-m-d"); if (!empty($codigoBarras)) { $sql = "INSERT INTO productos (codigoBarras, categoria, producto, precioCompra, precioVenta, beneficio, stock, minimoStock, ventas, fechaActualizacion) VALUES (:codigoBarras, :categoria, :producto, :precioCompra, :precioVenta, :beneficio, :stock, :minimoStock, :ventas, :fechaActualizacion)"; $stmt = $pdo->prepare($sql); $stmt->bindParam(':codigoBarras', $codigoBarras); $stmt->bindParam(':categoria', $categoria); $stmt->bindParam(':producto', $producto); $stmt->bindParam(':precioCompra', $precioCompra); $stmt->bindParam(':precioVenta', $precioVenta); $stmt->bindParam(':beneficio', $beneficio); $stmt->bindParam(':stock', $stock); $stmt->bindParam(':minimoStock', $minimoStock); $stmt->bindParam(':ventas', $ventas); $stmt->bindParam(':fechaActualizacion', $fechaActualizacion); if ($stmt->execute()) { $productosRegistrados = $productosRegistrados + 1; } else { $productosRegistrados = 0; } } } } $respuesta['totalCategorias'] = $categoriasRegistradas; $respuesta['totalProductos'] = $productosRegistrados; echo json_encode($respuesta); } } function BuscarIdCategoria($categoria, $pdo) { $sql = "SELECT idCategoria FROM categorias_productos WHERE categoria = :categoria"; $stmt = $pdo->prepare($sql); $stmt->bindParam(':categoria', $categoria); $stmt->execute(); // Obtener el resultado del fetch $resultado = $stmt->fetch(PDO::FETCH_ASSOC); // Retornar el valor de idCategoria o null si no se encuentra return ($resultado) ? $resultado['idCategoria'] : null; } ?>
Explicacicon del codigo
1. Carga del Archivo Excel
El código utiliza la biblioteca PhpSpreadsheet para cargar el archivo Excel. Verifica que se haya enviado un archivo y obtiene su nombre temporal.
<?php require_once('../../vendor/autoload.php'); require_once('../../conexion.php'); use PhpOffice\PhpSpreadsheet\IOFactory; if ($_SERVER['REQUEST_METHOD'] === 'POST') { if (!empty($_FILES['fileProductos']['tmp_name'])) { $nombreArchivo = $_FILES['fileProductos']['tmp_name']; $documento = IOFactory::load($nombreArchivo);
2. Procesamiento de Categorías
Itera sobre la hoja de categorías del Excel, insertando cada categoría en la tabla 'categorias_productos' de la base de datos. La fecha de actualización se establece en el momento de la inserción.
<?php for ($i = 2; $i <= $numeroFilasCategorias; $i++) { $categoria = $hojaCategorias->getCellByColumnAndRow(1, $i); $peso = $hojaCategorias->getCellByColumnAndRow(2, $i); $fechaActualizacion = date("Y-m-d"); if (!empty($categoria)) { $sql = "INSERT INTO categorias_productos (categoria, peso, fechaActualizacion) VALUES (:categoria, :peso, :fechaActualizacion)"; $stmt = $pdo->prepare($sql); $stmt->bindParam(':categoria', $categoria); $stmt->bindParam(':peso', $peso); $stmt->bindParam(':fechaActualizacion', $fechaActualizacion); if ($stmt->execute()) { $categoriasRegistradas = $categoriasRegistradas + 1; } else { $categoriasRegistradas = 0; } } } ? >
3. Procesamiento de Productos
Similar al paso anterior, itera sobre la hoja de productos y realiza la inserción en la tabla 'productos'. Busca el ID de la categoría correspondiente utilizando la función BuscarIdCategoria.
<?php for ($i = 2; $i <= $numeroFilasProductos; $i++) { $codigoBarras = $hojaProductos->getCell("A" . $i); $categoria = BuscarIdCategoria($hojaProductos->getCell("B" . $i), $pdo); $producto = $hojaProductos->getCell("C" . $i); $precioCompra = $hojaProductos->getCell("D" . $i); $precioVenta = $hojaProductos->getCell("E" . $i); $beneficio = $hojaProductos->getCell("F" . $i)->getCalculatedValue(); $stock = $hojaProductos->getCell("G" . $i); $minimoStock = $hojaProductos->getCell("H" . $i); $ventas = $hojaProductos->getCell("I" . $i); $fechaActualizacion = date("Y-m-d"); if (!empty($codigoBarras)) { $sql = "INSERT INTO productos (codigoBarras, categoria, producto, precioCompra, precioVenta, beneficio, stock, minimoStock, ventas, fechaActualizacion) VALUES (:codigoBarras, :categoria, :producto, :precioCompra, :precioVenta, :beneficio, :stock, :minimoStock, :ventas, :fechaActualizacion)"; $stmt = $pdo->prepare($sql); $stmt->bindParam(':codigoBarras', $codigoBarras); $stmt->bindParam(':categoria', $categoria); $stmt->bindParam(':producto', $producto); $stmt->bindParam(':precioCompra', $precioCompra); $stmt->bindParam(':precioVenta', $precioVenta); $stmt->bindParam(':beneficio', $beneficio); $stmt->bindParam(':stock', $stock); $stmt->bindParam(':minimoStock', $minimoStock); $stmt->bindParam(':ventas', $ventas); $stmt->bindParam(':fechaActualizacion', $fechaActualizacion); if ($stmt->execute()) { $productosRegistrados = $productosRegistrados + 1; } else { $productosRegistrados = 0; } } } ?>
4. Función BuscarIdCategoria
Esta función busca el ID de una categoría en la base de datos a partir de su nombre. Utilizada para relacionar productos con categorías existentes.
<?php function BuscarIdCategoria($categoria, $pdo) { $sql = "SELECT idCategoria FROM categorias_productos WHERE categoria = :categoria"; $stmt = $pdo->prepare($sql); $stmt->bindParam(':categoria', $categoria); $stmt->execute(); $resultado = $stmt->fetch(PDO::FETCH_ASSOC); return ($resultado) ? $resultado['idCategoria'] : null; } ?>
5. Respuesta JSON
Finalmente, el código devuelve una respuesta en formato JSON indicando el número total de categorías y productos registrados.
<?php $respuesta['totalCategorias'] = $categoriasRegistradas; $respuesta['totalProductos'] = $productosRegistrados; echo json_encode($respuesta); ?>
0 Comentarios
Si desea contactar comigo, lo puede hacer atravez deste formulario gracias