tarasov.evgeny |
05-05-2011 16:54 1670771 |
PowerShell и Excel
Добрый день
Необходимо в консоль выводить информацию из файла excel
Файл Excel это вроде базы. Каждая строка это один элемент данных. Данные об компьютере или сотруднике.
Необходимо, чтобы при наборе в консоли например имени - Иванов
Скрипт проходил по строкам листа - находил Иванов и отображал определенные ячейки b22, c22, k22 (это как пример, пусть это будет мобильный телефон, рабочий, адрес)
Евгений
|
примерно так
Код:
cls
function seach ($x){
$File = "D:\1.xlsx"
$Excel = New-Object -ComObject Excel.Application
$xlprocess = Get-Process excel
$Excel.visible = $false
$Workbook = $Excel.workbooks.open($file)
$Worksheets = $Workbooks.worksheets
$Worksheet = $Workbook.Worksheets.Item(1)
$SearchString = $x
$Range = $Worksheet.Range("A1").EntireColumn
$Search = $Range.find($SearchString)
$a=$Search.Row
$name=$Search.Value()
$data1= $Worksheet.Cells.Item($a,3).Text
$data2= $Worksheet.Cells.Item($a,5).Text
Write-Host "Имя: " $name "Данное1: " $data1 "Данное2: " $data2
$Excel.quit()
$xlprocess | kill }
|
ferget,
Код:
$xlprocess = Get-Process excel
…
$xlprocess | kill
на всякий случай? А если у меня уже были открыты экземпляры Microsoft Excel? Нехорошо.
|
согласен, нехорошо
но как отлавливать нужный процесс?
а то, если его не kill он останется висеть в памяти
|
Цитата:
Цитата ferget
он останется висеть в памяти »
|
тогда так:
Код:
$string = "Иванов"
$file = "D:\1.xlsx"
$ciBK = [System.Threading.Thread]::CurrentThread.CurrentCulture
$ciUS = [System.Globalization.CultureInfo]'en-US'
[System.Threading.Thread]::CurrentThread.CurrentCulture = $ciUS
$xl = New-Object -COM Excel.Application
$xl.Visible = $False
$bk = $xl.Workbooks.PSBase.GetType().InvokeMember('Open',[Reflection.BindingFlags]::InvokeMethod,$null,$xl.Workbooks,"$file",$ci)
$ws = $bk.Worksheets.Item(1)
$rn = $ws.Range("A1").EntireColumn
$sc = $bk.PSBase.GetType().InvokeMember('Find',[Reflection.BindingFlags]::InvokeMethod,$null,$rn,$string,$ci)
$v0= $ws.Cells.Item($sc.Row,1).FormulaLocal
$v1= $ws.Cells.Item($sc.Row,3).FormulaLocal
$v2= $ws.Cells.Item($sc.Row,5).FormulaLocal
Write-Host "Имя: " $v0 "Данное1: " $v1 "Данное2: " $v2
$bk.PSBase.GetType().InvokeMember('Close',[Reflection.BindingFlags]::InvokeMethod,$null,$bk,"",$ci)
$xl.Quit()
[System.Threading.Thread]::CurrentThread.CurrentCulture = $ciBK
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($xl)
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($sc)
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($rn)
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($ws)
Ссылки по теме:
How Can I Use Windows PowerShell to Automate Microsoft Excel?
BUG: "Old format or invalid type library" error when automating Excel
Getting Rid of a COM Object (Once and For All)
|
Цитата:
Цитата ferget
а то, если его не kill он останется висеть в памяти »
|
Это как,
не достаточно?
|
Цитата:
Цитата Iska
$Excel.quit()
не достаточно? »
|
по последней ссылке как раз "про это" )
|
amel27, спасибо за уточнение. Если я правильно понял, то это особенность работы враппера .Net для COM-объектов, специфичная для некоторых COM-объектов? Или для любых COM-объектов, вызываемых в PoSH?
Ещё один вопрос: будет ли завершён процесс Excel при завершении скрипта/сессии PoSH (без использованного в #5 кода) или так и останется «висеть» в памяти?
|
Цитата:
Цитата Iska
Ещё один вопрос: будет ли завершён процесс Excel при завершении скрипта/сессии PoSH (без использованного в #5 кода) или так и останется «висеть» в памяти? »
|
будут завершены все процессы Excel (если использовать только Quit, то при каждом зауске будет создаваться новый процесс)
я тут проверил и оказалось, что достаточно только quit, просто процесс excel завершается через некоторое время, первый запуск 10, затем время увеличивается до минут, и если запущен другой процесс excel, то не завершается до его завершения
|
Я к чему спрашиваю: в WSH JScript была похожая [внешне] ситуация: HTA javascript: Как правильно закрыть Excel?, но там, при завершении процесса скрипта, процессы Excel закрывались. Оттого хотел узнать, закроются ли здесь процессы Excel при закрытии скрипта/сессии PoSH.
|
WSH - это COM, там проблем с автозачисткой не должно быть...
у меня не закрывался, но (обычно) "висело" >1 процесса EXCEL (возможно они друг друга блокировали)
|
т.к. Excel не закрывался после отработки скрипта аж до завершения оболочки, а в моем случае оболочка должна была использоваться дальше, причем в это время могли отрабатываться и другие скрипты, которые также вызывали Excel и могли висеть ранее открытые экземпляры, то решил таким вот способом:
Код:
$erroractionpreference = "SilentlyContinue"
# список процессов до сорздания нашего объекта
$procBefore = Get-Process excel | Select-Object -ExpandProperty Id
#создаем новый объект
$objExcel = New-Object -ComObject Excel.Application
#делаем его видимым на момент тестирования
$objExcel.visible = $True
########################################################################
# основной блок обработки данных, который в данном случае не интересен #
########################################################################
# закрываем книгу с которой работали
$objWorkbook.Close()
# закрываем наш экземпляр Excel "по-правильному", после чего процесс тупо висит в памяти и кушает от 12 метров оперативки
$objExcel.Quit()
Remove-Variable $objExcel
# берем снимок процессов после запуска нашего экземпляра Excel
$procAfter = Get-Process excel | Select-Object -ExpandProperty Id
if ($procBefore -eq $null) # если переменная снимка процессов до создания нашего экземпляра пустая
{
kill (Get-Process excel | Select-Object -ExpandProperty Id) # то имеем ровно один экземпляр Excel, созданный скриптом, который смело можно убивать
}
else # в остальных случаях, когда у нас один и более экземпляров Excel было до создания нашего экземпляра
{
kill ($procAfter | Where-Object {$procBefore -notcontains $_}) # выбираем разницу между снимками до и после запуска и убиваем этот процесс
}
возможно не оптимизирован, но точно работает
может кому пригодится :)
|
Время: 09:55.
© OSzone.net 2001-