Abou Chleih

{the magic lies between the brackets}

Menü Schließen

Monat: August 2013

[C#] Sortieren einer DataTable-Spalte nach einer Spalte eines anderen DataTable

Ich hatte die Aufgabe eine Spalte einer DataTable bzw. die DataTable(1) an sich nach der Spalte einer anderen DataTable(2) zu sortieren ohne die Reihenfolge der zweiten DataTable(2) zu verändern.
Um zu verdeutlichen, wie die Aufgabenstellung genau aussah, habe ich hier Screenshots der DataTables visualisiert in einem DataGridView im Ist/Soll-Zustand:

Die Sort-Methode des DataGridView, ebenso wie die Sort-Eigenschaft eines DataViews,

DataTable.DefaultView.Sort = "Spaltenname ASC"

bieten nur die Möglichkeit eine Spalte auf(Ascending)- bzw. absteigend(Descending) zu sortieren.

So musste ich mir dann einen eigenen Weg finden, die Aufgabe zu lösen. Die Lösung möchte ich euch natürlich nicht vorenthalten.

 private void sortList(string pExcelDataColumnName, string pSortByListColumnName)
        {
            excelDataTable.Columns.Add("TempOrderColumn", typeof(Int32)); //Dient später zum Sortieren der Zeilen

            foreach (DataRow row in excelDataTable.Rows)
            {
                foreach (DataColumn column in excelDataTable.Columns)
                {
                    if (column.ColumnName == pExcelDataColumnName)
                    {
                        object tempRowIndex = GetRowIndexOfCellValue(row
, pSortByListColumnName); row["TempOrderColumn"] = tempRowIndex; } } } DataView dv = excelDataTable.DefaultView; dv.Sort = "TempOrderColumn ASC"; excelDataTable = dv.ToTable(); excelData_dataGridView.Refresh(); }

In dieser Methode erstellen wir erstmal eine weitere Spalte, welche uns später zum Sortieren dient, danach durchlaufen wir alle Zellen der unsortierten Liste(zweimal foreach) und fragen ab, ob sich einer der Zellen in der zuvor definierten Spalte befindet(Parameter der Methode).
Sollte dies der Fall sein, so rufen wir folgende Methode auf und übergeben den Inhalt der aktuellen Zelle, sowie den Namen der zu vergleichenden Spalte:

private object GetRowIndexOfCellValue(object pCellValue, string pSortByListColumnName)
        {
            foreach (DataRow row in sortByDataTable.Rows)
            {
                foreach (DataColumn column in sortByDataTable.Columns)
                {
                    if (column.ColumnName == pSortByListColumnName && pCellValue.Equals(row
)) { return sortByDataTable.Rows.IndexOf(row); } } } return -1; }

Diese Methode durchläuft sämtliche Zellen der Liste, nach welcher wir sortieren wollen und prüft ob sich die Zelle in der als Parameter übergeben Spalte befindet(indem sie den übergeben Spaltennamen mit jenem der aktuellen Spalte(Column) vergleicht) und ob der Inhalt der Zelle mit jenem Inhalt übereinstimmt, welcher als Parameter übergeben wurde.

Sollte beide Abfragen ‚wahr‘ sein, so geben wir den Index der aktuellen Zeile zurück. Dafür verwenden wir die folgende Methode

return sortByDataTable.Rows.IndexOf(row);

Der Rückgabewert wird dann mittels

row["TempOrderColumn"] = tempRowIndex;

in die temporäre Spalte geschrieben und zu guter Letzt mit folgendem Code sortiert:

            DataView dv = excelDataTable.DefaultView;
            dv.Sort = "TempOrderColumn ASC";
            excelDataTable = dv.ToTable();
            excelData_dataGridView.Refresh();

Dies ist nötig, da man einer DataTable nicht direkt sortieren kann und somit den Umweg über das Erstellen eines DataViews gehen muss, diesen dann mittels

dv.Sort = "Spaltenname ASC" //ASC steht für 'ascending' aufsteigend
//DESC steht für 'descending' absteigend

sortiert und das DataView dann wieder in die DataTable wandelt.

Das Ergebnis sieht wie folgt aus:
2013-08-23 15_51_20-Excel nach Liste sortieren

Nun muss ich nur noch eine Excel-Tabelle aus der DataTable bzw dem DataGridView erstellen. Wie man dies bewerkstelligt, zeige ich in meinem nächsten Blogeintrag

[C#] Auslesen einer Excel Datei #2 – OleDB

Teil 1: [C#] Auslesen einer Excel Datei #1 – Interop-Assembly

OleDB steht für Object Linking and Embedding, Database und bietet einem im Gegensatz zu Interop-Assembly die Möglichkeit auf verschiedenste Datenquellen (bspw. auch auf Datenbanken zuzugreifen). Zugleich muss im Gegensatz zu Interop-Assembly kein Microsoft Excel installiert sein und die meisten Controls, wie z.B. DataGridView, akzeptieren out-of-the-box die Datenquelle (Data Source) welche OleDB bietet.

Hier ein Zitat aus dem MSDN:

OLE DB is a set of COM-based interfaces that expose data from a variety of sources. OLE DB interfaces provide applications with uniform access to data stored in diverse information sources, or data stores. These interfaces support the amount of DBMS functionality appropriate to the data store, enabling the data store to share its data.

OleDB hat einige Vorteile gegenüber Interop-Assembly:

  • Microsoft Excel muss nicht installiert sein
  • Es ist um einiger schneller als Interop

Natürlich aber auch Nachteile

  • OleDB bietet im Vergleich zu Interop in Bezug auf Excel weniger Möglichkeiten, vor allem bezüglich Zelleninformationen, wie Farbe, Rahmen oder Formatierung

Nun aber zur Nutzung von OleDB

Normalerweise bindet Visual Studio automatisch System.Data-Assembly ein und wir müssen nur noch den Namespace mittels

using System.Data.OleDb;

einbinden

Sollte es dennoch zu folgender Fehlermeldung

Fehler 1

Der Typ- oder Namespacename „OleDb“ ist im Namespace „System.Data“ nicht vorhanden. (Fehlt ein Assemblyverweis?)

müssen wir einen Assemblyverweis erstellen.

Dazu einfach mit der rechten Maustaste auf „Verweise“ klicken:

20130811_OleDBTest - Microsoft Visual Studio_000033

„Verweis hinzufügen“ wählen und in den Framework-Assemblys nach System-Data suchen und diese Assembly dann wählen.20130811_Verweis-Manager - OleDBTest_000034

Zu guter Letzt noch mit „OK“ bestätigen.

Ich persönlich bevorzuge es Objekten mittels using eine definierte Gültigkeit zuzuweisen, dies bedeutet, dass das in der Using-Anweisung definierte Objekt nach dem Verlassen der Anweisung nicht mehr benötigt wird und zerstört werden kann.

Dadurch ist es aber nötig den ConnectionString, vor dem Erstellen der OleDbConnection zu definieren und per Paramter zu übergeben.
Um einen ConnectionString zu erstellen, verwende ich den OleDbConnectionStringBuilder:

Dieser bietet eine einfache Möglichkeit, den Inhalt von Verbindungszeichenfolgen zu erstellen und zu verwalten, die von der OleDbConnection-Klasse verwendet werden.


OleDbConnectionStringBuilder csbuilder = new OleDbConnectionStringBuilder();
 csbuilder.Provider = "Microsoft.ACE.OLEDB.12.0";
 csbuilder.DataSource = "Pfad zu Excel-Datei";
 csbuilder.Add("Extended Properties", "Excel 12.0 Xml;HDR=YES");

Der Provider ist eine Softwarebibliothek, welche die nötigen Werkzeuge bietet, um auf eine Datenquelle zuzugreifen. Im ConnectionString werden die Informationen, welche den Provider in die Lage versetzen auf die Quelle zuzugreifen, hinterlegt.
Für ConnectionStrings empfehle ich: http://www.connectionstrings.com/

Im Property DataSource wird der Pfad zu Excel-Datei angegeben.

Mittels der Methode Add werden die Informationen hinterlegt, welche den Typ der Datei und Informationen zum Inhalt definieren.
In diesem Beispiel wird hinterlegt, dass es sich um eine Excel-Datei handelt, welche mit Excel 2010 erstellt wurde(Excel 12.0) und deren erste Zeile Überschriften(Header/HDR) sind.

Da nun die wichtigsten Eigenschaften definiert wurden, können wir das erste Tabellenblatt der Excel-Datei auslesen.
Dazu verwenden wir die SQL-Abfrage

SELECT * FROM [“ + Name_des_Tabellenblattes + „]

(Die eckigen Klammern werden zwingend benötigt)

             using (OleDbConnection connection = new OleDbConnection(csbuilder.ConnectionString))
            {
                DataTable sheet1 = new DataTable();
                connection.Open();
                string sqlQuery = @"SELECT * FROM [" + Name_des_Tabellenblattes + "]";
                using (OleDbDataAdapter adapter = new OleDbDataAdapter(sqlQuery, connection))
                {
                    adapter.Fill(sheet1);
                    excelData_dataGridView.DataSource = sheet1;
                }
                connection.Close();
            }

Und erstellen ein Objekt vom Typ OleDbDataAdapter mit den Parametern „SQL-Query“ und dem ConnectionString.
Danach füllen wir den DataTable mittels adapter.Fill(Name_des_DataTables) und füllen ein DataGridView mittels

DataGridView.DataSource = Name_des_DataTables;

Namen der Tabellenblätter auslesen

Nun ist natürlich ungeschickt den Namen des Tabellenblattes hartcodiert im Code zu hinterlegen.
Um die Tabellenblattnamen auszulesen und in ein StringArray zu laden verwenden wir folgenden Code:

OleDbConnectionStringBuilder csbuilder = new OleDbConnectionStringBuilder();
csbuilder.Provider = "Microsoft.ACE.OLEDB.12.0";
csbuilder.DataSource = pExcelPath;
csbuilder.Add("Extended Properties", "Excel 12.0 Xml;HDR=YES");

System.Data.DataTable dt = null;

using (OleDbConnection connection = new OleDbConnection(csbuilder.ConnectionString))
{
    connection.Open();
    dt = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
    connection.Close();
}

String[] excelSheets = new String[dt.Rows.Count];

int i = 0;
foreach (DataRow row in dt.Rows)
{
    excelSheets[i] = row["TABLE_NAME"].ToString();
    i++;
}

Mit dem StringArray kann man nun eine ganze Menge anfangen.
Ich habe beispielsweise das StringArray als Parameter an ein Objekt einer Form übergeben, welches jeden String im Array(mittels foreach-Schleife) in eine ListView kopiert und man so das gewünschte Tabellenblatt auswählen kann.

DemoProjekt

Hier könnt ihr das Demoprojekt herunterladen:

20130811_Verweis-Manager - OleDBTest_000034

OleDBTest

Gabelausbau/-tausch bei der SV 650 S

Durch einen Unfall wurden bei der SV 650 S (Kante) die Standrohre verbogen, andere Schäden an der Gabel, wie verzogene Brücken ließen sich nicht ausschließen, deshalb besorgten wir uns eine neue Gabel, welche dann eingebaut werden musste.
Bevor man anfangen kann, sollte man die Verkleidung der SV abnehmen, d.h. Kanzel + Geweih entfernen.
Ich gehe hierauf nicht genauer ein, da es bei näherem Hinschauen selbsterklärend sein sollte.

Nun kann man die SV aufbocken. Wir hatten keinen Frontheber zur Verfügung, deshalb „bastelten“ wir uns eine eigene Lösung.
Mit Hilfe einer Leiter und eines Spanngurtes zogen wir die SV am Rahmen in die Luft. Diese Methode hatte sich schon beim Ausbau der Schwinge bewährt.

Nun beginnen wir:
Als erstes muss man mit Hilfe eines 12er Innensechskant (Inbus) das Vorderrad ausbauen, dazu die Sicherungsschraube lösen und die Vorderradachse mit Hilfe des 12er Inbus ausbauen.
Vorderradachse_ausbau
Sobald man die Achse entfernt hat, kann man das Rad nach vorne heraus ziehen.

Aufpassen!
Der, auf der in Fahrtrichtung linken Seite platzierte, Geschwindigkeitssensor darf nicht beschädigt werden!

Nun, da das Vorderrad ausgebaut ist, kann man den Frontfender und die Bremsanlage ab- bzw. ausbauen.

Ab sofort die vordere Bremse nicht mehr betätigen!

Um ersteren zu lösen, muss man die äußeren Verkleidungsschrauben mit einem Inbus und die, an der Innenseite angebrachten, Sechskantschrauben mit einem 10er Schlüssel entfernen.
Den Frontfender kann man dann auch einfach nach vorne herausziehen (auch hier etwas vorsichtig mit dem „Plastik“ umgehen).
Die Bremssättel löst man einfach, indem man die Halteschrauben mit einem 14er Außensechskant entfernt.
Die restlichen Halterung, also die der Bremsleitungen, des Geschwindigkeitssensor, … lösen.
Aufpassen, dass die Bremsssättel nicht einfach lose herumhängen und zu viel Zug auf den Leitungen liegt. Ich habe die Bremssättel einfach mit einem Kabelbinder an der Leiter festgebunden.

Nun liegen die Standrohre und Tauchrohre frei.
Die beiden kann man einfach nach unten raus ziehen, wenn man die folgenden Schrauben löst:
Standrohr_ausbau

Bei den Schrauben der Gabelbrücken handelt es sich, wenn ich mich richtig erinnere, um 14er Außensechskantschrauen, beim Stummel eventuell um einen 12er Außensechskant.

Nun entfernen wir die Steuerkopfmutter der oberen Gabelbrücke und entfernen diesezusammen mit der Unterlagscheibe (oder in Hochdeutsch: Unterlegscheibe).

Gabelbrücke_oben

Anschließend kann man die obere Gabelbrücke ganz einfach nach oben abziehen.
Im Anschluss entfernen wir die beiden Halterungsschrauben für die untere Gabelbrücke, dazu nehmen wir das gezeigte Spezialwerkzeug (im Boardwerkzeug).
Und lösen die obere Schraube, entfernen diese und die Zwischenlagscheibe, danach entfernen die Sicherungsschraube.
Jetzt lösen wir die Konterschraube und schrauben diese raus.
Eine zweite Person sollte gleichzeitig die untere Gabelbrücke mitsamt Lenkkopf halten, sodass diese nicht nach unten herausrutschen.
Gabelbrücke_oben_2

Nun hat man die Gabel ausgebaut und kann die neue einbauen, die Lager der alten können eventuell wiederverwendet werden.
Ein bisschen Fett auf die Lager und wieder aufschieben, aber die Lager nicht einfach fallen lassen!

Fertig.
Einbau erfolgt in umgekehrter Reihenfolge.

Anzugsmomente:
Vorderer Bremszylinder 39 Nm
Spannschrauben der Standrohre 23 Nm
Steuerkopfmutter 90 Nm
Vorderachse 65 Nm
Vorderachsen-Klemmschraube 23 Nm

Auf der Suche nach einem neuen Paar Reifen

Nachdem sich meine Contis vom Typ RoadAttack 2 immer mehr der Verschleißgrenze von 1,6 mm annähern, wird es Zeit sich nach einen neuen Paar Reifen umzusehen.
Zugegeben keine leichte Aufgabe, denn zum Einen waren die Contis auf trockener Straße eine Wucht und hatten durchaus noch Chancen wieder als Reifen meiner SV650S zu dienen, zum Anderen gibt es sehr viele potentielle Nachfolger, welche den Conti beerben könnten.
Wieso wechsle ich überhaupt die Reifen, wenn mir die Contis doch so gefallen haben? Ganz einfach, der Verschleiß ist hoch und das wird nun mal mit der Zeit teuer und wenn es Reifen gibt, welche von den Fahrqualitäten ähnlich sind und einen geringeren Verschleiß aufweisen, so wäre das natürlich doch ein sehr starkes Argument für einen Umstieg.

Nach einigen Recherchen standen folgende mögliche Nachfolger zur Auswahl:

  • Continental RoadAttack 2
  • Pirelli Angel ST
  • Michelin Pilot Power
  • Metzeler Z8 Interact

Letztendlich habe ich mich für den Pirelli Angel ST entschieden.

Folgende Gründe führten dazu:

  1. Im Motorrad Tourenreifen Test 2012 wurde der Pirelli auf den zweiten Platz gewählt(Trockengrip ist aber besser als beim erstplatzierten Z8 und der Verschleiß nur marginal höher, im Regen fahre ich sowieso immer vorsichtig)
  2. Dietmar Töpfer Reifenexperte bei tirendo.de empfiehlt in seinem Beitrag(unten angehängt) den Pirelli Angel ST und wird im nächsten Jahr den Nachfolger des ST, den GT kaufen.
  3. Ein Freund fährt ihn seit einiger Zeit auf seiner SV und ist zufrieden. Auch im SVRider-Forum wird der Reifen gelobt.

Möglicherweise wird es auch der Angel GT, bisher fehlen mir noch die Testberichte um den Schritt zu wagen, aber mein jetziger Satz Reifen hat ja noch ein wenig Profil.

Von der Rennstrecke auf die Straße – der langlebige Sporttourenreifen

Sporttourer sind das Ergebnis der Kombination von Alltagstauglichkeit mit sportlichen Fahreigenschaften. Die flotten Gefährte sind also nicht nur PS-stark, sondern bieten ihren Fahrern einen hohen Komfort mit einer gemütlicheren Sitzposition, einer Federung und etwas mehr Platz für den Sozius.

In vielen Fällen denken die Fahrer, dass Ihre Maschine, aufgrund der starken Motorisierung ebenbürtig der einer Sportmaschine, mit Rennreifen ausgestattet werden sollte. Falsch gedacht! Falls man wirklich mal auf der Rennstrecke unterwegs ist, hat man mit diesen den ultimativen Spaß, aber seien wir mal ehrlich: Wir quälen uns doch viel mehr mit diesen oft kaum weich zu kriegenden Reifen, als das wir das Fahren mit Ihnen wirklich genießen können.

Dem kann Abhilfe geschaffen werden, denn es hat sich gezeigt, dass die perfekte Alternative zum Sportreifen der Tourenreifen ist. Diese sind überwiegend sehr sportlich ausgelegt und stehen den Rennreifen in kaum einer Eigenschaft nach. Dazu stellte sich nach einem Vergleichstest zwischen Renn- und Tourenreifen der Zeitschrift Motorrad heraus, dass Tourenreifen im Schnitt eine längere Lebensdauer als Sportreifen haben. Dementsprechend ist man finanziell gesehen mit Tourenreifen auf der Überholspur. Erklären lässt sich das Ganze, wenn man sich den Entwicklungsprozess von Tourenreifen anguckt. Hierbei wird ziemlich stark mit dem Motorsport zusammengearbeitet. Das heißt, dass die Entwickler sich viele Eigenschaften von Rennreifen abgucken. Die Reifennmischungen dieser Pneus werden jedoch mit Fokus auf den täglichen Einsatz der Pneus abgeändert.

Man sollte sich jedoch nicht zu stark auf den Verschleiß seines Reifens konzentrieren. Auch andere Faktoren zählen. Der Sporttourenreifen Conti Road Attack 2 von Conti ist der ideale Begleiter für die Straße mit dem man ordentlich Gas geben kann. Ob trocken oder nass, eine hohe Lenkpräzision ist garantiert. Doch wer viel Spaß hat, muss auch Abstriche machen, denn der Reifen ist schnell verschlissen.

Wer mehr Wert auf die Langlebigkeit seines Reifens legt, sollte sich den Pirelli Angel ST genauer anschauen.Der ausgewogene Pirelli Pneu ist ebenso präzise wie der Road Attack 2. Außerdem überzeugt der „himmlische“ Reifen mit kurzen Bremswegen bei Nässe. Wie im Namen schon anklingt, erkennt man auf dem ungenutzten Pneu im Profildesign einen Engel, ist das Profil abgefahren, ist statt des Engels ein Dämon vorzufinden, der auf den Kauf eines neuen Reifens hinweist. Geniale Idee, genialer Tourenreifen!

Dietmar Töpfer ist Reifenexperte bei tirendo.de. Durch seine mehr als 30 Jahre Branchenerfahrung weiß er auf jede Reifen-Frage die passende Antwort

© 2018 Abou Chleih. Alle Rechte vorbehalten.

Thema von Anders Norén.