Pregunta

Tengo un trabajo C # /. Net que importa datos de Excel y luego los procesa. Nuestro cliente deja los archivos y los procesamos (importante porque no tengo ningún control sobre el archivo original).

Utilizo la biblioteca OleDb para llenar un conjunto de datos (odio escribir ese código. En serio, ¿hay algún código que un desarrollador de .Net teme escribir más que eso?). El archivo contiene algunos números como 30829300, 30071500, etc. El tipo de datos para esas columnas es "Texto".

Esos números se convierten a notación científica cuando importo los datos. ¿Hay alguna forma de evitar que esto suceda?

-Chris

¿Fue útil?

Solución

La biblioteca OleDb , en la mayoría de los casos, desordenará sus datos en una hoja de cálculo de Excel. Esto se debe en gran medida a que obliga a todo a un diseño de columna de tipo fijo, adivinando al tipo de cada columna a partir de los valores en las primeras 8 celdas de cada columna. Si adivina mal, terminas con cadenas de dígitos convertidas a notación científica. Blech!

Para evitar esto, es mejor omitir el OleDb y leer la hoja directamente. Puede hacerlo utilizando la interfaz COM de Excel (¡también blech!) O un lector de terceros compatible con .NET Excel. SpreadsheetGear es una de esas bibliotecas que funciona razonablemente bien y tiene una interfaz muy similar a la interfaz COM de Excel.

Otros consejos

Una solución a este problema es cambiar su declaración de selección, en lugar de SELECT * haga esto:

"SELECT Format([F1], 'General Number')  From [Sheet1$]"
 -or-
"SELECT Format([F1], \"#####\")  From [Sheet1$]"

Sin embargo, hacerlo explotará si sus celdas contienen más de 255 caracteres con el siguiente error: " La operación OLE DB de pasos múltiples generó errores. Verifique cada valor de estado de OLE DB, si está disponible. No se realizó ningún trabajo. & Quot;

Afortunadamente, a mi cliente no le importaron los errores en este escenario.

Esta página también tiene muchas cosas buenas para probar: http: //www.dicks- blog.com/archives/2004/06/03/external-data-mixed-data-types/

Usando esta cadena de conexión:

Provider=Microsoft.ACE.OLEDB.12.0; data source={0}; Extended Properties=\"Excel 12.0;HDR=NO;IMEX=1\"

con Excel 2010 he notado lo siguiente. Si el archivo Excel está abierto cuando ejecuta OLEDB SELECT, obtiene la versión actual de las celdas, no los valores guardados del archivo. Además, los valores de cadena devueltos para un número largo, un valor decimal y una fecha se ven así:

5.0130370071e+012
4.08
36808

Si el archivo no está abierto, los valores devueltos son:

5013037007084
£4.08
Monday, October 09, 2000

Si observa el archivo .XSLX real utilizando la herramienta de productividad Open XML SDK 2.0 (o simplemente descomprime el archivo y visualiza el XML en el bloc de notas) verá que Excel 2007 realmente almacena los datos en bruto en formato científico.

Por ejemplo, 0.00001 se almacena como 1.0000000000000001E-5

<x:c r="C18" s="11" xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
  <x:v>1.0000000000000001E-5</x:v>
</x:c>

Al mirar la celda en Excel, se muestra como 0.00001 tanto en la celda como en la barra de fórmulas. Por lo tanto, no siempre es cierto que OleDB está causando el problema.

He descubierto que la forma más fácil es elegir el formato Zip, en lugar del formato de texto para columnas con grandes 'números'.

¿Has intentado convertir el valor del campo en (int) o tal vez (Int64) mientras lo estás leyendo?

Busque la opción de cadena de conexión IMEX = 1 y la configuración de registro TypeGuessRows en google. En verdad, no hay una forma fácil de evitar esto porque el lector infiere tipos de datos de columna al mirar las primeras filas (8 por defecto). Si las filas contienen todos los números, entonces no tienes suerte.

Una solución alternativa desafortunada que he usado en el pasado es usar la opción de cadena de conexión HDR = NO y establecer el valor de configuración del registro TypeGuessRows en 1, lo que lo obliga a leer la primera fila como datos válidos para hacer su determinación del tipo de datos , en lugar de un encabezado. Es un truco, pero funciona. El código lee la primera fila (que contiene el encabezado) como texto y luego establece el tipo de datos en consecuencia.

Cambiar el registro es una molestia (y no siempre es posible), pero recomendaría restaurar el valor original después.

Si sus datos de importación no tienen una fila de encabezado, entonces una opción alternativa es preprocesar el archivo e insertar un carácter 'antes de cada uno de los números en la columna ofensiva. Esto hace que los datos de la columna se traten como texto.

Entonces, en general, hay un montón de trucos para solucionar esto, pero nada realmente infalible.

Tuve este mismo problema, pero pude solucionarlo sin recurrir a la interfaz COM de Excel o software de terceros. Implica una pequeña sobrecarga de procesamiento, pero parece estar funcionando para mí.

  1. Primero lea los datos para obtener los nombres de columna
  2. Luego cree un nuevo DataSet con cada una de estas columnas, configurando cada uno de sus DataTypes en cadena.
  3. Lea los datos nuevamente en este nuevo conjunto de datos Voila - la científica la notación ya no existe y todo se lee como una cadena.

Aquí hay un código que ilustra esto, y como una ventaja adicional, ¡es incluso StyleCopped!

public void ImportSpreadsheet(string path)
{
    string extendedProperties = "Excel 12.0;HDR=YES;IMEX=1";
    string connectionString = string.Format(
        CultureInfo.CurrentCulture,
        "Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"{1}\"",
        path,
        extendedProperties);

    using (OleDbConnection connection = new OleDbConnection(connectionString))
    {
        using (OleDbCommand command = connection.CreateCommand())
        {
            command.CommandText = "SELECT * FROM [Worksheet1$]";
            connection.Open();

            using (OleDbDataAdapter adapter = new OleDbDataAdapter(command))
            using (DataSet columnDataSet = new DataSet())
            using (DataSet dataSet = new DataSet())
            {
                columnDataSet.Locale = CultureInfo.CurrentCulture;
                adapter.Fill(columnDataSet);

                if (columnDataSet.Tables.Count == 1)
                {
                    var worksheet = columnDataSet.Tables[0];

                    // Now that we have a valid worksheet read in, with column names, we can create a
                    // new DataSet with a table that has preset columns that are all of type string.
                    // This fixes a problem where the OLEDB provider is trying to guess the data types
                    // of the cells and strange data appears, such as scientific notation on some cells.
                    dataSet.Tables.Add("WorksheetData");
                    DataTable tempTable = dataSet.Tables[0];

                    foreach (DataColumn column in worksheet.Columns)
                    {
                        tempTable.Columns.Add(column.ColumnName, typeof(string));
                    }

                    adapter.Fill(dataSet, "WorksheetData");

                    if (dataSet.Tables.Count == 1)
                    {
                        worksheet = dataSet.Tables[0];

                        foreach (var row in worksheet.Rows)
                        {
                            // TODO: Consume some data.
                        }
                    }
                }
            }
        }
    }
}

Busqué en Google este estado ... Aquí están mis pasos de solución

  • Para el archivo de plantilla de Excel

Coloumn de Excel de 1 formato como texto 2- escribir macro para deshabilitar las advertencias de error para Number - > conversión de texto

  Private Sub Workbook_BeforeClose(Cancel As Boolean)
Application.ErrorCheckingOptions.BackgroundChecking = Ture
End Sub
Private Sub Workbook_Open()
Application.ErrorCheckingOptions.BackgroundChecking = False
End Sub
  • En código detrás

3- mientras lee datos para importar intente analizar los datos entrantes a Int64 o Int32 ....

Me interesa saber si alguien recibió una respuesta a esto. He estado arriba y abajo de las redes y probé todas las combinaciones de IMEX y HDR. IMEX = 1 es el único con el que logré extraer valores de fecha, moneda y números generales. Pero grandes números aún se muestran como científicos. Solo necesito leer archivos y cambiar hojas de cálculo, registro, un tercero no es una opción.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top