Войти

Показать полную графическую версию : [решено] Выяснить открыта ли книга Excel и если открыта, подключится к ней


corbis
27-11-2014, 02:13
Вот такая возникла заморока и никак не найду способ реализации.

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

(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
А если не открыта — тогда что делать?

Не знаю, как у Вас, а у нас — выдаёт:
$xl = [Runtime.Interopservices.Marshal]::GetActiveObject('Excel.Application')
$xl.Workbooks | ForEach-Object -Process {$_.FullName}
E:\Песочница\0410\Книга1.xls


Ещё вариант: Converting VBScript's GetObject Function (http://technet.microsoft.com/en-us/library/ee176862.aspx).
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
Если книга закрыта, то открыть через 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
У меня вышеприведенный код выдает ошибку:
Исключение при вызове "GetActiveObject" с "1" аргументами: "Операция недоступна (Исключение из HRESULT: 0x800401E3 (MK_E_UNAVAILABLE))"
строка:1 знак:1
+ $xl = [Runtime.Interopservices.Marshal]::GetActiveObject('Excel.Application')
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : COMException
Это в случае, если файл открыт как обычно. »
Почитайте:
Форумы caduser.ru (http://www.caduser.ru/forum/index.php?PAGE_NAME=read&FID=7&TID=49097)
When CoCreateInstance returns 0x80080005 (CO_E_SERVER_EXEC_FAILURE) - Antimail - Site Home - MSDN Blogs (http://blogs.msdn.com/b/adioltean/archive/2005/06/24/432519.aspx)
и попробуйте проверить аналогичную методику с try и повторным запросом. У меня, кстати, в отличие от Вас, тоже XP (как у автора по первой ссылке), и проблема тоже не воспроизводится.

Может это уже проблемы Windows? Win 8.1, Office 2010 »
Теоретически всё может быть. Я лично сталкивался с различным поведением одной и той же версии PowerShell на разных ОС в казалось бы весьма простой ситуации.

P.S. Поройтесь ещё здесь: powershell GetActiveObject Exception from HRESULT 0x800401E3 MK_E_UNAVAILABLE - Поиск в Google (https://www.google.ru/search?q=powershell+GetActiveObject+Exception+from+HRESULT+0x800401E3+MK_E_UNAVAILABLE), может чего найдёте.

corbis
27-11-2014, 15:37
Супер!! тема с 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
corbis, если где-нибудь, когда-нибудь, в будущем наткнётесь на объяснение причин возникновения данной проблемы под новыми ОС и методами их решения — не сочтите за труд, отпишитесь здесь.




© OSzone.net 2001-2012