Access-o-Mania

Access-Forum (Deutsch/German) => Access Programmierung => Thema gestartet von: Markus Beck am Februar 10, 2022, 13:37:43

Titel: in access vba nach "uniqueidentifier" filtern
Beitrag von: Markus Beck am Februar 10, 2022, 13:37:43
Hallo Leute
Ich hänge mal wieder ganz schön durch und verstehe im wahrsten Sinne des Wortes nur noch Chinesisch.

Ich habe eine SQL Datenbank mit einer
Abfrage:    [dbo_View_CRM_AccountBase]  und einem
ID-Feld:    [AccountId] vom Typ "uniqueidentifier"

Ich habe die Tabelle mit Access verlinkt via ODBC (Driver17)
Über ein Formular, basierend auf meiner "Grundtabelle", greife ich mittels Combo Box auf die Tabelle zu und wähle einen Datensatz aus.
Dadurch wird der Wert der [AccountId] in meine "Grundtabelle" geschrieben.
Jetzt möchte ich über ein Recordset die Tabelle [dbo_View_CRM_AccountBase] nach dem ermittelten Wert filtern und weitere Informationen dieses Datensatzes abgreifen und in weitere Felder meiner   "Grundtabelle" schreiben.

Was bisher geht...
1.)   Das Referenzfeld gibt den Wert der [AccountId] richtig aus.
Wert = {B98A33FF-7930-E711-80E6-005056BF1656}
2.)   Der Zugriff mittels Recordset funktioniert
3.)   Die Umwandlung von [AccountId] in einen String klappt (denke ich jedenfalls)
            (mittels StringFromGUID realisiert)
            Rückgabewert nach .MoveFirst = {guid {15ED9045-315C-EA11-911D-000C2942B5AF}} , stimmt

Was geht (noch) nicht...
1.)   Ich kann nicht filtern auf Set rst
        Dabei weiss ich nicht ob es daran liegt, dass ich den Filter falsch definiere oder ob ich (was ich vermute) nicht mit dem String filtern kann
        sondern den String mittels GUIDFromString zuerst umwandeln und diesen Ausdruck dann für den Filter verwenden muss.
        Habe beides erfolglos versucht.

2.)   Bei GUIDFromString scheitere ich dann ganz.
        Zwar läuft der code fehlerfrei durch. Wenn ich aber (da debug.print nur ????? ausgibt) das Resultat in ein Textfeld kopiere, erhalte ich
        chinesische Zeichen... (Siehe Anhang)
        Ich habe zwar Felder mit chinesischen Zeichen, doch diese Kombination finde ich in der ganzen Datenbank nirgends.

Ich bin dankbar um jede Hilfestellung!

Grüsse aus China
Markus

Mein Code:
=======

Private Sub Command493_Click()
   
    Dim rst As Recordset
   
    strGUID_CRM_AccountId    '= Public Function                        'Habe ich beim Versuch verwendet, Set rst als WHERE -Filter zu verwenden
    Debug.Print "strGUID_CRM_AccountId = "; strGUID_CRM_AccountId
   
    GUID_CRM_AccountId    '= Public Function
    Debug.Print "GUID_CRM_AccountId = "; GUID_CRM_AccountId


 '   Set rst = CurrentDb.OpenRecordset("SELECT * FROM dbo_View_CRM_AccountBase", dbOpenDynaset, dbSeeChanges)   'Fall 1: Dies ist OK, ohne Filter
    Set rst = CurrentDb.OpenRecordset("SELECT * FROM dbo_View_CRM_AccountBase WHERE SQH_CRM_AccountId_Ref = GUID_CRM_AccountId", dbOpenDynaset, dbSeeChanges)   'Da hänge ich
    With rst    'Definition wo Daten gelesen werden sollen

        .MoveFirst      'in den ersten Datensatz springen
            'SQH_CompanyNameEN = rst.Fields("Name")                     'Funktioniert im Fall 1: ohne Filter, halt basierend auf den ersten Datensatz
            'SQH_CompanyNameCN = rst.Fields("eno_accountname_cn")       'Funktioniert im Fall 1: ohne Filter, halt basierend auf den ersten Datensatz

    End With

End Sub

------------------------------------------------------------------------------

Public Function strGUID_CRM_AccountId() As String

    Dim ctl As Control
    Dim strGUID As String
   
    ' Get the GUID.
    Set ctl = Forms!frm_RecordServiceQuotationHeaders!SQH_CRM_AccountId_Ref
        'Debug.Print TypeName(ctl.Value)
   
    ' Convert the GUID to a string.
    strGUID = StringFromGUID(ctl.Value)
        'Debug.Print TypeName(strGUID)
   
    strGUID_CRM_AccountId = strGUID
       'Debug.Print GUID_CRM_AccountId
 
 End Function

-------------------------------------------------------------------------------

Public Function GUID_CRM_AccountId()
 
 
    GUID_CRM_AccountId = GUIDFromString(strGUID_CRM_AccountId)      'Sollte den String wieder in GUID umwandeln
    'Debug.Print "GUID_CRM_AccountId = "; GUID_CRM_AccountId
 
End Function

---------------------------------------------------------------------------------

Private Sub Command567_Click()
    Debug.Print "strGUID_CRM_AccountId = "; strGUID_CRM_AccountId   'Holt den String aus der Public Function
    GUIDFromString (strGUID_CRM_AccountId)                          'Sollte den String wieder in GUID umwandeln
    Text568 = GUIDFromString(strGUID_CRM_AccountId)                 'Schreibt GUID in textfeld, da debug-print nur ???????? liefert
    Debug.Print Text568                                             'Überraschung! Es sind chinesische Zeichen

End Sub



Titel: Re: in access vba nach "uniqueidentifier" filtern
Beitrag von: Beaker s.a. am Februar 10, 2022, 17:26:43
Vermutlich fehlen da nur die "'" zum Stringvergleich
ZitatSet rst = CurrentDb.OpenRecordset("SELECT * FROM dbo_View_CRM_AccountBase WHERE SQH_CRM_AccountId_Ref = '" & GUID_CRM_AccountId & "'",
Titel: Re: in access vba nach "uniqueidentifier" filtern
Beitrag von: Markus Beck am Februar 11, 2022, 01:41:42
Vielen Dank Beaker für die schnelle Antwort.
Dies Konstellation hatte ich auch schon. Die führt aber zur Fehlermeldung...

   Run-time error '3061':
   Too few parameters. Expected 1.

... in dieser Zeile.

-------------------------------------------------

Auch diesen Ansatz habe ich schon versucht...
    Set rst = CurrentDb.OpenRecordset("SELECT * FROM dbo_View_CRM_AccountBase WHERE SQH_CRM_AccountId_Ref =" & GUID_CRM_AccountId, dbOpenDynaset, dbSeeChanges)

... aber der führt zur gleichen Fehlermeldung, jedoch mit Expected 2 statt 1:

Run-time error '3061':
Too few parameters. Expected 2.



GUIDFromString() gibt ja eine Resultat vom Typ Variant zurück.
Ich habe nichts dazu gefunden wie man Variant filtert.

Grüsse Markus

Titel: Re: in access vba nach "uniqueidentifier" filtern
Beitrag von: ebs17 am Februar 11, 2022, 10:26:54
Zitatwie man Variant filtert
Gar nicht. Variant kann alles sein. SQL erwartet aber recht stur konkrete Datentypen, stimmig mit dem Datentyp des zu filternden Feldes.

Wenn GUID_CRM_AccountId eine Funktion ist, musst Du das dem SQL-Interpreter auch klarmachen (Klammern!). Funktionen kann der SQL-Interpreter von Jet auswerten, Variablen nicht.
sSQL = "SELECT * FROM dbo_View_CRM_AccountBase WHERE SQH_CRM_AccountId_Ref = GUID_CRM_AccountId()"Wenn die Funktion keine Argumente von "außen" benötigt, kann man sie direkt in den SQL-String hineinnehmen. Anderenfalls muss man sie herausnehmen und für die Einbindung datentypgerecht formatieren, etwa
sSQL = "SELECT * FROM dbo_View_CRM_AccountBase WHERE SQH_CRM_AccountId_Ref = '" & GUID_CRM_AccountId(Argument) & "'"
Titel: Re: in access vba nach "uniqueidentifier" filtern
Beitrag von: PhilS am Februar 11, 2022, 10:47:56
Zitat von: ebs17 am Februar 11, 2022, 10:26:54[...] die Einbindung datentypgerecht formatieren [...]
Ich habe ja keine Ahnung, aber sollte die datentypgerechte Formatierung für eine GUID im Ergebnis dann nicht eher so aussehen:

sSQL = "SELECT * FROM dbo_View_CRM_AccountBase WHERE SQH_CRM_AccountId_Ref = {guid {12341234-1234-1234-1234-123412341234}}"
?
Titel: Re: in access vba nach "uniqueidentifier" filtern
Beitrag von: PhilS am Februar 11, 2022, 11:02:30
Zitat von: Markus Beck am Februar 10, 2022, 13:37:43Text568 = GUIDFromString(strGUID_CRM_AccountId)                 'Schreibt GUID in textfeld, da debug-print nur (https://www.access-o-mania.de/forum/Smileys/fugue/huh.png)(https://www.access-o-mania.de/forum/Smileys/fugue/huh.png)?? liefert
    Debug.Print Text568                                             'Überraschung! Es sind chinesische Zeichen
War das mit der Überraschung ironisch gemeint?

Wenn nein, wie würdest du dir die Darstellung des Byte-Arrays, das GUIDFromString (https://docs.microsoft.com/en-us/office/vba/api/access.application.guidfromstring?f1url=%3FappId%3DDev11IDEF1%26l%3Den-US%26k%3Dk(vbaac10.chm12558);k(TargetFrameworkMoniker-Office.Version%3Dv16)%26rd%3Dtrue) liefert, vorstellen?
Aus meiner, hier eher ahnungslosen, Sicht erscheint mir die unmittelbare Darstellung eines Byte-Arrays als Text weder sinnvoll noch zielführend. Für eine "freundlichere" Darstellung gibt es ja explizit das Pendant StringFromGUID (https://docs.microsoft.com/en-us/office/vba/api/access.application.stringfromguid?f1url=%3FappId%3DDev11IDEF1%26l%3Den-US%26k%3Dk(vbaac10.chm12557);k(TargetFrameworkMoniker-Office.Version%3Dv16)%26rd%3Dtrue).
Titel: Re: in access vba nach "uniqueidentifier" filtern
Beitrag von: ebs17 am Februar 11, 2022, 11:48:41
Ich habe auch keine praktischen Erfahrungen bei Verwendung von GUIDs. Mit der Abfrage unter Verwendung eines konstanten Inhalts kann man aber für sich testen, wie es sein soll, um dann im zweiten Schritt die Einbindung vorzunehmen.

SQL-Datentypen (https://docs.microsoft.com/de-de/office/client-developer/access/desktop-database-reference/sql-data-types)
Ah, es gibt einen eigenen Datentyp. Den müsste man dann üben, vermutlich auch in Abhängigkeit vom jeweils verwendeten SQL-Dialekt.
Aber VBA kennt GUID als Datentyp nicht, da müsste man doch Variant für eine Funktion einsetzen, im SQL-String dann passend verarbeiten.
Titel: Re: in access vba nach "uniqueidentifier" filtern
Beitrag von: Markus Beck am Februar 11, 2022, 12:50:18
Hallo Eberhard und Phil
Vielen Dank für Eure Unterstützung. Ehrlich gesagt, ich würde lügen wenn ich sage ich habe es jetzt verstanden...
Aber ich sehe die Ansätze wo ich suchen und mich weiter vertiefen kann.

Versuche das morgen mal zu integrieren und komme mit meinen Erkenntnissen zurück.
Wünsche Euch ein schönes Wochenende! 


@phil: Nein, war nicht ironisch. Mit chinesisch meine ich auch nicht eine Kombination von Buchstaben und Zahlen oder so, sondern wirkliche chinesische
           Buchstaben.   㫸䌭纀튀倀뽖嘖 (heisst übersetzt soviel wie: "The water is divided into two parts")
            Was ich erwartet habe? Keine Ahnung, aber nicht das. Das war nur ein Versuch weil ja debug.print lediglich mehrere ? ausgibt.
            Für mich war das der Beweis, dass meine Funktion "erfolgreich" war.  Naja, zumindest dass sie etwas macht :-)
Titel: Re: in access vba nach "uniqueidentifier" filtern
Beitrag von: Markus Beck am Februar 12, 2022, 04:12:42
Guten Morgen zusammen!
Dank Eurer Hilfe ist mir der Durchbruch gelungen. VIELEN HERZLICHEN DANK !!!

Mein Irrtum war folgender:
------------------------------
Anhand der Beschreibung im Netz über den Umgang mit SQL-Datentyp "uniqueidentifier" habe ich verstanden, dass man nicht einen String als Filter verwenden darf, sondern eine Umwandlung daraus via GUIDFromString().
Um den String zu erhalten habe ich den angezeigten Feld-Wert mittels StringFromGUID() umgewandelt, was auch das richtige Resultat ergibt:
nämlich..... aus dem Feldwert  {15ED9045-315C-EA11-911D-000C2942B5AF} wird der String-Wert  {guid {15ED9045-315C-EA11-911D-000C2942B5AF}}

Danach habe ich den String via GUIDFromString() umgewandelt -->  {guid {15ED9045-315C-EA11-911D-000C2942B5AF}}  zu ?(acht Fragezeichen) oder eben den resultierenden chinesischen Schriftzeichen und diese Funktion in den Filter eingesetzt. FALSCH!


Die Erkenntnis:
----------------
Nachdem ich Zugriff auf die SQL Tabelle hatte habe ich den Feldwert Debug.Print rst.Fields("AccountId") anzeigen lassen. Dieser entspricht zu meinem Erstaunen bereits dem String-Wert {guid {15ED9045-315C-EA11-911D-000C2942B5AF}} und nicht etwa wie erwartet dem Feldinhalt der SQL-Tabelle.

Somit lag Phil absolut richtig! Leider (mein Fehler) war das Feld WHERE "SQH_CRM_AccountId_Ref" auf meinem Formular und nicht in der SQL-Tabelle.
Die richtige Feldbezeichnung in SQL lautet "AccountId" und dann funktioniert es auch einwandfrei.


Die Lösung:
-------------
Also habe ich nun versucht das Resultat aus meiner Funktion strGUID_CRM_AccountId (welche  StringFromGUID() beinhaltet), in den Filter einzusetzen und siehe da,- es funktioniert!


Und hier der Vollständigkeit halber noch der Code der läuft:

--------------------------------------------------------------

Private Sub TEST_Click()


    Dim rst As Recordset
    Dim sSQL As String
   
    sSQL = "SELECT * FROM dbo_View_CRM_AccountBase WHERE AccountId =" & strGUID_CRM_AccountId          'PERFECT!!!
    Set rst = CurrentDb.OpenRecordset(sSQL, dbOpenDynaset, dbSeeChanges)
       
    With rst

        .MoveFirst
                Debug.Print rst.Fields("Name")
                Debug.Print rst.Fields("WebSiteURL")
                Debug.Print rst.Fields("AccountId")

    End With

End Sub

----------------------------------------------------------------

Public Function strGUID_CRM_AccountId() As String

    Dim ctl As Control
    Dim strGUID As String
   
    ' Get the GUID.
    Set ctl = Forms!frm_RecordServiceQuotationHeaders!SQH_CRM_AccountId_Ref
        Debug.Print TypeName(ctl.Value)
   
    ' Convert the GUID to a string.
    strGUID = StringFromGUID(ctl.Value)
        Debug.Print TypeName(strGUID)

    strGUID_CRM_AccountId = strGUID
       'Debug.Print GUID_CRM_AccountId
 
 End Function

---------------------------------------------------------------------------------

Byte()
String
Test Company Ltd.
https://www.test.cn
{guid {BA2DB704-ECAB-EA11-9123-000C2942B5AF}}