Вопрос или проблема
Следующая пакетная команда генерирует число – количество файлов, размер которых больше порогового значения, в данном случае 512K, хотя подсчет неверен на 1.
forfiles /P C:\ /M *.* /S /C "CMD /C if @fsize gtr 512000 echo @PATH @FSIZE"|findstr /r /n "^" |find /c ":"
Как захватить вывод в VBA?
Я нашел статью, которая делает то же самое, но ответ, по моему мнению, довольно сложный. Мне интересно, есть ли более простой способ захватить вывод, например, присвоив целое число командной строке?
Вы можете попробовать использовать метод Exec объекта Shell.
Например:
Dim WSH As WshShell
Dim sOut As String
Set WSH = New WshShell
sOut = WSH.Exec("your_cmd_string").StdOut.ReadAll
Одной из проблем, с которой я столкнулся при использовании этого метода, является то, что окно командной строки остается открытым во время выполнения команды. Его можно скрыть, но для этого потребуются вызовы API Windows.
В результате, при запуске команд оболочки из VBA я использую метод Run
с аргументом Hidden
и перенаправляю результаты в временный файл.
Ответ или решение
Для захвата вывода числового значения из командной строки в среде VBA часто используется метод Shell
. Однако этот метод имеет ограничения, особенно если необходимо получить результат выполнения команды без открытия командного окна. В таком случае более подходящим вариантом будет использование объекта WshShell
и метода Exec
, что позволит реализовать более гибкий способ работы. В этой статье мы подробно рассмотрим, как это сделать.
Работа с WshShell и Exec в VBA
Для начала необходимо убедиться, что у вас установлен объект Windows Script Host
. Это позволит вам работать с объектом WshShell
в вашем коде. Чтобы использовать этот объект, необходимо сделать следующее:
-
Добавьте ссылку на библиотеку:
- Откройте редактор VBA (нажмите
Alt + F11
в Excel, например). - Перейдите в
Tools
>References
. - Найдите и отметьте
Microsoft Scripting Runtime
(если требуется).
- Откройте редактор VBA (нажмите
-
Пример кода для выполнения команды и захвата вывода:
Используйте следующий код, который выполняет вашу команду и захватывает вывод в переменную:
Sub CaptureShellOutput()
Dim WSH As Object
Dim Exec As Object
Dim Command As String
Dim Output As String
Dim FilePath As String
Dim TempFile As String
Dim FileNum As Integer
' Указываем команду для выполнения
Command = "forfiles /P C:\ /M *.* /S /C ""CMD /C if @fsize gtr 512000 echo @PATH @FSIZE"" | findstr /r /n ""^"" | find /c "":""
' Создаем объект WshShell
Set WSH = CreateObject("WScript.Shell")
' Захватываем вывод в временный файл
TempFile = Environ("TEMP") & "\temp_output.txt"
Command = Command & " > """ & TempFile & """"
' Выполняем команду
WSH.Run Command, 0, True ' 0 - скрыть окно, True - дождаться завершения
' Открываем временный файл для чтения
FileNum = FreeFile
Open TempFile For Input As FileNum
Line Input #FileNum, Output ' Читаем результат
Close FileNum
' Печатаем или используем результат
MsgBox "Количество файлов: " & Output
' Удаляем временный файл
Kill TempFile
End Sub
Объяснение кода
- Настройка команды: Мы формируем строку команды, которая будет выполнена. Важно использовать двойные кавычки (
""
), чтобы избежать ошибок синтаксиса. - Создание объекта WshShell: Используя
CreateObject("WScript.Shell")
, мы инициализируем объект для выполнения команд. - Запуск команды: Метод
Run
используется для выполнения команды. Параметры0
иTrue
скрывают окно командной строки и заставляют VBA ожидать её завершения. - Чтение результата: Результаты команды сохраняются во временный файл, который затем мы открываем и читаем.
- Вывод результата: Результат выводится в виде сообщения, который мы можем использовать в дальнейшем.
- Удаление временного файла: Важно очищать временные файлы после их использования, чтобы не засорять файловую систему.
Заключение
Хотя использование метода Exec
может показаться более интуитивным, подход с временными файлами дает вам полный контроль над процессом и позволяет избежать множества проблем, связанных с отображением окон и синхронным виконанием. Данный метод также предоставляет гибкость, позволяя манипулировать выводом команды как необходимо. Таким образом, вышеуказанный пример является оптимальным решением для захвата числовых результатов из командной строки в среде VBA.