Die Klasse Datatable (im Namespace: System.Data) "stellt eine Tabelle mit im Arbeitsspeicher befindlichen Daten dar" und "ist ein zentrales Objekt in der ADO.NET-Bibliothek". Instanzen dieser Klasse werden meist verwendet, um Daten aus Datenbanken über einen Datenadapter abzurufen. Ein Tabellenschema (Spalten) kann aber auch per Code definiert und die Tabelle durch Hinzufügen von Zeilen mit Daten gefüllt werden (vgl. Routine 'FillTable'). Um Daten aus einer numerischen Tabellen-Spalte effizient weiterverarbeiten zu können, ist es oft zweckmäßig, sie zunächst in ein Array zu übertragen. Die DataTable-Erweiterungsmethode GetCol und ihre Varianten erledigen diesen Job:
Die Erweiterung 'GetCols' übernimmt eine Liste von Spaltennamen und trägt die zugehörigen Daten in ein Array von Arrays ein. Fehlt die Namensliste, werden alle Tabellendaten ausgelesen. Das funktioniert aber nur, falls alle Tabellen-Spalten numerisch sind. Falls Sie in der Tabelle eine Spalte mit Nullwerten abfragen wollen, aber weder Nullable-Strukturen verwenden noch diese Werte filtern möchten, steht als Alternative die Version 'GetColumn_DBL' zur Verfügung. Sie gibt STETS ein Double-Array zurück, in dem NULL-Werte durch den IEEE-Sonderwert 'Double.NaN' markiert sind. Bei Verwendung dieses Wertes gibt es einige wichtige Besonderheiten zu beachten:
Die Anwendungsbeispiele zeigen die Aufrufe der verschiedenen Abfrage-Varianten. Bei der Angabe einer nicht vorhandenen Tabelle oder eines nicht vorhandenen Spaltennamens im Parameter 'ColumName' kommt es zu einer Ausnahme (bei den Funktionen die keinen Try/Catch-Block enthalten). Um die Erweiterungen zu verwenden. muss das Modul 'mod_GetTableColumn' dem Projekt hinzugefügt werden. Aufrufbeispiele: ' Demo-Tabelle erstellen und füllen Dim dt As Data.DataTable = FillTable() ' Abfrage von numerische Spalten durch generische Methode ' (Zielarrays mit Nullable-Strukturen für fehlende Werte) Dim Byt?() As Byte = dt.GetCol(Of Byte)("Sp_Byte") Dim Integ?() As Integer = dt.GetCol(Of Integer)("Sp_Integer") Dim col_name As String = dt.Columns(2).ColumnName Dim Sng?() As Single = dt.GetCol(Of Single)(col_name) ' Zulässige Konvertierungen können bei ' der Abfrage vorgenommen werden Dim Dec_Sng?() As Decimal = _ dt.GetCol(Of Decimal)("Sp_Single") ' Die Abfrage von String-Spalten ' mit numerischem Inhalt ist möglich Dim Dec_Str?() As Decimal = dt.GetCol(Of Decimal)("Sp_String") ' alternative Abfrage-Variante (Fehlerbehandlung) ' (auch einschränkende Konvertierung ist zugelassen !!) Dim ulng?(0) As ULong If Not dt.GetCol("Sp_Single", ulng) Then MessageBox.Show("Abfrage scheitert") End If ' Diese Variante bietet auch die Möglichkeit zum Sortieren ' Nothing wird im Array nach vorne sortiert Dim shrt?(0) As Short If Not dt.GetCol("Sp_String", shrt, True) Then MessageBox.Show("Abfrage scheitert") End If ' Filternde Abfragevariante (Null-Werte sind entfernt) Dim intg() As Integer = dt.GetCol1(Of Integer)("Sp_String") ' Summe der Spalte 'Sp_Integer' berechnen ' Erweiterungsmethode 'SUM' in Linq.Enumerable Dim summe? As Integer = _ dt.GetCol(Of Integer)("Sp_Integer").Sum ' Die Erweiterungen in Linq.Enumerable stellen ' Überladungen für Nullable-Strukturen bereit und filtern ' bei der Berechnung NULL-Werte automatisch aus Dim ave? As Single = _ dt.GetCol(Of Single)("Sp_Single").Average ' Falls keine Werte in der Spalte vorliegen, entsteht ein ' Ergebnis-Array, das keine Elemente besitzt Dim dbl() As Double = dt.GetCol1(Of Double)("Sp_Null") ' Mehrere Spalten in ein Array von Arrays eintragen Dim dec_cols?()() As Decimal = dt.GetCols(Of Decimal) _ ("Sp_Single", "Sp_Integer", "Sp_String") ' Die Daten der Spalte "Sp_Integer" stehen in dec_cols(1) Dim dec_int?() As Decimal = dec_cols(1) ' Alle Spalten der Tabelle abfragen Dim tab_cols?()() As Decimal = dt.GetCols(Of Decimal)() ' Die Daten der Spalte "Sp_Decimal" stehen in tab_cols(4) Dim dec_val?() As Decimal = tab_cols(4) Hier das Modul mit den Erweiterungen für die Übertragung numerischer Tabellen-Spalten in ein Array: Option Strict On Option Explicit On Option Infer Off Imports System.Data Imports System.Linq Public Module mod_GetTableColumn ''' <summary>Abfrage einer Tabellenspalte ''' (incl. Nullwerte)</summary> ''' <typeparam name="T">Typ der Rückgabe</typeparam> ''' <param name="Table">Tabelle</param> ''' <param name="ColumnName">Name der Tabellenspalte</param> ''' <returns>Array mit Werten der Tabellenspalte</returns> <System.Runtime.CompilerServices.Extension()> _ Public Function GetCol(Of T As Structure) ( _ ByVal Table As System.Data.DataTable, _ ByVal ColumnName As String) As T?() Dim cv As New T 'Hilsvariable für TypInferenz (Rückgabe) Return (From row As System.Data.DataRow In Table _ Let colval As Nullable(Of T) = _ Get_T(row.Item(ColumnName), cv) _ Select colval).ToArray End Function ''' <summary>Abfrage einer Tabellenspalte ''' (Filter für Nullwerte)</summary> ''' <typeparam name="T">Typ der Rückgabe</typeparam> ''' <param name="Table">Tabelle</param> ''' <param name="ColumnName">Name der Tabellenspalte</param> ''' <returns>Array mit Werten der Tabellenspalte</returns> <System.Runtime.CompilerServices.Extension()> _ Public Function GetCol1(Of T As Structure) ( _ ByVal Table As System.Data.DataTable, _ ByVal ColumnName As String) As T() Dim cv As New T 'Hilsvariable für TypInferenz (Rückgabe) Return (From row As System.Data.DataRow In Table _ Let colval As Nullable(Of T) = _ Get_T(row.Item(ColumnName), cv) _ Where Not colval Is Nothing _ Let colval_filter As T = CType(colval, T) _ Select colval_filter).ToArray End Function ''' <summary>Kontrollierte Abfrage einer Tabellenspalte ''' (incl. Nullwerte)</summary> ''' <typeparam name="T">Typ der Rückgabe</typeparam> ''' <param name="Table">Tabelle</param> ''' <param name="ColumnName">Name der Tabellenspalte</param> ''' <param name="SortAscending">Daten ansteigend sortieren?</param> ''' <param name="col_vals">Array mit Spalten-Werten</param> <System.Runtime.CompilerServices.Extension()> _ Public Function GetCol(Of T As Structure) ( _ ByVal Table As System.Data.DataTable, _ ByVal ColumnName As String, ByRef col_vals As T?(), _ Optional ByVal SortAscending As Boolean = False) As Boolean Dim cv As New T 'Hilfsvariable für TypInferenz Try If Not SortAscending Then col_vals = (From row As System.Data.DataRow In Table _ Let colval As Nullable(Of T) = _ Get_T(row.Item(ColumnName), cv) _ Select colval).ToArray Else col_vals = (From row As System.Data.DataRow In Table _ Let colval As Nullable(Of T) = _ Get_T(row.Item(ColumnName), cv) _ Order By colval Select colval).ToArray End If Return True Catch ReDim col_vals(0) Return False End Try End Function ''' <summary>Abfrage der numerischen Spalten in einer Tabelle ''' </summary> ''' <typeparam name="T">Rückgabe-Datentyp</typeparam> ''' <param name="Table">abzufragende Tabelle</param> ''' <param name="ColumnNames">Liste der Spaltennamen</param> ''' <returns>Array aus Arrays mit Spaltenwerten</returns> <System.Runtime.CompilerServices.Extension()> _ Public Function GetCols(Of T As Structure) ( _ ByVal Table As System.Data.DataTable, _ ByVal ParamArray ColumnNames() As String) As T?()() Dim cz As Integer = ColumnNames.Length - 1 Dim cze As Integer = cz If cz < 0 Then cze = Table.Columns.Count - 1 Dim cs?(cze)() As T If cz > 0 Then For i As Integer = 0 To ColumnNames.Length - 1 cs(i) = Table.GetCol(Of T)(ColumnNames(i)) Next i Else For i As Integer = 0 To Table.Columns.Count - 1 cs(i) = Table.GetCol(Of T)(Table.Columns(i).ColumnName) Next i End If Return cs End Function Private Function Get_T(Of T1, T2 As Structure) ( _ ByVal colval As T1, ByVal cv As T2) As T2? ' Umwandlung eines Wertes, der Null sein kann ' in eine Nullable-Struktur des Typs T2 If System.DBNull.Value.Equals(colval) Then Return Nothing Else Return CType(Convert.ChangeType(colval, GetType(T2)), T2) End If End Function ''' <summary>Auslesen einer numerischen Datenspalte</summary> ''' <param name="Table">Datentabelle</param> ''' <param name="ColumnName">Name der Tabellen-Spalte</param> ''' <param name="OrderedAscendíng">Ansteigend sortieren?</param> ''' <returns>Spalteninhalt als Double-Array</returns> <System.Runtime.CompilerServices.Extension()> _ Public Function GetColumn_DBL ( _ ByVal Table As System.Data.DataTable, _ ByVal ColumnName As String, _ Optional ByVal OrderedAscendíng As Boolean = False) As Double() If Not OrderedAscendíng Then Return (From row As System.Data.DataRow In Table _ Let colval As Double = _ CDbl(GetDouble(row.Item(ColumnName))) _ Select colval).ToArray Else ' ansteigend sortierte Daten Return (From row As System.Data.DataRow In Table _ Let colval As Double = _ CDbl(GetDouble(row.Item(ColumnName))) _ Order By colval Select colval).ToArray End If End Function Private Function GetDouble(Of T)(ByVal colval As T) As Double ' EntryWert in Double wandeln ' Hilfsfunktion für GetColumn_DBL If System.DBNull.Value.Equals(colval) Then Return Double.NaN Else Return CType(Convert.ChangeType (colval, TypeCode.Double), Double) End If End Function Public Function FillTable() As System.Data.DataTable ' DataTable-Instanz erstellen ' und mit einigen Spalten versehen ' für die Aufrufbeispiele Dim dt As New System.Data.DataTable("Test-Tabelle") dt.Columns.Add("Sp_Byte", GetType(Byte)) dt.Columns.Add("Sp_Integer", GetType(Integer)) dt.Columns.Add("Sp_Single", GetType(Single)) dt.Columns.Add("Sp_String", GetType(String)) dt.Columns.Add("Sp_Decimal", GetType(Decimal)) dt.Columns.Add("Sp_Null", GetType(Integer)) Dim N As Integer = 10 ' Zeilenzahl ' Einige Datenzeilen eintragen For i As Integer = 1 To N If i Mod 2 = 0 Then ' Fehlende Werte in Sp_Single und Sp_String dt.Rows.Add(i, (100 - i) ^ 2, System.DBNull.Value, _ Nothing, (N + 1 - i) * 12345678.12345678, _ System.DBNull.Value) Else dt.Rows.Add(i, i, Microsoft.VisualBasic.Rnd, _ CDbl(100 * i), (N + 1 - i) * 12345678.12345678, _ System.DBNull.Value) End If Next i ' Rückgabe Return dt End Function End Module Dieser Tipp wurde bereits 16.939 mal aufgerufen.
Anzeige
![]() ![]() ![]() Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv! - nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten - Symbol-Galerie mit mehr als 3.200 Icons im modernen Look Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m. |
vb@rchiv CD Vol.6 ![]() ![]() Geballtes Wissen aus mehr als 8 Jahren vb@rchiv! Online-Update-Funktion Entwickler-Vollversionen u.v.m. Tipp des Monats ![]() Manfred Bohn IndexOf für mehrdimensionale Arrays Die generische Funktion "IndexOf" ermittelt das erste Auftreten eines bestimmten Wertes in einem n-dimensionalen Array Neu! sevDTA 3.0 Pro ![]() SEPA mit Kontonummernprüfung Erstellen von SEPA-Dateien mit integriertem BIC-Verzeichnis und Konto- nummern-Prüfverfahren, so dass ungültige Bankdaten bereits im Vorfeld ermittelt werden können. |
||||||||||||||||
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein. |