2012-04-26 24 views
5

Myślałem, że to będzie proste, ale okazuje się dość trudne. Wszelkie rady lub pomysły byłyby aprobowane.VBA Jak zmusić funkcję do powrotu po naciśnięciu przycisku formularza

Mam formularz w programie Excel, że po naciśnięciu określonego przycisku potrzebuję użytkownika, aby wprowadzić hasło przed uruchomieniem kodu dla tego przycisku.

mogę po prostu użyć inputbox, ale to pozwoli ktoś zobaczyć hasło, gdy jest on wpisany w. Więc chcę użyć drugiego formularza z pola tekstowego i ustaw jego PasswordChar parametr *

Tutaj to jest problem. Chcę użyć kodu jak ten

if checkPassword("Please enter your password") = False then exit sub 

checkPassword to funkcja, która pobiera ciąg jako parametr. Ta funkcja otwiera formularz i umieszcza wiadomość w etykietce. Użytkownik powinien wprowadzić hasło i kliknąć OK.

sub btnOK_Click() powinien sprawdzić, czy hasło jest poprawne, a następnie wymusić funkcję, która otworzyła formularz, aby powrócić True, jeśli hasło było w porządku lub False, jeśli hasło było nieprawidłowe.

Po prostu nie mogę wymyślić, jak wymusić powrót funkcji. Próbowałem ustawić zmienną globalną na wartość True lub False, gdy użytkownik kliknie przycisk OK, a następnie wyładuje formularz. Powoduje to, że funkcja zwraca, ale także resetuje wszystkie zmienne globalne ustawione przez formularz.

Oto moja funkcja, która zwraca postaci

Function checkPassword(message As String) As Boolean 

    frmPassword.Show 
    frmPassword.passwordMsg.Caption = message 

    'passwordStatus is a global variable 
    If passwordStatus = True Then checkPassword = True Else checkPassword = False 

End Function 

Oto sub umieszczonego przycisku OK formach:

Private Sub passwordok_Click() 

    If Me.passwordtext.Text = "password" Then 
     passwordStatus = True 
    Else 
     passwordStatus = False 
    End If 
    Unload Me 

End Sub 

Odpowiedz

3

Zwracanie wartości z okna jest wspólnym zadaniem & dość proste do zrobienia.

Najprostszy wzór polega na umieszczeniu funkcji w formularzu dialogowym, a funkcja ta wyświetla modalnie jego host.

Private passwordStatus As Boolean 

Function checkPassword(message As String) As Boolean 
    '//setup the form 
    Me.passwordMsg.Caption = message 

    '//show the form modally, this will not return until the form is unloaded 
    '//i.e. when the button is clicked; so values in private variable are still valid 
    Me.Show vbModal 

    '//form is unloaded (via unload me or a close) return the value; 
    checkPassword = passwordStatus 
End Function 

Private Sub passwordok_Click() 
    passwordStatus = Me.passwordtext.Text = "password" 
    Unload Me 
End Sub 

Używany jako

passworkOk = frmPassword.checkPassword("enter your blabla") 
+0

Cześć Alex, dzięki za to rozwiązanie. Próbowałem rozwiązania od Siddhartha i działało dobrze (Wielkie dzięki dla Siddhartha ponownie), ale twoje rozwiązanie jest bliższe temu, co pierwotnie chciałem zrobić. Wypróbowałem to i działa świetnie, znacznie prostsze i mniej obciążające. Dzięki – PrestonDocks

+0

użyłem tego, działa on niesamowicie, z wyjątkiem tego, że musiałem umieścić 'passwordStatus = Me.passwordtext.Text =" password "' po "wyładuj mnie", ponieważ rozładowanie resetuje tę zmienną, czy spowoduje to problemy? – user1759942

5

mogę po prostu użyć inputbox, ale to pozwoli każdemu zobaczyć hasło, gdy zostanie wpisane. Dlatego chcę użyć drugiego formularza z polem tekstowym i ustawić jego parametr PasswordChar na *

Oto coś z mojej bazy danych.

ZASTRZEŻENIE: nie miałem napisać to i ja nie pamiętam, kto napisał ten

WYKORZYSTANIA:

Private Sub passwordok_Click() 
    Dim Prompt, password As String 
    Prompt = "Please enter your password." 
    password = InputBoxDK(Prompt) 

    MsgBox password '<~~ Do whatever you want to do with this 
End Sub 

w module

Option Explicit 

Private Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, _ 
ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long 

Private Declare Function GetModuleHandle Lib "kernel32" Alias _ 
"GetModuleHandleA" (ByVal lpModuleName As String) As Long 

Private Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" _ 
(ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, _ 
ByVal dwThreadId As Long) As Long 

Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Long) As Long 

Private Declare Function SendDlgItemMessage Lib "user32" Alias "SendDlgItemMessageA" _ 
(ByVal hDlg As Long, ByVal nIDDlgItem As Long, ByVal wMsg As Long, _ 
ByVal wParam As Long, ByVal lParam As Long) As Long 

Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" _ 
(ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long 

Private Declare Function GetCurrentThreadId Lib "kernel32"() As Long 

'Constants to be used in our API functions 
Private Const EM_SETPASSWORDCHAR = &HCC 
Private Const WH_CBT = 5 
Private Const HCBT_ACTIVATE = 5 
Private Const HC_ACTION = 0 

Private hHook As Long 

Public Function NewProc(ByVal lngCode As Long, ByVal wParam As Long, _ 
ByVal lParam As Long) As Long 
    Dim RetVal 
    Dim strClassName As String, lngBuffer As Long 

    If lngCode < HC_ACTION Then 
     NewProc = CallNextHookEx(hHook, lngCode, wParam, lParam) 
     Exit Function 
    End If 

    strClassName = String$(256, " ") 
    lngBuffer = 255 

    'A window has been activated 
    If lngCode = HCBT_ACTIVATE Then 
     RetVal = GetClassName(wParam, strClassName, lngBuffer) 
     'Class name of the Inputbox 
     If Left$(strClassName, RetVal) = "#32770" Then 
      'This changes the edit control so that it display the password character *. 
      'You can change the Asc("*") as you please. 
      SendDlgItemMessage wParam, &H1324, EM_SETPASSWORDCHAR, Asc("*"), &H0 
     End If 
    End If 

    'This line will ensure that any other hooks that may be in place are 
    'called correctly. 
    CallNextHookEx hHook, lngCode, wParam, lParam 

End Function 

Public Function InputBoxDK(Prompt, Optional Title, Optional Default, Optional XPos, _ 
Optional YPos, Optional HelpFile, Optional Context) As String 
    Dim lngModHwnd As Long, lngThreadID As Long 
    lngThreadID = GetCurrentThreadId 
    lngModHwnd = GetModuleHandle(vbNullString) 
    hHook = SetWindowsHookEx(WH_CBT, AddressOf NewProc, lngModHwnd, lngThreadID) 
    InputBoxDK = InputBox(Prompt, Title, Default, XPos, YPos, HelpFile, Context) 
    UnhookWindowsHookEx hHook 
End Function 

SNAPSHOT

enter image description here

+0

Dziękujemy za udostępnienie kodu. Wszystko działało dobrze. – PrestonDocks

+0

Nie ma za co. Naprawdę chciałbym móc podać link do oryginalnego autora zamiast wklejać powyższy kod. Jeśli kiedykolwiek znajdę, wrócę i edytuję ten wpis. :) –

Powiązane problemy