簡體   English   中英

將Powershell腳本嵌入VBA宏中並從那里運行

[英]Embed powershell script in VBA macro and run it from there

我正在嘗試編寫這些簡潔的代碼,並且在最后部分遇到一些重大問題。 因此,目的是編寫一個代碼,將其放入文件夾中的所有.zip文件中,按名稱在每個文件夾中找到一個文件夾,進入內部,找到以“ _nl.inp”結尾的文件,然后將其復制到存檔之外。

在挖掘VBA方面的想法時,我只能找到如何解壓縮整個存檔的方法,而不僅僅是找到文件並將其拉出。 但是我設法找到了如何使用Powershell語言來做到這一點。 因此,我編寫了一個功能精美的Powershell腳本。 該腳本在下面。

$zZipFileName = "C:\Users\ccapsun2\Desktop\New loads formatting\load decks"
      $shap = new-object -com shell.application
      $folderitems = get-childitem $zZipFileName
      foreach($archive in $folderitems){
        $archive.name.substring(0,$archive.name.length -4)
        $zipFile = $shap.Namespace($archive.fullname) 
        $i = $zipFile.items()
        foreach($si in $i){ 
            if($si.getfolder -ne $null){
                 if($si.name -eq "LR_Front_Upper_Control_Arm"){ 
                     $fileSearch = $si.getfolder.Items()
                     foreach($sii in $fileSearch){
                         if ($sii.name.substring(($sii.name.length - 7),7) -eq "_nl.inp"){
                              $shap.namespace($zZipFileName).copyhere($sii)
                              rename-item ($zZipFileName + "\" + $sii.name) -newname ($archive.name.substring(0,$archive.name.length -4) + ".inp")
                         }
                     }
                 } 
            }
        }
     }

現在,此腳本可以正常工作,但我需要將其傳遞給$ zZipFileName的變量以及我的vba代碼中的字符串“ LR_Front_Upper_Control_Arm”,並且我還想將此Powershell腳本嵌入到我的VBA代碼中,以便所有這些-包含一張Excel工作表。 這將被我的團隊中其他人使用,他們對編程一無所知,我或者他們都不希望花費時間教育他們他們具有多個腳本文件和類似的東西。

我將繼續自己進行研究,但希望在這里能有所幫助。 到目前為止,我用VBA代碼嘗試過的操作如下

ShellVar = Shell("$zZipFileName = """ & folderPath & """" & vbNewLine & _
      "$shap = new-object -com shell.application" & vbNewLine & _
      "$folderitems = get-childitem $zZipFileName" & vbNewLine & _
      "foreach($archive in $folderitems){" & vbNewLine & _
      "$archive.name.substring(0,$archive.name.length -4)" & vbNewLine & _
      "$zipFile = $shap.Namespace($archive.fullname)" & vbNewLine & _
      "$i = $zipFile.items()" & vbNewLine & _
      "foreach($si in $i){" & vbNewLine & _
      "if($si.getfolder -ne $null){" & vbNewLine & _
      "if($si.name -eq """ & targetFolderName & """){" & vbNewLine & _
      "$fileSearch = $si.getfolder.Items()" & vbNewLine & _
      "foreach($sii in $fileSearch){" & vbNewLine & _
      "if ($sii.name.substring(($sii.name.length - 7),7) -eq ""_nl.inp""){" & vbNewLine & _
      "$shap.namespace($zZipFileName).copyhere($sii)" & vbNewLine & _
      "rename-item ($zZipFileName + ""\"" + $sii.name) -newname ($archive.name.substring(0,$archive.name.length -4) + "".inp"")" & vbNewLine & _
      "}" & vbNewLine & _
      "}" & vbNewLine & _
      "}" & vbNewLine & _
      "}" & vbNewLine & _
      "}" & vbNewLine & _
      "}", vbHide)

為了嘗試查看它如何工作,並產生更小的恐慌,並提示您首先需要將cmd窗口置於Powershell模式,我嘗試了以下小命令:

Shell "powershell && new-item 'C:\Users\ccapsun2\Desktop\New loads formatting\load decks\LR_Front_Upper_Control_Arm' -itemtype directory", vbNormalFocus

很好的舊互聯網建議使用&&將使cmd窗口按順序使用命令,但再次無效。

我也嘗試了以下鏈接的建議,但也沒有成功。

大約3天以來,我一直在緩慢前進,以挫敗為代價。 任何幫助將非常感激。 我可能會精神崩潰,並很快開始哭泣哈哈。

不是您的Powershell問題的答案,但是這是您在VBA中的解決方法。 我喜歡這種非遞歸方法來遍歷“常規”(非壓縮)子文件夾,並設法使其適應於zip存檔。

調整以適合!

Public Sub UnzipSpecificFiles()

    Const LOCAL_ZIP As Variant = "C:\_Stuff\temp\test.zip"
    Const DEST_FLDR As Variant = "C:\_Stuff\temp\"

    Dim Sh As Object, ns, itm, colFolders, fldr

    Set Sh = CreateObject("Shell.Application")

    Set colFolders = New Collection '<< zip folders to be processed
    colFolders.Add LOCAL_ZIP     '<<    ...starting here

    Do While colFolders.Count > 0
        Set fldr = Sh.Namespace(colFolders(1))
        colFolders.Remove 1
        For Each itm In fldr.Items
            If itm.IsFolder Then
                'add this subfolder to the collection for processing
                colFolders.Add fldr.self.Path & "\" & itm.Name
            Else
                'is a file, so see if it's the one we want...
                If itm.Name Like "*_nl.inp" Then
                    Debug.Print itm.Name
                    Sh.Namespace(DEST_FLDR).CopyHere itm
                    Exit Do '<< if you only expect one match
                End If
            End If
        Next itm
    Loop

End Sub

Tim的答案比我過於復雜的解決方案要好得多,但是如果有人想知道如何使它起作用,我將代碼更改為如下所示。

Public FSO As New FileSystemObject
Dim b
Set b = VBA.CreateObject("WScript.Shell")
Set a = FSO.CreateTextFile("C:\Temp\temp.ps1")
a.WriteLine ("$zZipFileName = '" & folderPath & "'")
a.WriteLine ("      $shap = new-object -com shell.application")
a.WriteLine ("      $folderitems = get-childitem $zZipFileName")
a.WriteLine ("      foreach($archive in $folderitems){")
a.WriteLine ("        $archive.name.substring(0,$archive.name.length -4)")
a.WriteLine ("        $zipFile = $shap.Namespace($archive.fullname)")
a.WriteLine ("        $i = $zipFile.items()")
a.WriteLine ("        foreach($si in $i){")
a.WriteLine ("            if($si.getfolder -ne $null){")
a.WriteLine ("                 if($si.name -eq '" & targetFolderName & "'){")
a.WriteLine ("                     $fileSearch = $si.getfolder.Items()")
a.WriteLine ("                     foreach($sii in $fileSearch){")
a.WriteLine ("                         if ($sii.name.substring(($sii.name.length - 7),7) -eq '_nl.inp'){")
a.WriteLine ("                              $shap.namespace($zZipFileName).copyhere($sii)")
a.WriteLine ("                              rename-item ($zZipFileName + '\' + $sii.name) -newname ($archive.name.substring(0,$archive.name.length -4) + '.inp')")
a.WriteLine ("                         }")
a.WriteLine ("                     }")
a.WriteLine ("                 }")
a.WriteLine ("            }")
a.WriteLine ("         }")
a.WriteLine ("      }")

ShellVar.Run "powershell ""C:\Temp\temp.ps1""", vbNormalFocus

最后一個問題是,我無法弄清楚如何使VBA代碼等待powershell腳本完成。 我嘗試在.Run命令的末尾添加, WaitOnReturn ,但沒有等待。 如果那是固定的,那么我只會添加一些東西來擺脫創建的腳本文件。 Kill a

folderPath和targetFolderName是從主宏傳遞的變量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM