Cómo tratar con fechas en Excel usando PHP

En el desarrollo de aplicaciones para empresas es bastante común tener que trabajar con Excel (Ya sea importando planillas a bases de datos o bien lo inverso).

En general, la libería PHPSpreadSheet funciona muy bien para estos casos (Algo más de información aquí), sin embargo, el tratamiento de las fechas no es tan sencillo como esperamos.

Cómo Excel maneja las fechas

El problema radica en que el valor almacenado en la celda no es en realidad una fecha… si no la cantidad de días transcurridos desde el primero de Enero de 1900 (Si tenés curiosidad abrí el Excel y probá la fórmula «=DATEVALUE(‘1900-01-01’)»).

Esto provoca que, al hacer algo como:

$value = $worksheet->getCell('A1')->getValue();

Obtengamos un número entero (Generalmente grande) en lugar de una fecha

Cómo leer datos de tipo fecha con PhpSpreadsheet

Para resolver este pequeño inconveniente PhpSpreadsheet dispone de un método especial:

$date = \PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($value);

Este método retorna un objeto de tipo DateTime.

A partir de este objeto podemos usar todas las operaciones que queramos.

Cómo escribir datos de tipo fecha con PhpSpreadsheet

Y ¿qué pasa si tenemos que generar valores fecha para exportar a Excel? (Básicamente lo inverso de lo anterior).

Para eso también tenemos un método especial:

\PhpOffice\PhpSpreadsheet\Shared\Date::PHPToExcel( $date )

Este método tomará un objeto DateTime de php y lo convertirá a su correspondiente valor numérico para ser guardado sin problemas en una planilla de cálculo Excel.

mchojrin

Por mchojrin

Ayudo a desarrolladores PHP a acceder mercados y clientes más sofisticados y exigentes

6 comentarios

  1. Buenas tardes, estoy tratando de formatear una hora que tengo en una celda en excel, como podría resolver esto para que cuando lea el excel en php me traiga la hora y no numeros como por ejemplo (0.33333333333333).

    Gracias de antemano.

    1. Puedes probar algo como:

      $date = \PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($value);

      Y luego usar $date->format(‘H:i:s’) para obtener un string con la hora, minutos y segundos.

  2. Buenos días.

    Me podrías decir si existe un comando que me retorne cuántos años, meses y días completos hay en un rango de fecha.

    Por ejemplo

    entrada 1: 10/05/2022
    entrada 2: 25/07/2042
    salida: «La duración es 10 años, 2 meses y 15 días»

    De antemano, te agradezco mucho.
    Quedo atenta a tu respuesta

    1. Hola Jessica:

      Gracias por tu pregunta. Se pueden usar diferentes librerías, una muy utilizada es Carbon. Personalmente prefiero las propias de PHP que son sumamente funcionales.

      Algo que puedes probar:


      <?php
      $entrada1 = DateTimeImmutable::createFromFormat("d/m/Y", "10/05/2022");
      $entrada2 = DateTimeImmutable::createFromFormat("d/m/Y", "25/07/2042");
      $diff = $entrada2->diff($entrada1);
      echo $diff->format("La duración es %Y años, %m meses y %d días");

      Exitos!

  3. La duda es la siguiente, tengo que leer secuencialmente los renglones de un archivo de Excel e insertarlos en una base de datos. Donde la fecha no esta necesariamente en una columna en particular y puede cambiar de columna, al momento de leer una fecha, en efecto me devuelve su valor como un entero, pero requiero guardarla como fecha, la conversión para de entero regresarla a fecha me queda clara, pero… ¿existe alguna manera de identificar que el tipo de dato almacenado en una celda es de tipo fecha? y así poderle aplicar la conversión, pues no todo valor numerico que vaya leyendo en mi proceso, se trata necesariamente de una fecha, gracias de antemano.

    1. Hola Sergio!

      Gracias por tu pregunta :). Es un poco raro el método pero sí, es posible.

      Las celdas pueden identificarse por su tipo usando el método getDataType(), sin embargo, éste método no distingue fechas de otros números.

      Lo que debes hacer es utilizar el método estático \PhpOffice\PhpSpreadsheet\Shared\Date::isDateTime() pasando como parámetro la celda en cuestión.

      Aquí te dejo un ejemplo que te dirá cuáles de las celdas de un archivo son fechas:


      <?php

      require_once 'vendor/autoload.php';

      $reader = PhpOffice\PhpSpreadsheet\IOFactory::createReaderForFile($argv[1]);
      $s = $reader->load($argv[1]);

      $ri = $s->getActiveSheet()->getRowIterator();
      foreach ($ri as $row) {
      $ci = $row->getCellIterator();

      foreach ($ci as $cell) {
          if (\PhpOffice\PhpSpreadsheet\Shared\Date::isDateTime($cell)) {
              echo $cell->getCoordinate().',';
          }
      }
      

      }

¿Te quedó alguna duda? Publica aca tu pregunta

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.