{"id":55000812,"date":"2012-02-01T00:00:00","date_gmt":"2020-05-22T21:51:58","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=812"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Reihenfolge_mit_Klasse","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Reihenfolge_mit_Klasse\/","title":{"rendered":"Reihenfolge mit Klasse"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg03.met.vgwort.de\/na\/e805b8751b58444c8eea14880c9c7f60\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>Wann immer Kriterien sich nicht nach dem Alphabet oder nach einem Zahlenwert sortieren lassen und eine individuelle Sortierung gefordert ist, entsteht Programmieraufwand. Sie m&uuml;ssen die betroffene Datenherkunft um ein Sortierfeld erweitern und einige Schaltfl&auml;chen oder anderweitige M&ouml;glichkeiten zum Einstellen der Sortierung bereitstellen. Dieser Beitrag stellt eine Klasse vor, mit der Sie die ben&ouml;tigten Techniken mit wenigen Codezeilen einbinden.<\/b><\/p>\n<p>In diesem Beitrag lernen Sie zun&auml;chst zwei Anwendungsf&auml;lle f&uuml;r den Einsatz der Reihenfolge-Klasse <b>clsOrder <\/b>kennen:<\/p>\n<ul>\n<li class=\"aufz-hlung\">Einsatz in einem Formular mit einem Listenfeld<\/li>\n<li class=\"aufz-hlung\">Einsatz in einem Formular mit einem Unterformular in der Datenblattansicht<\/li>\n<\/ul>\n<p>Anschlie&szlig;end erfahren Sie mehr &uuml;ber die in der Klasse verwendete Technik, um sp&auml;ter eigene Anpassungen vornehmen zu k&ouml;nnen. In beiden F&auml;llen sollen Daten der Tabelle <b>tblKategorien <\/b>der S&uuml;dsturm-Datenbank angezeigt und sortiert werden. Damit dies funktioniert, f&uuml;gen Sie der Tabelle ein Feld namens <b>ReihenfolgeID<\/b> hinzu (s.  Bild 1).<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2012_01\/ReihenfolgeMitKlasse-web-images\/pic001.png\" alt=\"pic001.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 1: Kategorientabelle mit dem Feld ReihenfolgeID<\/span><\/b><\/p>\n<p><b>Reihenfolge in Listenfeldern<\/b><\/p>\n<p>Um die Daten dieser Tabelle in einem Listenfeld darzustellen und die Datens&auml;tze durch &auml;ndern des Wertes des Feldes <b>ReihenfolgeID <\/b>in der entsprechenden Reihenfolge darzustellen, f&uuml;gen Sie einem neuen, leeren Formular zun&auml;chst ein entsprechendes Listenfeld hinzu. Damit das Listenfeld zu Testzwecken auch den Wert des Feldes <b>ReihenfolgeID <\/b>anzeigt, stellen Sie zun&auml;chst die Eigenschaft <b>Datensatzherkunft <\/b>auf den folgenden Ausdruck ein &#8211; dies sorgt gleichzeitig f&uuml;r die Darstellung in der richtigen Reihenfolge:<\/p>\n<pre>SELECT tblKategorien.KategorieID, tblKategorien.Kategoriename, tblKategorien.ReihenfolgeID\r\nFROM tblKategorien ORDER BY tblKategorien.ReihenfolgeID;<\/pre>\n<p>Au&szlig;erdem legen Sie f&uuml;r die beiden Eigenschaften <b>Spaltenanzahl <\/b>und <b>Spaltenbreiten <\/b>die beiden Werte <b>3 <\/b>und <b>0cm;5cm <\/b>fest. Auf diese Weise wird der Prim&auml;rschl&uuml;sselwert verborgen, der Kategoriename wird in einer Breite von <b>5cm <\/b>angezeigt und der Wert des Feldes <b>ReihenfolgeID <\/b>nimmt den &uuml;brigen Platz ein (das Listenfeld sollte eine entsprechende Breite aufweisen, also etwa <b>6cm<\/b>). Das Listenfeld soll den Namen <b>lstKontakte <\/b>erhalten.<\/p>\n<p>Au&szlig;erdem f&uuml;gen Sie dem Formular vier Schaltfl&auml;chen namens <b>cmdTop<\/b>, <b>cmdBottom<\/b>, <b>cmdUp <\/b>und <b>cmdDown<\/b> hinzu (s. Bild 2).<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2012_01\/ReihenfolgeMitKlasse-web-images\/pic002.png\" alt=\"pic002.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 2: Vorbereitung des Listenfeldes mit Schaltfl&auml;chen zum &auml;ndern der Reihenfolge<\/span><\/b><\/p>\n<p>Nun beginnt der interessante Teil: Das Formular soll mit entsprechender Funktionalit&auml;t ausgestattet werden. Diese steckt komplett in der Klasse <b>clsOrder<\/b>.<\/p>\n<p>Sie m&uuml;ssen diese Klasse nun instanzieren, mit einer im Klassenmodul des Formulars deklarierten Objektvariablen referenzieren und einige Eigenschaften f&uuml;r dieses Objekt festlegen. Zu guter Letzt rufen Sie auch noch eine Methode dieser Klasse auf.<\/p>\n<p>Grundvoraussetzung ist also, dass sich die Klasse <b>clsOrder <\/b>in der gleichen Datenbank befindet.<\/p>\n<p>Sollten Sie die Beispiele in einer neuen Datenbank ausprobieren wollen, importieren Sie also diese Klasse aus der Beispieldatenbank in die Zieldatenbank (Sie k&ouml;nnen auch den kompletten Quellcode der Klasse kopieren, in ein neues Klassenmodul einf&uuml;gen und dieses unter dem Namen <b>clsOrder<\/b> speichern).<\/p>\n<p>Danach weisen Sie der Eigenschaft <b>Beim Laden <\/b>des Formulars den Wert <b>[Ereignisprozedur] <\/b>zu und klicken auf die Schaltfl&auml;che mit den drei Punkten, um die entsprechende Ereignisprozedur anzulegen. F&uuml;gen Sie im Kopf des Moduls die folgende Deklarationszeile ein:<\/p>\n<pre>Dim objOrder As clsOrder<\/pre>\n<p>Komplettieren Sie dann die Ereignisprozedur <b>Form_Load <\/b>wie folgt, wobei Sie die Eigenschaften und Methoden ganz einfach wie in Bild 3 per IntelliSense ausw&auml;hlen:<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2012_01\/ReihenfolgeMitKlasse-web-images\/pic005.png\" alt=\"pic005.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 3: Auswahl von Eigenschaften und Methoden der Klasse clsOrder per IntelliSense<\/span><\/b><\/p>\n<pre>Private Sub Form_Load()\r\n    Set objOrder = New clsOrder\r\n    With objOrder\r\n        Set .Listbox = Me!lstKontakte\r\n        .Table = &quot;tblKategorien&quot;\r\n        .OrderField = &quot;ReihenfolgeID&quot;\r\n        .PrimaryKeyField = &quot;KategorieID&quot;\r\n        Set .Commandbutton_Top = Me!cmdTop\r\n        Set .Commandbutton_Bottom = Me!cmdBottom\r\n        Set .Commandbutton_Up = Me!cmdUp\r\n        Set .Commandbutton_Down = Me!cmdDown\r\n        .FillOrderID\r\n    End With\r\nEnd Sub<\/pre>\n<p>Die erste Zeile erzeugt zun&auml;chst eine neue Instanz der Klasse <b>clsOrder <\/b>und speichert einen Verweis darauf in der Objektvariablen <b>objOrder<\/b>. <\/p>\n<p>Die zweite Zeile legt fest, dass die Sortierfunktion auf die Daten des Listenfeldes <b>lstKontakte <\/b>angewendet werden soll. Dazu &uuml;bergeben Sie einen Verweis auf dieses Steuerelement an die Eigenschaft <b>Listbox<\/b>. Die Eigenschaft <b>Table <\/b>legt fest, auf welche Tabelle sich die &auml;nderung der Reihenfolge bezieht &#8211; in diesem Falle <b>tblKategorien<\/b>.<\/p>\n<p>Sie k&ouml;nnen auch eine Abfrage angeben, diese muss jedoch aktualisierbar sein. Der Eigenschaft <b>OrderField <\/b>&uuml;bergeben Sie den Namen des Feldes, nach dem die Daten sortiert werden sollen, also <b>ReihenfolgeID<\/b>. <b>PrimaryKeyField <\/b>erwartet schlie&szlig;lich den Namen des Prim&auml;rschl&uuml;sselfeldes der Tabelle, hier <b>KontaktID<\/b>.<\/p>\n<p>Die folgenden vier Anweisungen definieren, welche Schaltfl&auml;chen mit den Funktionen zum &auml;ndern der Reihenfolge versehen werden sollen. Schlie&szlig;lich rufen Sie noch die Methode <b>FillOrderID<\/b> auf. Diese Methode f&uuml;llt eventuell noch leere Sortierfelder mit den entsprechenden Zahlenwerten auf.<\/p>\n<p>Wenn Sie nun in die Formularansicht wechseln, k&ouml;nnen Sie die Schaltfl&auml;chen direkt einsetzen, um die Reihenfolge des aktuell aktivierten Eintrags im Listenfeld zu &auml;ndern &#8211; vorausgesetzt, es ist &uuml;berhaupt ein Eintrag aktiviert.<\/p>\n<p>Wenn das Listenfeld beim &Ouml;ffnen den Wert <b>Null <\/b>hat, ist keine der Schaltfl&auml;chen aktiviert. Klicken Sie auf das oberste Listenelement, werden die beiden Schaltfl&auml;chen zum Verschieben des aktuellen Eintrags ganz nach oben oder um eine Position nach oben deaktiviert (siehe Bild 4). Ist hingegen der unterste Eintrag ausgew&auml;hlt, sind die beiden Schaltfl&auml;chen zum Verschieben des aktuellen Eintrags um eine Position nach unten oder ganz nach unten deaktiviert.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2012_01\/ReihenfolgeMitKlasse-web-images\/pic003.png\" alt=\"pic003.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 4: Listenfeld mit aktiven Reihenfolge-Funktionen<\/span><\/b><\/p>\n<p><b>Reihenfolge f&uuml;r Unterformulare<\/b><\/p>\n<p>Die gleiche Technik funktioniert auch f&uuml;r Formulare, die Daten einer Tabelle in einem Unterformular in der Datenblattansicht anzeigen (Gleiches gilt f&uuml;r Endlosformulare). In der Beispieldatenbank finden Sie zwei Formulare namens <b>frmKategorien <\/b>und <b>sfmKategorien<\/b>, wobei Letzteres als Unterformular in der Datenblattansicht definiert ist.<\/p>\n<p>Das Unterformular ist &uuml;ber die Eigenschaft <b>Datenherkunft <\/b>an die Tabelle <b>tblKategorien <\/b>gebunden und zeigt die drei Felder <b>KategorieID<\/b>, <b>Kategoriename <\/b>und <b>ReihenfolgeID <\/b>an (s. Bild 5). Auch hier gibt es vier Schaltfl&auml;chen, die in diesem Fall <b>cmdGanzNachUnten<\/b>, <b>cmdNachUnten<\/b>, <b>cmdNachOben <\/b>und <b>cmdGanzNachOben <\/b>hei&szlig;en.<\/p>\n<p><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2012_01\/ReihenfolgeMitKlasse-web-images\/pic004.png\" alt=\"pic004.png\" \/><\/p>\n<p><b><span style=\"color:darkgrey\">Bild 5: Konstellation mit Haupt- und Unterformular<\/span><\/b><\/p>\n<p>Der Code zum Einbinden und Aktivieren des Klassenmoduls <b>clsOrder <\/b>sieht hier ein wenig anders aus:<\/p>\n<pre>Dim objOrder As clsOrder\r\nPrivate Sub Form_Load()\r\n    Set objOrder = New clsOrder\r\n    With objOrder\r\n        Set .Datasheet = Me!sfmKategorien.Form\r\n        .OrderField = &quot;ReihenfolgeID&quot;\r\n        .PrimaryKeyField = &quot;KategorieID&quot;\r\n        .Table = &quot;tblKategorien&quot;\r\n        Set .Commandbutton_Bottom = Me!cmdGanzNachUnten\r\n        Set .Commandbutton_Down = Me!cmdNachUnten\r\n        Set .Commandbutton_Top = Me!cmdGanzNachOben\r\n        Set .Commandbutton_Up = Me!cmdNachOben\r\n        .FillOrderID\r\n    End With\r\nEnd Sub<\/pre>\n<p>Der gro&szlig;e Unterschied liegt darin, dass hier nicht die Eigenschaft <b>Listbox<\/b>, sondern die Eigenschaft <b>Datasheet <\/b>gef&uuml;llt wird &#8211; in diesem Fall mit einem Verweis auf das im Unterformularsteuerelement enthaltene Formular.<\/p>\n<p><b>Datenblatt-Spezialit&auml;ten<\/b><\/p>\n<p>Wenn Sie die Reihenfolge von Daten im Datenblatt &auml;ndern m&ouml;chten, m&uuml;ssen Sie eigentlich einiges beachten: So kann es ja zum Beispiel vorkommen, dass der Datensatzzeiger auf dem neuen Datensatz landet, dass ein Datensatz gel&ouml;scht wird oder dass der Benutzer einen neuen Datensatz anlegt. Die Klasse <b>clsOrder <\/b>k&uuml;mmert sich um all diese F&auml;lle: Beim Anlegen eines neuen Datensatzes werden die Schaltfl&auml;chen zum Verschieben des Datensatzes bis zum Speichern zun&auml;chst deaktiviert.<\/p>\n<p>Erst nach dem Speichern des Datensatzes weist <b>clsOrder <\/b>dem Feld <b>ReihenfolgeID <\/b>einen Wert zu, der dem gr&ouml;&szlig;ten bisher vergebenen Wert plus eins entspricht. Au&szlig;erdem werden dann wieder die entsprechenden Schaltfl&auml;chen zum &auml;ndern der Reihenfolge aktiviert beziehungsweise deaktiviert.<\/p>\n<p><b>Vorstellung der verwendeten Techniken<\/b><\/p>\n<p>F&uuml;r Access-Entwickler, die selbst Hand an die Klasse <b>clsOrder <\/b>anlegen m&ouml;chten, um Anpassungen durchzuf&uuml;hren, folgt nun der technisch interessante Teil des Beitrags. Die Klasse verwendet zun&auml;chst einmal vier Objektvariablen, welche die Verweise zu den vier Schaltfl&auml;chen zum Einstellen der Reihenfolge aufnehmen sollen:<\/p>\n<pre>Private WithEvents m_Up As CommandButton\r\nPrivate WithEvents m_Down As CommandButton\r\nPrivate WithEvents m_Top As CommandButton\r\nPrivate WithEvents m_Bottom As CommandButton<\/pre>\n<p>Diese Objektvariablen sind mit dem Schl&uuml;sselwort <b>WithEvents <\/b>gekennzeichnet, damit wir innerhalb dieser Klasse Ereignisprozeduren f&uuml;r die mit den Variablen referenzierten Objekte definieren k&ouml;nnen.<\/p>\n<p>Immerhin soll ja die komplette Funktionalit&auml;t beim Klicken der Schaltfl&auml;chen in der Klasse <b>clsOrder <\/b>enthalten sein und nicht im Klassenmodul des Formulars &#8211; dieses soll nur die paar Konfigurationsanweisungen aufnehmen.<\/p>\n<p>Wenn Sie per VBA etwa die Eigenschaft <b>CommandButton_Up <\/b>mit einem Verweis auf die Schaltfl&auml;che <b>cmdNachOben <\/b>f&uuml;llen, l&ouml;st dies die folgende Prozedur aus:<\/p>\n<pre>Public Property Set Commandbutton_Up(cmd As CommandButton)\r\n    Set m_Up = cmd\r\n    Set m_Form = cmd.Parent\r\n    m_Form.OnCurrent = &quot;[Event Procedure]&quot;\r\n    m_Up.OnClick = &quot;[Event Procedure]&quot;\r\nEnd Property<\/pre>\n<p>Diese versieht die Objektvariable <b>m_Up<\/b> mit dem Verweis auf die betroffene Schaltfl&auml;che. Danach wird die Objektvariable <b>m_Form <\/b>mit einem Verweis auf das <b>Parent<\/b>-Objekt der Schaltfl&auml;che gef&uuml;llt, also dem Formular, in dem diese sich befindet.<\/p>\n<p>Der Eigenschaft <b>OnCurrent <\/b>der Objektvariable <b>m_Form <\/b>wird der Wert <b>[Event Procedure]<\/b> zugewiesen, was gleichbedeutend mit dem F&uuml;llen der Eigenschaft <b>Beim Anzeigen <\/b>mit <b>[Ereignisprozedur] <\/b>im Eigenschaftsfenster ist.<\/p>\n<p>Nur dass Access in diesem Fall nicht im Klassenmodul des Formulars, sondern im aktuellen Klassenmodul <b>clsOrder <\/b>nach einer entsprechenden Ereignisprozedur sucht. Im gleichen Zuge wird auch noch die Eigenschaft <b>OnClick <\/b>der soeben referenzierten Schaltfl&auml;che mit <b>[Event Procedure] <\/b>gef&uuml;llt.<\/p>\n<p>Die Prozeduren f&uuml;r die &uuml;brigen Schaltfl&auml;chen sind prinzipiell genau gleich aufgebaut. Dass alle die Objektvariable <b>m_Form <\/b>f&uuml;llen, liegt daran, dass nicht zwangsl&auml;ufig alle Schaltfl&auml;chen verwendet werden. Das Formular der Schaltfl&auml;che soll jedoch auf jeden Fall referenziert werden. Die Variable f&uuml;r das Formular wird so deklariert:<\/p>\n<pre>Private WithEvents m_Form As Form<\/pre>\n<p>Au&szlig;erdem soll entweder ein Listenfeld oder ein Unterformular angegeben werden, dessen Daten mit den angegebenen Schaltfl&auml;chen sortiert werden k&ouml;nnen. Der entsprechende Verweis landet in einer der beiden folgenden Objektvariablen:<\/p>\n<pre>Private WithEvents m_Datasheet As Form\r\nPrivate WithEvents m_Listbox As Listbox<\/pre>\n<p>Das Zuweisen des Listbox-Steuerelements ist ganz einfach. Hier werden nur der Verweis auf das Listenfeld &uuml;bergeben und die Ereignisprozedur <b>Nach Aktualisierung <\/b>vorbereitet:<\/p>\n<pre>Public Property Set Listbox(lst As Listbox)\r\n    Set m_Listbox = lst\r\n    m_Listbox.AfterUpdate = &quot;[Event Procedure]&quot;\r\nEnd Property<\/pre>\n<p>Diese Ereignisprozedur soll sp&auml;ter daf&uuml;r sorgen, dass je nach aktiviertem Listenfeldeintrag die richtigen Schaltfl&auml;chen aktiviert werden.<\/p>\n<p>Beim Unterformular kommen noch zwei weitere Ereignisprozeduren hinzu, eine wird ersetzt &#8211; au&szlig;erdem wird die Referenz auf das Unterformular in der Variablen <b>m_Datasheet <\/b>gespeichert:<\/p>\n<pre>Public Property Set Datasheet(frm As Form)\r\n    Set m_Datasheet = frm\r\n    m_Datasheet.OnCurrent = &quot;[Event Procedure]&quot;\r\n    m_Datasheet.BeforeUpdate = &quot;[Event Procedure]&quot;\r\n    m_Datasheet.OnDelete = &quot;[Event Procedure]&quot;\r\nEnd Property<\/pre>\n<p>Die Ereignisprozedur <b>AfterUpdate <\/b>des Listenfeldes wird durch <b>BeforeUpdate <\/b>ersetzt. Der Grund: Es kann sein, dass dieses Ereignis durch das Anlegen eines neuen Datensatzes ausgel&ouml;st wird. In diesem Fall soll vor dem Speichern noch ein entsprechender Wert in das Feld zur Festlegung der Reihenfolge (im Beispiel <b>ReihenfolgeID<\/b>) eingetragen werden. Das Ereignis <b>Beim Anzeigen <\/b>(<b>OnCurrent<\/b>) wird bei jedem Datensatzwechsel ausgel&ouml;st, das Ereignis <b>Beim L&ouml;schen <\/b>(<b>OnDelete<\/b>) beim L&ouml;schen eines Datensatzes.<\/p>\n<p><!--30percent--><\/p>\n<p>Die drei Eigenschaften <b>Table<\/b>, <b>PrimaryKeyField <\/b>und <b>OrderField <\/b>werden f&uuml;r Unterformulare wie auch f&uuml;r Listenfelder gleicherma&szlig;en ben&ouml;tigt. Die entsprechenden Werte landen nach der Zuweisung an die entsprechenden Eigenschaften in diesen lokalen Variablen:<\/p>\n<pre>Private m_PKField As String\r\nPrivate m_Orderfield As String\r\nPrivate m_Table As String<\/pre>\n<p>Die <b>Property Let<\/b>-Prozeduren, welche die entsprechenden Eigenschaften bereitstellen, nehmen schlicht die &uuml;bergebenen Werte entgegen und tragen diese in die oben deklarierten Variablen ein:<\/p>\n<pre>Public Property Let Table(str As String)\r\n    m_Table = str\r\nEnd Property\r\nPublic Property Let PrimaryKeyField(str As String)\r\n    m_PKField = str\r\nEnd Property\r\nPublic Property Let OrderField(str As String)\r\n    m_Orderfield = str\r\nEnd Property<\/pre>\n<p>Au&szlig;erdem muss zur ordnungsgem&auml;&szlig;en Funktion einmalig die Methode <b>FillOrderID<\/b> aufgerufen werden. Diese sieht wie in <span class=\"verweis-ohneumbruch\"><a href=\"#anker-32-anchor\">Listing 1<\/a><\/span> aus und ruft zun&auml;chst eine Funktion namens <b>CheckMembers <\/b>auf.<\/p>\n<p class=\"listingueberschrift\">Listing 1: Sortierung per Reihenfolge-Feld aktualisieren<\/p>\n<pre>Public Sub FillOrderID()\r\n    Dim db As DAO.Database\r\n    Dim rst As DAO.Recordset\r\n    If CheckMembers = False Then\r\n         Exit Sub\r\n    End If\r\n    Set db = CodeDb\r\n    Set rst = db.OpenRecordset(&quot;SELECT &quot; &amp; m_PKField &amp; &quot;, &quot; &amp; m_Orderfield &amp; &quot; FROM &quot; &amp; m_Table _\r\n        &amp; &quot; ORDER BY &quot; &amp; m_Orderfield, dbOpenDynaset)\r\n    Do While Not rst.EOF\r\n         rst.Edit\r\n        rst(m_Orderfield) = rst.AbsolutePosition + 1\r\n        rst.Update\r\n        rst.MoveNext\r\n    Loop\r\nEnd Sub<\/pre>\n<p>Diese Funktion nimmt einige Pr&uuml;fungen vor, welche die Funktionsf&auml;higkeit der Klasse sicherstellen. Sind die Pr&uuml;fungen nicht erfolgreich, wird die Prozedur abgebrochen &#8211; mehr dazu weiter unten.<\/p>\n<p>Danach &ouml;ffnet die Prozedur ein Recordset, das auf der als Datenherkunft verwendeten Tabelle basiert und nach dem Feld sortiert ist, das die Werte f&uuml;r die Reihenfolge enth&auml;lt. In dieser Reihenfolge durchl&auml;uft die Prozedur alle enthaltenen Datens&auml;tze und f&uuml;llt das Feld f&uuml;r die Reihenfolge mit durchnummerierten Werten. <\/p>\n<p class=\"zwischen-berschrift-oberer-spaltenrand\">Variablen pr&uuml;fen<\/p>\n<p>Die Funktion <b>CheckMembers <\/b>pr&uuml;ft, ob der Benutzer die f&uuml;r den Einsatz der Klasse ben&ouml;tigten Informationen beim &Ouml;ffnen des Formulars angegeben hat und liefert je nach Ergebnis den Wert <b>True <\/b>oder <b>False <\/b>zur&uuml;ck (s. <span class=\"verweis-ohneumbruch\"><a href=\"#anker-36-anchor\">Listing 2<\/a><\/span>). Das Ergebnis wird dar&uuml;ber hinaus in der wie folgt deklarierten und modulweit g&uuml;ltigen Variablen <b>bolMembersChecked <\/b>gespeichert:<\/p>\n<p class=\"listingueberschrift\">Listing 2: Pr&uuml;fung, ob alle notwendigen Informationen vorliegen<\/p>\n<pre>Private Function CheckMembers() As Boolean\r\n    If Not bolMembersChecked Then\r\n        If Len(m_Table) = 0 Then\r\n            MsgBox &quot;Geben Sie eine Tabelle f&uuml;r die Klasse clsOrder an.&quot;\r\n            Exit Function\r\n        End If\r\n        If Len(m_Orderfield) = 0 Then\r\n            MsgBox &quot;Geben Sie das Feld an, dass die Reihenfolge enth&auml;lt.&quot;\r\n            Exit Function\r\n        End If\r\n        If Len(m_PKField) = 0 Then\r\n            MsgBox &quot;Geben Sie das Prim&auml;rschl&uuml;sselfeld der Datenherkunft an.&quot;\r\n            Exit Function\r\n        End If\r\n        If m_Datasheet Is Nothing And m_Listbox Is Nothing Then\r\n            MsgBox &quot;Sie m&uuml;ssen ein Datenblatt oder ein Listenfeld zur Anzeig der Daten festlegen.&quot;\r\n            Exit Function\r\n        Else\r\n            If Not m_Datasheet Is Nothing Then\r\n                If m_Datasheet.HasModule = False Then\r\n                    MsgBox &quot;Das Unterformular muss ein Klassenmodul enthalten.&quot;\r\n                    Exit Function\r\n                End If\r\n            End If\r\n        End If\r\n        If Not m_Datasheet Is Nothing And Not m_Listbox Is Nothing Then\r\n            MsgBox &quot;Sie d&uuml;rfen nur ein Datenblatt oder ein Listenfeld f&uuml;r die Sortierung angeben.&quot;\r\n            Exit Function\r\n        End If\r\n        CheckMembers = True\r\n    Else\r\n        bolMembersChecked = True\r\n    End If\r\nEnd Function\r\nPrivate bolMembersChecked As Boolean<\/pre>\n<p>Dies ist notwendig, weil <b>CheckMembers <\/b>zu sp&auml;teren Gelegenheiten wiederholt aufgerufen wird. Hat <b>bolMembersChecked<\/b> dann den Wert <b>True<\/b>, wird die Funktion gleich wieder beendet.<\/p>\n<p>Die Funktion pr&uuml;ft folgende Zust&auml;nde:<\/p>\n<ul>\n<li class=\"aufz-hlung\">Hat der Benutzer eine Tabelle als Datenherkunft des Listenfeldes\/Unterformulars angegeben<\/li>\n<li class=\"aufz-hlung\">Wurde ein Feld f&uuml;r die Reihenfolge angegeben<\/li>\n<li class=\"aufz-hlung\">Wurde das Prim&auml;rschl&uuml;sselfeld der Tabelle angegeben<\/li>\n<li class=\"aufz-hlung\">Hat der Benutzer genau ein Listenfeld oder ein Unterformular angegeben<\/li>\n<li class=\"aufz-hlung\">Wenn die Klasse mit einem Unterformular arbeiten soll: Besitzt das Unterformular ein Klassenmodul Dies ist n&ouml;tig, weil die Klasse einige Ereignisprozeduren f&uuml;r das Unterformular bereitstellt &#8211; und diese funktionieren nur, wenn das Unterformular ein Klassenmodul besitzt.<\/li>\n<\/ul>\n<p>Diese Pr&uuml;fungen sollen auf jeden Fall durchgef&uuml;hrt werden, bevor die &uuml;brigen Anweisungen der Prozedur <b>FillOrderID <\/b>ausgef&uuml;hrt werden.<\/p>\n<p>Gegebenenfalls ruft die <b>Form_Load<\/b>-Ereignisprozedur des Formulars <b>FillOrderID<\/b> aber gar nicht auf. Damit die Pr&uuml;fung dennoch zumindest vor dem ersten &auml;ndern der Sortierung erfolgt, werden beim Zuweisen der bis zu vier Schaltfl&auml;chen die bereits weiter oben vorgestellten Anweisungen ausgel&ouml;st:<\/p>\n<pre>Set m_Form = cmd.Parent\r\nm_Form.OnCurrent = &quot;[Event Procedure]&quot;<\/pre>\n<p>Dies sorgt daf&uuml;r, dass eine Ereignisprozedur ausgef&uuml;hrt wird, und zwar f&uuml;r das Ereignis <b>Beim Anzeigen <\/b>des Formulars, in dem sich die Schaltfl&auml;chen befinden. Dieses Ereignis wird auf jeden Fall nach dem Ereignis <b>Beim Laden <\/b>ausgef&uuml;hrt, das ja &uuml;berhaupt erst die Klasse <b>clsOrder <\/b>instanziert. Dies bietet eine weitere M&ouml;glichkeit, die Funktion <b>CheckMembers <\/b>aufzurufen.<\/p>\n<p>Gleichzeitig wird die Prozedur <b>ActivateControls <\/b>gestartet, welche die Schaltfl&auml;chen abh&auml;ngig vom aktuell markierten Datensatz aktiviert oder deaktiviert:<\/p>\n<pre>Private Sub m_Form_Current()\r\n    CheckMembers\r\n    ActivateControls\r\nEnd Sub<\/pre>\n<p>Die Prozedur <b>ActivateControls <\/b>f&uuml;hrt mehrere Pr&uuml;fungen durch und aktiviert oder deaktiviert die verwendeten Schaltfl&auml;chen (s. <span class=\"verweis-ohneumbruch\"><a href=\"#anker-43-anchor\">Listing 3<\/a><\/span>). Genau genommen aktiviert sie zun&auml;chst alle vier Schaltfl&auml;chen, wobei sie zuvor sicherstellt, dass diese &uuml;berhaupt referenziert wurden &#8211; sonst geschieht nichts. Danach werden die Schaltfl&auml;chen je nach bestimmten Zust&auml;nden deaktiviert.<\/p>\n<p class=\"listingueberschrift\">Listing 3: Aktivieren\/Deaktivieren der Schaltfl&auml;chen<\/p>\n<pre>Private Sub ActivateControls()\r\n    If Not m_Up Is Nothing Then m_Up.Enabled = True\r\n    If Not m_Down Is Nothing Then m_Down.Enabled = True\r\n    If Not m_Top Is Nothing Then m_Top.Enabled = True\r\n    If Not m_Bottom Is Nothing Then m_Bottom.Enabled = True\r\n    If Not m_Datasheet Is Nothing Then\r\n        If Not bolDelete Then\r\n            Select Case m_Datasheet.Recordset.AbsolutePosition\r\n                Case 0\r\n                    EnableUp\r\n                Case m_Datasheet.Recordset.RecordCount - 1\r\n                    EnableDown\r\n                Case m_Datasheet.Recordset.RecordCount\r\n                    EnableUp\r\n                    EnableDown\r\n                Case -1\r\n                    EnableUp\r\n                    EnableDown\r\n            End Select\r\n        Else\r\n            EnableUp\r\n            EnableDown\r\n            bolDelete = False\r\n        End If\r\n        If m_Datasheet.NewRecord Then\r\n            EnableUp\r\n            EnableDown\r\n        End If\r\n    End If\r\n    If Not m_Listbox Is Nothing Then\r\n        If m_Listbox.ListIndex = 0 Then\r\n            EnableUp\r\n        End If\r\n        If m_Listbox.ListIndex = m_Listbox.ListCount - 1 + m_Listbox.ColumnHeads Then\r\n            EnableDown\r\n        End If\r\n        If IsNull(m_Listbox) Then\r\n            EnableUp\r\n            EnableDown\r\n        End If\r\n    End If\r\nEnd Sub<\/pre>\n<p>Die erste Unterscheidung betrifft das verwendete Steuerelement zur Darstellung der Daten. Handelt es sich um ein Unterformular oder ein Listenfeld Beim Unterformular kann es sein, dass der Benutzer soeben einen Datensatz gel&ouml;scht hat, was sich im Wert <b>True <\/b>f&uuml;r die Variable <b>bolDelete <\/b>niederschl&auml;gt (mehr dazu weiter unten).<\/p>\n<p>Wurde also zuletzt ein Datensatz gel&ouml;scht, deaktiviert die Prozedur alle vier Schaltfl&auml;chen durch den Aufruf der Prozeduren <b>EnableUp <\/b>und <b>EnableDown<\/b>. <b>EnableUp <\/b>deaktiviert die beiden Schaltfl&auml;chen, die Eintr&auml;ge nach oben verschieben:<\/p>\n<pre>Private Sub EnableUp()\r\n    If Not m_Up Is Nothing Then m_Up.Enabled = False\r\n    If Not m_Top Is Nothing Then m_Top.Enabled = False\r\nEnd Sub<\/pre>\n<p><b>EnableDown <\/b>erledigt dies f&uuml;r Eintr&auml;ge, die weiter unten landen sollen:<\/p>\n<pre>Private Sub EnableDown()\r\n    If Not m_Down Is Nothing Then m_Down.Enabled = False\r\n    If Not m_Bottom Is Nothing Then m_Bottom.Enabled = False\r\nEnd Sub<\/pre>\n<p>Au&szlig;erdem wird <b>bolDelete <\/b>auf <b>False <\/b>eingestellt, da diese Variable ausschlie&szlig;lich f&uuml;r den Einsatz in der aktuellen Prozedur Verwendung findet. Sollte <b>ActiveControls <\/b>beim n&auml;chsten Mal wieder durch das L&ouml;schen eines Datensatzes ausgel&ouml;st werden, wird <b>bolDelete <\/b>wieder den Wert <b>True <\/b>enthalten. Handelt es sich um das einfache Wechseln zu einem anderen Datensatz, erh&auml;lt <b>bolDelete <\/b>den Wert <b>False<\/b>.<\/p>\n<p><b>EnableUp <\/b>und <b>EnableDown <\/b>werden ebenfalls aufgerufen, wenn der aktuelle Datensatz neu ist. Dieser darf erst nach dem Speichern verschoben werden, da er erst dann einen Wert im Feld f&uuml;r die Reihenfolge erh&auml;lt.<\/p>\n<p>In allen anderen F&auml;llen pr&uuml;ft <b>ActivateControls <\/b>die Position des Datensatzzeigers im Unterformular (<b>m_Datasheet.Recordset.AbsolutePosition<\/b>) in einer <b>Select Case<\/b>-Anweisung.<\/p>\n<p>Lautet dieser Wert <b>0<\/b>, befindet sich der Datensatzzeiger auf dem ersten Datensatz. In diesem Fall werden die Schaltfl&auml;chen zum Verschieben nach oben deaktiviert. Befindet sich der Datensatzzeiger auf dem letzten Datensatz (<b>m_Datasheet.Recordset.RecordCount &#8211; 1<\/b>), sollen die Schaltfl&auml;chen zum Verschieben des Datensatzes nach unten deaktiviert werden. Entspricht der Wert der aktuellen Anzahl der Datens&auml;tze oder hat dieser den Wert <b>-1<\/b>, sollen alle Schaltfl&auml;chen deaktiviert werden.<\/p>\n<p>Die Pr&uuml;fung der Eintr&auml;ge des Listenfeldes ist erheblich einfacher. Entspricht der Wert der Eigenschaft <b>ListIndex <\/b>dem Wert <b>0<\/b>, wurde der erste Eintrag markiert &#8211; dementsprechend sollen die Schaltfl&auml;chen zum Verschieben nach oben deaktiviert werden. Ist <b>ListIndex <\/b>hingegen mit <b>m_Listbox.ListCount &#8211; 1 + m_Listbox.ColumnHeads <\/b>identisch, befindet sich die Markierung auf dem untersten Datensatz.<\/p>\n<p>Normalerweise reicht der Ausdruck <b>m_Listbox.ListCount &#8211; 1<\/b> aus, um diese Position zu erkennen. Es kann jedoch sein, dass das Listenfeld Spalten&uuml;berschriften anzeigt &#8211; dadurch wird <b>ListCount <\/b>um eins gr&ouml;&szlig;er. Dies kompensieren wir durch das Addieren des Wertes der Eigenschaft <b>ColumnHeads<\/b>, die bei Verwendung von Spalten&uuml;berschriften den Wert <b>True<\/b>, also <b>-1<\/b>, liefert, was genau der einen Zeile entspricht, die bei Verwendung von Spalten&uuml;berschriften zu viel ist. Hat das Listenfeld-Steuerelement den Wert <b>Null<\/b>, sollen alle Schaltfl&auml;chen deaktiviert werden.<\/p>\n<p><b>Aktualisieren des Unterformulars<\/b><\/p>\n<p>Damit die Schaltfl&auml;chen beim Wechsel des Datensatzes im Unterformular aktiviert beziehungsweise deaktiviert werden k&ouml;nnen, m&uuml;ssen Sie diese Aktion durch eine entsprechende Ereignisprozedur abfangen. Dies erledigt das Ereignis <b>Beim Anzeigen <\/b>des Unterformulars, das wir diesem ebenfalls &uuml;ber die entsprechende Objektvariable unterjubeln:<\/p>\n<pre>Private Sub m_Datasheet_Current()\r\n    ActivateControls\r\nEnd Sub<\/pre>\n<p><b>Aktualisieren des Listenfeldes<\/b><\/p>\n<p>Auch beim Ausw&auml;hlen eines neuen Eintrags im Listenfeld m&uuml;ssen die Schaltfl&auml;chen zum &auml;ndern der Reihenfolge gegebenenfalls aktiviert beziehungsweise deaktiviert werden. Dies erledigt die folgende Prozedur, die durch das Ereignis <b>Nach Aktualisierung <\/b>des Listenfeldes ausgel&ouml;st wird:<\/p>\n<pre>Private Sub m_Listbox_AfterUpdate()\r\n    ActivateControls\r\nEnd Sub<\/pre>\n<p><b>Neuen Datensatz mit Reihenfolge-Nummer versehen<\/b><\/p>\n<p>Der Benutzer soll im Unterformular nat&uuml;rlich auch neue Datens&auml;tze anlegen k&ouml;nnen, und zwar durch Eintragen der entsprechenden Daten unten in der Zeile mit dem neuen, leeren Datensatz. Dabei ist es wichtig, dass auch der neue Datensatz gleich einen Wert f&uuml;r das Feld zur Bestimmung der Reihenfolge (in den Beispielen <b>ReihenfolgeID<\/b>) erh&auml;lt. Dazu enth&auml;lt das Klassenmodul eine Ereignisprozedur, die durch das Ereignis <b>Vor Aktualisierung <\/b>ausgel&ouml;st wird und die wie folgt aussieht:<\/p>\n<pre>Private Sub m_Datasheet_BeforeUpdate(Cancel As Integer)\r\n    If m_Datasheet.NewRecord Then\r\n        FillNewOrderID\r\n    End If\r\nEnd Sub<\/pre>\n<p>Die Prozedur pr&uuml;ft, ob der aktuelle Datensatz ein neuer Datensatz ist, und ruft gegebenenfalls die Funktion <b>FillNewOrderID <\/b>auf:<\/p>\n<pre>Public Sub FillNewOrderID()\r\n    Dim lngOrderMax As Long\r\n    lngOrderMax = Nz(DMax(m_Orderfield, m_Table), 0)\r\n    lngOrderMax = lngOrderMax + 1\r\n    m_Datasheet(m_Orderfield).Value = lngOrderMax\r\nEnd Sub<\/pre>\n<p>Diese Prozedur ermittelt zun&auml;chst den bisher gr&ouml;&szlig;ten vergebenen Wert f&uuml;r das Reihenfolge-Feld. Dieser Wert wird um eins erh&ouml;ht und dem Reihenfolge-Feld des neuen Datensatzes zugewiesen, bevor dieser endg&uuml;ltig gespeichert wird.<\/p>\n<p><b>L&ouml;schen von Datens&auml;tzen<\/b><\/p>\n<p>Beim Einsatz eines Unterformulars kann es geschehen, dass der Benutzer einen Datensatz l&ouml;scht. In der Regel m&uuml;ssen die Schaltfl&auml;chen zum &auml;ndern der Reihenfolge dann entsprechend aktiviert beziehungsweise deaktiviert werden. Dies geschieht wie oben bereits beschrieben in der Prozedur <b>ActivateControls<\/b>. Allerdings muss die Variable <b>bolDelete<\/b>, die wie folgt deklariert wird, zuvor auf den Wert <b>True <\/b>eingestellt werden:<\/p>\n<pre>Private bolDelete As Boolean<\/pre>\n<p>Dies geschieht in einer Ereignisprozedur, die wie folgt aussieht:<\/p>\n<pre>Private Sub m_Datasheet_Delete(Cancel As Integer)\r\n    bolDelete = True\r\nEnd Sub<\/pre>\n<p>Damit die Ereignisprozedur auch ausgel&ouml;st wird, wird wie bereits weiter oben beschrieben die Eigenschaft <b>OnDelete <\/b>des Unterformulars auf den Wert <b>[Event Procedure] <\/b>eingestellt:<\/p>\n<pre>m_Datasheet.OnDelete = &quot;[Event Procedure]&quot;<\/pre>\n<p><b>Reihenfolge &auml;ndern<\/b><\/p>\n<p>Kommen wir zum eigentlichen Sinn der Klasse: dem &auml;ndern der Reihenfolge-Werte einer Tabelle. Ausgel&ouml;st wird dies durch das Anklicken einer der vier Schaltfl&auml;chen, die durch die Objektvariablen <b>m_Top<\/b>, <b>m_Bottom<\/b>, <b>m_Up <\/b>und <b>m_Down <\/b>referenziert wurden. Wenn der Benutzer beispielsweise auf <b>m_Top <\/b>klickt, soll die folgende Ereignisprozedur ausgel&ouml;st werden:<\/p>\n<pre>Private Sub m_Top_Click()\r\n    Dim lngTarget As Long\r\n    Dim lngMove As Long\r\n    If Not m_Datasheet Is Nothing Then\r\n        lngIDTemp = m_Datasheet(m_PKField)\r\n    End If\r\n    lngMove = GetMove\r\n    lngTarget = DMin(m_Orderfield, m_Table)\r\n    InterchangeOrder lngTarget, lngMove\r\n    RequeryControls lngTarget - lngMove + 1\r\nEnd Sub<\/pre>\n<p>Diese Prozedur ermittelt, sofern gerade ein Unterformular zur Anzeige der Daten verwendet wird, zun&auml;chst den Prim&auml;rschl&uuml;sselwert des zu verschiebenden Datensatzes und speichert diesen in der wie folgt modulweit deklarierten Variablen:<\/p>\n<pre>Private lngIDTemp As Long<\/pre>\n<p>Dieser wird ben&ouml;tigt, damit der Datensatz nach dem Aktualisieren des Unterformulars wieder markiert werden kann. Dann liest sie mit der Funktion <b>GetMove <\/b>den Reihenfolge-Wert des aktuell im Listenfeld oder im Datenblatt ausgew&auml;hlten Datensatzes aus.<\/p>\n<p>Beim Datenblatt gelingt dies ganz einfach, indem Sie den Wert des Reihenfolge-Feldes abfragen. Beim Listenfeld wird zun&auml;chst der Wert der gebundenen Spalte des aktuell ausgew&auml;hlten Eintrags ermittelt und dann mittels <b>DLookup<\/b>-Anweisung der Wert des entsprechenden Reihenfolge-Feldes:<\/p>\n<pre>Private Function GetMove() As Long\r\n    Dim lngMove As Long\r\n    If Not m_Datasheet Is Nothing Then\r\n        lngMove = m_Datasheet(m_Orderfield)\r\n    End If\r\n    If Not m_Listbox Is Nothing Then\r\n        If Not IsNull(m_Listbox) Then\r\n            lngMove = DLookup(m_Orderfield, m_Table, m_PKField &amp; &quot;=&quot; &amp; m_Listbox)\r\n        End If\r\n    End If\r\n    GetMove = lngMove\r\nEnd Function<\/pre>\n<p><b>Top<\/b> bedeutet, dass es ganz nach oben gehen soll &#8211; also soll der aktuelle Datensatz den Platz des obersten Datensatzes einnehmen und alle zwischen der aktuellen und der Zielposition befindlichen Datens&auml;tze um eine Position nach unten schieben. Dementsprechend ermittelt die Prozedur zun&auml;chst die Reihenfolge-ID des Zieldatensatzes und speichert diesen in der Variablen <b>lngTarget<\/b>. Dann ruft sie die Prozedur <b>InterchangeOrder <\/b>auf, welche die &auml;nderung der Reihenfolge-Werte durchf&uuml;hrt &#8211; mehr siehe weiter unten. Anschlie&szlig;end aktualisiert die <b>RequeryControls<\/b>-Prozedur noch die Steuerelemente beziehungsweise das Listenfeld oder das Unterformular:<\/p>\n<pre>Private Sub RequeryControls(Optional lngMoved As Long)\r\n    If Not m_Datasheet Is Nothing Then\r\n        m_Datasheet.Requery\r\n        m_Datasheet.Recordset.FindFirst m_PKField &amp; &quot;=&quot; &amp; lngIDTemp\r\n    End If\r\n    If Not m_Listbox Is Nothing Then\r\n        m_Listbox.Requery\r\n    End If\r\n    ActivateControls\r\nEnd Sub<\/pre>\n<p>Die Prozedur enth&auml;lt wieder zwei Bereiche f&uuml;r Unterformulare und Listenfelder. Handelt es sich beim zu aktualisierenden Steuerelement um ein Unterformular, wird dessen <b>Requery<\/b>-Methode aufgerufen und mit der <b>FindFirst<\/b>-Methode der Fokus wieder auf das verschobene Steuerelement gelegt. Listenfelder brauchen einfach nur aktualisiert zu werden, sie behalten die Markierung des Steuerelements einfach bei.<\/p>\n<p>Anschlie&szlig;end ruft die Prozedur noch die Routine <b>ActivateControls <\/b>auf, um gegebenenfalls Schaltfl&auml;chen zu aktivieren oder zu deaktivieren. Die Prozedur zum Verschieben eines Eintrags an das Ende der Liste sieht so &auml;hnlich wie die Prozedur zum Verschieben an die erste Position aus, daher beschreiben wir diese hier nicht explizit.<\/p>\n<p>Interessanter ist da schon die Prozedur, die einen Eintrag um eine Position nach oben schiebt &#8211; und hier speziell die Ermittlung des Eintrags, mit dem die Position getauscht werden soll. Dies gelingt wie folgt:<\/p>\n<pre>Private Sub m_Up_Click()\r\n    Dim lngTarget As Long\r\n    Dim lngMove As Long\r\n    If Not m_Datasheet Is Nothing Then\r\n        lngIDTemp = m_Datasheet(m_PKField)\r\n    End If\r\n    lngMove = GetMove\r\n    lngTarget = DMax(m_Orderfield, m_Table, m_Orderfield &amp; &quot;&lt;&quot; &amp; lngMove)\r\n    InterchangeOrder lngTarget, lngMove\r\n    RequeryControls lngMove - 1\r\nEnd Sub<\/pre>\n<p>Der Zieleintrag wird mit dem Aufruf der <b>DMax<\/b>-Funktion ermittelt, wobei der gr&ouml;&szlig;te Wert f&uuml;r das Reihenfolge-Feld ermittelt wird, der kleiner als der entsprechende Wert des zu verschiebenden Elements ist. Danach erfolgt das Vertauschen der Reihenfolge wiederum mit der Prozedur <b>InterchangeOrder <\/b>&#8211; gefolgt vom Aktualisieren der Steuerelemente.<\/p>\n<p><b>&auml;ndern der Reihenfolge<\/b><\/p>\n<p>Die Prozedur <b>InterchangeOrder <\/b>aus <span class=\"verweis-ohneumbruch\"><a href=\"#anker-44-anchor\">Listing 4<\/a><\/span> &uuml;bernimmt das &auml;ndern der Werte im Reihenfolge-Feld der betroffenen Tabelle &#8211; und zwar f&uuml;r alle denkbaren F&auml;lle. Die Prozedur erwartet die folgenden Parameter:<\/p>\n<ul>\n<li class=\"aufz-hlung\"><b>lngTargetOrderID<\/b>: Reihenfolge-ID des Datensatzes, auf dem der zu verschiebende Datensatz landen soll<\/li>\n<li class=\"aufz-hlung\"><b>lngMoveFirstOrderID<\/b>: Reihenfolge-ID des zu verschiebenden Datensatzes<\/li>\n<li class=\"aufz-hlung\"><b>lngMoveLastOrderID<\/b>: Optionaler und in dieser L&ouml;sung nicht verwendeter Parameter, der die Reihenfolge-ID eines weiteren Eintrags angibt. Damit k&ouml;nnten etwa im Listenfeld mehrere zusammenh&auml;ngende Eintr&auml;ge verschoben werden.<\/li>\n<\/ul>\n<p class=\"listingueberschrift\">Listing 4: Vertauschen der Reihenfolge von Eintr&auml;gen<\/p>\n<pre>Public Sub InterchangeOrder(lngTargetOrderID As Long, lngMoveFirstOrderID As Long, _\r\n        Optional lngMoveLastOrderID As Long)\r\n    Dim db As DAO.Database\r\n    Dim rst As DAO.Recordset\r\n    Dim intCountMove As Integer\r\n    Set db = CodeDb\r\n    If lngMoveLastOrderID = 0 Then\r\n         lngMoveLastOrderID = lngMoveFirstOrderID\r\n    End If\r\n    intCountMove = lngMoveLastOrderID - lngMoveFirstOrderID + 1\r\n    If lngTargetOrderID &lt; lngMoveFirstOrderID Then\r\n         Set rst = db.OpenRecordset(&quot;SELECT * FROM &quot; &amp; m_Table &amp; &quot; WHERE &quot; &amp; m_Orderfield &amp; &quot; &gt;= &quot; _\r\n            &amp; lngTargetOrderID &amp; &quot; AND &quot; &amp; m_Orderfield &amp; &quot; &lt;= &quot; &amp; lngMoveLastOrderID _\r\n            &amp; &quot; ORDER BY &quot; &amp; m_Orderfield, dbOpenDynaset)\r\n        Do While Not rst.EOF\r\n            rst.Edit\r\n            If rst(m_Orderfield) &lt; lngMoveFirstOrderID Then\r\n                rst(m_Orderfield) = rst(m_Orderfield) + intCountMove\r\n            Else\r\n                rst(m_Orderfield) = rst(m_Orderfield) - (lngMoveFirstOrderID - lngTargetOrderID)\r\n            End If\r\n            rst.Update\r\n            rst.MoveNext\r\n        Loop\r\n    Else\r\n        Set rst = db.OpenRecordset(&quot;SELECT * FROM &quot; &amp; m_Table &amp; &quot; WHERE &quot; &amp; m_Orderfield &amp; &quot; &gt;= &quot; _\r\n            &amp; lngMoveFirstOrderID &amp; &quot; AND &quot; &amp; m_Orderfield &amp; &quot; &lt;= &quot; &amp; lngTargetOrderID _\r\n            &amp; &quot; ORDER BY &quot; &amp; m_Orderfield, dbOpenDynaset)\r\n        Do While Not rst.EOF\r\n            rst.Edit\r\n            If rst(m_Orderfield) &lt;= lngMoveLastOrderID Then\r\n                rst(m_Orderfield) = rst(m_Orderfield) + (lngTargetOrderID - lngMoveLastOrderID)\r\n            Else\r\n                rst(m_Orderfield) = rst(m_Orderfield) - (lngMoveLastOrderID - lngMoveFirstOrderID + 1)\r\n            End If\r\n            rst.Update\r\n            rst.MoveNext\r\n        Loop\r\n    End If\r\nEnd Sub<\/pre>\n<p>Die Prozedur pr&uuml;ft zun&auml;chst, ob <b>lngMoveLastOrder <\/b>den Wert <b>0 <\/b>enth&auml;lt, was bedeutet, dass dieser Parameter nicht &uuml;bergeben wurde &#8211; dies ist in der vorliegenden Version immer der Fall, da das Verschieben mehrerer Eintr&auml;ge gleichzeitig nicht unterst&uuml;tzt wird. Daher wird <b>lngMoveLastOrderID <\/b>immer auf den gleichen Wert wie <b>lngMoveFirstOrderID <\/b>eingestellt. <b>intCountMove <\/b>wird mit der Differenz von <b>lngMoveLastOrderID <\/b>und <b>lngMoveFirstOrderID <\/b>gef&uuml;ttert und um eins erh&ouml;ht, was die Anzahl der zu verschiebenden Elemente liefert &#8211; hier immer <b>1<\/b>.<\/p>\n<p>Danach folgt eine Fallunterscheidung, die pr&uuml;ft, ob die Reihenfolge-ID des Zieleintrags gr&ouml;&szlig;er oder kleiner als die Reihenfolge-ID des zu verschiebenden Eintrags ist. Ist die Reihenfolge-ID des Zieleintrags kleiner, soll der zu verschiebende Eintrag nach oben verschoben werden, anderenfalls nach unten.<\/p>\n<p>Beim Verschieben nach oben wird nun ein Recordset ge&ouml;ffnet, das alle Datens&auml;tze der betroffenen Tabelle enth&auml;lt, deren Reihenfolge-ID gr&ouml;&szlig;er oder gleich der Reihenfolge-ID des Zieleintrags ist und deren Reihenfolge-ID kleiner oder gleich der Reihenfolge des zu verschiebenden Elements ist.<\/p>\n<p>Alle gefundenen Eintr&auml;ge werden anschlie&szlig;end innerhalb einer <b>Do While<\/b>-Schleife durchlaufen. Der jeweilige Datensatz wird mit der <b>Edit<\/b>-Methode in den Bearbeitungsmodus versetzt. Dabei wird der Wert der Reihenfolge-ID jeweils um eins erh&ouml;ht, wenn die Reihenfolge-ID kleiner als die des zu verschiebenden Datensatzes ist. Anderenfalls, und das ist der Fall, wenn die Reihenfolge-ID der Reihenfolge-ID des Zieleintrags entspricht, wird ein Zahlenwert von der Reihenfolge-ID des aktuellen Datensatzes subtrahiert, welcher der Anzahl der Elemente zwischen dem zu verschiebenden Element und dem Zielelement plus eins entspricht. <\/p>\n<p>Nach dem &auml;ndern der Reihenfolge-ID wird der Datensatz mit der <b>Update<\/b>-Methode gespeichert und die <b>MoveNext<\/b>-Methode sorgt f&uuml;r den Aufruf des folgenden Datensatzes.<\/p>\n<p>Der zweite Teil der <b>If&#8230;Then<\/b>-Bedingung f&uuml;hrt den Vorgang genau andersherum aus, sodass Eintr&auml;ge von oben nach unten verschoben werden k&ouml;nnen.<\/p>\n<p><b>Zusammenfassung und Ausblick<\/b><\/p>\n<p>Mit der Klasse <b>clsOrder <\/b>f&uuml;gen Sie Ihrer Datenbank auf einfache Weise die M&ouml;glichkeit zum Sortieren von Eintr&auml;gen nach einem selbst definierten, numerischen Feld hinzu. Sie brauchen nur diese Klasse in die Zieldatenbank zu importieren und einige Codezeilen zum Formular hinzuzuf&uuml;gen, das das Unterformular oder das Listenfeld mit den zu sortierenden Daten enth&auml;lt. Au&szlig;erdem k&ouml;nnen Sie bis zu vier Schaltfl&auml;chen anlegen, denen Sie Funktionen zum Verschieben des aktuellen Elements ganz nach oben oder unten oder um eine Position nach oben oder unten hinzuf&uuml;gen. Dazu brauchen Sie keine eigenen Ereignisprozeduren anzulegen, denn diese liefert die Klasse <b>clsOrder <\/b>gleich mit.<\/p>\n<h3>Downloads zu diesem Beitrag<\/h3>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>ReihenfolgeMitKlasse.mdb<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/{421605B0-736C-40F8-BAB1-3DE287F59205}\/aiu_812.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wann immer Kriterien sich nicht nach dem Alphabet oder nach einem Zahlenwert sortieren lassen und eine individuelle Sortierung gefordert ist, entsteht Programmieraufwand. Sie m&uuml;ssen die betroffene Datenherkunft um ein Sortierfeld erweitern und einige Schaltfl&auml;chen oder anderweitige M&ouml;glichkeiten zum Einstellen der Sortierung bereitstellen. Dieser Beitrag stellt eine Klasse vor, mit der Sie die ben&ouml;tigten Techniken mit wenigen Codezeilen einbinden.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[66012012,662012,44000023],"tags":[],"class_list":["post-55000812","post","type-post","status-publish","format-standard","hentry","category-66012012","category-662012","category-Mit_Formularen_arbeiten"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.9 (Yoast SEO v27.3) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Reihenfolge mit Klasse - Access im Unternehmen<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/access-im-unternehmen.de\/Reihenfolge_mit_Klasse\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Reihenfolge mit Klasse\" \/>\n<meta property=\"og:description\" content=\"Wann immer Kriterien sich nicht nach dem Alphabet oder nach einem Zahlenwert sortieren lassen und eine individuelle Sortierung gefordert ist, entsteht Programmieraufwand. Sie m&uuml;ssen die betroffene Datenherkunft um ein Sortierfeld erweitern und einige Schaltfl&auml;chen oder anderweitige M&ouml;glichkeiten zum Einstellen der Sortierung bereitstellen. Dieser Beitrag stellt eine Klasse vor, mit der Sie die ben&ouml;tigten Techniken mit wenigen Codezeilen einbinden.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Reihenfolge_mit_Klasse\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2020-05-22T21:51:58+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/vg03.met.vgwort.de\/na\/e805b8751b58444c8eea14880c9c7f60\" \/>\n<meta name=\"author\" content=\"Andr\u00e9 Minhorst\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andr\u00e9 Minhorst\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"27\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Reihenfolge_mit_Klasse\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Reihenfolge_mit_Klasse\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Reihenfolge mit Klasse\",\"datePublished\":\"2020-05-22T21:51:58+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Reihenfolge_mit_Klasse\\\/\"},\"wordCount\":4043,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Reihenfolge_mit_Klasse\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg03.met.vgwort.de\\\/na\\\/e805b8751b58444c8eea14880c9c7f60\",\"articleSection\":[\"1\\\/2012\",\"2012\",\"Mit Formularen arbeiten\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Reihenfolge_mit_Klasse\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Reihenfolge_mit_Klasse\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Reihenfolge_mit_Klasse\\\/\",\"name\":\"Reihenfolge mit Klasse - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Reihenfolge_mit_Klasse\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Reihenfolge_mit_Klasse\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/vg03.met.vgwort.de\\\/na\\\/e805b8751b58444c8eea14880c9c7f60\",\"datePublished\":\"2020-05-22T21:51:58+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Reihenfolge_mit_Klasse\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Reihenfolge_mit_Klasse\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Reihenfolge_mit_Klasse\\\/#primaryimage\",\"url\":\"http:\\\/\\\/vg03.met.vgwort.de\\\/na\\\/e805b8751b58444c8eea14880c9c7f60\",\"contentUrl\":\"http:\\\/\\\/vg03.met.vgwort.de\\\/na\\\/e805b8751b58444c8eea14880c9c7f60\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Reihenfolge_mit_Klasse\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Reihenfolge mit Klasse\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"name\":\"Access im Unternehmen\",\"description\":\"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access\",\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/access-im-unternehmen.de\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\",\"name\":\"Andr\u00e9 Minhorst Verlag\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"contentUrl\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"width\":370,\"height\":111,\"caption\":\"Andr\u00e9 Minhorst Verlag\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\",\"name\":\"Andr\u00e9 Minhorst\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"caption\":\"Andr\u00e9 Minhorst\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Reihenfolge mit Klasse - Access im Unternehmen","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/access-im-unternehmen.de\/Reihenfolge_mit_Klasse\/","og_locale":"de_DE","og_type":"article","og_title":"Reihenfolge mit Klasse","og_description":"Wann immer Kriterien sich nicht nach dem Alphabet oder nach einem Zahlenwert sortieren lassen und eine individuelle Sortierung gefordert ist, entsteht Programmieraufwand. Sie m&uuml;ssen die betroffene Datenherkunft um ein Sortierfeld erweitern und einige Schaltfl&auml;chen oder anderweitige M&ouml;glichkeiten zum Einstellen der Sortierung bereitstellen. Dieser Beitrag stellt eine Klasse vor, mit der Sie die ben&ouml;tigten Techniken mit wenigen Codezeilen einbinden.","og_url":"https:\/\/access-im-unternehmen.de\/Reihenfolge_mit_Klasse\/","og_site_name":"Access im Unternehmen","article_published_time":"2020-05-22T21:51:58+00:00","og_image":[{"url":"http:\/\/vg03.met.vgwort.de\/na\/e805b8751b58444c8eea14880c9c7f60","type":"","width":"","height":""}],"author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"27\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/Reihenfolge_mit_Klasse\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Reihenfolge_mit_Klasse\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Reihenfolge mit Klasse","datePublished":"2020-05-22T21:51:58+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Reihenfolge_mit_Klasse\/"},"wordCount":4043,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Reihenfolge_mit_Klasse\/#primaryimage"},"thumbnailUrl":"http:\/\/vg03.met.vgwort.de\/na\/e805b8751b58444c8eea14880c9c7f60","articleSection":["1\/2012","2012","Mit Formularen arbeiten"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Reihenfolge_mit_Klasse\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Reihenfolge_mit_Klasse\/","url":"https:\/\/access-im-unternehmen.de\/Reihenfolge_mit_Klasse\/","name":"Reihenfolge mit Klasse - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Reihenfolge_mit_Klasse\/#primaryimage"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/Reihenfolge_mit_Klasse\/#primaryimage"},"thumbnailUrl":"http:\/\/vg03.met.vgwort.de\/na\/e805b8751b58444c8eea14880c9c7f60","datePublished":"2020-05-22T21:51:58+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Reihenfolge_mit_Klasse\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Reihenfolge_mit_Klasse\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/Reihenfolge_mit_Klasse\/#primaryimage","url":"http:\/\/vg03.met.vgwort.de\/na\/e805b8751b58444c8eea14880c9c7f60","contentUrl":"http:\/\/vg03.met.vgwort.de\/na\/e805b8751b58444c8eea14880c9c7f60"},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Reihenfolge_mit_Klasse\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Reihenfolge mit Klasse"}]},{"@type":"WebSite","@id":"https:\/\/access-im-unternehmen.de\/#website","url":"https:\/\/access-im-unternehmen.de\/","name":"Access im Unternehmen","description":"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access","publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/access-im-unternehmen.de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/access-im-unternehmen.de\/#organization","name":"Andr\u00e9 Minhorst Verlag","url":"https:\/\/access-im-unternehmen.de\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/","url":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","contentUrl":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","width":370,"height":111,"caption":"Andr\u00e9 Minhorst Verlag"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f","name":"Andr\u00e9 Minhorst","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","caption":"Andr\u00e9 Minhorst"}}]}},"_links":{"self":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55000812","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/comments?post=55000812"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55000812\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55000812"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55000812"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55000812"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}