2010-09-28 10 views
6

In primo luogo, voglio dire che sono in acque profonde qui, poiché sto solo apportando alcune modifiche al codice che è stato scritto da qualcun altro in azienda, usando OleDbDataAdapter per "parlare" con Excel e non mi è familiare. C'è un bug che non riesco a seguire.Problema con l'utilizzo di OleDbDataAdapter per recuperare i dati da un foglio Excel

Sto cercando di utilizzare un OleDbDataAdapter per leggere in un file excel con circa 450 righe.

Nel codice si è fatto in questo modo:

connection = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source='" + path + "';" + "Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=1;\""); 
connection.Open(); 
OleDbDataAdapter objAdapter = new OleDbDataAdapter(objCommand.CommandText, connection); 
objAdapter.Fill(objDataSet, "Excel"); 

foreach (DataColumn dataColumn in objTable.Columns) { 
    if (dataColumn.Ordinal > objDataSet.Tables[0].Columns.Count - 1) { 
    objDataSet.Tables[0].Columns.Add(); 
    } 
    objDataSet.Tables[0].Columns[dataColumn.Ordinal].ColumnName = dataColumn.ColumnName; 
    objImport.Columns.Add(dataColumn.ColumnName); 
} 

foreach (DataRow dataRow in objDataSet.Tables[0].Rows) { 
    ... 
} 

Tutto sembra funzionare bene, tranne che per una cosa. La seconda colonna è piena di numeri per lo più a quattro cifre, come 6739, 3920 e così uno, ma le righe di un utente hanno valori alfanumerici come 8201NO e 8205NO. Quelle cinque celle sono segnalate come aventi contenuto vuoto invece del loro contenuto alfanumerico. Ho controllato in Excel e tutte le celle in queste colonne sono contrassegnate come Testo.

Questo è un file xls a proposito, e non xlsx.

Qualcuno ha qualche indizio sul motivo per cui queste celle vengono visualizzate come vuote nel DataRow, ma quelle numeriche vengono visualizzate correttamente? Ci sono altre colonne con contenuto alfanumerico che vengono mostrate bene.

+0

Grazie a tutti per avermi aiutato con questo problema. Mi hai fatto capire perché è successo, quindi ho trovato la soluzione giusta. Continuo a pensare che il modo in cui funziona sia abbastanza orribile, ma questa è un'altra storia :) –

risposta

8

Che cosa sta succedendo è che Excel sta cercando di assegnare un tipo di dati alla colonna del foglio di calcolo in base ai primi valori diversi in quella colonna. Sospetto che se guardi le proprietà in quella colonna dirà che è una colonna numerica.

Il problema si presenta quando si inizia a provare a interrogare quel foglio di calcolo utilizzando Jet. Quando pensa di avere a che fare con una colonna numerica e trova un valore varchar, non restituisce tranquillamente nulla. Neanche un messaggio di errore criptico da cui partire.

Come possibile soluzione, è possibile spostare uno dei valori alfanumerici nella prima riga di dati e quindi provare l'analisi. Sospetto che inizierai a ricevere i valori per le righe alfanumeriche quindi ...

Dai uno sguardo allo this article. Entra più in dettaglio su questo problema. Si parla anche di un possibile lavoro attorno al quale è:

Tuttavia, come da documentazione JET, si possibile ignorare l'impostazione attraverso la stringa di connessione Registro di sistema, se impostiamo IMEX = 1 (come parte di Extended proprietà), il JET imposterà il tipo di colonna tutte come UNICODE VARCHAR o adVarWChar indipendentemente value.hey chiave 'ImportMixedTypes'

+0

L'ho provato ora, e in effetti se metto la prima riga alfanumerica, allora funziona come previsto. Il mio problema è che non posso renderlo una regola generale, in quanto i clienti leggeranno nei loro fogli. Tuttavia, la mia soluzione era quella di "imbrogliare", in modo che io modifichi HDR = No nella stringa di connessione per assicurarmi che l'intestazione alfanumerica sia letta per rendere la colonna alfanumerica, quindi ho tagliato la prima riga del DataTable risultante. È abbastanza cattivo, ma non vedo altre opzioni qui. Grazie mille per il tuo aiuto per avermi indirizzato nella giusta direzione. –

+0

Molto subdolo. Se funziona funziona! –

1

IMEX=1 significa "Leggi dati misti come testo."

Ci sono alcuni trucchi, tuttavia. Jet utilizzerà solo più righe per determinare se i dati sono mescolati e, se si verifica che queste righe siano tutte numeriche, si otterrà questo comportamento.

Vedi connectionstrings.com per i dettagli:

Scopri i [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Jet\4.0\Engines\Excel] situati registro REG_DWORD "TypeGuessRows". Questa è la chiave per non consentire a Excel di utilizzare solo le prime 8 righe per indovinare il tipo di dati delle colonne. Impostare questo valore su 0 per eseguire la scansione di tutte le righe. Questo potrebbe danneggiare le prestazioni.Si noti inoltre che l'aggiunta dell'opzione IMEX = 1 potrebbe causare l'attivazione della funzione IMEX dopo solo 8 righe. Usa IMEX = 0 invece per essere sicuro di forzare il Registro TypeGuessRows = 0 (scansione di tutte le righe) per funzionare.

+0

Non so come Jet è esposto in Excel, ma in Access, è possibile modificare le cose in quel momento in fase di esecuzione nell'istanza corrente del motore di Jet db senza dover modificare il Registro di sistema e riavviare Access. –

+0

Grazie per questa informazione. Ha funzionato, ma è stato sorprendentemente lento, quindi ho dovuto usare il trucco "read and dispose header". –

1

Vorrei sconsigliare l'utilizzo del materiale del provider di dati OleDb per accedere a Excel se si può aiutare. Non ho avuto altro che problemi, proprio per le ragioni che altri hanno sottolineato. La performance tende ad essere atroce anche quando si hanno a che fare con fogli di calcolo di grandi dimensioni.

Si potrebbe provare questa soluzione open source: http://exceldatareader.codeplex.com/

+0

Sono totalmente d'accordo con te Mark. Penso che sia abbastanza orribile, ma in questo caso non ho alcuna opzione in quanto mi viene assegnato per correggere questo bug in un programma esistente, e non sono stati assegnati i tempi necessari per fare grandi refactoring. Terrò in considerazione il tuo link se dovessi farlo da capo in seguito. –

Problemi correlati