Почему Range.Borderround выдает «True» на консоль?

#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] класса, неожиданно производящий выходные данные.

Пример:

 # 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) .