Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   PowerShell и Excel (http://forum.oszone.net/showthread.php?t=206249)

tarasov.evgeny 05-05-2011 16:54 1670771

PowerShell и Excel
 
Добрый день

Необходимо в консоль выводить информацию из файла excel
Файл Excel это вроде базы. Каждая строка это один элемент данных. Данные об компьютере или сотруднике.
Необходимо, чтобы при наборе в консоли например имени - Иванов
Скрипт проходил по строкам листа - находил Иванов и отображал определенные ячейки b22, c22, k22 (это как пример, пусть это будет мобильный телефон, рабочий, адрес)


Евгений

ferget 06-05-2011 05:14 1671044

примерно так
Код:

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 }


Iska 06-05-2011 05:19 1671045

ferget,
Код:

$xlprocess = Get-Process excel

$xlprocess | kill

на всякий случай? А если у меня уже были открыты экземпляры Microsoft Excel? Нехорошо.

ferget 06-05-2011 05:28 1671046

согласен, нехорошо
но как отлавливать нужный процесс?
а то, если его не kill он останется висеть в памяти

amel27 06-05-2011 10:08 1671120

Цитата:

Цитата 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)

Iska 06-05-2011 10:29 1671135

Цитата:

Цитата ferget
а то, если его не kill он останется висеть в памяти »

Это как,
Код:

$Excel.quit()
не достаточно?

amel27 06-05-2011 11:00 1671153

Цитата:

Цитата Iska
$Excel.quit()
не достаточно? »

по последней ссылке как раз "про это" )

Iska 06-05-2011 13:30 1671250

amel27, спасибо за уточнение. Если я правильно понял, то это особенность работы враппера .Net для COM-объектов, специфичная для некоторых COM-объектов? Или для любых COM-объектов, вызываемых в PoSH?

Ещё один вопрос: будет ли завершён процесс Excel при завершении скрипта/сессии PoSH (без использованного в #5 кода) или так и останется «висеть» в памяти?

ferget 06-05-2011 14:57 1671295

Цитата:

Цитата Iska
Ещё один вопрос: будет ли завершён процесс Excel при завершении скрипта/сессии PoSH (без использованного в #5 кода) или так и останется «висеть» в памяти? »

будут завершены все процессы Excel (если использовать только Quit, то при каждом зауске будет создаваться новый процесс)

я тут проверил и оказалось, что достаточно только quit, просто процесс excel завершается через некоторое время, первый запуск 10, затем время увеличивается до минут, и если запущен другой процесс excel, то не завершается до его завершения

Iska 06-05-2011 15:27 1671315

Я к чему спрашиваю: в WSH JScript была похожая [внешне] ситуация: HTA javascript: Как правильно закрыть Excel?, но там, при завершении процесса скрипта, процессы Excel закрывались. Оттого хотел узнать, закроются ли здесь процессы Excel при закрытии скрипта/сессии PoSH.

amel27 06-05-2011 16:51 1671365

WSH - это COM, там проблем с автозачисткой не должно быть...
у меня не закрывался, но (обычно) "висело" >1 процесса EXCEL (возможно они друг друга блокировали)

ThaViper 15-11-2011 16:27 1795671

т.к. 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.

Время: 09:55.
© OSzone.net 2001-