Domanda

Ho un lavoro C # /. Net che importa i dati da Excel e li elabora. Il nostro client elimina i file e li elaboriamo (importante perché non ho alcun controllo sul file originale).

Uso la libreria OleDb per riempire un set di dati (odio scrivere quel codice. Seriamente, c'è qualche codice che uno sviluppatore .Net teme di scriverne di più?). Il file contiene alcuni numeri come 30829300, 30071500, ecc ... Il tipo di dati per quelle colonne è " Testo. & Quot;

Questi numeri vengono convertiti in notazione scientifica quando importi i dati. Esiste un modo per impedire che ciò accada?

-Chris

È stato utile?

Soluzione

La libreria OleDb verrà , il più delle volte, rovinare i tuoi dati in un foglio di calcolo Excel. Ciò è in gran parte dovuto al fatto che forza tutto in un layout di colonna di tipo fisso, indovinando sul tipo di ogni colonna dai valori nelle prime 8 celle di ogni colonna. Se indovina, si finisce con stringhe di cifre convertite in notazione scientifica. Blech!

Per evitare ciò, è meglio saltare OleDb e leggere il foglio direttamente da soli. Puoi farlo usando l'interfaccia COM di Excel (anche blech!) O un lettore compatibile con .NET Excel di terze parti. SpreadsheetGear è una di queste librerie che funziona abbastanza bene e ha un'interfaccia molto simile all'interfaccia COM di Excel.

Altri suggerimenti

Una soluzione alternativa a questo problema è quella di modificare l'istruzione select, invece di SELECT * eseguire questa operazione:

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

Tuttavia, facendo ciò esploderà se le tue celle contengono più di 255 caratteri con il seguente errore: " Errori generati dall'operazione OLE DB in più passaggi. Controllare ogni valore di stato OLE DB, se disponibile. Non è stato eseguito alcun lavoro. & Quot;

Fortunatamente il mio cliente non si è preoccupato di sbagliare in questo scenario.

Questa pagina ha anche un sacco di cose buone da provare: http: //www.dicks- blog.com/archives/2004/06/03/external-data-mixed-data-types/

Usando questa stringa di connessione:

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

con Excel 2010 ho notato quanto segue. Se il file Excel è aperto quando si esegue OLEDB SELECT, si ottiene la versione corrente delle celle, non i valori del file salvato. Inoltre, i valori di stringa restituiti per un numero lungo, un valore decimale e una data sono simili al seguente:

5.0130370071e+012
4.08
36808

Se il file non è aperto, i valori restituiti sono:

5013037007084
£4.08
Monday, October 09, 2000

Se guardi il file .XSLX effettivo usando lo Strumento di produttività Open XML SDK 2.0 (o semplicemente decomprimi il file e visualizzi l'XML nel blocco note) vedrai che Excel 2007 effettivamente archivia i dati grezzi in formato scientifico.

Ad esempio 0.00001 è memorizzato come 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>

Guardando la cella in Excel viene visualizzata come 0,00001 sia nella cella che nella barra della formula. Quindi non è sempre vero che OleDB sta causando il problema.

Ho scoperto che il modo più semplice è scegliere il formato Zip, piuttosto che il formato di testo per le colonne con 'numeri' grandi.

Hai provato a trasmettere il valore del campo a (int) o forse (Int64) mentre lo stai leggendo?

Cerca l'opzione della stringa di connessione IMEX = 1 e l'impostazione del Registro di sistema TypeGuessRows su google. In verità, non esiste un modo semplice per aggirare questo perché il lettore analizza i tipi di dati di colonna osservando le prime righe (8 per impostazione predefinita). Se le righe contengono tutti i numeri, sei sfortunato.

Una sfortunata soluzione che ho usato in passato è usare l'opzione stringa di connessione HDR = NO e impostare il valore di impostazione del Registro di sistema TypeGuessRows su 1, che lo costringe a leggere la prima riga come dati validi per determinare il tipo di dati , piuttosto che un'intestazione. È un trucco, ma funziona. Il codice legge la prima riga (contenente l'intestazione) come testo, quindi imposta il tipo di dati di conseguenza.

La modifica del registro è una seccatura (e non sempre è possibile) ma in seguito consiglierei di ripristinare il valore originale.

Se i tuoi dati di importazione non hanno una riga di intestazione, un'opzione alternativa è quella di pre-elaborare il file e inserire un carattere prima di ciascuno dei numeri nella colonna offensiva. Questo fa sì che i dati della colonna vengano trattati come testo.

Quindi, tutto sommato, ci sono un sacco di hack per aggirare questo, ma nulla di veramente infallibile.

Ho avuto lo stesso problema, ma sono stato in grado di aggirare il problema senza ricorrere all'interfaccia COM di Excel o al software di terze parti. Implica un piccolo overhead di elaborazione, ma sembra funzionare per me.

  1. Prima leggi nei dati per ottenere i nomi delle colonne
  2. Quindi crea un nuovo DataSet con ognuna di queste colonne, impostando ciascuno dei loro DataTypes su stringa.
  3. Leggi nuovamente i dati in questo nuovo set di dati. Voila: la scienza la notazione ora è sparita e tutto viene letto come una stringa.

Ecco un po 'di codice che illustra questo, e come bonus aggiuntivo, è anche 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.
                        }
                    }
                }
            }
        }
    }
}

Ho cercato su Google in questo stato .. Ecco i miei passi per la solitudine

  • Per il file Excel modello

Colonna Excel a 1 formato come testo 2- scrivere macro per disabilitare gli avvisi di errore per Numero - > conversione del testo

  Private Sub Workbook_BeforeClose(Cancel As Boolean)
Application.ErrorCheckingOptions.BackgroundChecking = Ture
End Sub
Private Sub Workbook_Open()
Application.ErrorCheckingOptions.BackgroundChecking = False
End Sub
  • Su codebehind

3- durante la lettura dei dati da importare prova ad analizzare i dati in arrivo su Int64 o Int32 ....

Sono interessato a sapere se qualcuno ha avuto una risposta a questo. Sono stato su e giù per le interwebs e ho provato tutte le combinazioni di IMEX e HDR. IMEX = 1 è l'unico con cui sono riuscito a estrarre i valori di data, valuta e numero generale. Ma i grandi numeri mostrano ancora come scientifici. Devo solo leggere i file e cambiare fogli di calcolo, registro, terze parti non è un'opzione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top