Вставьте скрипт powershell в макрос VBA и запустите его оттуда - PullRequest
0 голосов
/ 28 июня 2018

Я пытаюсь написать этот аккуратный кусочек кода и у меня возникают серьезные проблемы с последним кусочком. Таким образом, предполагалось написать код, который вошел бы во все 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, и строку «LR_Front_Upper_Control_Arm» из моего кода VBA, и я также хочу встроить этот скрипт 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 дней. Любая помощь приветствуется. У меня, вероятно, будет психическое расстройство и я скоро заплачу, ха-ха.

Ответы [ 2 ]

0 голосов
/ 29 июня 2018

Ответ Тима намного лучше, чем мое слишком сложное решение, но если кто-то когда-нибудь задумывается, как заставить его работать, я изменил код так, как показано ниже.

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. Я попытался добавить , WaitOnReturn в конце команды .Run, но это не ожидало. Если это будет исправлено, я бы только добавил что-то, чтобы избавиться от созданного файла скрипта. Что-то вроде Kill a.

folderPath и targetFolderName являются переменными, передаваемыми из основного макроса.

0 голосов
/ 28 июня 2018

Не ответ на вашу проблему с 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...