如何使用Excel VBA打开文件并使用默认应用程序

25

我希望有一个Excel电子表格,在A列中包含文件路径和名称。运行宏时,假设在A1中指定的文件应该在用户的计算机上打开。文件可以是.doc、.xls、.txt等,而不需要我的vba知道完整的应用程序路径,我如何让vba告诉计算机“请打开此文件并使用与扩展名关联的应用程序”?

我已经发现这个方法可以使用完整路径:

dblShellReturned = Shell("C:\Windows\System32\notepad.exe myfile.txt, vbNormalFocus)

我该如何让它与类似这样的东西一起工作:

dblShellReturned = Shell("myfile.txt", vbNormalFocus) ' how do I get this to work

提前感谢你!


2
您可以使用 ShellExcecute:http://support.microsoft.com/kb/170918 - Tim Williams
7
使用超链接,例如 ActiveWorkbook.FollowHyperlink "C:\test\myfile.txt" - tigeravatar
此问答适用于WINDOWS系统。若需Excel MAC解决方案,请参阅如何使用Excel Mac VBA打开非Excel文件 - JMichaelTX
5个回答

44

这在我的Excel和Word中有效。

Sub runit()
   Dim Shex As Object
   Set Shex = CreateObject("Shell.Application")
   tgtfile = "C:\Nax\dud.txt"
   Shex.Open (tgtfile)
End Sub

或者 ... 根据 Expenzor 的评论

CreateObject("Shell.Application").Open("C:\Nax\dud.txt")


1
这个方法在Access中对我也起作用,可以打开附件! - Steve Salowitz
13
创建对象("Shell.Application").打开("C:\Nax\dud.txt") - Expenzor

15

VBA的Shell命令需要一个exe文件,因此我一直在启动explorer.exe并将我的文件路径作为参数传递。它似乎也可以使用*.lnk快捷方式和Web URL。

Shell "explorer.exe C:\myfile.txt"

7

下面的代码是一个模板。然而,您可能需要将默认(工作)目录更新为文件的位置。

Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" _
                   (ByVal hwnd As Long, ByVal lpszOp As String, _
                    ByVal lpszFile As String, ByVal lpszParams As String, _
                    ByVal LpszDir As String, ByVal FsShowCmd As Long) _

Function StartDoc(DocName As String) As Long
      Dim Scr_hDC As Long
      Scr_hDC = GetDesktopWindow()
      StartDoc = ShellExecute(Scr_hDC, "Open", DocName, _
      "", "C:\", SW_SHOWNORMAL)
 End Function

1
这不是和@TimWilliams在上面的评论中建议的一样吗? :) - Siddharth Rout
8
哦,我并不总是注意评论。我错过了那一个。我不明白为什么人们会在那里放答案,这似乎违反了Stack Overflow的模式并且会搞乱搜索结果。 - AndASM
3
没问题 :) 有时候我也会错过评论。关于你的问题,在我个人看来,我们有些人在评论中回答问题是基于一些原因。我的原因如下(不一定适用于他人)... 1 发布答案没有太多价值,因为链接已经包含了所有信息,尤其是对于 MSDN 链接这样的情况 2 没必要重复造轮子。我们在这里不是为了收集赞,而是为了帮助人们 3 这个问题已经被问过很多次了 4 这是一个让问题提出者学习的绝佳机会。希望这回答了你的问题 :) - Siddharth Rout
顺便说一句,为了帮助楼主提供一个例子,+1。 - Siddharth Rout
6
@SiddharthRout 我更愿意将有用的内容放在问题中作为答案并关闭它,这样它就不会成为一个死胡同,但也不会漂浮在未回答问题列表中。那里面有一些值得回答的老问题,但它们淹没在一片混乱之中。 - AndASM
值得注意的是,“打开”动词并不总是与从资源管理器中运行文件相同。对于Excel模板.xltx,ShellExecute将打开模板,而CreateObject("Shell.Application").Open()将从模板创建一个新工作簿。 - Andre

4

我无法对现有答案进行评论(积分不够),因此我在回答中添加信息。

从Access 2010开始工作,我使用以下语法遇到了静默失败:

Dim URL As String
URL = "http://foo.com/"
CreateObject("Shell.Application").Open URL

如果我在括号中包裹URL,它就可以工作,但这似乎对于子程序(而不是函数)调用语法来说是错误的。我试图忽略返回值,但使用函数调用语法失败了,除非我加倍括号。我意识到括号不仅仅是语法糖 - 它们必须做些什么,这让我相信它们可能有助于隐式转换。
我注意到Open期望一个Variant,而不是String。因此,我尝试了CVar,它确实起作用了。考虑到这一点,以下是我首选的方法,因为它最小化了“为什么这里有多余的括号?”的问题。
Dim URL As String
URL = "http://foo.com/"
CreateObject("Shell.Application").Open CVar(URL)

这个教训告诉我们,在进行OLE自动化调用时,一定要明确地让Access VBA适当地转换类型!


我发现括号的解释很有帮助——我也尝试过不用它们,但这是唯一一个解释它们不是可选项的答案。 - Frogrammer-Analyst

2

Shell32.Shell COM对象,也称为Shell.Application,可以包装ShellExecute Win32 API函数:

  • Add a reference to Microsoft Shell Controls And Automation type library to VBA project via Tools->References..., then

    Dim a As New Shell32.Shell
    Call a.ShellExecute("desktop.ini")
    
  • Alternatively, without any references:

    Call CreateObject("Shell.Application").ShellExecute("desktop.ini")
    
有趣的是,在这里(WinXP),使用提供自动完成功能的变量时,成员列表中缺少ShellExecute(但仍然可以使用)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接