有没有办法在VBA中的DIR(path)处理超过260的string?
鉴于以下片段:
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
如果string小于260,它可以正常工作,并显示find和未find文件的预期行为。
是否需要使用long(> 260)path名称来处理DIR?
笔记
-
文件重组不是一个选项
-
我在Excel 2007中运行这个
这里有一些代码应该工作,无论深度…基本上,它指定相对path – 所以你永远不会调用长stringdir
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
简单地说(回答标题的答案):不.VBA的Dir
函数根本不适用于超过260个字符的path。
长版本: http : //msdn.microsoft.com/en-us/library/aa365247 ( VS.85).aspx#maximum_path_length (然后Ctrl + F和search“260”)
最大path长度限制
在Windows API(以下段落中讨论一些例外)中,path的最大长度是MAX_PATH,定义为260个字符。 本地path按以下顺序组织:驱动器号,冒号,反斜杠,用反斜杠分隔的名称组件以及终止的空字符。 例如,驱动器D上的最大path是“D:\一些256个字符的pathstring”,其中“”代表当前系统代码页的不可见的终止空字符。 (字符<>在这里用于视觉清晰,不能是有效pathstring的一部分。)注意Windows API中的文件I / O函数将“/”转换为“\”,作为将名称转换为NT-样式名称,除非使用“\?\”前缀,如以下部分所述。 Windows API有许多function,也有Unicode版本允许扩展长度path的最大总path长度为32,767个字符。 此类path由用反斜杠分隔的组件组成,每个组件由GetVolumeInformation函数的lpMaximumComponentLength参数(此值通常为255个字符)中返回的值组成。 要指定扩展长度path,请使用“\?\”前缀。 例如,“\?\ D:\非常长的path”。 注意32,767字符的最大path是近似值,因为系统在运行时可能会将“\?\”前缀扩展为更长的string,并且此扩展适用于总长度。
我认为关于Win32 File NameSpaces的部分值得一试:
对于文件I / O,pathstring的“\?\”前缀告诉Windows API禁用所有stringparsing并将紧随其后的string直接发送到文件系统。 例如,如果文件系统支持较大的path和文件名,则可以超出由Windows API执行的MAX_PATH限制。 有关正常最大path限制的更多信息,请参阅上一节“最大path长度限制”。
必须有一个可以DECLARE
和使用的Win32 API函数,但是这不是使用DIR
函数。 对不起,没有一个漫长的path名称来testing任何东西…
我没有办法testing这个,所以你只有一个可能的方法的几个粗略的笔记。
''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
我发现这个MS页面: 命名文件,path和命名空间
最大path长度限制在Windows API中(下面讨论的一些例外),path的最大长度是MAX_PATH,定义为260个字符。 本地path按以下顺序组织:驱动器号,冒号,反斜杠,用反斜杠分隔的名称组件以及终止的空字符。 例如,驱动器D上的最大path是“D:\一些256个字符的pathstring”,其中“”代表当前系统代码页的不可见的终止空字符。 (字符<>在这里用于视觉清晰,不能是有效pathstring的一部分。)注意Windows API中的文件I / O函数将“/”转换为“\”,作为将名称转换为NT-样式名称,除非使用“\?\”前缀,如以下部分所述。
Windows API有许多function,也有Unicode版本允许扩展长度path的最大总path长度为32,767个字符。 此类path由用反斜杠分隔的组件组成,每个组件由GetVolumeInformation函数的lpMaximumComponentLength参数(此值通常为255个字符)中返回的值组成。 要指定扩展长度path,请使用“\?\”前缀。 例如,“\?\ D:\非常长的path”。 注意32,767字符的最大path是近似值,因为系统在运行时可能会将“\?\”前缀扩展为更长的string,并且此扩展适用于总长度。
根据通用命名约定(UNC)构build的path也可以使用“\?\”前缀。 要使用UNC指定这样的path,请使用“\?\ UNC \”前缀。 例如,“\?\ UNC \ server \ share”,其中“server”是计算机的名称,“share”是共享文件夹的名称。 这些前缀不被用作path本身的一部分。 它们表示应该通过最小的修改将path传递给系统,这意味着您不能使用正斜杠来表示path分隔符,或者表示当前目录的句点,或者使用双点来表示父目录。 因为不能使用相对path的“\?\”前缀,所以相对path始终限制为总共MAX_PATH个字符。
所以对于非常长的UNCpath,我改变了path的开始,如下所示,它的工作原理。
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)