给出以下代码段:
Dim s As String: s = "S:\vic\bla\[..insert more here..]\data.xml"
Debug.Print Len(s)
Debug.Print Dir(s)
如果Len(s) >= 260
我收到错误说明以下内容:
Run-time error '53':
File not found
如果字符串小于260,它可以正常工作并显示已找到和未找到文件的预期行为。
是否可以让DIR使用长(> 260)个路径名?
注释
文件重组不是一个选项
我在Excel 2007中运行它
答案 0 :(得分:6)
短暂放(以答案标题为答案):否.VBA的Dir
函数不适用于超过260个字符的路径。
长版本:http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maximum_path_length(然后按Ctrl + F并搜索“260”)
最大路径长度限制
在Windows API中(以下段落中讨论了一些例外),最大长度 对于路径是MAX_PATH,定义为260个字符。本地人 path按以下顺序构成:驱动器号,冒号, 反斜杠,名称由反斜杠分隔的组件和终止 空字符。例如,驱动器D上的最大路径是“D:\ some 256个字符的路径字符串“where”“表示不可见的 终止当前系统代码页的空字符。 (该 字符< >这里使用的是视觉清晰度,不能成为其中的一部分 有效的路径字符串。)注意Windows API中的文件I / O函数 将“/”转换为“\”作为将名称转换为NT样式名称的一部分, 除了使用“\?\”前缀时,如下所述 部分。 Windows API具有许多也具有Unicode的功能 版本允许最大总路径的扩展长度路径 长度为32,767个字符。这种类型的路径由 由反斜杠分隔的组件,每个组件都返回到返回的值 GetVolumeInformation的lpMaximumComponentLength参数 function(此值通常为255个字符)。指定一个 扩展长度路径,使用“\?\”前缀。例如,“\?\ D:\ very 长路径“。注意最大路径为32,767个字符 近似,因为“\?\”前缀可能会扩展到更长 系统在运行时的字符串,这个扩展适用于 总长度。
我认为关于 Win32 File NameSpaces 的部分值得一试:
对于文件I / O,路径字符串的“\?\”前缀告诉Windows 用于禁用所有字符串解析并发送后续字符串的API 它直接到文件系统。例如,如果是文件系统 支持大路径和文件名,可以超过MAX_PATH Windows API强制执行的限制。更多 有关正常最大路径限制的信息,请参阅前面的内容 部分最大路径长度限制。
必须有DECLARE
并且可以使用的Win32 API函数,但是没有使用DIR
函数。对不起,手边没有长路径来测试任何东西...
答案 1 :(得分:3)
以下是一些代码,无论深度如何都应该有效... 基本上,它指定了相对路径 - 因此您永远不会使用长字符串
来调用dir
Function deepFileExists(longFileName As String)
' slowly make your way to the deepest folder...
' assuming "\" is used as separator
' you could add some code to replace "/" with "\"...
Dim pathFragment As String, currentDir As String
Dim slash As Integer, lastSlash As Integer
slash = InStr(1, longFileName, "\")
lastSlash = 0
pathFragment = Mid(longFileName, 1, slash - 1)
currentDir = CurDir ' save the current directory
ChDrive pathFragment ' making sure we have the right drive
ChDir pathFragment & "\" ' be at the root of this drive's directory
lastSlash = slash
slash = InStr(slash + 1, longFileName, "\")
While (slash > 0)
pathFragment = ".\" & Mid(longFileName, lastSlash + 1, slash - lastSlash)
ChDir pathFragment
'MsgBox "changing directory to " & pathFragment
lastSlash = slash
slash = InStr(slash + 1, longFileName, "\")
Wend
' now we can look for the file:
Dim a
a = Dir(Mid(longFileName, lastSlash + 1))
If Len(a) > 0 Then
deepFileExists = True
Else
deepFileExists = False
End If
End Function
答案 2 :(得分:2)
我无法对此进行测试,因此您只需要对可能的方法进行一些粗略的说明。
''Reference: Windows Script Host Object Model
Dim fs As New FileSystemObject
Dim fl As Folder
Dim fl2 As Folder
Set fl = fs.GetFolder("Z:\Docs\test\ThisIsInOrderToCreate\ALongFilePath\")
Set fl2 = fl.SubFolders("WithASubFolder")
Debug.Print fl2.ShortPath
For Each File In fl2.Files
If File.Name = "file.txt" Then
Debug.Print "Found"
End If
Next
''May be possible
a = Dir(fl.ShortPath & "\file.*")
另外,关于以上评论:
Set WshNetwork = CreateObject("WScript.Network")
WshNetwork.MapNetworkDrive "L:", "\\mydrive\share"
''Important to destroy when you are finished
Set WshNetwork = Nothing
答案 3 :(得分:0)
我找到了这个MS页面: Naming Files, Paths, and Namespaces
最大路径长度限制 在Windows API中(以下段落中讨论了一些例外),路径的最大长度为MAX_PATH,定义为260个字符。本地路径按以下顺序构成:驱动器号,冒号,反斜杠,由反斜杠分隔的名称组件以及终止空字符。例如,驱动器D上的最大路径是" D:\某些256个字符的路径字符串"在哪里""表示当前系统代码页的不可见的终止空字符。 (字符<>在此处用于视觉清晰度,不能是有效路径字符串的一部分。) 注意Windows API转换中的文件I / O函数" /"到" \"作为将名称转换为NT样式名称的一部分,除非使用" \?\"前缀详见以下部分。
Windows API有许多函数也具有Unicode版本,允许扩展长度路径,最大总路径长度为32,767个字符。这种类型的路径由用反斜杠分隔的组件组成,每个组件都取决于GetVolumeInformation函数的lpMaximumComponentLength参数中返回的值(此值通常为255个字符)。要指定扩展长度路径,请使用" \?\"字首。例如," \?\ D:\非常长的路径"。 注意最大路径为32,767个字符是近似值,因为" \?\"系统在运行时可以将前缀扩展为更长的字符串,并且此扩展适用于总长度。
" \?\"前缀也可以与根据通用命名约定(UNC)构造的路径一起使用。要使用UNC指定此类路径,请使用" \?\ UNC \"字首。例如," \?\ UNC \ server \ share",其中" server"是计算机的名称和"分享"是共享文件夹的名称。这些前缀不会用作路径本身的一部分。它们表明路径应该以最小的修改传递给系统,这意味着您不能使用正斜杠表示路径分隔符,或者表示当前目录的句点,或者表示父目录的双点。因为你不能使用" \?\"带有相对路径的前缀,相对路径总是限制为总共MAX_PATH个字符。
因此,对于非常长的UNC路径,我改变了路径的起点,如下所示,它可以工作。
Const MAX_PATH_LENGTH As Integer = 260
If Len(fname) > MAX_PATH_LENGTH Then
fname = "\\?\UNC\" & Mid$(fname, 3)
End If
Set fsoObject = New Scripting.FileSystemObject
FileExists = fsoObject.FileExists(fname)
答案 4 :(得分:0)
由于我无法回复包含deepfileexists代码的评论,因此以下代码经过修改,以便您可以找到网络路径(因为他回答说他有网络位置)
您需要一个调用system32的函数来建立到网络驱动器的直接路径。我从here
获得了代码这里是代码,将私有函数插入模块顶部,否则将无法正常工作。如果您想将其打开到整个工作簿,则可以将功能保持与该模块的专用联系。
Private Declare Function SetCurrentDirectoryA Lib "kernel32" _
(ByVal lpPathName As String) As Long
然后是带有修改后代码的函数,以接受存在以\\ p开头的网络驱动器的情况
Function deepFileExists(longFileName As String)
' slowly make your way to the deepest folder...
' assuming "\" is used as separator
' you could add some code to replace "/" with "\"...
Dim pathFragment As String, currentDir As String
Dim slash As Integer, lastSlash As Integer
If Left(longFileName, 2) = "\\" Then
slash = InStr(3, longFileName, "\")
Else
slash = InStr(1, longFileName, "\")
End If
lastSlash = 0
pathFragment = Mid(longFileName, 1, slash - 1)
currentDir = CurDir ' save the current directory
If Not Left(pathFragment, 2) = "\\" Then
ChDrive pathFragment ' making sure we have the right drive
ChDir pathFragment & "\" ' be at the root of this drive's directory
Else
SetCurrentDirectoryA (pathFragment)
End If
lastSlash = slash
slash = InStr(slash + 1, longFileName, "\")
While (slash > 0)
pathFragment = ".\" & Mid(longFileName, lastSlash + 1, slash - lastSlash)
If Not Left(longFileName, 2) = "\\" Then
ChDir pathFragment
Else
SetCurrentDirectoryA (pathFragment)
End If
'MsgBox "changing directory to " & pathFragment
lastSlash = slash
slash = InStr(slash + 1, longFileName, "\")
Wend
' now we can look for the file:
Dim a As String
Dim something As String
something = Mid(longFileName, lastSlash + 1)
a = Dir(something)
If Len(a) > 0 Then
deepFileExists = True
Else
deepFileExists = False
End If
End Function