Liebes Forum,
ich habe ein komisches Phänomen:
In meiner Datenbank will ich in einem Textfeld festhalten, welcher Nutzer eine Änderung an einem Datensatz in einem Formular gemacht hat.
Dazu lese ich über Environ("Username") den Windowsbenutzernamen aus.
Da die Benutzernamen bei uns kryptische Zeichen sind habe ich in einer Tabelle zu den Benutzernamen noch die Klarnamen gespeichert.
In einer Funktion fncUserName verkette ich dann den Benutzername mit dem Klarnamen, den ich per SQL-String aus der Tabelle auslese.
Diese Funktion fncUserName rufe ich beim Ereignis Form_BeforeUpdate des Formulars auf
Das funktioniert, wenn ich die beiden Elemente ohne weiteres Textelemente verkette:
---------------------
Dim rsKlarname As Recordset
Dim strSQLstring As String
Dim strUserKlarname As String
strSQLstring = "SELECT nutzer FROM Nutzer WHERE idm = '" & Environ("username") & "';"
Set rsKlarname = db.OpenRecordset(strSQLstring, dbOpenDynaset)
strUserKlarname = rsKlarname(0) & Environ("Username")
Debug.Print strUserKlarname
fncUserName = strUserKlarname
----------------------
schreibt ganz richtig in Direktfenster und Textfeld
Großmannir35urir
Das ist aber ein bisschen doof lesbar, weswegen ich gerne ein kleines Textelement einfügen würde, z.B.
---------------------
(....)
strUserKlarname = rsKlarname(0) & " - " & Environ("Username")
Debug.Print strUserKlarname
fncUserName = strUserKlarname
----------------------
Dann schreibt er noch richtig
Großmann - ir35urir
in das Direktfenster. In das Textfeld aber schreibt er einfach gar nichts.
Kann das jemand erklären?
Viele Grüße
Jürgen
Hallo Namensvetter,
zeige den Code, der die Zuweisung erledigen soll. Im gezeigten Schnipsel werden nur Variablen befüllt. Code bitte immer in Tags packen, ist dann besser zu lesen.
Ausserdem macht
fncUserName = strUserKlarname
aus meiner Sicht keinen Sinn.
Hallo Namensvetter,
danke für die schnelle Antwort. Das Feld wird so befüllt:
F!Aenderung_Nutzer = fncUserName()
War das gemeint?
Vielen Dank und viele Grüße
Jürgen
ja, das war gemeint ... wenn der Code im offenen Form gestartet wird, schreib mal
Me!Aenderung_Nutzer = fncUserName()
von anderswo gestartet
Forms!Formname!Aenderung_Nutzer = fncUserName()
Hallo,
mhmm, m. E. sollte das so heißen
Function fncUserName() as String
Dim rsKlarname As Dao.Recordset
Dim strSQLstring As String
Dim strUserKlarname As String
Dim strUsername As String
strUsername = Environ("username")
strSQLstring = "SELECT nutzer FROM Nutzer WHERE idm = '" & strUsername & "'"
Set rsKlarname = Currentdb.OpenRecordset(strSQLstring, dbOpenSnapshot)
fncUserName = rsKlarname(0) & " - " & strUsername
End Function
und
Sub Form_BeforeUpdate(Cancel as Integer)
Me!Aenderung_Nutzer = fncUserName()
End Sub
oder kürzer:
:Function fncUserName() as String
Dim strUsername as String
strUsername = Environ("username")
fncUserName = Currentdb.OpenRecordset("SELECT nutzer FROM Nutzer WHERE idm = '" & strUsername & "'", dbOpenSnapshot) (0) & " - " & strUsername
End Function
Und: Bitte IMMER die vollständigen Prozeduren posten...
... und weil sich der Benutzername während einer Sitzung nicht ändert, könnte man die Auswertung in eine statische Variablen schreiben.Option Explicit
Public Enum UserNamePart
unpLoginPart
unpPlainText
unpCombined
End Enum
Public Function GetUserName(Optional ByVal NamePart As UserNamePart _
= unpCombined) As String
Static LoginName As String, PlainName As String
Const USR_QRY As String = _
"SELECT nutzer FROM Nutzer WHERE idm = [@idm];"
If Len(LoginName) = 0 Then
LoginName = Environ$("USERNAME")
On Error Resume Next 'man weiß ja nie
With CurrentDb.CreateQueryDef(vbNullString, USR_QRY)
.Parameters("@idm") = LoginName
PlainName = .OpenRecordset()(0)
End With
End If
Select Case NamePart
Case unpPlainText: GetUserName = PlainName
Case unpCombined: GetUserName = PlainName & " - " & LoginName
Case Else: GetUserName = LoginName
End Select
End Function
Vielen Dank für die vielen und schnellen Antworten!
@Jürgen: veränderter Aufruf hat leider nichts gebracht
@DF6GL: das Environ("Username") vorher als String zu deklariern hatte ich schon probiert. Die ganze Funktion als String war eine neue Idee, hat aber leider nicht funktioniert :-(
@Lachtaube: die Konstantendeklaration ist ein neuer Ansatz. Der Code übersteigt meine bescheidenen VBA-Kenntnisse, aber vielleicht probiere ich es mal.
Noch mal vielen Dank und Grüße aus Franken
Jürgen
Hallo,
funktioniert denn überhaupt mein Vorschlag?
Mit
Zitat...hat aber leider nicht funktioniert...
kann man nichts anfangen.. :(
allmächt - a Frangee ...
Moin Jürgen,
wenn du Hilfe erwartest, solltest du endlich den vollständigen Code posten ...
Hallo Jürgen,
Was ist denn ein "Frangee" ?
Bin zu jung oder zu alt um das zu kennen?
gruss ekkehard
;) ;) ;) 8)
--->
Zitatund Grüße aus Franken
Vorsicht Jürgen, ich bin auch a Frangee ;D ;D ;D
(aber nur während meiner ersten 3 Jahre..)
@ Franz
ich war wenigstens mal ne Weile in Franken zur Ausbildung ... und wohne in Franken (thal) ;)
Alles klar, - die Italiener. ;)
Hallo an alle Franken (und sonstige :-)),
Wenn das relevante Formular geändert wird erfolgt über ein Klassenmodul:
Private Sub Form_BeforeUpdate(Cancel As Integer)
On Error Resume Next
If IsNull(Nachname) And IsNull(Organisation) Then
MsgBox "Die Felder 'Nachname' und 'Organisation' dürfen nicht beide leer sein!" & Chr$(13) & Chr$(10) & "(Rückgängig mit Esc)", 16
Cancel = True
Else
void = Touch()
End If
End Sub
Die Funktion Touch() steht in einem allgemeinen Modul
Function Touch()
On Error Resume Next
Dim F As Form
Set F = Screen.ActiveForm
If IsNull(F!Eingabe_Nutzer) Then
F!Eingabe = Now
F!Eingabe_Nutzer = fncUserName()
Else
F!Aenderung = Now
F!Aenderung_Nutzer = fncUserName()
End If
End Function
Die fncUserName() steht im gleichen allgemeinen Modul:
Public Function fncUserName() As String
Dim db As DAO.Database
Dim rsKlarname As Recordset
Dim strSQLstring As String
Dim strUserKlarname As String
Set db = CurrentDb
strSQLstring = "SELECT nutzer FROM Nutzer WHERE idm = '" & Environ("username") & "';"
Set rsKlarname = db.OpenRecordset(strSQLstring, dbOpenDynaset)
strUserKlarname = rsKlarname(0) & " - " & Environ("Username")
Debug.Print strUserKlarname
fncUserName = strUserKlarname
End Function
Die Ausgabe im Direktfenster stimmt; nur in das Textfeld schreibt er einfach gar nichts.
Viele Grüße
Jürgen
also bei mir wird ein Eintrag geschrieben. Lass dir mal mit debug.print f.name innerhalb touch den Namen des Forms ausgeben.
Dann würde ich mal in Touch() die Fehlerbehandlung auskommentieren, einen Haltepunkt setzen und verfolgen, was während des Ablaufs passiert.
Der Name des Formulars stimmt.
Wenn ich
strUserKlarname = rsKlarname(0) '& " - " & Environ("Username")
auskommentiere gehts. Sonst wieder nicht.
Ich habe auch spaßhalber mal den Text nach hinten gestellt. Auch hier geht nur die auskommentierte Variante
strUserKlarname = rsKlarname(0) & Environ("Username") '& " - "
Ein
strUserKlarname = rsKlarname(0) & " - "
funktioniert auch.
Wenn es bei Dir geht, dann liegt es vielleicht aber nicht am Code, sondern an einem Verweis. Hat jemand eine Idee?
Gruß
Jürgen
ersetz als erstes mal die aufgeblasene Funktion durch
Public Function fncUserName()
fncUserName = DLookup("nutzer", "Nutzer", "idm='" & Environ("username") & "'") & " - " & Environ("Username")
End Function
der Einzeiler liefert das gewünschte Ergebnis. btw ein Feld gleich der Tabelle zu benennen ist unschön ...
Wenn du das eingebaut und getestet hast, gehts weiter ...
Seltsame. Environ gehört zwar zu den Sandbox-Funktionen, die der Ausdruck-Dienst von Access ablehnt - dass das auch in VBA so ist, wäre mir neu. Mit welcher Access-Version bist Du denn unterwegs?
Ansonsten kannst Du es ja mal mit der API-Version versuchen.Private Declare Function GetEnvironmentVariableW Lib "kernel32" ( _
ByVal lpName As LongPtr, _
ByVal lpBuffer As LongPtr, _
ByVal nSize As Long) As Long
Public Function GetEnvironmentVariable(ByRef EnvVar As String) As String
Dim rVal As Long, buf As String
rVal = GetEnvironmentVariableW(StrPtr(EnvVar), 0, 0)
If rVal > 0 Then
buf = String$(rVal, vbNullChar)
rVal = GetEnvironmentVariableW(StrPtr(EnvVar), StrPtr(buf), rVal)
If rVal > 0 Then
GetEnvironmentVariable = Left$(buf, rVal)
Else
MsgBox "DLL call error: " & Err.LastDllError
End If
End If
End Function
[edit]Da habe ich wohl nicht richtig mitgelesen. Schau mal, ob die Autokorrektur im Steuerelement aktiv ist.[/edit]
Hallo,
und weiter oben (unten) hatte ich das Gleiche (den Einzeiler) in Grün vorgeschlagen.... ::)
Die Accessversion ist 2010.
@DFGL und el_gomero: Einzeiler funktioniert. Danke und sorry, dass ich den vorherigen übersehen habe. Das Problem tritt aber weiter auf.
@Lachtaube: danke für den Code, aber ich habe API noch nie benutzt und traue mich so spontan nicht ran.
Ich habe kurzzeitig überlegt, ob vielleicht die " in Environ("Username") stören, aber ein Versuch mit Right(Environ(40), 8)
hat nichts gebracht :-(.
Auch
Environ$("username")
war ohne Ergebnis :-(
Viele Grüße
Jürgen
ok, wenn der Einzeiler bei dir funktioniert, gehen wir zum nächsten Schritt ...
...
void(strForm) = Touch()
...
was ist void? Ein Textfeld auf dem Form, für das der Bezug Me! weggelassen wurde? Wieso soll dem etwas zugewiesen werden? Touch gibt jedenfalls nichts zurück ...
Da erwischt Du mich auf dem falschen Fuß. Ich nutze eine Datenbank, deren Basis vor langer Zeit entwickelt wurde und der Entwickler damals hat in dem allgemeine Modul die void als
Global void As Variant
ohne Erläuterung definiert. Das void taucht immer mal wieder auf und ich verstehe den Sinn nicht ganz Ich muss aber dazu sagen, dass der als Informatiker richtig Ahnung davon hatte und sehr gut war - im Gegensatz zu mir...
Ich habe das Touch mal umgangen und rufe die fncUserName direkt im Klassenmodul auf.
Private Sub Form_BeforeUpdate(Cancel As Integer)
On Error Resume Next
If IsNull(Nachname) And IsNull(Organisation) Then
MsgBox "Die Felder 'Nachname' und 'Organisation' dürfen nicht beide leer sein!" & Chr$(13) & Chr$(10) & "(Rückgängig mit Esc)", 16
Cancel = True
Else
Me!Aenderung_Nutzer = fncUserName()
'void = Touch()
End If
End Sub
Das Problem bleibt leider :-(
gibt es im aktiven Formular denn ein Feld namens Aenderung_Nutzer? Wenn ja was passiert, wenn du aus dem Direktfenster
Forms!DeinForm!Aenderung_Nutzer = fncUserName()
oder
Forms!DeinForm!Aenderung_Nutzer = "Hallo Jürgen"
eingibst?
Nachtrag: wenn man mit 10 Zeilen programmiert, was mit 1 Zeile erledigt werden kann, mag das Gründe haben und sieht auf jeden Fall imposant aus, aber ...
Hallo,
es wäre sinnvoll, anstatt im Nebel zu stochern, die DB (repariert/komprimiert, evtl. datenreduziert und gezippt) hier hochzuladen...
statt datenreduziert:
Neue leere DB erstellen und alle diesbezüglich relevanten Objekte dort importieren. (Tabelle, Formular, evtl. Abfrage und Code) und die hier hochladen.
:) :) :) :) :) :)
und
:-X :-X :-X :-X :-X
Das ist jetzt etwas bis zimelich sehr peinlich, dass ich da nicht eher drauf gekommen bin. Die direkte Befüllung im Direktfenster hat jetzt eine Fehlermeldung produziert, die vorher nie gezeigt wurde. Das Feld Aenderung_Nutzer war schlicht zu klein und der Text hat nicht reingepasst. Nach Erhöhung der Feldgröße ging es.
Tausend Dank an alle, die sich so viel Mühe gegeben haben!
Gruß
Jürgen
Zitat
...
Die direkte Befüllung im Direktfenster hat jetzt eine Fehlermeldung produziert, die vorher nie gezeigt wurde.
...
Das hat man von dem OnError Resume Next ... so viel zum Thema "Ahnung und sehr gut" ...
Egal, schön, dass es läuft.