I insert textbox to my Excel 2013 document and put some text
正体字/繁体字
with UTF-8 symbols
In textbox its looks ok but when I trying to msgbox it with command
MsgBox ActiveSheet.Shapes("Textbox 1").TextFrame.Characters.Text
I get something like
???/???
So how to set UTF_8 charset to get normally this text in msgbox or into variable?
You can create something that looks like a MsgBox and functions like a MsgBox, but can better handle UniCode:
Public Declare Function MessageBoxU Lib "user32" Alias "MessageBoxW" _
(ByVal hwnd As Long, _
ByVal lpText As Long, _
ByVal lpCaption As Long, _
ByVal wType As Long) As Long
Sub MsgBoxSubstitute()
Dim s As String
s = ChrW(8451)
MessageBoxU 0, StrPtr(s), StrPtr("MsgBox Substitute"), 0
End Sub
Using the Windows API. Note it has a nice built-in mechanism to dismiss the message.
The only workaround is to create a form and display your message in a label. I think labels are UTF-8 enabled.
Related
I have a string containing unicode characters in VBA.
I want to display that string in a message box containing it.
However, instead of the string, the message box only contains a questionmark.
MCVE:
Dim s As String
s = ChrW(5123)
MsgBox s
MsgBox is not compatible with non-ANSI unicode characters.
We can display message boxes with the WinAPI MessageBoxW function, however, and that is .
Let's declare that function, and then create a wrapper for it that's nearly identical to the VBA MsgBox function:
Private Declare PtrSafe Function MessageBoxW Lib "User32" (ByVal hWnd As LongPtr, ByVal lpText As LongPtr, ByVal lpCaption As LongPtr, ByVal uType As Long) As Long
Public Function MsgBoxW(Prompt As String, Optional Buttons As VbMsgBoxStyle = vbOKOnly, Optional Title As String = "Microsoft Access") As VbMsgBoxResult
MsgBoxW = MessageBoxW(Application.hWndAccessApp, StrPtr(Prompt), StrPtr(Title), Buttons)
End Function
This function is only compatible with Microsoft Access. However, for Excel you can swap Application.hWndAccessApp with Application.hWnd to make it work. For other VBA compatible applications, you'll have to find the appropriate way to get the hWnd.
You can use it like MsgBox, as long as you don't use the context-dependent help functionality:
Dim s As String
s = ChrW(5123)
MsgBoxW s
An alternative could be my ModernBox:
MsgMox ChrW(5125) & ChrW(5123) & ChrW(5121) & ChrW(5130), vbInformation, "Unicode"
Display:
I'm trying to have the user select an instance or open Workbook of Excel. The idea is to have a window that will display all open Instances of Excel and then display the Workbooks within these instances. I've done some self research and what I've found below...
Public Declare Function GetDesktopWindow Lib "user32" () As Long
Public Declare Function FindWindowEx Lib "user32" Alias _
"FindWindowExA" (ByVal hWnd1 As Long, ByVal hWnd2 As Long, ByVal lpsz1 As String, ByVal lpsz2 As String) As Long
Function ExcelInstances() As Long
Dim hWndDesk As Long
Dim hWndXL As Long
'Get a handle to the desktop
hWndDesk = GetDesktopWindow
Do
'Get the next Excel window
hWndXL = FindWindowEx(GetDesktopWindow, hWndXL, _
"XLMAIN", vbNullString)
'If we got one, increment the count
If hWndXL > 0 Then
ExcelInstances = ExcelInstances + 1
End If
'Loop until we've found them all
Loop Until hWndXL = 0
End Function
Problem:
When I ran the code, I am getting the error message:
Compile Error:
Only comments may appear after End Sub, End Function or End Property
It's highlighting the first line in the code, and I believe it has something to do with the "user32" string?
Question:
This code will only give me a COUNT of how many instances of Excel are currently open. Is there any way to return the names of the instances and then another sub routine that would return the Workbooks within the instances as well? I've seen a solution making use of VB.Net; however I'd like to avoid this so that I can try to keep everything consolidated into a single Excel Spreadsheet (if possible).
I have a table of products where there is say a pdf for a specific products user manual. I'm storing the model name and it's file path in my products table (in Access). I've created a form in Access that allows the user to search by product name and it narrows down the number of files and shows the results from the search in a list box. However my biggest problem is opening the actual PDF. It opens the file, but I have to store the file path exactly how it is and the path of the files are long. Is there a way to open the PDF hyperlinks without using the Followhyperlink command? Or is there a way that I can show only the file name of the pdf in my list box rather than the entire path name? If I change the display text in my products table it doesn't open the hyperlink, I get an error. Any help would be greatly appreciated!
Application.FollowHyperLink() has problems with security, especially when opening files on a network drive. See e.g. here: http://blogannath.blogspot.de/2011/04/microsoft-access-tips-tricks-opening.html
A better method is the ShellExecute() API function.
Essentially it looks like this (trimmed from http://access.mvps.org/access/api/api0018.htm ):
' This code was originally written by Dev Ashish.
' http://access.mvps.org/access/api/api0018.htm
Private Declare Function apiShellExecute Lib "shell32.dll" _
Alias "ShellExecuteA" _
(ByVal hwnd As Long, _
ByVal lpOperation As String, _
ByVal lpFile As String, _
ByVal lpParameters As String, _
ByVal lpDirectory As String, _
ByVal nShowCmd As Long) _
As Long
Public Const WIN_NORMAL = 1 'Open Normal
Private Const ERROR_SUCCESS = 32&
Public Function fHandleFile(stFile As String) As Boolean
Dim lRet As Long
lRet = apiShellExecute(hWndAccessApp(), "Open", stFile, vbNullString, vbNullString, WIN_NORMAL)
If lRet > ERROR_SUCCESS Then
' OK
fHandleFile = True
Else
Select Case lRet
' Handle various errors
End Select
fHandleFile = False
End If
End Function
Now for your listbox:
Set it to 2 columns, the first being the model name, the second the file path.
Set the column width of the second column to 0, so it will be invisible.
And in the doubleclick event, call fHandleFile with the second column (file path):
Private Sub lstManuals_DblClick(Cancel As Integer)
Call fHandleFile(Me.lstManuals.Column(1))
End Sub
I cobbled this test procedure together in Outlook 2013 from other posts.
It should display a popup box, and then close after 3 seconds.
It never closes.
Sub MessageBoxTimer()
Dim AckTime As Integer, InfoBox As Object
Set InfoBox = CreateObject("WScript.Shell")
AckTime = 3
Select Case InfoBox.Popup("Click OK (this window closes automatically after 3 seconds).", _
AckTime, "This is your Message Box", 0)
Case 1, -1
Exit Sub
End Select
End Sub
Some research suggests that this may be a bug in some MS Office applications. I'm basing this on the fact that this and this don't seem to say anything which suggests you're using the command in the wrong way, and this shows that other users have managed to get precisely this code to work.
I tested this on my Windows PC running Excel with Office 365 and have had the same issue as you - the message box is displayed, but not closed. I found a suggested workaround here, and the discussion on that page may be of some interest to you (particularly one user's description of trying to submit a bug report to Microsoft about VBA). The solution, proposed by a user called ウィンドウズスクリプトプログラマ, is to make a call through to the native user32.dll by declaring an external function - this page has some examples of how to call C dlls with VBA.The MessageBoxTimeout function is said to be undocumented by Microsoft, but you can find out a lot about it here.
The other option, which worked for me, is run a vbscript call to Shell.Popup with mshta.exe:
Function Test()
Dim Shell
Set Shell = CreateObject("WScript.Shell")
Shell.Run "mshta.exe vbscript:close(CreateObject(""WScript.shell"").Popup(""Test"",3,""Message""))"
End Function
To get this to work with more complex messages, you may need to escape some characters. There is another SO question here which shows other uses for mshta's ability to execute vbscript in a shell/ console.
Finally, as was suggested by one user, you could simply create a custom user form with a doevents loop that counts down and then closes itself.
The WScript.Shell .Popup seems to be hit or miss in Office VBA.
If you are looking for a MsgBox that works in Office VBA and supports a timeout, I posted another method that uses a Windows API call. It supports timeout, carriage returns, and return values. You can find the code at this link. I did not think it was proper etiquette to post it again here.
Note that the mshta method mentioned by #Orphid does not support carriage returns and always shows the message on the primary monitor.
Yes, I can confirm that result: the 'Timeout' on the WsShell.Popup function is no longer working in Office.
It took me a while to notice, because popup dialogs with a 'cancel' button seem to be affected less. So this might be a usable workaround for you:
Dim msg AS String
Dim Title as String
msg ="Click 'Ok' or 'Cancel' (this window closes automatically after 3 seconds)."
Title = Application.name & ": Message Box test"
Select Case InfoBox.Popup(msg, AckTime, Title, vbQuestion + vbOkCancel)
If that doesn't work, you're going to need a much longer explanation: reimplementing the 'Timeout' using an API Timer Callback. As the author of that answer, I should warn you that this is using a sledgehammer to crack a nut after attempting the task with a prolonged naval bombardment.
I have tried the following code to control VBA msg box auto closer after 40 sec. You can try also it. It will work for you.
'The first part
#If Win64 Then '64?
Private Declare PtrSafe Function MsgBoxTimeout _
Lib "user32" _
Alias "MessageBoxTimeoutA" ( _
ByVal hwnd As LongPtr, _
ByVal lpText As String, _
ByVal lpCaption As String, _
ByVal wType As VbMsgBoxStyle, _
ByVal wlange As Long, _
ByVal dwTimeout As Long) _
As Long
#Else
Private Declare Function MsgBoxTimeout _
Lib "user32" _
Alias "MessageBoxTimeoutA" ( _
ByVal hwnd As Long, _
ByVal lpText As String, _
ByVal lpCaption As String, _
ByVal wType As VbMsgBoxStyle, _
ByVal wlange As Long, _
ByVal dwTimeout As Long) _
As Long
#End If
'The second part
Sub btnMsgbox(message As String)
Call MsgBoxTimeout(0, message, "", vbInformation, 0, 40000)
End Sub
In an already open word document select all text
copy selected text to clipboard
check default browser open at correct web address
if not open default browser at web address "http://thisaddress.com"
give focus to browser
paste clipboard text into input box called "input1"
or some other way to get MSword document contents to a web page input?
Currently the workflow involves a secretary logging in to the website, then filling out a web form, switching to their open MS Word document, selecting all, copying the WP document, then back to the web form and pasting into an input box, then hitting submit. What I want to do ideally have a button in MS word which opens the browser to the correct web page then copies and pastes the document into the correct input box on the page (in fact it will be the only textarea form field).
The MS Word VBA code is:
Option Explicit
Enum W32_Window_State
Show_Normal = 1
Show_Minimized = 2
Show_Maximized = 3
Show_Min_No_Active = 7
Show_Default = 10
End Enum
Private Declare Function ShellExecute Lib "shell32.dll" _
Alias "ShellExecuteA" (ByVal hWnd As Long, _
ByVal lpOperation As String, ByVal lpFile As String, _
ByVal lpParameters As String, ByVal lpDirectory As String, _
ByVal nShowCmd As Long) As Long
Function OpenURL(URL As String, WindowState As W32_Window_State) As Boolean
' Opens passed URL with default application, or Error Code (<32) upon error
Dim lngHWnd As Long
Dim lngReturn As Long
lngReturn = ShellExecute(lngHWnd, "open", URL, vbNullString, _
vbNullString, WindowState)
OpenURL = (lngReturn > 32)
End Function
Sub TestMacro()
Application.ActiveDocument.Select
Selection.Copy
OpenURL "http://localhost:8500/index.cfm?wordContent=" & Selection, W32_Window_State.Show_Maximized
End Sub
and in the coldfusion handling form
<html>
<head>
</head>
<body>
<form id="form1">
<Textarea ID="txtArea" rows=6><cfoutput>#url.wordContent#</cfoutput></textarea>
</form>
</body>
</html>
Just would like to work out how to not open a new browser window if one is already open.
In case you can modify the web-application, you may do the following:
MS-Word: Copy content to clipboard.
MS-Word: Open Url as "http://thisaddress.com/SomePage?pasteClipboard=true"
SomePage: if query-string param pasteClipboard == true, then add a javascript function to get the clipboard data into your form field.
Update:
In your macro you simply call Selection.Copy, and to open the URL using default browser check this link http://www.experts-exchange.com/Programming/Languages/Visual_Basic/Q_23225744.html
Using the code from the previous link, I made a test macro as :
Sub TestMacro()
Application.ActiveDocument.Select
Selection.Copy
OpenURL "http://thisaddress.com/SomePage?pasteClipboard=true", W32_Window_State.Show_Maximized
End Sub
I hope this was helpful.
Update 2:
Just use W32_Window_State.Show_Default, Here is the full macro:
Option Explicit
Enum W32_Window_State
Show_Normal = 1
Show_Minimized = 2
Show_Maximized = 3
Show_Min_No_Active = 7
Show_Default = 10
End Enum
Private Declare Function ShellExecute Lib "shell32.dll" _
Alias "ShellExecuteA" (ByVal hWnd As Long, _
ByVal lpOperation As String, ByVal lpFile As String, _
ByVal lpParameters As String, ByVal lpDirectory As String, _
ByVal nShowCmd As Long) As Long
Function OpenURL(URL As String, WindowState As W32_Window_State) As Boolean
' Opens passed URL with default application, or Error Code (<32) upon error
Dim lngHWnd As Long
Dim lngReturn As Long
lngReturn = ShellExecute(lngHWnd, "open", URL, vbNullString, _
vbNullString, WindowState)
OpenURL = (lngReturn > 32)
End Function
Sub TestMacro()
Application.ActiveDocument.Select
Selection.Copy
OpenURL "http://thisaddress.com/SomePage?pasteClipboard=true", W32_Window_State.Show_Default
End Sub
Another option is to look into controlling Internet Explorer from inside Word using a control.
Here is an example.
Note, this will only work with IE (unless there are dll versions of Firefox etc.)