如何从路径中提取文件名?

77

如何在VBA中从 C:\Documents\myfile.pdf 中提取文件名myfile.pdf


尝试使用split函数从路径中获取文件名: MSDN链接 - jonaspp
16个回答

155

VBA在Office 2000/2003中处理文件和目录最好的方法是使用脚本库。

创建一个文件系统对象,并使用它来进行所有操作。

早期绑定:

在IDE中添加对Microsoft Scripting Runtime的引用(工具 > 引用)。

Dim fso as new FileSystemObject
Dim fileName As String
fileName = fso.GetFileName("c:\any path\file.txt")

Late binding(有关注释请参考)

With CreateObject("Scripting.FileSystemObject")
    fileName = .GetFileName(FilePath)
    extName = .GetExtensionName(FilePath)
    baseName = .GetBaseName(FilePath)
    parentName = .GetParentFolderName(FilePath)
End With

FileSystemObject非常好用。它提供了许多功能,例如以面向对象的方式获取特殊文件夹(我的文档等),创建、移动、复制、删除文件和目录。


12
在Excel VBA中,Dim fileName As String; Dim fso as Object; Set fso = CreateObject("Scripting.FileSystemObject"); fileName = fso.GetFilename(path);的意思是声明一个字符串类型的变量fileName和一个Object类型的变量fso,然后使用CreateObject方法创建一个Scripting.FileSystemObject对象并将其分配给fso变量。最后,通过调用fso.GetFilename(path)方法来获取指定路径下文件的文件名并将其分配给fileName变量。 - IceArdor
5
警告:如果出现“未定义的用户类型”错误,您需要设置对VB脚本运行时库的引用。加载VB编辑器(ALT+F11),从下拉菜单中选择工具> 引用,在可用引用列表中选中“Microsoft Scripting Runtime”旁边的复选框,然后单击确定。 - Ian Stanway
2
不是一个好的解决方案:它需要外部依赖于VBA。该代码在所有VBA环境中都无法工作。 - Skrol29
2
@Skrol29,全世界每个Windows电脑都包含该库。无需担心。被接受的答案在Mac上也不起作用。那些系统地延迟绑定脚本运行时的人不知道自己在做什么,也不知道为什么要这样做。这个答案完全可以接受,并且比被接受的答案好得多。 - Mathieu Guindon
4
使用 Scripting Runtime 的延迟绑定对你没有任何好处。这样做会在运行时导致性能损失,而且无法进行编译期检查,这意味着如果你打错了某个函数的名称,直到运行代码时你才会发现问题,因为代码可以顺利编译通过。不要对一个自 Windows 98 起就是标准程序库的库进行延迟绑定。 - Mathieu Guindon
显示剩余2条评论

58
Dir("C:\Documents\myfile.pdf")

如果文件存在,将返回文件名。


5
不好,因为它假定路径是程序可以读取的物理文件。 - Skrol29
嗨@Skrol29,你能否帮忙更详细地解释一下这个问题? - Harry Duong
@HarryDuong Dir 返回文件名,但仅当该位置实际存在该文件时。如果文件不存在,则 Dir 返回一个空字符串。如果您知道文件存在,例如当您提示用户选择文件时,则这是获取文件名的快速简便方法。如果您不知道文件是否存在,则来自 @ArturPiwkowski 的 Split 更好。两个 Splits 将比任何字符串操作更快。 - Dick Kusleika
@Harry Duong:函数Dir()会在计算机上执行扫描,以检查给定的掩码。在这个例子中,掩码是期望文件的名称。如果文件不存在于计算机上,则Dir()返回一个空值。但是,在许多情况下,您需要从不存在的路径中提取名称。例如,要创建文件的路径或刚刚删除的文件的路径。 - Skrol29

48

这段内容来自snippets.dzone.com

Function GetFilenameFromPath(ByVal strPath As String) As String
' Returns the rightmost characters of a string upto but not including the rightmost '\'
' e.g. 'c:\winnt\win.ini' returns 'win.ini'

    If Right$(strPath, 1) <> "\" And Len(strPath) > 0 Then
        GetFilenameFromPath = GetFilenameFromPath(Left$(strPath, Len(strPath) - 1)) + Right$(strPath, 1)
    End If
End Function

1
正确,但如果你使用的是Mac呢?不幸的是,这不是一个跨平台的解决方案。 - Thomas Fankhauser
1
那么在Windows上就会出问题了,对吧?我已经想到使用Application.PathSeparator,但不幸的是,在OSX VBA中甚至返回旧的:表示法的路径。我不得不编写一个将这些路径转换的函数。 - Thomas Fankhauser
6
这样做可以起作用,但是过于递归,特别是对于VBA来说(它不会自动将尾递归转换为循环)。 - Mary
5
在我看来,Zen在https://dev59.com/jnI-5IYBdhLWcg3wpqMK#1755577中给出的答案更好。代码重用,无递归,无嵌入常量。 - Matt
@ThomasFankhauser 这是一个旧评论,但我很困惑:为什么你会期望有一个跨平台的解决方案呢?(而且目前不到五分之一的用户使用Mac) - ashleedawg
@ashleedawg 因为如果Application.PathSeparator具有错误的值,并且VBA跨平台运行,则具有OS感知的Application.PathSeparator没有意义。 - Thomas Fankhauser

41

我已经阅读了所有的回答,并且我想添加一个因其简单性而胜出的答案。与被接受的答案不同,这不需要递归。它也不需要引用FileSystemObject。

Function FileNameFromPath(strFullPath As String) As String

    FileNameFromPath = Right(strFullPath, Len(strFullPath) - InStrRev(strFullPath, "\"))

End Function

http://vba-tutorial.com/parsing-a-file-string-into-path-filename-and-extension/ 这个网站有这段代码,以及其他用于解析文件路径、扩展名甚至是不带扩展名的文件名的函数。


3
对我来说最好的:智能化、轻便且可越野。 - Skrol29
5
对于简化的加一操作,甚至可以省略函数,直接使用"="这一行代码,或者在循环中用于多个文件。 - tahwos
2
我更喜欢这个答案,而不是其他任何答案。它可以轻松地在任何其他子程序或函数中重复使用,而且不需要对引用进行任何调整。 - mattlore
这很棒,因为你可以在受限制的脚本环境中使用它(在我的情况下是RPA)。 - charles ross

15
我无法相信一些答案是如此复杂(不冒犯!)
这里有一个可以完成任务的单行函数:

**Extract Filename from <code>x:\path\filename</code>:**

Function getFName(pf)As String:getFName=Mid(pf,InStrRev(pf,"\")+1):End Function

**Extract Path from <code>x:\path\filename</code>:**

Function getPath(pf)As String:getPath=Left(pf,InStrRev(pf,"\")):End Function

示例:

examples


我不喜欢单行函数的风格,除非你是在尝试 Code Golf。我正在寻找一种可以嵌入到 SQL 查询中的方法,而你的代码(没有函数)是最简单的:Left(pf,InStrRev(pf,"\"))。这利用了 mid() 的第三个参数是可选的。 - Ben

10
Dim sFilePath$, sFileName$
sFileName = Split(sFilePath, "\")(UBound(Split(sFilePath, "\")))

不太聪明,因为它运行了两次 Split(sFilePath, "\") - Skrol29

5
在Excel宏中获取文件名的方法是:
filname = Mid(spth, InStrRev(spth, "\", Len(spth)) + 1, Len(spth))
MsgBox Mid(filname, 1, InStr(filname, ".") - 1)

5

这里是我编写的一个简单的VBA解决方案,可用于Windows、Unix、Mac和URL路径。

sFileName = Mid(Mid(sPath, InStrRev(sPath, "/") + 1), InStrRev(sPath, "\") + 1)

sFolderName = Left(sPath, Len(sPath) - Len(sFileName))

您可以使用以下代码测试输出:
'Visual Basic for Applications 
http = "https://www.server.com/docs/Letter.txt"
unix = "/home/user/docs/Letter.txt"
dos = "C:\user\docs\Letter.txt"
win = "\\Server01\user\docs\Letter.txt"
blank = ""

sPath = unix 
sFileName = Mid(Mid(sPath, InStrRev(sPath, "/") + 1), InStrRev(sPath, "\") + 1)
sFolderName = Left(sPath, Len(sPath) - Len(sFileName))

Debug.print "Folder: " & sFolderName & " File: " & sFileName

另外参考:维基百科 - 路径(计算机)

该链接介绍了路径的更多信息。

5
如果您想要一个更强大的解决方案,既可以提供完整文件夹路径又可以提供文件名,那么这里就是:
Dim strFileName As String, strFolderPath As String
Dim lngIndex As Long
Dim strPath() As String

strPath() = Split(OpenArgs, "\")   'Put the Parts of our path into an array
lngIndex = UBound(strPath)
strFileName = strPath(lngIndex)    'Get the File Name from our array
strPath(lngIndex) = ""             'Remove the File Name from our array
strFolderPath = Join(strPath, "\") 'Rebuild our path from our array

作为子程序/函数:
Private Sub SeparatePathAndFile(ByRef io_strFolderPath As String, ByRef o_strFileName As String)    
    Dim strPath() As String
    Dim lngIndex As Long

    strPath() = Split(io_strFolderPath, "\")  'Put the Parts of our path into an array
    lngIndex = UBound(strPath)
    o_strFileName = strPath(lngIndex)   'Get the File Name from our array
    strPath(lngIndex) = ""              'Remove the File Name from our array
    io_strFolderPath = Join(strPath, "\")     'Rebuild our path from our array  
End Sub

您需要将文件的完整路径作为第一个参数传递,它将被设置为文件夹的路径,而第二个参数将被设置为文件名。


5
如果您确定文件在磁盘上存在,则最简单的方法是:
Dim fileName, filePath As String
filePath = "C:\Documents\myfile.pdf"
fileName = Dir(filePath)

如果您不确定文件是否存在,或者只想从给定路径中提取文件名,则最简单的方法是:

fileName = Mid(filePath, InStrRev(filePath, "\") + 1)

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