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

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

corbis 27-11-2014 02:13 2436134

Выяснить открыта ли книга Excel и если открыта, подключится к ней
 
Вот такая возникла заморока и никак не найду способ реализации.

С выяснением того, что книга открыта я придумал такой вариант:

Код:

(Get-Process excel | Select-Object -Property MainWindowTitle) -match "Заказы_2014.xls"
Но вот как подключится к открытой книге не пойму. Вариант с закрытием и последующим открытием через скрипт не подходит.
Если кто-то с книгой работает, прерывать работу нельзя.

Код:

$xl = [Runtime.Interopservices.Marshal]::GetActiveObject('Excel.Application')
$xl.Workbooks

Такой код списка открытых книг не выдает, хотя автор привел этот пример именно для этой цели.
Намучался с поиском ответа, прошу помощи.

Iska 27-11-2014 04:46 2436144

А если не открыта — тогда что делать?

Не знаю, как у Вас, а у нас — выдаёт:
Скрытый текст
Код:

$xl = [Runtime.Interopservices.Marshal]::GetActiveObject('Excel.Application')
$xl.Workbooks | ForEach-Object -Process {$_.FullName}

Цитата:

Код:

E:\Песочница\0410\Книга1.xls



Ещё вариант: Converting VBScript's GetObject Function.
Что-то наподобие…

Код:

function Release-Ref ($ref) {
    ([System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$ref) -gt 0)
    [System.GC]::Collect()
    [System.GC]::WaitForPendingFinalizers()
}

[reflection.assembly]::LoadWithPartialName("'Microsoft.VisualBasic") | Out-Null
$oWorkBook = [Microsoft.VisualBasic.Interaction]::GetObject("E:\Песочница\0410\Книга1.xls")

$oExcel = $oWorkBook.Application
$oExcel.Visible = $true
$oExcel.Windows.Item(1).Visible = $true

$oWorkBook.Path, $oWorkBook.Name
$oWorkBook.Worksheets.Item(1).Cells.Item(1, 1).Value()

$oWorkBook.Close($false)
$oExcel.Quit()

Release-Ref($oWorkBook)
Release-Ref($oExcel)


corbis 27-11-2014 13:04 2436312

Если книга закрыта, то открыть через comObject, тогда вообще никаких проблем.
У меня вышеприведенный код выдает ошибку:

Код:

Исключение при вызове "GetActiveObject" с "1" аргументами: "Операция недоступна (Исключение из HRESULT: 0x800401E3 (MK_E_UNAVAILABLE))"
строка:1 знак:1
+ $xl = [Runtime.Interopservices.Marshal]::GetActiveObject('Excel.Application')
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : COMException

Это в случае, если файл открыт как обычно. Если файл запускается скриптом, то код:

Код:

$xl = [Runtime.Interopservices.Marshal]::GetActiveObject('Excel.Application')
$xl.Workbooks | ForEach-Object {$_.FullName}

выдает:

Код:

C:\Users\User\Test\Заказы.xls
Может это уже проблемы Windows? Win 8.1, Office 2010
Проверил на Win 7 и Office 2007. Та же картина.

Iska 27-11-2014 14:14 2436349

Цитата:

Цитата corbis
У меня вышеприведенный код выдает ошибку:
Цитата:

Исключение при вызове "GetActiveObject" с "1" аргументами: "Операция недоступна (Исключение из HRESULT: 0x800401E3 (MK_E_UNAVAILABLE))"
строка:1 знак:1
+ $xl = [Runtime.Interopservices.Marshal]::GetActiveObject('Excel.Application')
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : COMException
Это в случае, если файл открыт как обычно. »

Почитайте:
Форумы caduser.ru
When CoCreateInstance returns 0x80080005 (CO_E_SERVER_EXEC_FAILURE) - Antimail - Site Home - MSDN Blogs
и попробуйте проверить аналогичную методику с try и повторным запросом. У меня, кстати, в отличие от Вас, тоже XP (как у автора по первой ссылке), и проблема тоже не воспроизводится.

Цитата:

Цитата corbis
Может это уже проблемы Windows? Win 8.1, Office 2010 »

Теоретически всё может быть. Я лично сталкивался с различным поведением одной и той же версии PowerShell на разных ОС в казалось бы весьма простой ситуации.

P.S. Поройтесь ещё здесь: powershell GetActiveObject Exception from HRESULT 0x800401E3 MK_E_UNAVAILABLE - Поиск в Google, может чего найдёте.

corbis 27-11-2014 15:37 2436412

Супер!! тема с try catch прокатила. Спасибо за наводку. Работает, конечно, с задержкой, но мне в данном случае это безразлично.
Привожу свой вариант, может кому пригодится.

Код:

[reflection.assembly]::LoadWithPartialName("'Microsoft.VisualBasic") | Out-Null
$oWorkBook = [Microsoft.VisualBasic.Interaction]::GetObject("C:\Users\User\Test\Заказы.xls")

try
 {
 $oExcel = [Runtime.Interopservices.Marshal]::GetActiveObject('Excel.Application')
$oExcel.Workbooks | ForEach-Object {$_.FullName}
 }
 catch [Microsoft.Office.Interop.Excel.Application]
 {
 $oExcel = [Runtime.Interopservices.Marshal]::GetActiveObject('Excel.Application')
 $oExcel.Workbooks | ForEach-Object {$_.FullName}
 }

$oWorkBook.Path, $oWorkBook.Name
$oWorkSheet = $oWorkBook.WorkSheets.Item(1)
$oWorkSheet.Cells.Item(1, 1).Value()


Iska 27-11-2014 15:56 2436424

corbis, если где-нибудь, когда-нибудь, в будущем наткнётесь на объяснение причин возникновения данной проблемы под новыми ОС и методами их решения — не сочтите за труд, отпишитесь здесь.


Время: 21:05.

Время: 21:05.
© OSzone.net 2001-