2011-08-19 15 views
25

Ho un problema con un DataRow con cui sono davvero alle prese.DataRow: Seleziona il valore della cella per un nome di colonna specificato

Il datarow viene letto da un foglio di calcolo Excel utilizzando un OleDbConnection.

Se provo a selezionare i dati da DataRow utilizzando il nome della colonna, restituisce DBNull anche se ci sono dati lì.

Ma non è proprio così semplice.

datarow.Table.Columns[5].ColumnName restituisce "la mia colonna".
datarow["my column"] restituisce DBNull.
datarow[5] restituisce 500.
datarow[datarow.Table.Columns[5].ColumnName] restituisce DBNull. (solo per assicurarsi che non sia un errore di battitura!)

Potrei semplicemente selezionare le cose dal datarow utilizzando il numero di colonna, ma non mi piace farlo poiché se l'ordine delle colonne cambia, il software si interromperà.

+0

datarow.Table.Rows? – sll

+0

puoi mostrare il tuo codice? – Reniuz

+0

Che aspetto ha il foglio di calcolo? Ha delle righe vuote in cima? Qual è la tua stringa di connessione? Qual è la più piccola quantità di codice necessaria per riprodurlo che potremmo guardarla? (incluso foglio campioni) – Will

risposta

37

Quale versione di .NET stai usando? Da .NET 3.5, esiste un assembly System.Data.DataSetExtensions, che contiene varie estensioni utili per dataTable, dataRows e simili.

Puoi provare a utilizzare

row.Field<type>("fieldName"); 

se questo non funziona, si può fare questo:

DataTable table = new DataTable(); 
var myColumn = table.Columns.Cast<DataColumn>().SingleOrDefault(col => col.ColumnName == "myColumnName"); 
if (myColumn != null) 
{ 
    // just some roww 
    var tableRow = table.AsEnumerable().First(); 
    var myData = tableRow.Field<string>(myColumn); 
    // or if above does not work 
    myData = tableRow.Field<string>(table.Columns.IndexOf(myColumn)); 
} 
+0

Contrassegnare questo come la risposta in quanto mi ha portato a capire cosa stava succedendo. Risulta che quando usavo Quick Watch, ho digitato l'id della colonna sbagliata. La digitazione dell'id della colonna corretta ha restituito nulla anche se nella riga c'erano dei dati.Non sono del tutto sicuro del motivo per cui è stato restituito nulla, ma suppongo che abbia a che fare con l'interpretazione dei tipi di dati, perché questa era l'unica riga con un valore non nullo e la sostituzione di null con 0 in tutte le altre righe ha reso anche il valore corretto di questa riga. – VaticanUK

4

Suggerimento

DataTable table = new DataTable(); 
table.Columns.Add("Column#1", typeof(int)); 
table.Columns.Add("Column#2", typeof(string)); 
table.Rows.Add(5, "Cell1-1"); 
table.Rows.Add(130, "Cell2-2"); 

EDIT: aggiunto più

string cellValue = table.Rows[0].GetCellValueByName<string>("Column#2"); 

public static class DataRowExtensions 
{ 
    public static T GetCellValueByName<T>(this DataRow row, string columnName) 
    { 
     int index = row.Table.Columns.IndexOf(columnName); 
     return (index < 0 || index > row.ItemArray.Count()) 
        ? default(T) 
        : (T) row[index];   
    } 
} 
+0

e come si usa questo codice per ottenere dati per ** nome colonna **? – Reniuz

+0

@ Renuz: aggiornato – sll

33

Questo deve essere una nuova funzione o qualcosa, altrimenti non so perché non è stato menzionato.

È possibile accedere al valore di una colonna in un oggetto DataRow utilizzando row["ColumnName"]:

DataRow row = table.Rows[0]; 
string rowValue = row["ColumnName"].ToString(); 
+0

Se la voce di dati è NULL, credo che verrà generato un errore quando viene chiamato ToString. – Zorgarath

+0

@Zorgarath, fatto vero. Riceverai anche un errore se 'table' non ha righe. – Jimmy

1

In cima a quello che ha detto Jimmy, si può anche fare la select generica utilizzando Convert.ChangeType insieme con i necessari controlli nulli:

public T GetColumnValue<T>(DataRow row, string columnName) 
    { 
     T value = default(T); 
     if (row.Table.Columns.Contains(columnName) && row[columnName] != null && !String.IsNullOrWhiteSpace(row[columnName].ToString())) 
     { 
      value = (T)Convert.ChangeType(row[columnName].ToString(), typeof(T)); 
     } 

     return value; 
    } 
6

trovo più facile accedervi nel modo seguente:

 for (int i = 0; i < Table.Rows.Count-1; i++) //Looping through rows 
     { 
      var myValue = Table.Rows[i]["MyFieldName"]; //Getting my field value 

     } 
Problemi correlati