#xml #powershell #powershell-7.0
#excel #powershell #вывод
Вопрос:
Использование borderround выдает «True» на консоль.
$range = $sum_wksht.Range('B{0}:G{0}' -f ($crow))
$range.BorderAround(1, -4138)
Это можно преодолеть, используя одно из следующих действий.
$wasted = $range.BorderAround(1, -4138)
[void]$range.BorderAround(1, -4138)
Зачем это нужно? Я неправильно создаю диапазон? Есть ли лучший обходной путь?
Комментарии:
1. согласно тому, что я могу найти на сайте MSDocs, этот метод имеет возвращаемый объект. я не могу найти , что это такое … но
True
обычно это сообщение об успехе «это сработало». обычно это подавляется присваиванием$Null =
, приведением к void[void]$range.BorderAround(1, -4138)
или использованием| Out-Null
. 2-й самый быстрый, 1-й самый распространенный, 3-й намного медленнее, чем два других. скорость не имеет значения, если вы не делаете это часто , тхо. [ усмешка ]
Ответ №1:
Зачем это нужно?
Это необходимо, потому что BorderAround
метод имеет возвращаемое значение, а в PowerShell любая команда или выражение ...
, которые выводят (возвращают) данные, неявно выводятся в поток вывода (успешного), который по умолчанию отправляется на хост, который обычно является консольным окном (терминалом), в котором выполняется сеанс PowerShell.
То есть данные отображаются в консоли / терминале, если это не:
- захваченный (
$var = ...
) - отправляется по конвейеру для дальнейшей обработки (
... | ...
; команда последнего сегмента конвейера может выдавать или не выдавать сам вывод) - перенаправлено (
... >
)
или любая их комбинация.
То есть:
$range.BorderAround(1, -4138)
является (более эффективным) сокращением для:
Write-Output $range.BorderAround(1, -4138)
(Явное использование Write-Output
редко требуется.)
Поскольку вам не нужен этот вывод, вы должны его подавить, для чего у вас есть несколько вариантов:
$null = ...
[void] (...)
... > $null
... | Out-Null
$null = ...
может быть лучшим общим выбором, потому что:
- Он передает намерение подавить заранее
- Хотя
[void] = (...)
это тоже так, часто требуется, чтобы вы заключали выражение в(...)
по синтаксическим причинам; например,[void] 1 2
работает не так, как задумано, только[void] (1 2)
; аналогично, команда всегда должна быть заключена в(...)
;[void] New-Item test.txt
не работает, только[void] (New-Item test.txt)
делает.
- Хотя
- Он хорошо работает как с выводом команд (например,
$null = Get-AdUser ...
), так и с выводом выражений (например,$null = $range.BorderAround(1, -4138)
).
И наоборот, избегайте ... | Out-Null
, потому что это обычно намного медленнее (за исключением крайнего случая вывода выражения без побочных эффектов в PowerShell (Core) 6 ) [1].
Однако, если вам нужно отключить все выходные потоки — не только успешный вывод, но и ошибки, подробный вывод, … — вы должны использовать *> $null
Почему PowerShell выдает вывод неявно?
- Как оболочка, поведение вывода PowerShell основано на потоках, как в традиционных оболочках, таких как
cmd.exe
или Bash. (В то время как традиционные оболочки имеют 2 выходных потока — stdout и stderr — PowerShell имеет 6, чтобы обеспечить более сложную функциональность — см. about_Redirection .)- Командлет, скрипт или функция могут выполнять запись в выходные потоки так часто, как они хотят, и такие выходные данные обычно мгновенно доступны для отображения, но особенно для потенциальных потребителей, что позволяет выполнять потоковую обработку по очереди, которую обеспечивает конвейер.
- Это контрастирует с традиционными языками программирования, поведение вывода которых основано на возвращаемых значениях, обычно предоставляемых с помощью
return
ключевого слова, которое объединяет выходные данные (возвращаемое значение) с управлением потоком (выход из области видимости и возврат к вызывающему).- Частая ошибка заключается в том, что
return
оператор PowerShell должен действовать одинаково, но это не так:return <val>
это просто синтаксический сахар для<val>; return
, т. Е. Неявный вывод<val>
, за которым следует безусловный возврат управления вызывающей стороне; примечательно, что использованиеreturn
не исключает генерации вывода из более ранних операторов в той же области.
- Частая ошибка заключается в том, что
- В отличие от традиционных оболочек, PowerShell не требует явной команды записи в поток вывода для получения выходных данных:
- Хотя у PowerShell есть аналог
echo
, а именноWrite-Output
, его использование требуется редко.- Среди редких случаев, когда
Write-Output
полезно предотвратить перечисление коллекции при выводе с-NoEnumerate
помощью или использовать общий параметр-OutVariable
как для выходных данных, так и для записи их в переменную (что обычно требуется только для выражений, поскольку поддерживаются сами командлеты и расширенные функции / скрипты-OutVariable
).
- Среди редких случаев, когда
- Неявное поведение вывода:
- как правило, это благо:
- для интерактивного экспериментирования — просто введите любое утверждение, особенно включая такие выражения, как
[IO.Path]::GetExtension('foo.txt')
и[math]::Pow(2, 32)
— и посмотрите его результат (похожий на поведение REPL). - для написания краткого кода, в котором не нужно описывать подразумеваемое поведение (см. Пример ниже).
- для интерактивного экспериментирования — просто введите любое утверждение, особенно включая такие выражения, как
- иногда это может быть ловушкой:
- для пользователей, привыкших к семантике традиционных языков программирования.
- из-за потенциального случайного загрязнения выходного потока операторами, которые не ожидают получения выходных данных, например, в вашем случае; более типичным примером является
.Add()
метод[System.Collections.ArrayList]
класса, неожиданно производящий выходные данные.
- как правило, это благо:
- Хотя у PowerShell есть аналог
Пример:
# Define a function that takes an array of integers and
# outputs their hex representation (e.g., '0xa' for decimal 10)
function Get-HexNumber {
param([int[]] $numbers)
foreach ($i in $numbers) {
# Format the integer at hand
# *and implicitly output it*.
'0x{0}' -f $i.ToString('x')
}
}
# Call the function with integers 0 to 16 and loop over the
# results, sleeping 1 second between numbers.
Get-HexNumber (0..16) | ForEach-Object { "[$_]"; Start-Sleep 1 }
Вышесказанное приводит к следующему:
[0x0]
# 1-second pause
[0x1]
# 1-second pause
[0x2]
...
[0x10]
Это демонстрирует потоковый аспект поведения: Get-HexNumber
выходные данные доступны для ForEach-Object
вызова командлета по мере его создания, а не после Get-HexNumber
завершения.
[1] В PowerShell (Core) 6 Out-Null
имеет оптимизацию, если единственный предыдущий сегмент конвейера является выражением без побочных эффектов, а не вызовом метода или команды; например, 1..1e6 | Out-Null
выполняется почти мгновенно, потому что выражение, по-видимому, даже не выполняется. Однако такой сценарий нетипичен, и выполнение функционального эквивалента Write-Output (1..1e6) | Out-Null
занимает много времени, намного дольше, чем $null = Write-Output (1..1e6)
.