Neuigkeiten:

Ist euer Problem gelöst, dann bitte den Knopf "Thema gelöst" drücken!

Mobiles Hauptmenü

Record überspringen

Begonnen von hooKa, November 17, 2015, 11:11:07

⏪ vorheriges - nächstes ⏩

hooKa

Hallo Community,

ich habe ein kleines Anliegen. Ich habe eine Abfrage, die mir folgende Daten ausspuckt:


Wie ihr sehen könnt, kriege ich für eine SAP-Nummer 3 Records. Nun habe ich eine Update-Prozedur, die mir die Datumsspalte ändert und dort ein neues Datum reinschreibt.
Jedoch möchte ich, dass der erste Record für die SAP-Nummer übersprungen wird (id 42) und erst mit dem zweiten Record beginnt (id 49).
Ich habe es schon mit

while not rst.eof
    if firstrecord then
         firstrecord = false
    else
         process record
    end if
    rst.movenext
wend

.. probiert, aber das klappt nicht, für das zweite Datum wird ein falsches geschrieben, nämlich der 18. nicht der 21. Alternativ wollte ich es mit DCount machen, also wenn es für eine SAP-Nummer mehr als einen Eintrag gibt, dann soll er den zweiten updaten und nicht den ersten. Aber ich glaube, dann würde er stur alles updaten, weil es immer mehr als einen Eintrag gibt.

Ich möchte das allgemein für alle SAP-Nummern machen.

Könnt ihr mir vielleicht kurz dabei helfen?


MaggieMay

Hallo,
Zitatfür das zweite Datum wird ein falsches geschrieben, nämlich der 18. nicht der 21.
da müsstest du wohl auch noch den Code dazu zeigen und noch einmal genauer beschreiben was du überhaupt vorhast, bspw. welches Datum womit überschrieben werden soll.
Freundliche Grüße
MaggieMay

hooKa

Ok, ich hole nochmal ein bisschen aus :D Hab mir fast gedacht, dass es nicht reicht, aalso:

Aus dieser Tabelle hole ich mein Datum (tblDatenAusExcelNeu):


Wie du siehst habe ich 2 Datumsspalten (AngelgtAm, Kalendertag) für eine SAP-Nummer (Verkaufsbeleg).
Mein Ergebnis vom ersten Post kennst du ja bereits. Dort müsste in der Datumsspalte für den zweiten Eintrag der 21.11 stehen, aber es steht der 18.11.
Meine Update-Prozedur sieht so aus:

    Set rstSapSys = dbs.OpenRecordset("SELECT * FROM tblSAPSys Order By sapsys_KMATID, sapsys_autoid", dbOpenDynaset)
    Set rstDaten = dbs.OpenRecordset("SELECT * FROM tblDatenAusExcelNeu", dbOpenSnapshot)

    With rstSapSys
        If .RecordCount > 0 Then .MoveFirst
        While Not .EOF
                ' save order number and material number to variable, we'll use 'em later
                varOrderNumber = ![sapsys_SAPNr]
                varMatID = ![sapsys_KMATID]
                ' find order number with matching material number in tblDatenAusExcelNeu:
                rstDaten.FindFirst "[Verkaufsbeleg] = " & varOrderNumber & " And [MaterialID] = " & varMatID
                If Not rstDaten.NoMatch Then
                    ' If we found it we're lucky!

                    DoEvents
                    Do While (varOrderNumber = ![sapsys_SAPNr] And ![sapsys_KMATID] = varMatID)
                        ' compare the dates
                        ' we need to update only if:
                        ' 1. sapsys_date <> AnglegtAm and
                        ' 2. sapsys_KMATID = MaterialID
                             
                        If ![sapsys_date] <> rstDaten![Kalendertag] And ![sapsys_KMATID] = rstDaten![MaterialID] Then
                            .Edit
                            ![sapsys_date] = rstDaten![Kalendertag]
                            .Update
                        End If
                                               
                    DoEvents
                    .MoveNext

                    ' exit loop if we are end of file pointer
                    If .EOF Then Exit Do
                        rstDaten.FindNext "[Verkaufsbeleg] = " & varOrderNumber & " And [MaterialID] = " & varMatID
                        ' we also exit if there's no more match
                        If rstDaten.NoMatch Then Exit Do
                        Loop
                Else
                    .MoveNext
                    DoEvents
                End If
        Wend
    End With


Nur irgendetwas hakt da noch. Nur ich komme einfach nur drauf was.
In diesem Bespiel ist ja in der ersten Zeile das Datum gleich (18.11 in AngelegtAm und 18.11 in Kalendertag). Nun habe ich aber Fälle, wo es in der ersten Zeile unterschiedlich ist. Dann dürfte er aber nicht den Kalendertag nehmen, sondern soll nicht updaten bzw. beim AngelegtAm-Datum bleiben.

Versteht du, was ich meine? :)

MaggieMay

Nicht wirklich, ich erkenne da noch keine Regel.
ZitatWie du siehst habe ich 2 Datumsspalten (AngelgtAm, Kalendertag) für eine SAP-Nummer (Verkaufsbeleg).
Was im ersten Beitrag scheinbar noch keine Rolle spielte...

Soll es so sein, dass ab dem 2. Datensatz je Verkaufsbeleg das Datum "AngelegtAm" auf das Datum "Kalendertag" desselben Datensatzes eingestellt werden soll? Oder soll ein Datum (welches?) von einem Datensatz auf den nächsten (wohin genau?) übernommen werden?

ZitatNun habe ich aber Fälle, wo es in der ersten Zeile unterschiedlich ist.
Was bedeutet das und welche Auswirkungen soll das haben? Sollte nicht der erste Datensatz (je Verkaufsbeleg?) sowieso übersprungen werden?
Freundliche Grüße
MaggieMay

hooKa

ZitatNicht wirklich, ich erkenne da noch keine Regel.

Was im ersten Beitrag scheinbar noch keine Rolle spielte...
Meine Regel bzw. Lösung, auf die ich gekommen bin ist die, dass immer der erste Match bzw. Datensatz übersprungen wird. Vielleicht gibt es noch einen anderen Weg, aber ich denke, mit dem Überspringen vom ersten Datensatz sollte es funktionieren.

ZitatSoll es so sein, dass ab dem 2. Datensatz je Verkaufsbeleg das Datum "AngelegtAm" auf das Datum "Kalendertag" desselben Datensatzes eingestellt werden soll? Oder soll ein Datum (welches?) von einem Datensatz auf den nächsten (wohin genau?) übernommen werden?

Die Sache ist die, dass ich aus den Rohdaten (tblDatenAusExcelNeu) beim ersten Kopieren immer das AngelegtAm-Datum erstmal nehme. Das heißt, dass in der Spalte sapsys_date (erster Post) sowieso schon das Datum aus der Spalte AngelegtAm steht.

Nur möchte ich jetzt das Datum aus der Spalte Kalendertag nur dann in die Spalte sapsys_date schreiben, wo es nicht dem Datum in Spalte AngelegtAm entspricht. Da es vorkommen kann, dass es für den ersten Datensatz das AngelegtAm-Datum nicht dem Kalendertag-Datum entspricht, klappt meine Code nicht, er würde ein falsches Datum kopieren, nämlich das Kalendertag-Datum. Das soll aber nicht passieren, der erste Datensatz soll immer das AngelegtAm-Datum haben.

ZitatWas bedeutet das und welche Auswirkungen soll das haben? Sollte nicht der erste Datensatz (je Verkaufsbeleg?) sowieso übersprungen werden?

Letzteres trifft zu, das ist ja meine Idee. Wenn ich immer den ersten Datensatz überspringe, dann brauche ich mich nicht darum zu kümmern, ob das Datum für den ersten Datensatz gleich oder ungleich ist. Erst ab dem zweiten Datensatz soll verglichen werden :)

Deswegen hatte ich ja die Idee mit dem firstrecord = false, nur funktioniert das leider nicht. Er nimmt dann immer den 18.11 überall rein.

MaggieMay

ZitatDeswegen hatte ich ja die Idee mit dem firstrecord = false
Davon sieht man aber leider in dem zuletzt geposteten Codes nichts mehr. Es ist immer schlecht etwas zu beurteilen, das aus dem Kontext gerissen wurde. Dass es sich hier um Daten aus zwei Tabellen handelt, die miteinander verglichen werden sollte, wurde eingangs auch nicht erwähnt. Tut mir leid, aber mir fehlt immer noch das finale Verständnis für den Sinn und Zweck der Aktion.

Freundliche Grüße
MaggieMay

hooKa

#6
Den firstrecord = false Part habe ich wieder entfernt, weil er nicht klappt.

Ich wollte das mit den Daten auch nicht unbedingt erwähnen, weil ich dachte, dass es als Information nicht unbedingt benötigt wird für mein Problem.
Das einzige, was ich möchte ist, dass er mir beim matching-Part den ersten Match überspringt und mit dem zweiten Match beginnt.
Ich habe jetzt wirklich alles probiert, aber ich kriege es einfach nicht :(
Das heißt, hiernach:

                If Not rstDaten.NoMatch Then
                    ' If we found it we're lucky!
                    DoEvents
                    Do While (varOrderNumber = ![sapsys_SAPNr] And ![sapsys_KMATID] = varMatID)

.. müsste nach meinem Verständnis irgendwo hin, dass er den ersten Match überspringt. Habe es schon mit .MoveNext versucht und .FindNext und so vor dem .Edit, aber das klappt auch nicht.

MaggieMay

ZitatDen firstrecord = false Part habe ich wieder entfernt, weil er nicht klappt.
Naja, du hast das vermutlich falsch umgesetzt, aber wenn du immer nur Code-Fragmente zeigst, kann man das nicht wirklich beurteilen.

Mit Hilfe einer Beispiel-DB und ein paar Testdaten würde das sicher schnell zu lösen sein, denn noch ist einiges unklar, bspw. in welcher Beziehung die Tabellen zueinander stehen, ich meine, gibt es für jeden Datensatz in der SAP-Tabelle auch einen in der Excel-Tabelle? Und warum wird diese im Gegensatz zur SAP-Tabelle unsortiert geladen? Und wenn nur die tatsächlich benötigten Datenfelder anstelle von "*" in den Select-Statements angegeben würden, könnte auch das hilfreich sein.

Also lass uns am besten mal selbst einen Blick drauf werfen, dann kriegen wir die Kuh schon vom Eis. ;-)
Freundliche Grüße
MaggieMay

hooKa

Hallo Maggie,
ich hab's leider nicht geschafft früher zu antworten.

Da die DB leider unternehmensinterne Daten enthält, würde das meinem Chef nicht ganz so gut gefallen, wenn ich diese Daten einfach rausgebe :) Ich weiß, dass das natürlich die Problemlösung etwas erschwert, aber ich bin mir sicher, mit ein paar Screenshots kriegt man das ganze auch hin, hoffe ich :) Ich meine, der Code der Update-Prozedur ist ja wichtig und nicht die Beziehungen der Tabellen. Deswegen versuche ich jetzt nochmal ganz genau zu erklären, was ich mache:

Ich habe eine Ausgangstabelle mit "Rohdaten" namens tblDatenAusExcelNeu:

Hier gibt es ja zwei Datumsspalten sowie den Verkaufsbeleg und eine Material-Nummer.

Nun habe ich eine zweite Tabelle, in der die Aufträge stehen namens tblSAPSys:

Ganz rechts ist hier das Datumsfeld. Und jetzt möchte ich, dass ein bestimmtes Datum in diese Spalte (sapsys_date) für dieselbe SAP-Nummer geschrieben wird. Nämlich entweder das Datum aus Spalte AngelegtAm oder Kalendertag.

Dazu habe ich folgende Prozedur, die das ganze machen soll:

Public Sub UpdateSapSysDate()

    Dim dbs As DAO.Database
    Dim rstSapSys As DAO.Recordset
    Dim rstDaten As DAO.Recordset
    Dim varOrderNumber As Variant
    Dim varOrderDate As Variant
    Dim varMatID As Variant

    Set dbs = CurrentDb
    ' open our tables
    Set rstSapSys = dbs.OpenRecordset("SELECT * FROM tblSAPSys Order By sapsys_KMATID, sapsys_autoid", dbOpenDynaset)
    Set rstDaten = dbs.OpenRecordset("SELECT * FROM tblDatenAusExcelNeu", dbOpenSnapshot)

    With rstSapSys
        If .RecordCount > 0 Then .MoveFirst
        While Not .EOF
                ' save order number and material number to variable, we'll use 'em later
                varOrderNumber = ![sapsys_SAPNr]
                varMatID = ![sapsys_KMATID]
                ' find order number with matching material number in tblDatenAusExcelNeu:
                rstDaten.FindFirst "[Verkaufsbeleg] = " & varOrderNumber & " And [MaterialID] = " & varMatID
                If Not rstDaten.NoMatch Then
                    ' If we found it we're lucky!
                    DoEvents
                    Do While (varOrderNumber = ![sapsys_SAPNr] And ![sapsys_KMATID] = varMatID)
                        ' compare the dates
                        ' we need to update only if:
                        ' 1. sapsys_date <> AnglegtAm and
                        ' 2. sapsys_KMATID = MaterialID
                           
                        If ![sapsys_date] <> rstDaten![Kalendertag] And ![sapsys_KMATID] = rstDaten![MaterialID] Then
                            .Edit
                            ![sapsys_date] = rstDaten![Kalendertag]
                            .Update
                        End If
                           
                    DoEvents
                    .MoveNext
                    ' exit loop if we are end of file pointer
                    If .EOF Then Exit Do
                    rstDaten.FindNext "[Verkaufsbeleg] = " & varOrderNumber & " And [MaterialID] = " & varMatID
                    ' we also exit if there's no more match
                    If rstDaten.NoMatch Then Exit Do
                    Loop
                Else
                    .MoveNext
                    DoEvents
                End If
        Wend
    End With

    ' close objects
    Set rstSapSys = Nothing
    Set rstDaten = Nothing
    Set dbs = Nothing
End Sub


Das Problem ist aber, dass er, wie auf den Bildern zu erkennen ist, immer das Kalendertag-Datum reinschreibt in sapsys_date, wenn AngelegtAm sowie Kalendertag vom Verkaufsbeleg unterschiedlich sind.
Das ist natürlich in so fern doof, als dass er dann, wenn ein Auftrag neu angelegt wurde, diesem ein falsches Datum zuweist.
Standardmäßig habe ich es jetzt so gemacht, dass er immer erst die sapsys_date-Spalte mit dem AngelegtAm-Datum befüllt und nur guckt, ob es eine Differenz gibt. Da es aber z.B. in dem Beispiel oben beim ersten Datensatz schon einen Unterschied gibt, ist das schlecht. Hier müsste er das AngelegtAm-Datum lassen.

Daher eben meine Frage: Wie kann ich in meinen Code einbauen, dass er den ersten Datensatz dann überspringt, den er für einen Verkaufsbeleg findet?

MaggieMay

Du hast die Frage nach der Anzahl der Datensätze nicht beantwortet, aber auf den Screenshots sieht es so aus, als ob es viele Import-Datensätze zu einem SAP-Datensatz gäbe - ist das zutreffend? Somit überschreibst du das SAP-Datum also mehrfach?  ???

ZitatDas Problem ist aber, dass er, wie auf den Bildern zu erkennen ist, immer das Kalendertag-Datum reinschreibt in sapsys_date
Vom "immer" kann bei einem einzigen gezeigten Datensatz wohl kaum die Rede sein.

Zitateinbauen, dass er den ersten Datensatz dann überspringt, den er für einen Verkaufsbeleg findet
Was nützt dir das, wenn dann doch der nächste Datensatz dafür sorgt, dass das SAP-Datum überschrieben wird?   :-\
Freundliche Grüße
MaggieMay

hooKa

ZitatVom "immer" kann bei einem einzigen gezeigten Datensatz wohl kaum die Rede sein.
Es sind mehrere Datensätze, ich habe viele SAP-Nummern :)

ZitatWas nützt dir das, wenn dann doch der nächste Datensatz dafür sorgt, dass das SAP-Datum überschrieben wird?   :-\
Es soll ja nur der erste Match nicht berührt werden. In meinem Code habe ich ja den Part "If Not rstDaten.NoMatch Then".
Im Prinzip soll hier ja rein, dass beim ersten Match, zu dem es eine SAP-Nummer gibt, kein Update durchgeführt wird. So bewahre ich das AngelegtAM-Datum. Erst beim zweiten soll dann das Update erfolgen :)

Eine SAP-Nummer kann mehrere Datensätze umfassen und auch verschiedene Datum-Daten enthalten.
Hier z.B. ist ein Beispiel, bei dem mein Code nicht mehr klappt. In den Rohdaten steht einmal der 18.11 und dann der 21.11.
Er müsste also für den ersten Match den 18.11 (AngelegtAm) eintragen und ab dem zweiten Match den 21.11 (Kalendertag).


Was aber passiert ist, dass er erst für den dritten den 21.11 nimmt:

.. und das passt ja leider auch nicht. Also irgendwie funktioniert der Algorithmus noch nicht :/

ebs17

Anstatt zu springen und zu hopsen könnte man schlicht an eine Aktualisierungsabfrage denken, wo man die ungewünschten (z.B. ersten) Datensätze vorher durch Filtern entfernt. Das sollte einfacher und vor allem schneller sein.

ZitatDie Sache ist die, dass ich aus den Rohdaten (tblDatenAusExcelNeu) beim ersten Kopieren immer das AngelegtAm-Datum erstmal nehme.
Ein ERSTES KOPIEREN lässt einige Nachfolgevorgänge vermuten.
Vielleicht sollte man gleich Daten richtig eintragen statt Kopieren und Nachwurschteln.

Es könnte sein, dass sich manche Probleme gar nicht erst ergeben, wenn man erst über Abläufe (einfach, fehlerarm direkt, schnell) nachdenkt und dafür Methoden sucht. Daher vertiefe ich mich nun nicht in NoMatch-Probleme.
Mit freundlichem Glück Auf!

Eberhard

MaggieMay

#12
Hi,
ZitatDa die DB leider unternehmensinterne Daten enthält
niemand will hier firmeninterne Daten sehen, wie ich bereits schrieb:
ZitatMit Hilfe einer Beispiel-DB und ein paar Testdaten

Eine Beispiel-DB sollte darüberhinaus nur die zum Nachstellen des Problems erforderlichen Objekte enthalten. Darum nennt man sie ja auch Beispiel- (oder Demo-) DB. Sonst würde man ja schreiben "Lade deine DB mal hoch", aber sowas sagt man höchstens wenn klar ist, dass die DB noch in den Kinderschuhen steckt und nicht produktiv eingesetzt wird. Davon abgesehen sollte jede produktiv eingesetzte Anwendung in Frontend und Backend aufgeteilt werden, so dass man die Daten leicht von den übrigen Objekten trennen und gegen Spieldaten austauschen kann.

Mag sein, dass mein Hirn schon an zu schwächeln fängt, aber ich werde beim besten Willen nicht schlau aus deinen Beschreibungsversuchen.

ZitatEs sind mehrere Datensätze, ich habe viele SAP-Nummern
Davon bin ich ausgegangen, die Frage aber war doch, wie viele Datensätze zu einem Verkaufsbeleg/SAP-Nr aus der Excel-Tabelle stehen wie vielen aus der SAP-Tabelle gegenüber?! Das liest sich aus deinen Screenshot mal so, mal so. Beispiele sollten aber stets so gewählt werden, dass sie möglichst eindeutige Rückschlüsse zulassen.

Das nur als grundsätzliche Hinweise. Ansonsten würde auch ich den Schwachpunkt deines Lösungsansatzes im "Herumspringen und -hopsen" in zwei Recordsets sehen. Konkrete Alternativ-Vorschläge können aber zum derzeitigen Zeitpunkt mangels Detailkenntnissen wohl kaum gemacht werden.
Freundliche Grüße
MaggieMay