Leer una fecha desde xlsx usando open xml sdk


Tengo una fecha en formato "4/5/2011" (mes/día/año) en un archivo xlsx en una de las celdas. Estoy tratando de analizar el archivo y cargar esos datos en algunas clases.

Hasta ahora la parte donde analizo la celda se ve así:

string cellValue = cell.InnerText;
if (cell.DataType != null)
{
    switch (cell.DataType.Value)
    {
        case CellValues.SharedString:
            // get string from shared string table
            cellValue = this.GetStringFromSharedStringTable(int.Parse(cellValue));
            break;
    }
}

Esperaba que esa fecha fuera una celda.Tipo de datos. La verdad es que al analizar la celda con la fecha "4/5/2011", el valor de la celda.El tipo de datos es null y el valor de la celda es "40638" y no es un índice de la tabla de cadenas compartidas. (He intentado que antes y terminó con una excepción.)

¿Alguna idea? Gracias

Author: Santhos, 2012-11-01

5 answers

Open XML almacena las fechas como el número de días a partir del 1 de enero de 1900. Bueno, omitiendo el incorrecto 29 de febrero de 1900 como un día válido. Usted debe ser capaz de encontrar algoritmos para ayudarle a calcular el valor correcto. Creo que algunos desarrolladores usan DateTime.FromOADate() como ayudante.

Además, la clase Cell tiene la propiedad DataType como Número por defecto. Así que si es null, es un número, que incluye fechas en nuestro caso.

Solo se accede a la tabla de cadenas compartidas cuando la fecha almacenada es anterior a la época (1 Jan 1900 en este caso). Y luego en ese caso, el valor de celda de la clase de celda contiene el índice de la tabla de cadenas compartidas.

 29
Author: Vincent Tan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-16 09:37:20

Puede usar DateTime.FromOADato (41690)

 10
Author: mzoabi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-01 01:54:22

Tuve el mismo problema-cambié a EPPlus http://epplus.codeplex.com /

Tenga en cuenta que tiene licencia LGPL. Por lo tanto, si necesita que su base de código esté a salvo del problema de la GPL, simplemente use la biblioteca tal cual y su licencia base de código original esté a salvo.

 3
Author: CKmum,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-01 12:18:55

Añadiendo mi valor de 2 peniques. Estoy procesando una plantilla, por lo que sé que una celda dada está destinada a ser una Fecha y hora. Así que termino en este método con un parámetro de cadena excelDateTime que contiene el valor de la celda, que normalmente será un número OADate como "42540.041666666664".

public static bool TryParseExcelDateTime(string excelDateTimeAsString, out DateTime dateTime)
{
    double oaDateAsDouble;
    if (!double.TryParse(excelDateTimeAsString, out oaDateAsDouble)) //this line is Culture dependent!
        return false;
    //[...]
    dateTime = DateTime.FromOADate(oaDateAsDouble);

Mi problema es que el usuario final está en Alemania, y debido a que este es un sitio web, hemos establecido el hilo.Hilo actual.CurrentCulture and Thread.Hilo actual.CurrentUICulture to "DE-de". Y cuando llamas double.TryParse, usa la cultura para analizar el número. Así que esta línea: double.TryParse("42540.041666666664", out oaDate) funciona, pero devuelve 42540041666666664 como en Alemania el punto es un separador de grupos. DateTime.FromOADate entonces falla porque el número está fuera de rango (minOaDate = -657435.0, maxOaDate = +2958465.99999999).

Esto me hace pensar que:

  1. independientemente de la configuración regional en el equipo de un usuario, el documento OpenXML contiene números formateados en una configuración regional predeterminada (US? invariante? en cualquier caso, con el punto como separador decimal). He buscado, pero no he encontrado la especificación para esto.
  2. al hacer double.TryParse en una cadena OADate potencial, debemos hacerlo con double.TryParse(excelDateTimeAsString, NumberStyles.Any, CultureInfo.InvariantCulture, out oaDateAsDouble)). Estoy usando CultureInfo.InvariantCulture, pero debería ser lo que sea el punto 1, que no estoy seguro.
 0
Author: Thierry_S,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-23 14:31:31

Cada celda tiene 2 propiedades r(CellReference) y s (StyleIndex)

StyleIndex para números es 2 y para fecha es 3

Fecha está en ODate y puede convertir a formato de cadena

Value = DateTime.FromOADate (doble.Parse(valor)).ToShortDateString ();

 -1
Author: Israel Cortés,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-28 17:18:40