英文:
Excel VBA, MsgBox Yes or No, but must be "Si" or "No"
问题
我有一个相当简单的问题,我认为应该有一种更简单的方法来做这件事,但我还没有找到我想要的答案。
相当简单,
我有一个带有+vbYesNo
的消息框,
但我的最终用户是西班牙语使用者,所以除了"Yes"或"No"消息框按钮之外,所有陈述都是西班牙语。
有没有一种快速的方法可以将这两个按钮都更改为西班牙语?至少将"Yes"更改为"Si"。
我进行了一些研究,似乎唯一的方法是将整个消息框创建为用户窗体,并添加具有自定义标签的命令按钮。
有没有一种方法可以通过宏更改此特定的Excel文件的语言(.xlsm),以供最终用户使用?
此外,最终用户和我都将默认的Office语言设置为英语,更改它不是一个选项。
你有什么建议?
英文:
I have a fairly easy question that I think there should be an easier way to do it, but I haven't been able to find the answer that I want.
Pretty simple,
I have a MsgBox with +vbYesNo
,
But my end user is a Spanish speaker, so all the statements are in Spanish, except for the "Yes" or "No" message box buttons.
Is there a quick way to change both buttoms to spanish?, well at least the "Yes" by "Si".
I did some research, and seems that the only way is to create the whole msgbox as a userform and add Commandbuttons with custom labels.
Is there a way to change the language of this specific excel file with macros (.xlsm) just for use by the end user?
Also, the end user and I have the default Office language set to English, and changing it is not an option.
What do you recommend?
答案1
得分: 4
以下是代码的翻译部分:
您可以钩入消息框并更改按钮文本。对于64位系统,您的WINAPI将如下:
Option Explicit
Private Const MB_YESNOCANCEL = &H3&
Private Const MB_YESNO = &H4&
Private Const MB_RETRYCANCEL = &H5&
Private Const MB_OKCANCEL = &H1&
Private Const MB_OK = &H0&
Private Const MB_ABORTRETRYIGNORE = &H2&
Private Const MB_ICONEXCLAMATION = &H30&
Private Const MB_ICONQUESTION = &H20&
Private Const MB_ICONASTERISK = &H40&
Private Const MB_ICONINFORMATION = MB_ICONASTERISK
Private Const IDOK = 1
Private Const IDCANCEL = 2
Private Const IDABORT = 3
Private Const IDRETRY = 4
Private Const IDIGNORE = 5
Private Const IDYES = 6
Private Const IDNO = 7
Private Const IDPROMPT = &HFFFF&
Private Const WH_CBT = 5
Private Const GWL_HINSTANCE = (-6)
Private Const HCBT_ACTIVATE = 5
Private Type MSGBOX_HOOK_PARAMS
hwndOwner As LongPtr
hHook As Long
End Type
Private MSGHOOK As MSGBOX_HOOK_PARAMS
Private Declare PtrSafe Function GetCurrentThreadId Lib "kernel32" () As Long
Public Declare PtrSafe Function GetDesktopWindow Lib "user32" () As LongPtr
Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias _
"GetWindowLongA" (ByVal hwnd As LongPtr, ByVal nIndex As Long) As Long
Private Declare PtrSafe Function MessageBox Lib "user32" Alias _
"MessageBoxA" (ByVal hwnd As LongPtr, ByVal lpText As String, _
ByVal lpCaption As String, ByVal wType As Long) As Long
Private Declare PtrSafe Function SetDlgItemText Lib "user32" Alias _
"SetDlgItemTextA" (ByVal hDlg As LongPtr, ByVal nIDDlgItem As Long, _
ByVal lpString As String) As Long
Private Declare PtrSafe Function SetWindowsHookEx Lib "user32" Alias _
"SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As LongPtr, _
ByVal hmod As LongPtr, ByVal dwThreadId As Long) As Long
Private Declare PtrSafe Function SetWindowText Lib "user32" Alias _
"SetWindowTextA" (ByVal hwnd As LongPtr, ByVal lpString As String) As Long
Private Declare PtrSafe Function UnhookWindowsHookEx Lib "user32" _
(ByVal hHook As Long) As Long
Dim mbFlags As VbMsgBoxStyle
Dim mbFlags2 As VbMsgBoxStyle
Dim mTitle As String
Dim mPrompt As String
Dim mBtn1 As String
Dim mBtn2 As String
Dim mBtn3 As String
Private Function MessageBoxH(hwndThreadOwner As LongPtr, _
hwndOwner As LongPtr, mbFlags As VbMsgBoxStyle) As LongPtr
Dim hInstance As Long
Dim hThreadId As Long
hInstance = GetWindowLong(hwndThreadOwner, GWL_HINSTANCE)
hThreadId = GetCurrentThreadId()
With MSGHOOK
.hwndOwner = hwndOwner
.hHook = SetWindowsHookEx(WH_CBT, AddressOf MsgBoxHookProc, hInstance, hThreadId)
End With
MessageBoxH = MessageBox(hwndOwner, Space$(120), Space$(120), mbFlags)
End Function
Private Function MsgBoxHookProc(ByVal uMsg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
If uMsg = HCBT_ACTIVATE Then
SetWindowText wParam, mTitle
SetDlgItemText wParam, IDPROMPT, mPrompt
Select Case mbFlags
Case vbAbortRetryIgnore
SetDlgItemText wParam, IDABORT, mBtn1
SetDlgItemText wParam, IDRETRY, mBtn2
SetDlgItemText wParam, IDIGNORE, mBtn3
Case vbYesNoCancel
SetDlgItemText wParam, IDYES, mBtn1
SetDlgItemText wParam, IDNO, mBtn2
SetDlgItemText wParam, IDCANCEL, mBtn3
Case vbOKOnly
SetDlgItemText wParam, IDOK, mBtn1
Case vbRetryCancel
SetDlgItemText wParam, IDRETRY, mBtn1
SetDlgItemText wParam, IDCANCEL, mBtn2
Case vbYesNo
SetDlgItemText wParam, IDYES, mBtn1
SetDlgItemText wParam, IDNO, mBtn2
Case vbOKCancel
SetDlgItemText wParam, IDOK, mBtn1
SetDlgItemText wParam, IDCANCEL, mBtn2
End Select
UnhookWindowsHookEx MSGHOOK.hHook
End If
MsgBoxHookProc = False
End Function
Public Function CustomMsgBox(mhwnd As LongPtr, _
mMsgbox As VbMsgBoxStyle, Title As String, _
Prompt As String, Optional mMsgIcon As VbMsgBoxStyle, _
Optional btnA As String, Optional btnB As String, _
Optional btnC As String) As String
Dim customText As LongPtr
mbFlags = mMsgbox
mbFlags2 = mMsgIcon
mTitle = Title
mPrompt = Prompt
mBtn1 = btnA
mBtn2 = btnB
mBtn3 = btnC
customText = MessageBoxH(mhwnd, GetDesktopWindow(), mbFlags Or mbFlags2)
Select Case customText
Case IDABORT: CustomMsgBox = mBtn1
Case IDRETRY: CustomMsgBox = mBtn2
Case IDIGNORE: CustomMsgBox = mBtn3
Case IDYES: CustomMsgBox = mBtn1
Case IDNO: CustomMsgBox = mBtn2
Case IDCANCEL: CustomMsgBox = mBtn3
Case IDOK: CustomMsgBox = mBtn1
End Select
End Function
所以,您可以像这样调用消息框:
Sub TestYN()
Const MY_YES As String = "是"
Const MY_NO As String = "否"
Dim dialogResult As String
dialogResult = CustomMsgBox(1, vbYesNo, "发送邮件...", "是否要继续?", vbInformation, MY_YES, MY_NO)
Debug.Print "选择的按钮是 " & dialogResult
End Sub
希望这有帮助!如果您有其他问题,请随时提问。
英文:
You could hook into the message box and change the button text there. For 64-bit, your WINAPIs would be:
Option Explicit
Private Const MB_YESNOCANCEL = &H3&
Private Const MB_YESNO = &H4&
Private Const MB_RETRYCANCEL = &H5&
Private Const MB_OKCANCEL = &H1&
Private Const MB_OK = &H0&
Private Const MB_ABORTRETRYIGNORE = &H2&
Private Const MB_ICONEXCLAMATION = &H30&
Private Const MB_ICONQUESTION = &H20&
Private Const MB_ICONASTERISK = &H40&
Private Const MB_ICONINFORMATION = MB_ICONASTERISK
Private Const IDOK = 1
Private Const IDCANCEL = 2
Private Const IDABORT = 3
Private Const IDRETRY = 4
Private Const IDIGNORE = 5
Private Const IDYES = 6
Private Const IDNO = 7
Private Const IDPROMPT = &HFFFF&
Private Const WH_CBT = 5
Private Const GWL_HINSTANCE = (-6)
Private Const HCBT_ACTIVATE = 5
Private Type MSGBOX_HOOK_PARAMS
hwndOwner As LongPtr
hHook As Long
End Type
Private MSGHOOK As MSGBOX_HOOK_PARAMS
Private Declare PtrSafe Function GetCurrentThreadId Lib "kernel32" () As Long
Public Declare PtrSafe Function GetDesktopWindow Lib "user32" () As LongPtr
Private Declare PtrSafe Function GetWindowLong Lib "user32" Alias _
"GetWindowLongA" (ByVal hwnd As LongPtr, ByVal nIndex As Long) As Long
Private Declare PtrSafe Function MessageBox Lib "user32" Alias _
"MessageBoxA" (ByVal hwnd As LongPtr, ByVal lpText As String, _
ByVal lpCaption As String, ByVal wType As Long) As Long
Private Declare PtrSafe Function SetDlgItemText Lib "user32" Alias _
"SetDlgItemTextA" (ByVal hDlg As LongPtr, ByVal nIDDlgItem As Long, _
ByVal lpString As String) As Long
Private Declare PtrSafe Function SetWindowsHookEx Lib "user32" Alias _
"SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As LongPtr, _
ByVal hmod As LongPtr, ByVal dwThreadId As Long) As Long
Private Declare PtrSafe Function SetWindowText Lib "user32" Alias _
"SetWindowTextA" (ByVal hwnd As LongPtr, ByVal lpString As String) As Long
Private Declare PtrSafe Function UnhookWindowsHookEx Lib "user32" _
(ByVal hHook As Long) As Long
Dim mbFlags As VbMsgBoxStyle
Dim mbFlags2 As VbMsgBoxStyle
Dim mTitle As String
Dim mPrompt As String
Dim mBtn1 As String
Dim mBtn2 As String
Dim mBtn3 As String
Private Function MessageBoxH(hwndThreadOwner As LongPtr, _
hwndOwner As LongPtr, mbFlags As VbMsgBoxStyle) As LongPtr
Dim hInstance As Long
Dim hThreadId As Long
hInstance = GetWindowLong(hwndThreadOwner, GWL_HINSTANCE)
hThreadId = GetCurrentThreadId()
With MSGHOOK
.hwndOwner = hwndOwner
.hHook = SetWindowsHookEx(WH_CBT, AddressOf MsgBoxHookProc, hInstance, hThreadId)
End With
MessageBoxH = MessageBox(hwndOwner, Space$(120), Space$(120), mbFlags)
End Function
Private Function MsgBoxHookProc(ByVal uMsg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
If uMsg = HCBT_ACTIVATE Then
SetWindowText wParam, mTitle
SetDlgItemText wParam, IDPROMPT, mPrompt
Select Case mbFlags
Case vbAbortRetryIgnore
SetDlgItemText wParam, IDABORT, mBtn1
SetDlgItemText wParam, IDRETRY, mBtn2
SetDlgItemText wParam, IDIGNORE, mBtn3
Case vbYesNoCancel
SetDlgItemText wParam, IDYES, mBtn1
SetDlgItemText wParam, IDNO, mBtn2
SetDlgItemText wParam, IDCANCEL, mBtn3
Case vbOKOnly
SetDlgItemText wParam, IDOK, mBtn1
Case vbRetryCancel
SetDlgItemText wParam, IDRETRY, mBtn1
SetDlgItemText wParam, IDCANCEL, mBtn2
Case vbYesNo
SetDlgItemText wParam, IDYES, mBtn1
SetDlgItemText wParam, IDNO, mBtn2
Case vbOKCancel
SetDlgItemText wParam, IDOK, mBtn1
SetDlgItemText wParam, IDCANCEL, mBtn2
End Select
UnhookWindowsHookEx MSGHOOK.hHook
End If
MsgBoxHookProc = False
End Function
Public Function CustomMsgBox(mhwnd As LongPtr, _
mMsgbox As VbMsgBoxStyle, Title As String, _
Prompt As String, Optional mMsgIcon As VbMsgBoxStyle, _
Optional btnA As String, Optional btnB As String, _
Optional btnC As String) As String
Dim customText As LongPtr
mbFlags = mMsgbox
mbFlags2 = mMsgIcon
mTitle = Title
mPrompt = Prompt
mBtn1 = btnA
mBtn2 = btnB
mBtn3 = btnC
customText = MessageBoxH(mhwnd, GetDesktopWindow(), mbFlags Or mbFlags2)
Select Case customText
Case IDABORT: CustomMsgBox = mBtn1
Case IDRETRY: CustomMsgBox = mBtn2
Case IDIGNORE: CustomMsgBox = mBtn3
Case IDYES: CustomMsgBox = mBtn1
Case IDNO: CustomMsgBox = mBtn2
Case IDCANCEL: CustomMsgBox = mBtn3
Case IDOK: CustomMsgBox = mBtn1
End Select
End Function
So, you'd simply call the message box like so:
Sub TestYN()
Const MY_YES As String = "Si"
Const MY_NO As String = "Non"
Dim dialogResult As String
dialogResult = CustomMsgBox(1, vbYesNo, "Enviar Correos...", "¿Desea continuar?", vbInformation, MY_YES, MY_NO)
Debug.Print "Selected button was " & dialogResult
End Sub
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论