В это статье мы покажем, как получить доступ к данным в файлах Excel напрямую из PowerShell. Возможности прямого обращения к данным Excel из PowerShell открывает широкие возможности по инвентаризации и построению различных отчетов по компьютерам, серверам, инфраструктуре, Active Directory и т.д.
Содержание:
- Доступ к данным в Excel из консоли PowerShell
- Как получить данные из Active Directory и сохранить их в книге Excel?
Обращение к Excel из PowerShell выполняется через отдельный Component Object Model (COM) объект. Это требует наличие установленного Excel на компьютере.
Прежде, чем показать, как обратиться к данным в ячейке файла Excel, необходимо рассмотреть архитектуру уровней представления в документе Excel. На следующем рисунке показаны 4 вложенных уровня в объектной модели Excel:
- Уровень приложения (Application Layer) – запущенное приложение Excel;
- Уровень книги (WorkBook Layer) – одновременно могут быть открыты несколько книг (документов Excel);
- Уровень листа (WorkSheet Layer) – в каждом xlsx файле может быть несколько листов;
- Ячейки (Range Layer) – здесь можно получить доступ к данным в конкретной ячейке или диапазонe ячеек.
Доступ к данным в Excel из консоли PowerShell
Рассмотрим на простом примере как получить доступ из PowerShell к данным в Excel файле со списком сотрудников.
Сначала нужно запустить на компьютере приложение Excel (application layer) через COM объект:
$ExcelObj = New-Object -comobject Excel.Application
После выполнения этой команды на компьютере запускается в фоновом режиме приложение Excel. Чтобы сделать окно Excel видимым, нужно изменить свойство Visible COM объекта:
$ExcelObj.visible=$true
Все свойства объекта Excel можно вывести так:
$ExcelObj| fl
Теперь можно открыть файл (книгу, workbook) Excel:
$ExcelWorkBook = $ExcelObj.Workbooks.Open("C:PSad_users.xlsx")
В каждом файле Excel может быть несколько листов (worksheets). Выведем список листов в текущей книге Excel:
$ExcelWorkBook.Sheets| fl Name, index
Теперь можно открыть конкретный лист (по имени или по индексу):
$ExcelWorkSheet = $ExcelWorkBook.Sheets.Item("AD_User_List")
Текущий (активный) лист Excel можно узнать командой:
$ExcelWorkBook.ActiveSheet | fl Name, Index
Теперь вы можете получить значения из ячеек документа Excel. Можно использовать различные способы адресации ячеек в книге Excel: через диапазон (Range), ячейку (Cell), столбец (Columns) или строку(Rows). Ниже я привел разные примеры получения данных из одной и той же ячейки:
$ExcelWorkSheet.Range("B2").Text
$ExcelWorkSheet.Range("B2:B2").Text
$ExcelWorkSheet.Range("B2","B2").Text
$ExcelWorkSheet.cells.Item(2, 2).text
$ExcelWorkSheet.cells.Item(2, 2).value2
$ExcelWorkSheet.Columns.Item(2).Rows.Item(2).Text
$ExcelWorkSheet.Rows.Item(2).Columns.Item(2).Text
Как получить данные из Active Directory и сохранить их в книге Excel?
Рассмотрим практический пример использования доступа к данным Excel из PowerShell. Например, нам нужно для каждого пользователя в Excel файле получить информацию из Active Directory. Например, его телефон (атрибут telephoneNumber), отдел (department) и email адрес (mail).
# Импорт модуля Active Directory в сессию PowerShell
import-module activedirectory
# Сначала откройте книгу Excel:
$ExcelObj = New-Object -comobject Excel.Application
$ExcelWorkBook = $ExcelObj.Workbooks.Open("C:PSad_users.xlsx")
$ExcelWorkSheet = $ExcelWorkBook.Sheets.Item("AD_User_List")
# Получаем количество заполненных строк в xlsx файле
$rowcount=$ExcelWorkSheet.UsedRange.Rows.Count
# Перебираем все строки в столбце 1, начиная со второй строки (в этих ячейках указано доменное имя пользователя)
for($i=2;$i -le $rowcount;$i++){
$ADusername=$ExcelWorkSheet.Columns.Item(1).Rows.Item($i).Text
# Получаем значение атрибутов пользователя в AD
$ADuserProp = Get-ADUser $ADusername -properties telephoneNumber,department,mail|select-object name,telephoneNumber,department,mail
#Заполняем ячейки данными из AD
$ExcelWorkSheet.Columns.Item(4).Rows.Item($i) = $ADuserProp.telephoneNumber
$ExcelWorkSheet.Columns.Item(5).Rows.Item($i) = $ADuserProp.department
$ExcelWorkSheet.Columns.Item(6).Rows.Item($i) = $ADuserProp.mail
}
#Сохраните xls файл и закройте Excel
$ExcelWorkBook.Save()
$ExcelWorkBook.close($true)
В результате в Excel файле для каждого пользователя были добавлены столбцы с информацией из AD.
Рассмотрим еще один пример построения отчета с помощью PowerShell и Excel. Допустим, вам нужно построить Excel отчет о состоянии службы Print Spooler на всех серверах домена.
# Создать объект Excel
$ExcelObj = New-Object -comobject Excel.Application
$ExcelObj.Visible = $true
# Добавить рабочую книгу
$ExcelWorkBook = $ExcelObj.Workbooks.Add()
$ExcelWorkSheet = $ExcelWorkBook.Worksheets.Item(1)
# Переименовывать лист
$ExcelWorkSheet.Name = 'Статус сервиса spooler'
# Заполняем шапку таблицы
$ExcelWorkSheet.Cells.Item(1,1) = 'Имя сервера'
$ExcelWorkSheet.Cells.Item(1,2) = 'Имя службы'
$ExcelWorkSheet.Cells.Item(1,3) = 'Статус службы'
# Выделить шапку таблицы жирным. задать размер шрифта и ширину столбцов
$ExcelWorkSheet.Rows.Item(1).Font.Bold = $true
$ExcelWorkSheet.Rows.Item(1).Font.size=14
$ExcelWorkSheet.Columns.Item(1).ColumnWidth=25
$ExcelWorkSheet.Columns.Item(2).ColumnWidth=25
$ExcelWorkSheet.Columns.Item(3).ColumnWidth=25
# получим список всех Windows Server в домене
$computers = (Get-ADComputer -Filter 'operatingsystem -like "*Windows server*" -and enabled -eq "true"').Name
$counter=2
# подключается к каждому компьютеру и получаем статус службы
foreach ($computer in $computers) {
$result = Invoke-Command -Computername $computer –ScriptBlock { Get-Service spooler | select Name, status }
#Заполняем ячейки Excel данными с сервера
$ExcelWorkSheet.Columns.Item(1).Rows.Item($counter) = $result.PSComputerName
$ExcelWorkSheet.Columns.Item(2).Rows.Item($counter) = $result.Name
$ExcelWorkSheet.Columns.Item(3).Rows.Item($counter) = $result.Status
$counter++
}
# сохраните полученный отчет и закройте Excel:
$ExcelWorkBook.SaveAs('C:psservice-report.xlsx')
$ExcelWorkBook.close($true)
Область применения возможностей доступа из PowerShell в Excel очень широка. Начиная от простого построения отчетов, например, из Active Directory, и заканчивая возможностью создания PowerShell скриптов для актуализации данных в AD из Excel.
Например, вы можете поручить сотруднику отдела кадров вести реестр пользователей в Excel. Затем с помощью PowerShell скрипта через Set-ADUser сотрудник может автоматически обновлять данные пользователей в AD (достаточно делегировать пользователю права на изменение этих атрибутов пользователей AD и показать как запускать PS скрипт). Таким образом можно вести актуальную адресную книгу с актуальными номерами телефонами и должностями.
January 10th, 2014
Summary: Microsoft PowerShell MVP, Tobias Weltner, talks about Windows PowerShell and Excel interaction.
Microsoft Scripting Guy, Ed Wilson, is here. Let’s welcome back guest blogger, Tobias Weltner…
Microsoft Excel is a great tool to share Windows PowerShell data. However, the scripting tactics have changed from the good old VBScript times. Let’s take a look at how Windows PowerShell can output data to Excel fast, safe, and reliably.
Out-GridView: Built-in “mini-Excel”
Before I touch Excel, let’s first look at its little cousin, which ships with Windows PowerShell: Out-GridView.
It’s trivial to use: simply pipe anything to Out-GridView, and it will happily display the content in a mini-spreadsheet:
Get-Process | Where-Object { $_.MainWindowTitle } | Out-GridView
You can even use Out-GridView as a generic selection dialog box. Add the parameter –passThru (added in PowerShell 3.0). This parameter adds two new buttons to the lower right area of the grid view, and when you select something, it will be returned to you.
Curious? This piece of script pipes all top-level applications to the grid view, and when you select one and click OK, it will be immediately deleted:
Get-Process |
Where-Object MainWindowTitle |
Out-GridView -Title ‘Select Program To Kill’ -PassThru |
Stop-Process
That’s admittedly a bit rude (and dangerous, too, because you will lose all unsaved data). So here is a gentleman’s version that will actually ask if there is unsaved data. It also allows the program to clean up its resources before it closes.
Get-Process |
Where-Object MainWindowTitle |
Out-GridView -Title ‘Select Program To Kill’ -PassThru |
ForEach-Object { $_.CloseMainWindow() }
Excel: Out-GridView on steroids
So what about Excel? Why use it at all? Well, there are things that Out-GridView cannot do. You cannot save the data, and you cannot hand it over to someone else. And of course, you cannot use the many sophisticated formatting options that are found in Microsoft Excel spreadsheets.
Out-GridView can show a maximum of 30 columns. So if an object has more than 30 properties, Out-GridView silently suppresses the rest. I’d call this a bug, but maybe it’s a feature, too. Anyhow, here is a script to prove the point:
1..100 |
ForEach-Object { $hash = [Ordered]@{} }{$hash.”Column$_” = $_}{ New-Object PSObject -Property $hash} | Out-GridView
This creates an object with 100 properties. Out-GridView only displays the first 30. Time for Excel…the real thing.
Wouldn’t it be nice to be able to do this:
Get-Process | Where-Object { $_.MainWindowTitle } | Out-Excel
Or, for that matter, this (and finally get all object properties and not just the first 30):
1..100 |
ForEach-Object { $hash = [Ordered]@{} }{$hash.”Column$_” = $_}{ New-Object PSObject -Property $hash} |
Out-Excel
Well, you can.
Out-Excel actually is a ridiculously simple Windows PowerShell function:
function Out-Excel
{
param($Path = “$env:temp$(Get-Date -Format yyyyMMddHHmmss).csv”)
$input | Export-CSV -Path $Path -UseCulture -Encoding UTF8 -NoTypeInformation
Invoke-Item -Path $Path
}
Get-Process | Where-Object { $_.MainWindowTitle } | Out-Excel
You get a report that includes all the technical data from all of your running main applications. With all of the object properties—nothing is left out.
Basically, you can pipe anything into Out-Excel. It works pretty much like Out-GridView (except that you cannot turn Excel into a selection dialog, of course).
$input is an automatic Windows PowerShell variable. It delivers all data that is piped from the upstream cmdlet, and this data is then written to a CSV file and opened with Excel.
Because Excel always shows all properties, you may want to use Select-Object and select only the properties you really care about:
Get-Process |
Where-Object { $_.MainWindowTitle } |
Select-Object -Property Name, Company, Description, CPU |
Out-Excel
Writing directly to Excel
Going the CSV route is fast and robust, but cannot use color in cells or apply any other formatting.
That’s why some years ago in VBScript, people started to use a COM object to access the Excel object model. Although this works in Windows PowerShell, too, it is not very reliable anymore. Excel lives in the old COM world, and Windows PowerShell lives in the modern .NET world.
The underlying .NET Framework needs extensive marshalling to access the COM objects (which makes it very slow). In some scenarios, it fails altogether, for example, when type libraries do not fit together because operating system and office binaries use different locales. Even if everything works, and you waited for the code to finish, Excel will continue to linger in memory because of leaking handles. It’s just too complicated.
Here is sample code that does access Excel’s object model directly. You have been warned. Don’t be mad at me if the code fails or is really, really slow:
$excel = New-Object -ComObject Excel.Application
$excel.Visible = $true
$workbook = $excel.Workbooks.Add()
$sheet = $workbook.ActiveSheet
$counter = 0
Get-Service |
ForEach-Object {
$counter++
$sheet.cells.Item($counter,1) = $_.Name
$sheet.cells.Item($counter,2) = $_.DisplayName
$sheet.cells.Item($counter,3) = $_.Status
}
Here is the fast and clean way that is used by Windows PowerShell to create the same report:
Get-Service |
Select-Object -Property Name, DisplayName, Status |
Export-Csv -Path $env:tempreport.csv -Encoding UTF8 -UseCulture -NoTypeInformation
Invoke-Item -Path $env:tempreport.csv
Actually, Windows PowerShell is not even touching the internals of Excel; but instead, it is producing CSV files that can then be opened by Excel.
Formatting data with colors
Unfortunately, importing CSV data is a black and white world. You cannot use color in cells or format the spreadsheet otherwise.
Well actually, you can. This will create the very same report of services. This time, running services will show in green and stopped services in red.
# write HTML intro code:
$begin =
{
‘<table>’
‘<tr>’
‘<th>DisplayName</th><th>Status</th><th>Required</th><th>Dependent</th>’
‘</tr>’
}
# this is executed for each data object:
$process =
{
if ($_.Status -eq ‘Running’)
{
$style = ‘<td style=”color:green; ; font-family:Segoe UI; font-size:14pt”>’
}
else
{
$style = ‘<td style=”color:red; font-family:Segoe UI; font-size:14pt”>’
}
‘<tr>’
‘{0}{1}</td><td>{2}</td><td>{3}</td><td>{4}</td>’ -f $style, $_.DisplayName, $_.Status, ($_.RequiredServices -join ‘,’), ($_.DependentServices -join ‘,’)
‘</tr>’
}
# finish HTML fragment:
$end =
{
‘</table>’
}
$Path = “$env:temptempfile.html”
# get all services and create custom HTML report:
Get-Service |
ForEach-Object -Begin $begin -Process $process -End $end |
Set-Content -Path $Path -Encoding UTF8
# feed HTML report into Excel:
Start-Process -FilePath ‘C:Program Files*Microsoft OfficeOffice*EXCEL.EXE’ -ArgumentList $Path
The trick is to create an HTML report that gives you all the formatting opportunities you need. To create a Excel spreadsheet with color, the HTML file needs to be fed directly into excel.exe.
Note how Windows PowerShell automatically identifies the Excel version you use. Start-Process accepts a file path that can contain wildcard characters. By replacing version numbers in the path, Windows PowerShell can launch any Excel version that happens to be installed.
If you wanted to know that path, too, then simply ask Resolve-Path:
Resolve-Path -Path ‘C:Program Files*Microsoft OfficeOffice*EXCEL.EXE’ |
Select-Object -ExpandProperty Path -First 1
Turning arrays into string
Take a look at the Excel spreadsheet that uses color again. Look at the columns RequiredServices and DependentServices. They are just fine—which might surprise you. Because typically, when Windows PowerShell exports arrays of information, they do not display well in Excel.
Check this out, for example…
The next piece of script outputs the 10 newest error events from your System event log to Excel. When you look at the data, the columns Data and ReplacementStrings contain unreadable stuff.
To make array content display correctly in Excel, arrays need to be converted to strings. Here’s sample script that illustrates how easily that can be done:
$Path = “$env:temp$(Get-Date -Format yyyyMMddHHmmss)report.csv”
Get-EventLog -LogName System -EntryType Error -Newest 10 |
Select-Object -Property * |
ForEach-Object {
$_.ReplacementStrings = $_.ReplacementStrings -join ‘,’
$_.Data = $_.Data -join ‘,’
$_
} |
Export-CSV -Path $Path -UseCulture -Encoding UTF8 -NoTypeInformation
Invoke-Item -Path $Path
When you run the script, the columns now reveal their content. And here is why…
The script first piped the data to Select-Object –Property *. Typically, you would use Select-Object to select the columns you want to have in your report. Select-Object will also do another thing: It copies the data into a new object, and this new object is yours. You can do whatever you want with it.
That’s the prerequisite for the subsequent Foreach-Object loop. Inside of it, you can fine tune, change, or revise the data in any way you wish. So the script takes the properties that contain arrays, ReplacementStrings, and Data, and converts these arrays to strings by using the –join operator. That’s it. Just don’t forget to put back the $_ variable inside Foreach-Object so that the downstream cmdlets can receive it.
Thank you, Tobias. Awesome script as usual.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy
Данный материал является переводом оригинальной статьи «ATA Learning : Adam Bertram : PowerShell and Excel: Seize the Power!».
Microsoft Excel — один из тех вездесущих инструментов, от которых большинство из нас не может уйти, даже если хочет. Многие ИТ-специалисты используют Excel, как небольшую базу данных, в которой хранятся тонны данных в различных процедурах автоматизации. Каков наилучший сценарий автоматизации и Excel? Это, например, PowerShell!
Работу с таблицами Excel непросто автоматизировать. В отличие от менее функционального (и более простого) аналога файла CSV, книги Excel — это не просто текстовые файлы. Для работы со сложными книгами Excel потребует от PowerShell манипуляции с Component Object Model (COM), для чего раньше нужно было установить Excel. Однако, на самом деле, это вовсе не обязательно. Например, проницательный участник сообщества PowerShell, Doug Finke, создал модуль PowerShell, названный ImportExcel. Модуль устраняет сложность работы с Excel и позволяет легко работать с книгами Excel через PowerShell сценарии!
В этой статье рассмотрим пример того, что можно сделать в PowerShell и Excel с помощью модуля ImportExcel, а также рассмотрим несколько популярных вариантов использования.
Предварительные требования
При запуске модуля ImportExcel в системе Windows отдельные зависимости не требуются. Однако, если вы работаете с MacOS, вам необходимо установить пакет mono-libgdiplus, используя команду вида:
brew install mono-libgdiplus
Примечание: Все примеры в этой статье будут построены с использованием macOS, но все они должны работать и на других платформах. При использовании macOS, не забудьте перезапустить сеанс PowerShell, прежде чем продолжить.
Установка модуля ImportExcel
Начните с загрузки и установки модуля через PowerShell Gallery, запустив:
Install-Module ImportExcel -Scope CurrentUser
Через несколько секунд все будет в порядке.
Использование PowerShell для экспорта в рабочий лист Excel
Возможно, вы знакомы со стандартными командлетами PowerShell Export-Csv и Import-Csv. Эти командлеты позволяют читать и экспортировать объекты PowerShell в файлы CSV. К сожалению, в PowerShell нет таких же встроенных командлетов для Excel. Но, используя модуль ImportExcel, вы можете создать такой функционал!
Один из наиболее частых запросов системного администратора — это экспорт объектов PowerShell в рабочий лист Excel. С помощью командлета Export-Excel из модуля ImportExcel, вы можете легко сделать это. Командлет Export-Excel принимает любой объект точно так же, как делает Export-Csv. Этому командлету можно передать любой объект.
Например, возможно, вам нужно найти какие-то процессы, запущенные на вашем локальном компьютере, и поместить их в книгу Excel.
Чтобы найти процессы, запущенные в системе с помощью PowerShell, используйте командлет Get-Process, который возвращает каждый запущенный процесс и различную информацию о каждом процессе. Чтобы экспортировать эту информацию в Excel, используйте командлет Export-Excel, указывающий путь к создаваемой книге Excel. Вы можете увидеть пример команды и снимок экрана сгенерированного файла Excel ниже.
Get-Process | Export-Excel -Path './processes.xlsx
Поздравляем! Вы экспортировали всю информацию точно так же, как Export-Csv, но, в отличие от Export-Csv, мы можем сделать эти данные намного интереснее. Убедитесь, что имя рабочего листа называется «Proccesses», данные находятся в таблице, а размер строк устанавливается автоматически.
Добавим к командлету параметр -AutoSize для автоматического изменения размера всех строк, -TableName, чтобы указать имя таблицы, которая будет включать все данные, и имя параметра -WorksheetName для процессов, и сможем увидеть на снимке экрана ниже, что в итоге получится.
Get-Process | Export-Excel -Path './processes.xlsx' -AutoSize -TableName 'Processes' -WorksheetName 'Proccesses'
Командлет Export-Excel имеет множество параметров, которые можно использовать для создания книг Excel всех видов. Для получения полной информации о возможностях Export-Excel, запустите:
Get-Help Export-Excel
Использование PowerShell для импорта в Excel
Итак, ранее вы экспортировали некоторую информацию в файл с именем process.xlsx. Возможно, теперь вам нужно переместить этот файл на другой компьютер и импортировать / прочитать эту информацию. Командлет Import-Excel к вашим услугам.
При простейшем использовании вам нужно только указать путь к документу / книге Excel с помощью параметра -Path, как показано ниже. Вы увидите, что он читает первый рабочий лист, в данном случае рабочий лист «Processes», и возвращает объекты PowerShell.
Import-Excel -Path './processes.xlsx'
Может быть, у вас есть несколько листов в книге Excel? Вы можете прочитать конкретный рабочий лист с помощью параметра -WorkSheetname.
Import-Excel -Path './processes.xlsx' -WorkSheetname 'SecondWorksheet'
Вам нужно читать только определенные столбцы из рабочего листа Excel? Используйте параметр -HeaderName, чтобы указать только те параметры, которые вы хотите прочитать.
Import-Excel -Path './processes.xlsx' –WorkSheetname 'Processes' -HeaderName 'CPU','Handle'
Командлет Import-Excel имеет другие параметры, которые можно использовать для чтения книг Excel всех типов. Чтобы получить полное изложение всего, что может делать Import-Excel, запустите:
Get-Help Import-Excel
Использование PowerShell для получения (и установки) значений ячеек Excel
Теперь вы знаете, как читать весь лист Excel с помощью PowerShell. Но что, если вам нужно только одно значение ячейки? Технически вы можете использовать Import-Excel и отфильтровать нужное значение с помощью Where-Object, но это будет не слишком эффективно.
Вместо этого, используя командлет Open-ExcelPackage, вы можете «преобразовать» книгу Excel в объект PowerShell, который затем можно будет читать и изменять. Этот командлет аналогичен использованию New-Object -ComObject ‘Excel.Application’, если работать напрямую с COM-объектами.
Чтобы найти значение ячейки, сначала откройте книгу Excel, чтобы занести его в память. Затем выберите лист внутри книги.
$excel = Open-ExcelPackage -Path './processes.xlsx'
$worksheet = $excel.Workbook.Worksheets['Processes']
Этот процесс похож на способ открытия книг с помощью COM-объекта ‘Excel.Workbooks.Open’.
После того, как рабочий лист назначен переменной, вы можете перейти к отдельным строкам, столбцам и ячейкам. Возможно, вам нужно найти все значения ячеек в строке A1. Вам просто нужно сослаться на свойство ‘Cells’, указав индекс A1, как показано ниже.
$worksheet.Cells['A1'].Value
Вы также можете изменить значение ячеек на листе, присвоив другое значение, например:
$worksheet.Cells['A1'] = 'differentvalue'
Будучи хранимым в оперативной памяти, важно высвобождать пакет Excel с помощью командлета Close-ExcelPackage.
Close-ExcelPackage $excel
Конверсия Excel в файлы CSV с помощью PowerShell
Если у вас есть содержимое листа Excel, представленное с помощью объектов PowerShell, преобразование листов Excel в CSV просто требует отправки этих объектов в командлет Export-Csv.
Используя созданную ранее книгу processes.xlsx, прочтите первый рабочий лист, который получает все данные в объекты PowerShell, а затем экспортируйте эти объекты в CSV с помощью приведенной ниже команды.
Import-Excel './processes.xlsx' | Export-Csv -Path './processes.csv' -NoTypeInformation
Конверсия множества рабочих листов
Если у вас есть книга Excel с несколькими листами, вы также можете создать файл CSV для каждого листа. Для этого вы можете найти все листы в книге с помощью командлета Get-ExcelSheetInfo. Когда у вас есть имена рабочих листов, вы можете передать их в параметр -WorksheetName, а также использовать имя листа в качестве имени файла CSV.
Ниже вы можете найти необходимый пример кода.
$sheets = (Get-ExcelSheetInfo -Path './processes.xlsx').Name
foreach ($sheet in $sheets) {
Import-Excel -WorksheetName $sheet -Path './processes.xlsx' | Export-Csv "./$sheet.csv" -NoTypeInformation
}
Заключение
Используя модуль ImportExcel из библиотеки модулей PowerShell, вы можете импортировать, экспортировать и управлять данными в книгах Excel точно так же, как и в CSV, без установки Excel!
(оригинал статьи: https://adamtheautomator.com/powershell-excel/ )
Microsoft Excel — один из тех вездесущих инструментов, от которых большинство из нас не может убежать, даже если мы попытаемся. Многие ИТ-специалисты используют Excel как небольшую базу данных, в которой хранятся тонны данных в различных процедурах автоматизации. Каков наилучший сценарий автоматизации и Excel? PowerShell!
Таблицы Excel всегда было заведомо сложно создавать сценариями и автоматизировать. В отличие от менее функционального (и более простого) аналога файла CSV, книги Excel — это не просто текстовые файлы. Для работы со сложными книгами Excel требуется PowerShell Component Object Model (COM) objects , так как вам нужно было установить Excel. Уже нет.
К счастью, проницательный участник сообщества PowerShell, Doug Finke, создал модуль PowerShell, названный ImportExcel для нас, простых смертных. Модуль ImportExcel устраняет всю эту сложность. Это позволяет легко управлять книгами Excel прийти к PowerShell сценариям!
В этой статье давайте рассмотрим, что вы можете делать с PowerShell и Excel с помощью модуля ImportExcel, а также рассмотрим несколько популярных вариантов использования.
Пререквизиты
При запуске модуля ImportExcel в системе Windows отдельные зависимости не требуются. Однако, если вы работаете с macOS, вам необходимо установить пакет mono-libgdiplus, используя brew install mono-libgdiplus. (Все примеры в этой статье будут построены с использованием macOS, но все примеры должны работать на разных платформах.)
Если вы используете macOS, не забудьте перезапустить сеанс PowerShell, прежде чем продолжить!
Установка модуля ImportExcel
Начните с загрузки и установки модуля через PowerShell Gallery, запустив Install-Module ImportExcel -Scope CurrentUser. Через несколько секунд все будет в порядке.
Использование PowerShell для экспорта в рабочий лист Excel
Возможно, вы знакомы со стандартными командлетами PowerShell Export-Csv и Import-Csv. Эти командлеты позволяют читать и экспортировать объекты PowerShell в файлы CSV. К сожалению, нет командлетов Export-Excel и Import-Excel . Но, используя модуль ImportExcel, вы можете создать свой собственный функционал.
Один из наиболее частых запросов системного администратора — это экспорт объектов PowerShell в рабочий лист Excel. С помощью командлета Export-Excel в модуле ImportExcel, вы можете легко сделать это.
Например, возможно, вам нужно найти какие-то процессы, запущенные на вашем локальном компьютере, и поместить их в книгу Excel.
Командлет Export-Excel принимает любой объект точно так же, как делает Export-Csv. Этому командлету можно передать любой объект.
Чтобы найти процессы, запущенные в системе с помощью PowerShell, используйте командлет Get-Process, который возвращает каждый запущенный процесс и различную информацию о каждом процессе. Чтобы экспортировать эту информацию в Excel, используйте командлет Export-Excel, указывающий путь к создаваемой книге Excel. Вы можете увидеть пример команды и снимок экрана сгенерированного файла Excel ниже.
Get-Process | Export-Excel -Path ‘./processes.xlsx’
Поздравляю! Вы экспортировали всю информацию точно так же, как Export-Csv , но, в отличие от Export-Csv, мы можем сделать эти данные намного интереснее. Убедитесь, что имя рабочего листа называется Processes, данные находятся в таблице, а размер строк устанавливается автоматически.
Используя параметр переключателя AutoSize для автоматического изменения размера всех строк, TableName, чтобы указать имя таблицы, которая будет включать все данные, и имя параметра WorksheetName для процессов, вы можете увидеть на снимке экрана ниже, что можно построить.
Get-Process | Export-Excel -Path ‘./processes.xlsx’ -AutoSize -TableName Processes -WorksheetName Proccesses
Командлет Export-Excel имеет множество параметров, которые можно использовать для создания книг Excel всех видов. Для полного изложения всего, что Export-Excel может делать, запустите Get-Help Export-Excel.
Использование PowerShell для импорта в Excel
Итак, вы экспортировали некоторую информацию в файл с именем process.xlsx в предыдущем разделе. Возможно, теперь вам нужно переместить этот файл на другой компьютер и импортировать / прочитать эту информацию. Без проблем. У вас есть Import-Excel к вашим услугам.
При простейшем использовании вам нужно только указать путь к документу / книге Excel с помощью параметра Path, как показано ниже. Вы увидите, что он читает первый рабочий лист, в данном случае рабочий лист Processes, и возвращает объекты PowerShell.
Import-Excel -Path ‘./processes.xlsx’
Может быть, у вас есть несколько листов в книге Excel? Вы можете прочитать конкретный рабочий лист с помощью параметра WorksheetName.
Import-Excel -Path ‘./processes.xlsx’ -WorkSheetname SecondWorksheet
Вам нужно читать только определенные столбцы из рабочего листа Excel? Используйте параметр HeaderName, чтобы указать только те параметры, которые вы хотите прочитать.
Import-Excel -Path ‘./processes.xlsx’ -WorkSheetname Processes -HeaderName ‘CPU’,’Handle’
Командлет Import-Excel имеет другие параметры, которые можно использовать для чтения книг Excel всех типов. Чтобы получить полное изложение всего, что может делать Import-Excel, запустите Get-Help Import-Excel.
Использование PowerShell для получения (и установки) значений ячеек Excel
Теперь вы знаете, как читать весь лист Excel с помощью PowerShell, но что, если вам нужно только одно значение ячейки? Технически вы можете использовать Import-Excel и отфильтровать нужное значение с помощью Where-Object, но это будет не слишком эффективно.
Вместо этого, используя командлет Open-ExcelPackage, вы можете «преобразовать» книгу Excel в объект PowerShell, который затем можно будет читать и изменять. Чтобы найти значение ячейки, сначала откройте книгу Excel, чтобы занести его в память.
$excel = Open-ExcelPackage -Path ‘./processes.xlsx’
Open-ExcelPackage аналогичен использованию New-Object -comobject excel.application, если работать напрямую с COM-объектами.
Затем выберите лист внутри книги.
$worksheet = $excel.Workbook.Worksheets[‘Processes’]
Этот процесс похож на способ открытия книг с помощью COM-объекта excel.workbooks.open.
После того, как рабочий лист назначен переменной, вы можете перейти к отдельным строкам, столбцам и ячейкам. Возможно, вам нужно найти все значения ячеек в строке A1. Вам просто нужно сослаться на свойство Cells, указав индекс A1, как показано ниже.
$worksheet.Cells[‘A1’].Value
Вы также можете изменить значение ячеек на листе, присвоив другое значение, например $worksheet.Cells[‘A1’] = ‘differentvalue’
Будучи в оперативной памяти, важно высвободить пакет Excel с помощью командлета Close-ExcelPackage.
Close-ExcelPackage $excel
Конверсия Excel в файлы CSV с PowerShell
Если у вас есть содержимое листа Excel, представленное с помощью объектов PowerShell, «преобразование» листов Excel в CSV просто требует отправки этих объектов в командлет Export-Csv.
Используя созданную ранее книгу processes.xlsx, прочтите первый рабочий лист, который получает все данные в объекты PowerShell, а затем экспортируйте эти объекты в CSV с помощью приведенной ниже команды.
Import-Excel ‘./processes.xlsx’ | Export-Csv -Path ‘./processes.csv’ -NoTypeInformation
Если вы сейчас откроете получившийся CSV-файл, вы увидите те же данные внутри рабочего листа «Processes» (в этом примере).
Конверсия множества рабочих листов
Если у вас есть книга Excel с несколькими листами, вы также можете создать файл CSV для каждого листа. Для этого вы можете найти все листы в книге с помощью командлета Get-ExcelSheetInfo. Когда у вас есть имена рабочих листов, вы можете передать их в параметр WorksheetName, а также использовать имя листа в качестве имени файла CSV.
Ниже вы можете найти необходимый пример кода.
## find each sheet in the workbook $sheets = (Get-ExcelSheetInfo -Path ‘./processes.xlsx’).Name ## read each sheet and create a CSV file with the same name foreach ($sheet in $sheets) { Import-Excel -WorksheetName $sheet -Path ‘./processes.xlsx’ | Export-Csv «./$sheet.csv» -NoTypeInformation }
Заключение
Используя модуль ImportExcel PowerShell module, вы можете импортировать, экспортировать и управлять данными в книгах Excel точно так же, как и в CSV, без установки Excel!
While ago I needed to do some manipulation on Excel spreadsheets but had no Office installed on the server. For the specific case, I looked for a way to complete my task with PowerShell. A quick look into Google search results and…
Even though the name is not specified, both articles talk about the ImportExcel module (if you scroll down the results a bit you will see this link).
If you like the topic please have a look at the series of different usage scenarios.
Winter series of PowerShell and Excel
What is ImportExcel?
I will use Doug’s description from the GitHub repository:
This PowerShell Module allows you to read and write Excel files without installing Microsoft Excel on your system. No need to bother with the cumbersome Excel COM-object. Creating Tables, Pivot Tables, Charts and much more has just become a lot easier.
That’s right! No need to install Microsoft Excel.
I have recently tested the 7.1.0 version and it contains about 60 functions. Some of the functions are:
Add-ConditionalFormatting
Add-ExcelTable
Compare-Worksheet
ConvertFrom-ExcelToSQLInsert
Export-Excel
Import-Excel
Join-Worksheet
PieChart
Pivot
ImportExcel – quick start
Firstly, to get the module installed on my machine I have ran this short script:
# set the execution policy for the current process
Set-ExecutionPolicy Bypass -Scope Process
# install and import module
Install-Module -Name ImportExcel
Import-Module -Name ImportExcel
# confirm the module is installed
Get-Module -Name ImportExcel
<#
ModuleType Version Name ExportedCommands
---------- ------- ---- ----------------
Script 7.1.0 ImportExcel {Add-ConditionalFormatting, Add-ExcelChart, Add-ExcelDataValidationRule, Add-ExcelName...}
#>
Secondly, let’s see what this tool can do! I would like to see all the commands from the module and export their names to the Excel spreadsheet:
# get all the functions from the module and export as a spreadsheet
Get-Command -Module ImportExcel | SELECT Name | Export-Excel
As a result, I am getting new Excel windows open with temporary name tmpF12D located in $env:TEMP with output formatted as a spreadsheet table Table1.
That was easy, but I want to see more.
ImportExcel – how to?
I have created an Excel spreadsheet from PowerShell, but what else I could do?
ImportExcel – how to work with worksheets?
As a matter of fact the ImportExcel module allows to manipulate worksheets.
# go to the temporary location
Set-Location $env:TEMP
# load the spreadsheet
$filename = 'tmpF12D.xlsx'
$excel = Open-ExcelPackage -Path $filename
# add an extra sheet to the end
Add-Worksheet -ExcelPackage $excel -WorksheetName Mikey -MoveToEnd
# and save it back to the file and show the file
Close-ExcelPackage -ExcelPackage $excel -Show
<#
Unfortunately getting an error:
Exception calling "Save" with "0" argument(s): "Error saving file C:UsersMikeyAppDataLocalTemptmpF12D.xlsx"
At C:UsersmichaMikeyOneDriveDocumentsWindowsPowerShellModulesImportExcel7.1.0PublicClose-ExcelPackage.ps1:27 char:29
+ else {$ExcelPackage.Save() }
+ ~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : InvalidOperationException
#>
And the reason for that is simple – I had the file open. Therefore I am going to close it and repeat the above script:
# load the spreadsheet
$filename = 'tmpF12D.xlsx'
$excel = Open-ExcelPackage -Path $filename
# close the open file
([Runtime.InteropServices.Marshal]::GetActiveObject('Excel.Application').workbooks | Where-Object {$_.FullNameURLEncoded -eq $excel.File }).Close($false)
# similar effect would be using the KillExcel switch
# close WHOLE Excel app (not just the specific file) and load to variable
$excel = Open-ExcelPackage -Path $filename -KillExcel
# add an extra sheet to the end
Add-Worksheet -ExcelPackage $excel -WorksheetName Mikey -MoveToEnd
# and save it back to the file and show the file
Close-ExcelPackage -ExcelPackage $excel -Show
As shown above, adding an empty sheet was amazingly easy (and I have learned a new thing about closing files). How about populating it with the data?
# load the spreadsheet
$filename = 'tmpF12D.xlsx'
$excel = Open-ExcelPackage -Path $filename
([Runtime.InteropServices.Marshal]::GetActiveObject('Excel.Application').workbooks | Where-Object {$_.FullNameURLEncoded -eq $excel.File }).Close($false)
# add new worksheet at the beginning
Add-Worksheet -ExcelPackage $excel -WorksheetName Process -MoveToStart
# get the data into a new sheet as a named table
# freeze the first row and column with an auto-sized length
Get-Process | Export-Excel -ExcelPackage $excel -WorksheetName Process -TableName Process -Show -AutoSize -FreezeTopRow -FreezeFirstColumn
Perfect, we have some data. Pivot? Why not.
ImportExcel – how to make pivot tables?
For example, using Add-PivotTable is straightforward (and from now on I am closing the whole Excel). Also, note the Activate switch at the end. When you open the Excel file the worksheet that was used in the command will show up first.
# load the spreadsheet
$filename = 'tmpF12D.xlsx'
$excel = Open-ExcelPackage -Path $filename -KillExcel
# add a simple pivot table
Add-PivotTable -ExcelPackage $excel -PivotRows Name -PivotColumns PriorityClass -PivotData @{'CPU' = 'sum'} -SourceWorkSheet process -PivotTableName 'Pivot' -Activate
# save it to the file and display
Close-ExcelPackage -ExcelPackage $excel -Show
Additionally, if something went wrong with our data and we need to recreate the pivot table. No problem. Drop the worksheet and create a new pivot table.
# load the spreadsheet
$filename = 'tmpF12D.xlsx'
$excel = Open-ExcelPackage -Path $filename -KillExcel
# drop the pivot table worksheet (using the filename, not the package)
Remove-Worksheet -FullName $filename -WorksheetName Pivot
# add some more stuff to the pivot table
Add-PivotTable -ExcelPackage $excel -PivotRows Name -PivotColumns PriorityClass -PivotData @{'CPU' = 'sum'; 'Company' = 'count'} -SourceWorkSheet process -PivotTableName 'Pivot' -Activate -NoTotalsInPivot -PivotTableStyle Dark1
# save it to the file and display
Close-ExcelPackage -ExcelPackage $excel -Show
As a result of both operations we get two tables;
ImportExcel – how to make pivot table charts?
It is common to have a pivot table chart alongside the data. In fact, ImportExcel module supports that too.
# load the spreadsheet
$filename = 'tmpF12D.xlsx'
$excel = Open-ExcelPackage -Path $filename -KillExcel
# setup definition for the first pivot table; note the IncludePivotChart
$PTDef = New-PivotTableDefinition -PivotTableName "P1" -SourceWorkSheet "Process" -PivotRows "Company" -PivotData @{'Cpu' = 'average'} -IncludePivotChart -ChartType BarClustered3D
# join the definition for the second pivot table
$PTDef += New-PivotTableDefinition -PivotTableName "P2" -SourceWorkSheet "Process" -PivotRows "Company" -PivotData @{'Cpu' = 'average'} -IncludePivotChart -ChartType Pie3D
# Export with the PivotTableDefinition
Export-Excel -ExcelPackage $excel -PivotTableDefinition $PTDef -Show -Activate
That does not limit the user to create pivot table charts on a new worksheet. It is quite simple to add more charts on the worksheet. Just to avoid overlapping of the charts and tables set the Address (for placing table [A]) and ChartRow / ChartColumn (to set location for a chart [B]).
# load the spreadsheet
$filename = 'tmpF12D.xlsx'
$excel = Open-ExcelPackage -Path $filename -KillExcel
# define parameters for another pivot table and chart
$PTParams = @{
PivotTableName = "P3"
Address = $excel.P2.cells["A22"] # top-left corner of the table
SourceWorkSheet = $excel.Process
PivotRows = @("Company")
PivotData = @{'Cpu' = 'average'}
PivotTableStyle = 'Light21'
IncludePivotChart = $true
ChartType = "BarClustered3D"
ChartRow = 22 # place the chart below row 22nd
Activate = $true
}
# add the objects
Add-PivotTable @PTParams -PassThru
# save it to the file and display
Close-ExcelPackage $excel -Show
Amazing! In fact, it would be a day-long session to show all the scenarios just for pivot tables and charts.
Summary
To sum up, ImportExcel PowerShell module has many features and it is a powerful task. I showed you today how to do basic operations on worksheets and pivot tables/charts. Next week will describe more about regular charts and conditional formatting.
Thank you,
Mikey