Unter .NET kann man prüfen, ob das hier wahr ist:
System.Diagnostics.Debugger.IsAttached
System.Diagnostics.Debugger.IsAttached
Falls ja, befinden wir uns in der IDE. Ansonsten sind wir ein Kompilat (nein, kein Kombinat, das war etwas anderes…)
Natürlich lohnt es nicht, einen Blogeintrag über das Löschen von Datensätzen in einer Datenbank zu schreiben. Es sei denn, der Dorftrottel hat die Tabelle entworfen… Dann kann es nämlich durchaus vorkommen ist es meistens so, dass in der Tabelle kein Index und keine Art von Schlüssel vorkommt. Natürlich wird bei der Dateneingabe auch nie geprüft, ob ein entsprechender Eintrag vielleicht schon vorhanden ist. Es kommt dann wie es kommen muss: Irgendwann fallen doppelte (in allen Feldwerten gleichlautende) Datensätze an. Und dann ist es nicht mehr weit, bis jemand schreit, dass ein Datensatz oder n Einträge gelöscht werden müssen.
Wie löscht man nun gleiche Einträge, wenn sich die Datensätze nicht unterscheiden? Mit SQL geht’s nicht, da man keine Einschränkung zur Auswahl eines Datensatzes findet. Mit dem Management-Studio geht’s auch nicht, es meckert, dass eventuell alle Datensätze betroffen sind. Also einfach alle Datensätze wegpölen und neu eingeben?
Mit SQL geht’s aber doch, wenigstens seit SQL Server 2005. Dort kann man in der DELETE Anweisung (wie auch in der UPDATE Anweisung) ein TOP ROW angeben. Um den ersten eines doppelten Eintrags zu löschen, reicht es
DELETE TOP (1) FROM tabelle WHERE feld = xyz
DELETE TOP (1) FROM tabelle WHERE feld = xyz
zu schreiben. Es wird dann tatsächlich der erste (bzw. beliebige) Eintrag eines doppelten (drei-, vier-, n-fachen) Eintrags gelöscht.
Daran bin ich fast schon einmal verzweifelt. Ein Menü zu durchlaufen ist in meinen Augen schwieriger als man zunächst denkt.
“Ganz oben” gibt es den/das MenuStrip. Das ist die oberste Hierarchie (optisch kann man sich das MenuStrip als “das erste Menü unterhalb der Titelleiste” denken). Alles andere sind DropdownItems (bzw. ToolStripMenuItems), die am MenuStrip hängen. So viel zum theoretischen Unterbau. Wer mehr darüber erfahren möchte, kann googlen.
Da eine Menüstruktur verschachtelt sein kann, müssen auch alle Unterknoten durchlaufen werden. Es bietet sich an, dafür eine Rekursion zu verwenden. (Das war übrigens eine der ganz wenigen Stellen in meinem Leben, an denen ich spontan gedacht habe: das eignet sich supergut für eine Rekursion.)
Einen Haken hat die Sache noch: bei Separatoren (horizontale Trennlinien im Menü) fällt der Cast des DropDownItems in ein ToolStripMenuItem auf die Nase. Deswegen muss das vorher noch abgefragt werden.
(Ziel der Übung war es übrigens, den Tooltip jedes einzelnen Menüeintrags zu leeren. Das MenuStrip bringt eine eigene ToolTip-Verwaltung mit sich. Daher funktioniert es nicht, einfach das formulargebundene ToolTip-Control zu deaktivieren, da die Tooltips der Menüs nicht daran hängen.)
Private Sub LoescheToolTips() For i As Integer = 0 To MenuStrip1.Items.Count - 1 Unterknoten(MenuStrip1.Items(i)) Next End Sub
Private Sub LoescheToolTips()
For i As Integer = 0 To MenuStrip1.Items.Count - 1
Unterknoten(MenuStrip1.Items(i))
Next
End SubPrivate Sub Unterknoten(ByVal Tsmi As ToolStripMenuItem) For j As Integer = 0 To Tsmi.DropDownItems.Count – 1 Tsmi.DropDownItems(j).ToolTipText = "" ‘ Hier kann man den Menüpunkt verwursten. If Tsmi.DropDownItems(j).IsOnDropDown Then If Not (TypeOf Tsmi.DropDownItems(j) Is System.Windows.Forms.ToolStripSeparator) Then Unterknoten(DirectCast(Tsmi.DropDownItems(j), ToolStripMenuItem)) End If End If Next End Sub
Private Sub Unterknoten(ByVal Tsmi As ToolStripMenuItem)
For j As Integer = 0 To Tsmi.DropDownItems.Count – 1
Tsmi.DropDownItems(j).ToolTipText = "" ‘ Hier kann man den Menüpunkt verwursten.
If Tsmi.DropDownItems(j).IsOnDropDown Then
If Not (TypeOf Tsmi.DropDownItems(j) Is System.Windows.Forms.ToolStripSeparator) Then
Unterknoten(DirectCast(Tsmi.DropDownItems(j), ToolStripMenuItem))
End If
End If
Next
End SubWeil ich immer wieder gerne vergesse, wie es mit diesem Listview unter VB6 funktioniert…
Hier eine kleine Demo, die ein Listview aufbaut. Durch Klick auf einen Spaltenkopf wird nach der Spalte sortiert.
Das war schon alles.
' Im Projekt müssen die "Microsoft Windows Common Controls 6.0" hinzugefügt werden. ' Es muss Version 6 sein! Version 5 erkennt "MSComctlLib.ColumnHeader" nicht. ' Ein ListView1 muss der Form hinzugefügt werden. Private Sub Form_Load() Dim lvI As Long Dim lvListitem As ListItem ListView1.View = lvwReport ListView1.HideColumnHeaders = False ListView1.ColumnHeaders.Add , "E1", "Sp1" ListView1.ColumnHeaders.Add , "E2", "Test" ListView1.ColumnHeaders.Add , "E3", "Drei" For lvI = 1 To 10 Set lvListitem = ListView1.ListItems.Add(, "E" & lvI, lvI) lvListitem.SubItems(1) = CStr(Int(Rnd * 100)) lvListitem.SubItems(2) = "Test" Next lvI End Sub
' Im Projekt müssen die "Microsoft Windows Common Controls 6.0" hinzugefügt werden. ' Es muss Version 6 sein! Version 5 erkennt "MSComctlLib.ColumnHeader" nicht. ' Ein ListView1 muss der Form hinzugefügt werden. Private Sub Form_Load() Dim lvI As Long Dim lvListitem As ListItem ListView1.View = lvwReport ListView1.HideColumnHeaders = False ListView1.ColumnHeaders.Add , "E1", "Sp1" ListView1.ColumnHeaders.Add , "E2", "Test" ListView1.ColumnHeaders.Add , "E3", "Drei" For lvI = 1 To 10 Set lvListitem = ListView1.ListItems.Add(, "E" & lvI, lvI) lvListitem.SubItems(1) = CStr(Int(Rnd * 100)) lvListitem.SubItems(2) = "Test" Next lvI End Sub
Private Sub ListView1_ColumnClick(ByVal ColumnHeader As MSComctlLib.ColumnHeader) ListView1.SortKey = ColumnHeader.SubItemIndex ListView1.Sorted = True End Sub
Private Sub ListView1_ColumnClick(ByVal ColumnHeader As MSComctlLib.ColumnHeader) ListView1.SortKey = ColumnHeader.SubItemIndex ListView1.Sorted = True End Sub
Die wichtigsten Tue und TueNicht für Programmierer in Kurzform:
Akzeptiere, dass geschulte Leute, die mal wichtige Algorithmen entwickelt haben, Plan davon hatten. Erfinde den Quicksort nicht neu. Benutze den Standard.
Kommentare sind wichtig. Aber kommentiere keine Funktion, die “ErmittleKundenname” heißt mit dem Kommentar “Ermittelt den Kundennamen”. Beschreibe, warum du den Kundennamen genau so ermittelst, wie du es in dieser Routine tust.
Auch bei kleinen Programmen. Du kannst so immer wieder zu der Stelle zurückspringen, bevor du dich furchtbar verfranst hast. Du hast Überblick und Ordnung. Disziplin kann auch gut sein.
Schwierig, denn jeder Programmierer hat andere Vorstellungen vom programmieren. Deswegen: halte dich an Standards. Dann klappt’s auch mit dem Kollegen.
Jedes Goodie, was du einbaust, damit der Kunde sieht, wie toll du bist, kommt irgendwann zu dir zurück. Entweder als Ding, was du ständig warten musst oder als überflüssigen Tand, den du wieder ausbauen musst. Wenn du unbedingt etwas “cooles” einbauen möchtest, sprich es mit dem Kunden vorher ab!
Er ist der Geldgeber. Er zahlt deine Miete, dein Essen, deinen Lebensstandard. Der Kunde muss letzten Endes glücklich sein. Mache alles, damit er glücklich ist.