打开 ZipFile,查找特定文件类型并保存文件名

Posted

技术标签:

【中文标题】打开 ZipFile,查找特定文件类型并保存文件名【英文标题】:Open ZipFile, Look for Specific File Type And Save File Name 【发布时间】:2019-08-11 03:33:47 【问题描述】:

所以我在这里发布了一个问题:

VBA - Find Specific Sub Folders by Name Identifiers

这个问题非常广泛,但我遇到了需要帮助识别和解决的具体问题。现在,我设法在原始帖子中解决了这些问题,但是,仍有很大一部分问题没有得到解答,我只想在能够发布完整结果时关闭问题。

目前,我还需要做的,最后 4 个步骤:

    打开压缩文件 寻找 .png 扩展名 获取 .png 文件的名称 在 Excel 的单元格中输入名称

我面临的问题是正确打开 zip 文件。我浏览过很多关于这方面的帖子,但似乎没有什么对我有用。

我最接近完成任务的是我在这里找到的:

https://www.ozgrid.com/forum/forum/help-forums/excel-general/109333-how-to-count-number-of-items-in-zip-file-with-vba-2007

我想,如果至少我能够输入 zip 文件,我就可以从那里开始工作。但是,唉,我仍然停留在简单地尝试打开文件。

这是我的代码(使用上面的链接):

Sub CountZipContents()

    Dim zCount As Double, CountContents As Double
    Dim sh As Object, fld As Object, n As Object
    Dim FSO As Object

    CountContents = 0
    zCount = 0

    x = "C:\Users\UserName\Desktop\Today\MyFolder\"

    Set FSO = CreateObject("Scripting.FileSystemObject")

    If FSO.FolderExists(x) Then

        For Each FileInFolder In FSO.GetFolder(x).Files

            If Right(FileInFolder.Name, 4) = ".png" Then

                CountContents = CountContents + 1

            ElseIf Right(FileInFolder.Name, 4) = ".Zip" Then

                Set sh = CreateObject("Shell.Application")
                Set ZipFile = sh.Namespace(CVar(x & "\" & FileInFolder.Name))

                Debug.Print FileInFolder.Name

                For Each fileInZip In ZipFile.Items

                    If LCase(fileInZip) Like LCase("*.png") Then

                        CountContents = CountContents + 1

                    End If

                Next

            End If

        Next FileInFolder

    End If

    Set sh = Nothing

End Sub

我得到的问题是在这一行:

For Each fileInZip In ZipFile.Items

错误信息:

对象变量或未设置块

每当我尝试使用Shell 时,如下所示:

Dim oShell As New Shell

我收到此错误:

用户自定义类型未定义

以下内容:

链接https://msdn.microsoft.com/en-us/library/windows/desktop/bb776890(v=vs.85).aspx

Dim oApp As Object

Set oApp = CreateObject("WScript.Shell")

'get a shell object
Set oApp = CreateObject("Shell.Application")

If oApp.Namespace(ZipFile).Items.count > 0 Then

我收到此错误:

对象不支持该属性或方法

在这一行:

If oApp.Namespace(ZipFile).Items.count > 0 Then

对我尝试过的链接的引用:

https://wellsr.com/vba/2015/tutorials/open-and-close-file-with-VBA-Shell/ http://www.vbaexpress.com/forum/showthread.php?38616-quot-shell-quot-not-work-in-Excel Excel VBA - read .txt from .zip files

我只是不明白为什么这一步要花这么多时间才能完成。

【问题讨论】:

第一期;我没有看到您定义了 FileInZip 是什么。对于第二个问题,您还没有定义 Shell 是什么。 VBA 正在寻找这两者的对象引用。 @ZackE 谢谢你的回复。根据我的理解,FileInZip 将只是ZipFile 中的一个元素。类似于未定义FileInFolder,但填充了基本文件夹中文件变量的空白。请参阅此行FileInFolder In FSO.GetFolder(x).Files。没有定义Shell 的第二个问题是 1) 在我发现的每个示例中,没有人“定义”Shell,他们只是像引用任何其他数据类型一样引用它。 2)如果有要添加的参考,我不知道,我似乎也找不到。 【参考方案1】:

您的主要问题是一个非常简单的问题:您的路径"C:\Users\UserName\Desktop\Today\MyFolder\" 已经包含一个尾部反斜杠,并且当您设置您的ZipFile-变量时,您在路径和文件名之间添加了另一个。这将导致shell-command 失败并且ZipFilenothing

代码存在一些小问题。我建议使用 FileSystemObject 的GetExtensionName 来获取扩展名并将其转换为小写,以便捕获所有文件,无论它们是.PNG.png 还是.Png

   For Each FileInFolder In FSO.GetFolder(x).Files
        Dim fileExt As String
        fileExt = LCase(FSO.GetExtensionName(FileInFolder.Name))

        If fileExt = "png" Then
            CountContents = CountContents + 1
            Debug.Print "unzipped " & FileInFolder.Name
        ElseIf fileExt = "zip" Then

            Dim ZipFileName As String, ZipFile, fileInZip
            Set sh = CreateObject("Shell.Application")
            ZipFileName = x & FileInFolder.Name
            Set ZipFile = sh.Namespace(CVar(ZipFileName))

            For Each fileInZip In ZipFile.Items
                If LCase(FSO.GetExtensionName(fileInZip)) = "png" Then
                    CountContents = CountContents + 1
                    Debug.Print "zipped in " & FileInFolder.Name & ": " & fileInZip
                End If
            Next
        End If
    Next FileInFolder

另外强烈建议使用Option Explicit 并定义所有变量。并将命令拆分成更小的部分。这只需花费您几秒钟的时间输入额外的行,但在调试代码时会有所帮助:

' Instead of
' Set ZipFile = sh.Namespace(CVar(x & "\" & FileInFolder.Name)) 
' write
Dim fName as string
fName = x & "\" & FileInFolder.Name; ' Now you can check fName and see the problem.
Set ZipFile = sh.Namespace(CVar(fName))

【讨论】:

非常感谢!!!也感谢您的建议,我计划稍后通过代码修复它并使其更清洁和高效,但您至少给出了一些关于从哪里开始的建议。非常感谢你,我的大脑已经因为试图弄清楚它而感到疼痛。这工作100%! :)【参考方案2】:

试试这个:

Option Explicit

' Just to test CheckZipFolder
Sub TestZip()

    Dim sZipFold As String: sZipFold = "C:\Temp\MyZip.zip"      ' Change this to the path to your zip file
    CheckZipFolder sZipFold

End Sub


Sub CheckZipFolder(ByVal sZipFold As String)

    Dim oSh As New Shell        ' For this, you need to add reference to 'Microsoft Shell Controls and Automation'
    Dim oFi As Object

    ' Loop through all files in the folder
    For Each oFi In oSh.Namespace(sZipFold).Items

        ' Checking for file type (excel file in this case)
        If oFi.Type = "Microsoft Excel Worksheet" Then
            MsgBox oFi.Name
            '..... Add your actions here
        End If

        ' This will make the UDF recursive. Remove this code if not needed
        If oFi.IsFolder Then
            CheckZipFolder oFi.Path
        End If
    Next

    ' Clear object
    Set oSh = Nothing

End Sub

【讨论】:

感谢您的回答 :) 首先,非常感谢您告诉我 Shell 使用哪个参考。其次,我没有收到任何错误,但话虽如此,If Statement 似乎没有找到匹配项,即使 zip 文件夹中有一个 .xls 文件。

以上是关于打开 ZipFile,查找特定文件类型并保存文件名的主要内容,如果未能解决你的问题,请参考以下文章

打开不支持的压缩类型的 zipfile 静默返回空文件流,而不是抛出异常

如何在 Java 中使用 ZipFile 类递归打开所有文件,包括文件夹下的文件

下载和打开 zipfile

遍历已安装的卷以查找特定的文件类型

如何读取 zip 文件的内容并保存文件

Python zipfile:RuntimeError:文件密码错误