В моём скрипте два обязательных параметра: путь к исходному текстовому файлу, и знак разделитель (по умолчанию — пробел):
1 2 3 4 5 6 7 8 9 10 11 12 |
[CmdletBinding()] param ( # Путь к текстовому файлу [Parameter(Mandatory=$true)] [string[]]$Path, # Разделитель # По умолчанию - пробел [Parameter(Mandatory=$true)] [char]$Separator = ' ' ) |
Считываем наш файл и запускаем Excel:
1 2 3 4 5 6 7 |
# Читаем файл Write-Verbose "Читаем файл $Path" $Content = Get-Content $Path # Запускаем Excel Write-Verbose 'Запускаем Excel...' $Excel = New-Object -ComObject Excel.Application |
Для наглядности я всегда в своих скриптах добавляю поддержку стандартных параметров, в частности –Verbose для того, чтобы было видно, что в данный момент делает скрипт:
1 2 3 4 5 6 7 8 9 |
# Если указан параметр Verbose if ($PSBoundParameters.Verbose) { # Выводим подробные сообщения $VerbosePreference = "Continue" # Делаем excel видимым $Excel.Visible = $true } |
В частности, в данном скрипте кроме вывода собственных сообщений, при задании —Verbose я ещё делаю видимым Excel. (Всегда нравится наблюдать за реакцией коллег, когда после нескольких взмахов руками над клавиатурой запускается Excel, сам записывает данные, сам форматирует текст и закрывается :))
Стандартные подготовительные действия для последующей работы с Excel:
1 2 3 4 5 |
# Добавляем рабочую книгу $WorkBook = $Excel.Workbooks.Add() # Цепляемся к первому листу $WorkSheet = $WorkBook.Worksheets.Item(1) |
Далее начинается непосредственно работа. Каждая строка из файла разбивается на подстроки (блоки, разделённые указанным символом разделителем) и каждый блок записывается в свою собственную ячейку:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# Цикл по строкам foreach ($Line in $Content) { # Переменные для обозначения ячеек в Excel-файле # Строка $Row++ # Первый столбец $Column = 1 # Строка разбитая на блоки $Result = $Line -split $Separator # Каждый блок из строки записываем в xls-файл foreach ($Item in $Result) { $WorkSheet.Cells.Item($Row, $Column) = $Item # Переходим в следующий столбец $Column++ } } |
По сути это всё. Далее при необходимости можно форматировать файл, как будет угодно, например выровнять ширину ячеек, чтобы текст помещался:
1 2 |
$UsedRange = $WorkSheet.UsedRange $UsedRange.EntireColumn.AutoFit() | Out-Null |
Осталось сохранить результат и выйти. В моём случае xls-файл сохраняется в том же каталоге, что и исходный текстовый файл, с тем же именем (за исключением расширения):
1 2 3 4 5 6 7 8 9 10 11 12 |
# Путь к исходному файлу $FolderPath = (Get-ChildItem $Path).DirectoryName # Имя исходного файла без расширения $BaseName = (Get-ChildItem $Path).BaseName # Путь к готовому xls-файлу $xlsPath = Join-Path $FolderPath "$BaseName.xls" # Сохраняем и выходим $WorkBook.SaveAs($xlsPath) $Excel.Quit() |
Как-то читал, что COM-объекты устроены не так, как объекты .NET, и за ними нужно “вручную” освобождать память, вот так:
1 2 3 4 5 6 |
$null = [Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$Excel) [gc]::Collect() [gc]::WaitForPendingFinalizers() Remove-Variable Excel |
Конечно, это не комплексное решение: здесь нет проверки на то является-ли указанный файл действительно текстовым, присутствуют-ли в нём разделители, и много чего ещё. Я только показал алгоритм работы.