-
Jan 22nd, 2019, 05:36 PM
#1
Thread Starter
Fanatic Member
Opening a DOCX with Office 2007
Hey guys. I have a DOCX file and I'd like to open from my program.
I don't want to use the Microsoft Word Object Model because it's version dependent and I don't know which version the end user will have on his system.
I would like to use ShellExecute to open the file.
The code I'm using is:
ShellExecute me.hWnd, "open", strFile, vbNullString, vbNullString, SW_SHOW
This works well with every other document type but not Word files.
strFile is the full file/path name to the file so for example: c:\docs\mydoc.docx
I've checked that Word is installed and the file strFile is correct and exists and it's in Word format and all the obvious things.
What happens is that Word opens but the DOCX file does not display on the screen. This happens on every computer I'm using so it's not a problem with DOCX being registered and it also happens with older DOC files. Am I missing something? Any help appreciated.
-
Jan 22nd, 2019, 07:24 PM
#2
Re: Opening a DOCX with Office 2007
I am on Win10 and my docx opened just fine, fully displaying the file. I'm using Office365
Is it possible that the file is in a folder that user of your app does not have read/write access to? Throwing stuff at the wall to see what sticks.
Definitely cache the return value of the ShellExecute call. That may help explain things. Here is the documentation if the result does not return a value > 32.
Also, can you post your ShellExecute API declaration?
-
Jan 22nd, 2019, 09:19 PM
#3
Addicted Member
Re: Opening a DOCX with Office 2007
Can you open the word files using the "Run dialog" as follows?
If "No", there is something wrong..., have you installed more than one Office versions?
-
Jan 23rd, 2019, 02:47 AM
#4
Re: Opening a DOCX with Office 2007
MS Word is using DDE when opening files w/ ShellExecute, so you need to not terminate you app immediately after calling the API *and* you have to pump messages for DDE to complete successfully.
I'm usually using the sister ShellExecuteEx API to be able to wait until the shelled process becomes responsive like this:
Code:
Option Explicit
'--- for ShellExecuteEx
Private Const SEE_MASK_NOCLOSEPROCESS As Long = &H40
Private Const SEE_MASK_NOASYNC As Long = &H100
Private Const SEE_MASK_FLAG_NO_UI As Long = &H400
Private Const SW_SHOWDEFAULT As Long = 10
Private Declare Function ShellExecuteEx Lib "shell32" Alias "ShellExecuteExA" (lpExecInfo As SHELLEXECUTEINFO) As Long
Private Declare Function WaitForInputIdle Lib "user32" (ByVal hProcess As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Type SHELLEXECUTEINFO
cbSize As Long
fMask As Long
hWnd As Long
lpVerb As String
lpFile As String
lpParameters As String
lpDirectory As Long
nShow As Long
hInstApp As Long
' optional fields
lpIDList As Long
lpClass As Long
hkeyClass As Long
dwHotKey As Long
hIcon As Long
hProcess As Long
End Type
Public Function ShellOpen(sUrl As String, Optional LastDllError As Long) As Boolean
Dim uShell As SHELLEXECUTEINFO
With uShell
.cbSize = LenB(uShell)
.fMask = SEE_MASK_NOCLOSEPROCESS Or SEE_MASK_NOASYNC Or SEE_MASK_FLAG_NO_UI
.hWnd = 0
.lpVerb = "open"
.lpFile = sUrl
.lpParameters = vbNullString
.nShow = SW_SHOWDEFAULT
End With
If ShellExecuteEx(uShell) = 0 Then
LastDllError = Err.LastDllError
Else
Call WaitForInputIdle(uShell.hProcess, 5000)
Call CloseHandle(uShell.hProcess)
End If
ShellOpen = (LastDllError = 0)
End Function
Private Sub Form_Click()
Dim lError As Long
Screen.MousePointer = vbHourglass
Debug.Print Timer
If Not ShellOpen("d:\temp\aaa.docx", lError) Then
Debug.Print "Error " & lError
End If
Debug.Print Timer
Screen.MousePointer = vbDefault
End Sub
Basicly SEE_MASK_NOASYNC is required (this prevents spawning a worker thread in *your* process to do the child process spawning. . . Turtles all the way down!). Don't trust samples that use ShellExecuteEx w/o this flag.
The SEE_MASK_FLAG_NO_UI is common sense -- you don't want this API to show error messages but immediately to return error codes. You will show MsgBox from your app, so you don't want some unskinned dialog boxes from some obscure ShellExecuteEx API:-)).
The SEE_MASK_NOCLOSEPROCESS is needed to get child process handle to be used w/ WaitForInputIdle for smoother end-user experience of your app. Otherwise long starting apps like MS Word and Acrobat Reader will render your app responsive *prematurely*, while still no document window pops up from the started app. This might prompt the end-user to click your action button second time, not sure if the first click was acknowledged, effectively starting MS Word *second* time. . . You get the idea how messy the UX becomes, even if users "train" themselves to wait patiently, not to trust any mouse hourglasses you show, as to not trick themselves to double click your command buttons. . .
cheers,
</wqw>
-
Jan 23rd, 2019, 11:00 AM
#5
Thread Starter
Fanatic Member
Re: Opening a DOCX with Office 2007
Thanks for all the help guys. Much appreciated. I have been running all these samples inside the IDE. Nothing worked at all.
Finally I compiled the EXE and the compiled program works fine. Real head scratcher but I guess it's good to know that's how it works. On my system anyway.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|