В это статье мы покажем, как получить доступ к данным в файлах 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 скрипт). Таким образом можно вести актуальную адресную книгу с актуальными номерами телефонами и должностями.
I want to convert a textfile to Excel Format. I use the following script from Technet:
# Script name: ConvertTilde.ps1
# Created on: 2007-01-06
# Author: Kent Finkle
# Purpose: How Can I Convert a Tilde-Delimited File to Microsoft Excel Format?
$s = gc C:ScriptsTest.txt
$s = $s -replace("~","`t")
$s | sc C:ScriptsTest.txt
$xl = new-object -comobject excel.application
$xl.Visible = $true
$wb = $xl.Workbooks.Open("C:ScriptsTest.txt")
$wb.SaveAs(“D:ExcelTest.xlsx”)
The Script works, excel opens and imports the txt, but the saved Files are just txt files renamed to xlsx — how can I get Excel to change the File Format?
asked Mar 21, 2014 at 13:42
I would investigate the FileFormat parameter of the SaveAs method, although it won’t magically convert a text file into a nicely formatted workbook.
answered Mar 21, 2014 at 13:46
Alan BAlan B
4,02224 silver badges33 bronze badges
1
В комментариях к статье Powershell и Excel. Часть 2: форматирование ячеек мне задали вопрос:
подскажите, каким образом занести данные с файла 123.txt в Excel?
Там же в комментариях развелась целая дискуссия на эту тему. А недавно сам столкнулся с похожей проблемой. В моём случае файлов было несколько, и мало того, что нужно было перенести данные из текстового файла в Excel, так их ещё нужно было проанализировать. Поэтому решил поделиться своим способом конвертирования текстового файла в файл Excel.
В моём скрипте два обязательных параметра: путь к исходному текстовому файлу, и знак разделитель (по умолчанию — пробел):
[CmdletBinding()] param ( # Путь к текстовому файлу [Parameter(Mandatory=$true)] [string[]]$Path, # Разделитель # По умолчанию - пробел [Parameter(Mandatory=$true)] [char]$Separator = ' ' )
Считываем наш файл и запускаем Excel:
# Читаем файл Write-Verbose "Читаем файл $Path" $Content = Get-Content $Path # Запускаем Excel Write-Verbose 'Запускаем Excel...' $Excel = New-Object -ComObject Excel.Application
Чтобы было веселее Для наглядности я всегда в своих скриптах добавляю поддержку стандартных параметров, в частности –Verbose для того, чтобы было видно, что в данный момент делает скрипт:
# Если указан параметр Verbose if ($PSBoundParameters.Verbose) { # Выводим подробные сообщения $VerbosePreference = "Continue" # Делаем excel видимым $Excel.Visible = $true }
В частности, в данном скрипте кроме вывода собственных сообщений, при задании —Verbose я ещё делаю видимым Excel. (Всегда нравится наблюдать за реакцией коллег, когда после нескольких взмахов руками над клавиатурой запускается Excel, сам записывает данные, сам форматирует текст и закрывается :))
Стандартные подготовительные действия для последующей работы с Excel:
# Добавляем рабочую книгу $WorkBook = $Excel.Workbooks.Add() # Цепляемся к первому листу $WorkSheet = $WorkBook.Worksheets.Item(1)
Далее начинается непосредственно работа. Каждая строка из файла разбивается на подстроки (блоки, разделённые указанным символом разделителем) и каждый блок записывается в свою собственную ячейку:
# Цикл по строкам foreach ($Line in $Content) { # Переменные для обозначения ячеек в Excel-файле # Строка $Row++ # Первый столбец $Column = 1 # Строка разбитая на блоки $Result = $Line -split $Separator # Каждый блок из строки записываем в xls-файл foreach ($Item in $Result) { $WorkSheet.Cells.Item($Row, $Column) = $Item # Переходим в следующий столбец $Column++ } }
По сути это всё. Далее при необходимости можно форматировать файл, как будет угодно, например выровнять ширину ячеек, чтобы текст помещался:
$UsedRange = $WorkSheet.UsedRange $UsedRange.EntireColumn.AutoFit() | Out-Null
Осталось сохранить результат и выйти. В моём случае xls-файл сохраняется в том же каталоге, что и исходный текстовый файл, с тем же именем (за исключением расширения):
# Путь к исходному файлу $FolderPath = (Get-ChildItem $Path).DirectoryName # Имя исходного файла без расширения $BaseName = (Get-ChildItem $Path).BaseName # Путь к готовому xls-файлу $xlsPath = Join-Path $FolderPath "$BaseName.xls" # Сохраняем и выходим $WorkBook.SaveAs($xlsPath) $Excel.Quit()
Как-то читал, что COM-объекты устроены не так, как объекты .NET, и за ними нужно “вручную” освобождать память, вот так:
$null = [Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$Excel) [gc]::Collect() [gc]::WaitForPendingFinalizers() Remove-Variable Excel
В результате память может и освобождается, но процесс Excel остаётся запущенным и невидимым.
Ну и напоследок пару скриншотов, как это работает.
Если исходный текстовый файл имеет вид:
То готовый xls-файл будет выглядеть так:
Конечно, это не комплексное решение: здесь нет проверки на то является-ли указанный файл действительно текстовым, присутствуют-ли в нём разделители, и много чего ещё. Я только показал алгоритм работы.
Convert Text to Excel using PowerShell
Posted on 1 August، 2017 Updated on 13 August، 2017
In this post, we will convert text file to Excel using PowerShell.
Pre-requisite : you should have Microsoft Office Excel installed on your machine
1. This is a sample of the data to be converted, If you want to try it your self please Copy paste the below box to a file named sourceFile.txt
2. Now, open the PowerShell_ISE and paste the below script in it
#This script is to convert text files to formalized excel sheet.
#Please make sure txt file is applied in this format
#Header1, Header2, Header3, Header4
#X1, X2, X3, X4
#Y1, Y2, Y3, Y4
#Z1, Z2, Z3, Z4
#Constants
$SourcePath = "C:tempsourceFile.txt"
$DestinationPath = "C:tempdestinationPath"
$deleimter= ","; #You can replace it by any other delimeter ';' or '/'#You can leave this part as it is
$SourceTxt = Get-Content $SourcePath
$xlsxFile = $DestinationPath + ".xlsx"if (Test-Path ($xlsxFile))
{
Remove-Item $xlsxFile
}
#$SourceTxt >> $txtFile
[threading.thread]::CurrentThread.CurrentCulture = 'en-US'
$xl=New-Object -ComObject "Excel.Application"
$wb=$xl.Workbooks.Add()
$ws=$wb.ActiveSheet
$xl.Visible=$True
$cells=$ws.Cells
$Content = Get-Content $SourcePath
$numOfRows = $Content.Length
$numOfColumns = $Content[0].split($deleimter).Count
for ($i=0; $i -lt $numOfRows ;$i++)
{
$rowData = $Content[$i].split($deleimter)
for ($j=0; $j -lt $numOfColumns; $j++)
{
$cellData = $rowData[$j]
$cells.item($i+1,$j+1) = $cellData
}
}
#Apply some Format for Excel header
$xl.Cells.EntireColumn.AutoFit()
$xl.Cells.EntireColumn.AutoFilter()
$xl.Rows.Item(1).Font.Bold = $True
$xl.Rows.Item(1).Interior.ColorIndex = 44
#Save Sheet
$wb.SaveAs($xlsxFile)
$wb.Close()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($wb)
$xl.Quit()
#Clean up
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($xl)
#Remove-Variable -Name xl
#[gc]::Collect()
#[gc]::WaitForPendingFinalizers()
3. Output should be something like this:
This entry was posted in Scripting and tagged Excel.Application, Notepad, PowerShell text to excel, Text to Excel, txt to xls.
- Remove From My Forums
-
Question
-
I would like to be able to retrieve specific lines of text from a TXT file and load into an Excel spreadsheet.
The file I am retrieving the text from has 5 lines of data that repeats several times in the file but each line ends with unique data. I want to be able to drop each line into a separate column in Excel. Example: Line 2 in column one, Line 4 in column two.
Then every line that starts the same as Line 2 will go to column one.I am thinking I need to use Get-Content to grab all the text from the file but how do I find specific lines in the text and export them to an excel spreadsheet?