VBA获取文件夹所有文件属性:确定GetDetailsOf最后属性索引
首先,你的CountProperties函数的核心问题是遇到第一个空属性名就停止遍历,但实际上Windows的Shell属性索引中,存在“中间空、后面还有有效属性名”的情况——比如某些系统保留索引、或者针对特定文件类型的属性,可能在连续几个索引为空后,后面又出现有效的属性名称,这就导致你的函数提前退出,漏统计了后面的属性。
另外,你提到用On Error Resume Next捕获越界错误无效,这完全正常:GetDetailsOf方法对任何≥0的整数索引都不会抛出错误,只会返回空字符串,所以死循环是必然的结果。
一、正确获取最后一个有属性名的索引
要准确找到最后一个非空属性名的索引,我们可以换个思路:遍历一个足够覆盖所有系统属性的索引范围(Windows系统的Shell属性索引通常不会超过350,Windows 11可能稍多,设到400足够保险),记录所有返回非空字符串的最大索引。
修改后的CountProperties函数如下:
Function CountProperties(ByRef FldPath) As Long Dim objShell As Object Dim objFolder As Object Dim testStr As String Dim maxValidIndex As Long Dim i As Long Set objShell = CreateObject("Shell.Application") ' 处理路径末尾的斜杠,确保正确获取Folder对象 If Right(FldPath, 1) = "\" Then Set objFolder = objShell.Namespace(Left(FldPath, Len(FldPath) - 1)) Else Set objFolder = objShell.Namespace(FldPath) End If maxValidIndex = -1 ' 初始化为-1,表示未找到有效属性 ' 遍历足够大的索引范围,覆盖所有可能的系统属性 For i = 0 To 400 testStr = objFolder.GetDetailsOf(objFolder.Items, i) If testStr <> vbNullString Then maxValidIndex = i ' 更新最大有效索引 End If Next i ' 返回最后一个有效属性的索引;如果要返回属性数量,就返回maxValidIndex + 1 CountProperties = maxValidIndex End Function
二、同一机器上各文件夹的属性数量是否一致?
答案是基本一致:Shell属性的定义是系统级的,和具体文件夹无关。不管你访问的是普通文件夹、图片文件夹还是下载文件夹,底层可用的属性索引集合是相同的——只是某些属性在特定文件夹下可能没有对应的值(比如“拍摄日期”在普通文档文件夹中可能为空),但属性名称本身是存在的。
只有极少数特殊情况(比如第三方软件添加的自定义属性)可能在某些文件夹中不生效,但这种情况非常少见。
额外提示
如果你需要遍历所有属性值,拿到maxValidIndex后,就可以从0到这个索引循环调用GetDetailsOf,确保不会漏掉任何属性。另外,如果你发现某些属性在特定文件类型下才会有值,可以结合objFolder.Items中的具体文件来测试(比如用某个图片文件代替objFolder.Items,这样能看到针对该文件类型的专属属性)。
内容的提问来源于stack exchange,提问作者Ryszard Jędraszyk

