PDA

Vollständige Version anzeigen : Makrobedingungen - Beispiel Tabellenoperation


jörgq
10.05.2004, 14:31
Aufgabenstellung:
Import einer MS-EXCEL-Tabelle in eine ACCESS-Datenbank zur schnelleren Auswertung und ggf. Verknüpfung an eine andere Datenbank zwecks Datenvergleich / Aktualisierung.
Die Struktur der vorgefundenen Tabelle ist Excel-typisch - bestehend aus:
- Überschriftenzeilen (enthält in der 2.Spalte den Namen des Gegenstandes bzw. den eigentlichen Datensatz)
- in einigen Spalten neben der Namenspalte untereinander zwischen 1 bis 6 Werte = verschiedene Eigenschaften des Gegenstandes (also auf bis zu 6 Zeilen untereinander verteilt)
- die Werte müssen jeder eine eigene Spalte bzw. den Wert in die eigentliche Datensatzzeile (die, mit dem Namen) hinkopiert bekommen.

Lösung:
Ein Makro, daß pro eigentlichem Datensatz von Zeile zu Zeile und dort von Zelle zu Zelle hüpft und so die untereinanderstehenden Werte in Spalten dahinter kopiert, sofern in der Namensspalte eine Nullmarke ist.
-> hier der Ausschnitt, bei dem es zur Fehlermeldung kommt:

Makro-____Bedingung_Aktion______________Kommentar_____________
name
____________________________________________________________
___________________GeheZuSteuerelement_(Feldname="Kennzeichng")
____[Kennzeichng]=" "_AusführenMakro______(gehe zu 1)____________
___________________StoppMakro_______________________________
1__________________GeheZuSteuerelement_(Feldname="Einteilung")___
___________________AusführenBefehl______(kopieren)______________
___________________GeheZuSteuerelement_(Feldname="Einteil_1")____
___________________AusführenBefehl______(einfügen)
___________________StoppMakro_______________________________


Erläuterung:
" " ist als Abbruchbedingung gedacht, wenn ein Feld ein Leerzeichen enthält, muß in den nebenstehenden Spalten und weiter in den nachfolgenden Zeilen derselben Spalten geprüft werden, ob dort noch Werte stehen; steht in "Kennzeichng" ein beliebiges (alphanumerisches) Zeichen, handelt es sich um den Inhalt des eigentlichen Datensatzes des nächsten Namens.
Das Makro wird von einem anderen Makro wiederholt aufgerufen; genausooft, wieviele eigentliche Datensätze bzw. Namen in der Importtabelle vorhanden sind (bzw. vorhanden sein könnten).
Es funktioniert soweit alles - bis auf die Makrobedingung.

Problem bzw. Fehler(falsch)meldung lautet:
"Microsoft Access kann den eingegebenen Namen 'Kennzeichng' nicht finden. Sie haben eventuell ein Steuerelement angegeben das sich nicht auf dem aktuellen Objekt befand und für das Sie keinen Formular- oder Berichtskontext angegeben haben. ..." (...es folgte dann noch eine Anleitung für Formulare bzw. Berichte einschl. OK - Schaltfläche)

Zitat aus der online-Hilfe:

"Makrobedingungen - Beispiele

Ausdruck Bedingung

[Ort]="Paris"

Führt die Aktion aus, wenn Paris der Wert im Feld Ort des Formulars ist, aus dem das Makro ausgeführt wird.

u.s.w."

Unverständlich ist, daß im Schritt "GeheZuSteuerelement" der Feldname 'Kennzeichng' richtig erkannt wird. Der Datensatzzeiger steht auch in der richtigen Zelle...
Wenn ich in dem Makro eine Zeile zum Kopieren des Wertes in die Zwischenablage einfüge, kann ich dort den korrekt ausgelesenen Wert sehen:
...
___________________GeheZuSteuerelement_(Feldname="Kennzeichng")
___________________AusführenBefehl______(kopieren)______________
____[Kennzeichng]=" "_AusführenMakro______(gehe zu 1)____________
...

Für eine Umwegprogrammierung über "AusführenCode" und Auslesen der Zwischenablage, Vergleich auf das " " und anschließend auf Grundlage des Vergleichsergebnisses im Makro weitermachen --- fehlen mir Kenntnisse in VB bzw. VBA.
Der Methode "SVERWEIS()" in Excel traue ich eine programmierbare Lösung nicht zu; auch dürfte dort die Verarbeitungsgeschwindigkeit indiskutabel in den Keller gehen...

Handelt es sich um einen Bug, daß ich im Objekt "Tabelle" nicht die vergleichbaren Operationen, wie im Formular machen kann? Denn auch mit vollständiger Syntax [t_Import].[Kennzeichng]=" " wird anstelle des Vergleichs die Fehlermeldung ausgegeben ("... kann den eingegebenen Namen 't_Import' nicht finden...").

J_Eilers
10.05.2004, 14:46
Hi,

und hier die Gründe gegen Makros (http://home.arcor.de/ar/arne.d/datenbanken/grundlagen/makros/index.html#SEC2). Wenn du es unbedingt mit Makros lösen möchtest, dann vergiß meinen Post. Ansonsten solltest du dir mal das Beispiel ExcelToAccess (http://www.kraasch.de) von Reinhard Kraasch ansehen. Dort wird so etwas umgesetzt.

jörgq
11.05.2004, 21:52
Vielen Dank, Jan, für den Tip, vor allem für die sofortige Reaktion!
Ich habe mir als erstes -schon gestern- die Excel to Access - Datenbank über den von Dir bereitgestellten Link gezogen und in die VBA-Programmierung des Formulars reingesehen. Mein größtes Problem ist dabei, daß ich die EXCEL-internen Variablen- bzw. Feldbezeichnungen nicht kenne - welche ich speziell bei "XMAX" und "YMAX" und ggf. weiteren vermute. Wie ich schon schrieb - es fehlen mir hier Kenntnisse, für die ich im Falle der Anpassung vorliegender Lösung an meine Aufgabenstellung für zumindest 1 Buchtip sehr dankbar wäre (ich bevorzuge diesbezgl. die Ausleihe aus einer UNI-Bibliothek und denke weniger an den freier beweglichen Kauf zutreffender Literatur).

Aber erst muß ich noch den anderen Weg prüfen -Umwandlung eines Makro in VBA-Code- wohin Du mir den anderen Link mit weiterführenden Hinweisen gleich mitgeliefert hattest (ich befürchte jedoch auch nach Umwandling dieselbe FM "...Name 'Kennzeichng' nicht gefunden..." oder so ähnlich --- aber erst werde ich das noch ausprobieren!!!).

Oberflächlich betrachtet bin ich offensichtlich in eine -scheinbar- auf keinem der beiden Wege lösbare Situation geraten.
Leider schließt die Forderung, unter 5k einschl. Anhang in der Beitragslänge zu bleiben, die Abbildung der vorgefundenen -extrem liederlichen (!)- Datenstruktur der Excel-Ausgangstabelle als Beispielanhang aus; eine Hinterlegung auf meiner -evtl.- homepage geht z.Zt. nicht.
Wenn es sich um eine ähnliche Form wie "Koordinaten.xls" handeln würde, hätte ich sicher ein Gemisch aus SQL-Anweisungen und -ausversehen- ggf. Makro-Steuerung als Lösung gefunden... ;-)

Für nächste Woche habe ich mir vorgenommen, die ganze Sache als unlösbar aufzugeben oder hier zumindest den Ansatz für eine Lösung mitzuteilen.

J_Eilers
12.05.2004, 07:18
Moin,

vielleicht könnte man sich auch einfach die Tabelle in Access holen/verknüpfen und diese dann mit SQL (und) einem Recordset zerlegen. Aber dazu müsste man schon mehr über den Aufbau und das Ergebnis wissen.

Ein Buch kann ich dir leider nicht empfehlen, da ich nur das A2k Handbuch und dieses Forum habe.

jörgq
14.05.2004, 08:20
Hallo Jan,
hier die aus Access als *.txt exportierte Beispieltabelle. Die tatsächlichen Daten einschl. Quelle darf ich vorerst nicht preigeben.

Es sind 2 Dateien aus dem folgenden mit Hilfe des Editors wieder herzustellen (bitte KEINE Leerzeile davor oder dahinter hinzufügen) und in Access in einer neuen Datenbank als Tabelle 't_imp' zu importieren, erste Zeile enthält die Spaltenüberschriften:

schema.ini
-----------------
[t_imp.txt]
ColNameHeader=True
CharacterSet=1252
Format=TabDelimited
Col1=ID Integer
Col2=GName Char Width 255
Col3=E1 Char Width 255
Col4=E2 Char Width 255
Col5=E3 Char Width 255
Col6=E4 Char Width 255

t_imp.txt
--------------
"ID" "GName" "E1" "E2" "E3" "E4"
1 "limits"
2 "Esel" " F" " F+" " U: 19"
3 " R: 12" " U: "
4 " S: 25-9"
5 "Kuckuck" " F" " F" " U: 19"
6 " R: 15" " U: "
7 " S: 2-7/8-24"
8 "Katze" " F; R" " F-C-" " U: 20"
9 " C; R" " R: 1" " U: "
10 " S: 2"
11 "Maus" " C; C+; R" " N-" " U: 19"
12 " B" " R: 4" " U: 28"
13 " B+" " S: 61 "
14 " X"
15 " I4"
16 " N; R"
17
18 "Hund" " R14" " T+-C-" " U: 19"
19 " T+; R26/28" " R: 27" " U: "
20 " C; R45" " S: 45 "
21
22 "Ente" " T+; R2" " T+" " P = 5 %" " U: 19"
23 " C; R4" " R: 34" " 1 % = P < 5 %" " U: 22"
24 " S: 9" " 0,5 % = P < 1 %"
25 " 0,2 % = P < 0,5 %"
26 " 0,02 % = P < 0,2 %"
27
28 "Kuh" " F; R11" " F-T-" " P = 20 %" " U: 19"
29 " R" " R: 1" " 1 % = P < 20 %" " U: 25"
30 " T" " S: 6" " 0,2 % = P < 1 %"
31 " R+"
32

Ich hoffe, daß die eigenartigen Beispielnamen nicht weiter stören...
Die ersten 3 Zeilen wären auch gar kein Problem, da es hier (außer zuviel Leerzeichen in den Zellenwerten) wiederkehrende Wertanteile gibt.

Zum Begriff "RECORDSET" habe ich die online-Hilfe gelesen --- und leider nicht verstanden. Wenn es dabei darum geht, daß zu jeder Namenszeile eine genau gleiche Anzahl nachfolgender Zeilen gehört (als Voraussetzung), dann ist das hier NICHT möglich - die Zeilenzahl variiert zwischen mindestens 3 und maximal 8 Zeilen.

Umwandlung des Makro in VBA-Code habe ich gestern kurz getestet mit dem Ergebnis:
... gleiche Fehlermeldung, wie vor der Umwandlung: "... kann den eingegebenen Namen 't_imp' nicht finden..." usw.

Zur Anpassung der Lösung von R.Kraasch war noch keine Zeit (wie schon in voriger Antwort erwähnt, muß ich die Lösung nicht "gestern schon" herausfinden; da nächste Woche Feiertag einschl. Urlaub ist, setze ich mir als Termin Ende Mai fest).

J_Eilers
14.05.2004, 08:34
Erstmal vorneweg: Du möchtest bestimmte Bereiche einer ExcelTabelle in Access impotieren und diese innerhalb von Access in unterschiedliche Tabellen schreiben?

Könntest du eine BeispielExcelTabelle mit Fantasiewerten hochladen? Ich denke man kann sich diese Tabelle in Access erstellen und dann mittels RecordSet zerlegen.

Beschreibe bitte genau, welches Feld in welche Tabelle+Feld kommen soll. Ich werde dann versuchen etwas nachzubilden und dir dann den Code zeigen / versuchen zu erklären.

jörgq
26.05.2004, 21:39
Hallo Jan,
leider erst mit Verzögerung kann ich mich heute wieder zu Wort melden.
Als Anhang unten eine etwas geänderte (und drastisch gekürzte) Beispieltabelle (woher habe ich nur die Info gehabt, daß nur max 5 kB erlaubt seien?). Der Versuch über die in den lfd. Text reinkopierten Daten entspr. meines letzten Beitrags funktionierte leider nicht...
Jetzt also noch mal und richtig:
Zur Problemstellung ist alles erst mal gesagt (siehe oben).
Zum Lösungsansatz über "auslesen Zwischenablage" habe ich hier im gleichen Forum mit ebendiesem Suchbegriff den Eintrag von olafu bzw. Olaf vom 04.10.2003 "kopierte Daten in MsgBox anzeigen" (Antworten von strausto bzw. Torsten) gefunden; habe aber wie vor erwähnt keine ausreichenden Kenntnisse zu VBA, um die für meinen Fall ggf. relevanten Zeilen eines Moduls herauszufinden und entsprechend im Makro zu verwenden.
Wie schon beschrieben: Der Datensatzzeiger steht in der von mir gewollten Zeile und das aktuelle Feld ist auch korrekt (habe ich anstelle Leerzeichen auch mit einem Buchstaben ausprobiert - FM bleibt hartnäckig, das ACCESS kennt beim Ausführen des Bedingungsvergleichs weder den Namen des aktuellen Feldes noch den Namen der Tabelle (so z.B. bei verwendung der vollständigen Syntax für Makrobedingungen)).
schiebt man eine Makrozeile "AusführenBefehl" und Argument "Kopieren" vor die entscheidende Vergleichszeile, steht in der Zwischenablage der Korrekte Wert (der also nur ein Leerzeichen oder alles mögliche andere sein kann) --- siehe auch mein erster Beitrag Erläuterungen im unteren Teil.
Übrigens: Der Termin "Ende Mai" hat großzügigen Aufschub bekommen... ;-)

jörgq
15.06.2004, 11:18
Hallo Jan,
der Freitag dieser Woche sei KEIN ULTIMATUM (entspr. unseres heutigen PN-Wechsels) aber mehr denn eine Bitte als Termin für einen Zwischenstand.
Siehe auch im "Anhang: db_imp_97.zip" in meiner vorhergehenden Antwort...
Mit freundlichen Grüßen
Jörg Q.

J_Eilers
15.06.2004, 11:22
Jetzt weiß ich auch wieder um was es ging ;)

Muss die Tabelle so aufgebaut sein? Denn aus meiner Sicht ist diese nicht normalisiert.

jörgq
17.06.2004, 09:41
Hallo Jan,
bitte lies Dir nochmal meine Aufgabenstellung vom Anfang vom 10.05.04 und folgende durch.
Die Tabelle ist doch nur der Ausgangspunkt und kommt als Ergebnis einer Abfrage irgendwoher aus dem Internet und enthält ca. 11000 Zeilen - Handarbeit für Nachbesserungen ist also ausgeschlossen. Auch die sinnlosen Leerzeichen vor und hinter den Werten in den Feldern der Tabelle kommen davon.
Bitte prüfe anhand des von mir gelieferten Beispiels (siehe zip-Datei) die Methode "Auslesen der Zwischenablage" und ggf. eine in VBA geschriebene Funktion, in der ich eine Bedingung in Abhängigkeit vom Inhalt der Zwischenablage so formulieren kann, daß die Access Makro-Entscheidung über Sprung zur nächsten Makromarke (z.B. 41) oder Beendigung des Makros UM2 möglich wird.
Du kannst es ruhig wie am 10.05. beschrieben im Makroteil UM2 der db_imp_97.mdb ausprobieren:
...ab Makro-Zeile 67...
---------------GeheZuSteuerelement-----(Feldname="E2")
---------------AusführenBefehl---------------(kopieren)
---------------AusführenCode----------------(VBA-Funktion <=== das könnte Deine sein)
---------------StoppMakro
41-----------GeheZuSteuerelement-----(Feldname="E1")
...es folgen weitere (ca. 150) Makro-Zeilen...
Ich hoffe sehr darauf, daß die VBA-Funktion die eher umsetzbare Lösung ist. ;-)

J_Eilers
17.06.2004, 09:51
Hallo Jörg,

ich denke sehr wohl, dass ich weiß, was du meinst, aber was bringt es eine nichtnormalisierte Tabelle in eine andere nichtnormalisierte Tabelle umzuwandeln? Wenn das DB-Design dem entsprechend geändert werden könnte, könnte man sich dran versuchen. Aber was bringt ein Workaround, wenn es vermutlich gleich das nächste Workaround mit sich bringt?

Meine Meinung: Entweder bringen wir beides in Ordnung oder ich spare mir die Mühe. Sorry, aber das ist sonst eine Sysiphusarbeit.

jörgq
17.06.2004, 11:00
Hallo Jan,
keinesfalls möchte ich Dich zu einem weiteren unnötigen Umweg lenken, siehe bitte den einzigen Beispieldatensatz in "Beispieldatensatz_Ergebnistabelle", in der richtigen Ergebnistabelle müßten 7 Datensätze stehen (hier steht jetzt nur 1 mit der willkürlichen ID "22").
Eingang und Ergebnis unterscheiden sich durch die "menschlich-übersichtliche" Anordnung von Informationen der Eingangstabelle in 6 Spalten zu 1 bis 6 Zeilen pro (Beispiel-)Tiername und der Ergebnistabelle in 25 Spalten zu je NUR 1 Zeile pro (Beispiel-)Tiername.
Dieses Ergebnis ist deswegen so wichtig, weil dann alle Informationen zu einem Tier in genau einer Zeile stehen und es Fälle gibt, bei denen in den Originaldaten tatsächlich alle 25 Spalten mit einem Wert pro Datensatz gefüllt sind.
Sollten Dir Fragen zur Auswerteproblematik hochkommen, so habe ich diese bereits gelöst mittels SQL-Abfragen und darin geschachtelten Unterabfragen.

J_Eilers
17.06.2004, 11:06
Die Ergebnistabelle enthält sich wiederholende Spalten! Das widerspricht dem Grundprinzip der Datennormalisierung.
Man kann sich für jede sich wiederholende Spalte eine eigene Tabelle oder ähnliches Konstrukt erstellen, damit sich diese Spalten nicht wiederholen, sondern diese Daten in Zeilen zu einer Spalte gespeichert werden.
Dann kann sich ganz einfach die Daten aus den entsprechenden Tabellen holen, wenn man die ID hat.
Sicher könnte man alles in eine Tabelle schreiben. Aber das Workaround für das Speichern ist sehr viel aufwendiger, als wenn ich die Daten in eine normalisierte Tabelle schreiben würde.
Evtl schaust du dir mal den Link "relationale Datenbanken" in meiner Signatur an. Bei Bedarf kann ich dir zeigen, wie ich es lösen würde. Aber das würde einen anderen Tabellenaufbau beinhalten.

jörgq
17.06.2004, 11:15
Hallo Jan,
danke für den Hinweis auf den link "relationale Datenbanken", er ist SEHR GUT.
Bitte prüfen dennochmal meinen Weg zur Ergebnistabelle (hatte ich aus versehen vergessen, daß diese nur einen Zwischenschritt für Datenaktualisierung einer anderen Datenbank darstellt? - dann Entschuldigung bitte, auch bei den Mitlesenden im Forum...)

J_Eilers
17.06.2004, 13:31
Versuchs mal damit:

Dim rsAlt As DAO.Recordset
Dim rsNeu As DAO.Recordset
Dim db As DAO.Database
Dim i As Integer

Set db = CurrentDb
Set rsAlt = db.OpenRecordset("Eingangstabelle", dbOpenSnapshot)
Set rsNeu = db.OpenRecordset("Beispieldatensatz_Ergebnistabelle", dbOpenDynaset)

With rsAlt
.MoveNext
While Not .EOF
If Not IsNull(!GName) Then
rsNeu.AddNew
i = 1
Else
rsNeu.MoveLast
rsNeu.Edit
i = i + 1
End If
If Not IsNull(!GName) Then rsNeu!GName = !GName
If Not IsNull(!E1) Then rsNeu("E1_" & i) = !E1
If Not IsNull(!E2) Then rsNeu("E2_" & i) = !E2
If Not IsNull(!E3) Then rsNeu("E3_" & i) = !E3
If Not IsNull(!E4) Then rsNeu("E4_" & i) = !E4
rsNeu.Update
.MoveNext
Wend
End With

rsAlt.Close
rsNeu.Close
db.Close
Set rsAlt = Nothing
Set rsNeu = Nothing
Set db = Nothing

Ob es jetzt das gewünschte liefert kann ich dir nicht sagen, aber als Grobgerüst sollte es reichen. Eine ID wird hier nicht mitgepflegt, so dass du entweder den Schlüßel löschst oder dir überlegst, wie diese Zahl zustandekommen soll.

jörgq
17.06.2004, 13:36
Hallo Jan,
bitte mache Dir keine Gedanken wegen der sich wiederholdenen Spalten der Ergebnistabelle, sie sind absichtlich mit einer fortlaufenden Bezeichnung gewählt - im Original haben alle ihren eigenen Namen (bis auf die Bereichsangaben) die wiederum von einer Unmenge an Randbedingungen abhängen. So stehen die Bereichsangaben in einer anderen Datenbank alle in einer eigenen Tabelle bezogen über ihre spezielle Eigenschafts-ID. Alle anderen Spalten sind in ebenderanderen DB zu Tabellen mit meistens 2 bis maximal 5 Spalten aufgeteilt.
Die in der "db_imp_97.mdb" von mir gezeigte "Ergebnistabelle" ist nur ein Zwischenschritt für einen zwingend notwendigen Datenvergleich mit der - wie vor erwähnten - anderen etwas umfangreicheren Datenbank; und dies in großen Zeitabständen entsprechend Gesetzgebungs- und -änderungsverlauf der BRD.
Da die Beziehungen in der anderen DB sehr komplex sind, hatte ich gehofft, es mit dem Erstellen einer nur einmal nach einem Datenimport benötigten Tabelle genügen zu lassen, da diese auch nur einmal zum Vergleich zwecks Datensicherheit (und darüber hinaus ggf. als "backup" des Datenimports liegenbleibt bis zur nächsten Aktualisierung) - auch wenn diese erstmal grundlegend gegen die anzustrebende Normalform von Tabellen in relationalen Datenbanken verstößt.
Ein Direktvergleich zwischen (Internet-)Quelle und den zutreffenden Werten in den Tabellen der anderen Datenbank ist leider nicht möglich (Zugriffsverfügbarkeit, Downloadrate, mehrseitige Datenschutzgründe).

jörgq
17.06.2004, 13:47
Hallo Jan,
vielen Dank für die schnelle Hilfe!
Am Dienstag 22.06.04 spätestens nach erfolgtem Test und Anpassung schreibe ich den Erfolg mit Dateianhang (oder Nichterfolg mit weiterer Suchrichtung oder Aufgabe) hier ins Forum...

jörgq
22.06.2004, 22:59
Hallo Jan,
Deinen VBA-Code habe ich in einem "Modul1" eingefügt, bin mir aber sicher, daß ich es nicht richtig gemacht habe und bitte Dich, Dir die "db_imp1_97.mdb" nochmal anzusehen.

So erhalte ich nach einfügen und kompilieren des VBA-Codes in "Modul1" für 6. Zeile die FM:
___
Set db = CurrentDb
---
"Fehler beim kompilieren:
Außerhalb einer Prozedur ungültig"

Bevor der Compiler dann weitermeckert, gleich noch eine Frage zur Syntax der folgenden Zeilen:

If Not IsNull(!GName) Then rsNeu!GName = !GName

...muß dann die folgende Zeile...

If Not IsNull(!E1) Then rsNeu("E1_" & i) = !E1

...nicht eher so lauten...

If Not IsNull(!E1) Then rsNeu!("E1_" & i) = !E1
...?

Die ID sollte mitgepflegt werden, hat allerdings nur untergeordnete Bedeutung (Kontrollfunktion für Stichproben / Prüfung der Ergebnistabelle), da der Vergleich zu den anderen DB-Tabellen über (hier nicht aufgeführte) Schlüsselnummern erfolgt - ein alleiniger Vergleich auf GName wird zu unsicher wegen Eingabefehlern in der Quelle.
Eventuell wird eine weitere, neue ID (durch einfügen neue Spalte und setzen auf AutoWert) in der Ergebnistabelle ganz gut aussehen.
Ist für den Eintrag der ID die Position der zusätzlichen Zeile im folgenden richtig:

i = 1
rsNeu!ID = !ID
Else
...?

Die Idee mit der Verarbeitung der Laufvariablen in den von mir willkürlich so extrem einfach festgelegten Spaltenamen gefällt mir übrigens sehr gut; werde ich ggf. im Original so lassen, da die Inhalte bzw. Werte eindeutig in sich selbst vor dem späteren fachlichen Hintergrund sind.

+++

Um bei der Anwendung von VBA-Code dazuzulernen (und hier aber leider auf die Gefahr hin, wegen meines Hangs zur Makroverwendung zu nerven), habe ich ein weiteres "Modul2" nach Vorlage aus der Klassenbibliothek von "http://msdn.microsoft.com/library/deu/default.asp?url=/library/DEU/cpref/html/frlrfSystemWindowsFormsClipboardClassGetDataObjectTopic.asp" mit teilweisem Erraten der Syntax erstellt. --- UND eine FM kassiert...
Es kommt bei der Ausführung des Makros M2 eine FM "beim Kompilieren ...Syntaxfehler im Modul2", bitte, wenn es ein ganz leicht zu behebender Fehler sein sollte, würde mir das für spätere Anwendungen als Beispiellösung für einen Funktionsaufruf in einer Makrobedingung ...und für die Verwendung der Zwischenablage im Besonderen sehr wichtig sein.
Ist der Zeitaufwand zu groß, weil sowieso im Ansatz des VBA-Codes schon falsch, dann solltest Du "Modul2" sogleich löschen und bitte nur das "Modul1" mit den Recordsets gängig machen, danke.

J_Eilers
23.06.2004, 07:30
Moin Jörg,

Du solltest den Code schon in einer Funktion zusammenfassen. Schreibe mal folgendes darüber:

Public Function Transponieren()

'Der Code

End Function

Damit sollte es dann auch gehen. Da du mit A97 arbeitest kannst du die Deklaration vermutlich auch anders machen:

Dim rsAlt As Recordset
Dim rsNeu As Recordset
Dim db As Database
Dim i As Integer

Da ich hier mit A2K arbeite und hier ADO Standard ist, deklariere ich DAO-Objekte immer so.

Das mit der ID sollte so klappen.

If Not IsNull(!E1) Then rsNeu!("E1_" & i) = !E1

Wird nicht funktionieren. Denn mit rsNeu!Feldname kann man nur den Feldnamen direkt ansprechen. mit rsNeu.Eigenschaft spricht man Eigenschaften des Recordsets oder Funktionen an. Um variabel einen Feldnamen anzusprechen geht es nur mit dieser Schreibweise:
rsNeu("Feld" & Variable)
Dahinter kannst du dann eine Funktion/Eigenschaft oder auch das Feld als solches ansprechen.

Zum ClipBoard kann ich dir leider auch nichts sagen, da ich mich damit noch nicht beschäftigt habe.

jörgq
24.06.2004, 00:17
Hallo Jan,
danke für Deine weiteren Hinweise, die ich nun wie folgt im Modul1 eingebaut habe:


Option Compare Database

Public Function Transponieren()

Dim rsAlt As Recordset
Dim rsNeu As Recordset
Dim db As Database
Dim i As Integer

Set db = CurrentDb
Set rsAlt = db.OpenRecordset("Eingangstabelle", dbOpenSnapshot)
Set rsNeu = db.OpenRecordset("Beispieldatensatz_Ergebnistabelle", dbOpenDynaset)

With rsAlt
.MoveNext
While Not .EOF
If Not IsNull(!GName) Then
rsNeu.AddNew
i = 1
rsNeu!ID = !ID
Else
rsNeu.MoveLast
rsNeu.Edit
i = i + 1
End If
If Not IsNull(!GName) Then rsNeu!GName = !GName
If Not IsNull(!E1) Then rsNeu("E1_" & i) = !E1
If Not IsNull(!E2) Then rsNeu("E2_" & i) = !E2
If Not IsNull(!E3) Then rsNeu("E3_" & i) = !E3
If Not IsNull(!E4) Then rsNeu("E4_" & i) = !E4
rsNeu.Update
.MoveNext
Wend
End With

rsAlt.Close
rsNeu.Close
db.Close
Set rsAlt = Nothing
Set rsNeu = Nothing
Set db = Nothing

End Function 'Transponieren()


Leider erhalte ich nun FM "Fehler beim kompilieren, benutzerdefinierter Typ nicht definiert" für die Zeile:


Dim db As Database


...
Modul2 ist für mich erst mal gestorben, ggf. werde ich dazu nach Abschluß (dieser Methode mit den Recordsets) ein neues Thema schreiben; habe dazu noch nicht genügend lange dieses Forum einschl. vor allem des Archivs durchsucht...
...

Zum Schluß noch eine Frage:
Wegen der ADO/DAO-Datenzugriffsproblematik werde ich also bei der A97-Version dann bleiben müssen?! Wird denn das nicht im Hintergrund vom Datenbankdienstprogramm für die Herunterkonvertierung miterledigt? (Leider kann ich das Beispiel zur Problematik "ADO: Recordset.Find funktioniert nicht" im Hinweis "Wichtig: Bitte vor der Benutzung des Forums lesen ..." nicht finden, um erst mal selber nachzulesen).

J_Eilers
24.06.2004, 07:22
Fangen wir mal von hinten. Torstens Beitrag ist inzwischen vermutlich auf Seite 5 oder noch weiter hinten. Es gibt halt Unterschiede sowohl in der Programmierung von DAO und ADO. Und zusätzlich gibt es auch noch Unterschiede in den Funktionen.

Nein du musst nicht bei A97 bleiben. Ich selbst arbeite ja auch mit A2K und dort entstammt der Code. Das einzige was du dabei machen musst ist einen Verweis auf die Microsoft DAO 3.xx im VBA-Fenster unter Extras / Verweise zu setzen und die Variablen entsprechend zu deklarieren.
Ich bin davon ausgegangen, dass du mit A97 arbeitest, weil dein Beispiel in A97 ist und es keinen Hinweis in deinem Profil gibt. Jetzt verrate mir doch bitte erstmal in welcher Accessversion du arbeitest.

Und nein der Assistent ändert nirgendswo Code, nur weil es auf einmal A97 sein soll.

jörgq
25.06.2004, 10:19
Hallo Jan,
danke für Deine Hinweise.
Haken im Fenster "Verweise db_imp1" bei 'Microsoft DAO 3.x Object Library' ist jetzt auch gesetzt.
Modul1 sieht nun so aus:


Option Compare Database

Public Function Transponieren()

Dim rs As DAO.Recordset
Dim rsAlt As DAO.Recordset
Dim rsNeu As DAO.Recordset
Dim db As DAO.Database
Dim i As Integer

Set db = CurrentDb
Set rs = db.OpenRecordset(SQL_String, dbOpenDynaset)
Set rsAlt = db.OpenRecordset(t_imp, dbOpenSnapshot)
Set rsNeu = db.OpenRecordset(Beispieldatensatz_Ergebnistabelle, dbOpenDynaset)

With rsAlt
.MoveNext
While Not .EOF
If Not IsNull(!GName) Then
rsNeu.AddNew
i = 1
rsNeu!ID = !ID
Else
rsNeu.MoveLast
rsNeu.Edit
i = i + 1
End If
If Not IsNull(!GName) Then rsNeu!GName = !GName
If Not IsNull(!E1) Then rsNeu(E1_ & i) = !E1
If Not IsNull(!E2) Then rsNeu(E2_ & i) = !E2
If Not IsNull(!E3) Then rsNeu(E3_ & i) = !E3
If Not IsNull(!E4) Then rsNeu(E4_ & i) = !E4
rsNeu.Update
.MoveNext
Wend
End With

rsAlt.Close
rsNeu.Close
db.Close
Set rsAlt = Nothing
Set rsNeu = Nothing
Set db = Nothing

End Function 'Transponieren()


Es folgt FM "Laufzeitfehler '3078':
Das Microsoft Jet-Datenbankmodul findet die Eingangstabelle oder Abfrage " nicht. Stellen Sie sicher, dass sie existiert und der Name richtig eingegeben wurde."
Zunächst habe ich dann alle "-Zeichen im Code gesucht und gelöscht ohne eine FM beim Kompilieren zu bekommen (ist oben im Code bereits geschehen).
Die FM bleibt.
Nach Click auf Schaltfläche "Debuggen" wird folgende Zeile markiert:

Set rs = db.OpenRecordset(SQL_String, dbOpenDynaset)

Die in der FM auch mitangebotene Schaltfläche Hilfe hat mir leider erst mal nicht weitergeholfen.
Nach Ausführen von "Datenbank reparieren und komprimieren" ließ sich das Modul1 nicht mehr ausführen, es wird die Eingabe eines Makronamens für "db_imp1" verlangt.
So gibt es nun das "Makro1", in dem eine einzige Zeile "AusführenCode" mit dem Argument 'Transponieren ()' steht. Beim starten "Makro1" kommt wieder FM >>Laufzeitfehler '3078':...findet... " nicht...<< usw. siehe oben.
Ein weiteres Mal Ausführen von "Datenbank reparieren und komprimieren" einschl. MS-Access schließen und wieder öffnen brachte keine Besserung.
:-/
Wonach muß ich nun also suchen oder wo könnte das Dingens sich das "-Zeichen 'falsch gemerkt' haben?

J_Eilers
25.06.2004, 10:33
Wer lesen kann, ist klar im Vorteil ;)

Wenn du die Option Explicit unter das Compare Database verwenden würdest, hätte Access dich vielleicht auf den richtigen Weg gebracht.
Denn im Moment verwendest du undefinierte Variablen für die Grundlagen der Recordsets:

Set rsAlt = db.OpenRecordset("t_imp", dbOpenSnapshot)
Set rsNeu = db.OpenRecordset("Beispieldatensatz_Ergebnistabelle", dbOpenDynaset)

Strings gehören immer in Anführungszeichen. Variablen hingegen nicht.

jörgq
28.06.2004, 07:59
Hallo Jan,
danke für Deine Hinweise.
'Option Explicit' habe ich hinzugefügt (bitte, bei welcher Gelegenheit hätte ich diesen Hinweis lesen können oder müssen(?) - ich habe alles so dokumentiert, wie es mir passiert ist!!!).

Modul1 ist auf dem Abschlußstand wie folgt:

Option Compare Database
Option Explicit

Public Function Transponieren()

Dim rs As DAO.Recordset
Dim rsAlt As DAO.Recordset
Dim rsNeu As DAO.Recordset
Dim db As DAO.Database
Dim i As Integer

Set db = CurrentDb
Set rsAlt = db.OpenRecordset("Eingangstabelle", dbOpenSnapshot)
Set rsNeu = db.OpenRecordset("Ergebnistabelle", dbOpenDynaset)

With rsAlt
.MoveNext
While Not .EOF
If Not IsNull(!GName) Then
rsNeu.AddNew
i = 1
rsNeu!ID = !ID
Else
rsNeu.MoveLast
rsNeu.Edit
i = i + 1
End If
If Not IsNull(!GName) Then rsNeu!GName = !GName
If Not IsNull(!E1) Then rsNeu("E1_" & i) = !E1
If Not IsNull(!E2) Then rsNeu("E2_" & i) = !E2
If Not IsNull(!E3) Then rsNeu("E3_" & i) = !E3
If Not IsNull(!E4) Then rsNeu("E4_" & i) = !E4
rsNeu.Update
.MoveNext
Wend
End With

rsAlt.Close
rsNeu.Close
db.Close
Set rsAlt = Nothing
Set rsNeu = Nothing
Set db = Nothing

End Function 'Transponieren()

Ich bin sehr dankbar dafür,was ich durch Herrn J_Eilers' Hilfe in VBA-Programmierung dazulernen konnte und hoffe für ähnlich (unlösbare?) Aufgaben auf weitere gute Zusammenarbeit in diesem Forum.
Bis später denn...

+++

PS.:
Als ich die Lösung noch nicht hatte, hatte ich mir die Finger fast schon wieder wund geschrieben mit der Fehlerbeschreibung:
>>Es folgte zunächst FM "Laufzeitfehler '3265': Element in dieser Auflistung nicht gefunden."
Nach Click auf Schaltfläche "Debuggen" ...<<
2usw. usw. ...
...und wirkliche Fehlerursache war eine Eingangstabelle mit irgendeinem Zwischenbearbeitungsstand. Die Tabelle enthielt mit Leerzeichen gefüllte Felder; die dann auf Nullmarke geprüft wurden...

;-)

J_Eilers
28.06.2004, 08:06
Aus der Hilfe:

Option Explicit-Anweisung


Wird auf Modulebene verwendet, um die explizite Deklaration aller Variablen in diesem Modul zu erzwingen.

Syntax

Option Explicit

Bemerkungen

Wird die Option Explicit-Anweisung verwendet, so muß sie im jeweiligen Modul vor jeder Prozedur stehen.

Wenn Sie die Option Explicit-Anweisung in einem Modul verwenden, müssen alle Variablen explizit mit den Anweisungen Dim, Private, Public, ReDim oder Static deklariert werden. Wenn Sie einen nicht deklarierten Variablennamen verwenden, tritt zur Kompilierungszeit ein Fehler auf.

Wenn Sie die Option Explicit-Anweisung nicht verwenden, erhalten alle nichtdeklarierten Variablen den Typ Variant, solange mit einer DefTyp-Anweisung kein anderer Standardtyp festgelegt wird.

Anmerkung Mit Option Explicit vermeiden Sie falsch geschriebene Namen bereits bestehender Variablen oder Verwechslungen im Code bei unklarem Gültigkeitsbereich von Variablen.

Entweder von Hand dazuschreiben oder unter den VBA Optionen ein Häkchen bei Variablendeklaration erforderlich machen.

Wie kommt man drauf...hmm, also bei mir ist es eine Standerdeinstellung und die Fehlermeldung, die du bekommen hast, reicht nicht aus, damit man weiß, was gemeint ist. Hier zählt wohl leider die Aussage, entweder man weiß es oder nicht. :(

BTW Heiße ich Jan und hab nichts gegen das Du ;)

jörgq
28.06.2004, 08:37
Hallo Jan,
nochmals wiederhole ich, daß ich mich sehr darüber FREUE, in Zusammenarbeit mit Dir auf Basis dieses GUTEN Forums eine für mich so dringend benötigte Beispiellösung erarbeiten gekonnt zu haben.
(Der Satz "...Herrn J_Eilers' Hilfe..." war für ALLE gedacht, die hier ansonsten regelmäßig mitgelesen haben, und sollte eher eine nochmalige HERAUSHEBUNG Deiner Person bewirken - also KEINE Distanzierung oder sonst so was unverständliches!)
Ich verabschiede mich auch nicht für immer, denn das nächste (unlösbare) Problem kommt bestimmt - siehe "clipboard"-Funktion ...lauert schon in der Ecke - die ich GERN wieder mit DIR oder jemand anderem dieses Forums zu gegebener Zeit lösen möchte.
Als denn, bis später denn...