質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

PowerShell

Windows PowerShellはコマンドラインインターフェースであり、システム管理を含むWindowsタスク自動化のためのスクリプト言語です。

Q&A

解決済

1回答

4211閲覧

PowerShellで Excel操作時 Intersect が使えなくて困っています。

kamikazelight

総合スコア305

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

PowerShell

Windows PowerShellはコマンドラインインターフェースであり、システム管理を含むWindowsタスク自動化のためのスクリプト言語です。

0グッド

0クリップ

投稿2019/02/06 08:38

再現用のソースコード

そのままだと説明が難しかったので最初にコードを載せます。

poweshell

1Using Namespace System.Runtime.InteropServices 2 3$AP = New-Object -ComObject "Excel.Application" 4$Ap.Visible = $true 5$Bk = $Ap.Workbooks.Add() 6$Sh = $Bk.ActiveSheet 7$Sh.Range("A1:D10").Value = "test" 8 9$Ap2 = [Marshal]::GetActiveObject("Excel.Application") 10$Sh2 = $Ap2.ActiveSheet 11 12$Ap.Intersect($Sh.UsedRange, $Sh.Rows(3)).Address($false, $false) # New-Object 取得できない(エラー表示で「オーバーロードで引数が2つのものが見つからない」っとでる) 13$Ap2.Intersect($Sh2.UsedRange, $Sh2.Rows(3)).Address($false, $false) # Marshal 取得できる 14 15$Ap.Workbooks | foreach { $_.Close($false) } 16$Ap.quit() 17Remove-Variable Ap, Bk, Sh, Ap2 18[GC]::Collect()

やりたいこと

新規インスタンス(New-Object)でExcelを起動して EnableEvents を False に設定してから
指定ファイルを読取専用で開いて 特定行の条件に一致したセルからデータを取得したい。

特定行の条件に一致したセルを検索するときにUserRange外のセルは確認する必要がない為
UserRange内の指定行のセルだけ取得したかったです。
そのために Intersect を利用しようとしましたが使えませんでした。
New-Object を使用した場合Intersect は引数2つでは使えないのでしょうか?
教えて頂きたいです。

やりたいこと内の操作の理由

下記条件を満たすためです。

  • 処理を行うパソコンでExcelを使用中の可能性がある
  • 使用中のExcelには影響は与えたくない
  • 使用中のExcelはVBAが使用されている可能性がある(イベント含み)
  • 操作対象のExcelファイルにはVBAが使用されている(イベント含み)
  • 操作対象のExcelファイルのVBAは動作させてはいけない
  • 操作対象のExcelファイルは変更(上書き保存)してはいけない
  • 操作対象のExcelファイルは共有場所にある
  • 操作対象のExcelファイルはいつ別PCで利用されるか分からない
  • 別PCでの作業の邪魔はしてはならない

試したこと

再現用のソースコードに記載しましたが
New-Objectで生成したExcelインスタンスでは引数が2つではIntersectが利用できませんでしたが
[Marshal]で取得したインスタンスでは問題なく利用できました。

そこからNew-Objectで生成したExcelインスタンス を [Marshal]で取得したインスタンスと同じ型に
キャストしてみようと試みましたが失敗に終わりました。

補足情報(FW/ツールのバージョンなど)

Win10
powershell V5

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

原因の推測

経験上、PowerShellの~のオーバーロードで、引数の数が "2" であるものが見つかりません。のエラーは、引数の型が一致していない場合にも発生します。

それを踏まえて、$Ap.Intersect.OverloadDefinitionsを確認すると、
引数1,2はMicrosoft.Office.Interop.Excel.Rangeと、PIA(プライマリ相互運用アセンブリ)の型を要求していることがわかります。
これは、New-Objectで取得した$Apの型が、PIAで定義されているMicrosoft.Office.Interop.Excel.Applicationであるためです。

しかしPowerShell上では、New-Object以外の方法で取得したCOMオブジェクトは全て__ComObjectになってしまい、__ComObjectからPIAの型にキャストすることができません(経験上・C#などでは可能)。

そのため、$Apの型だけがPIAで定義されている型で、それ以外がCOMオブジェクトになってしまい、型が一致しないため~のオーバーロードで~のエラーになったと思われます。

対策

型を明示する

以下のように、変数の型を明示すると動作するようになりました。

[Microsoft.Office.Interop.Excel.~]でも動く理由は不明ですが、COMオブジェクト用の特別処理が行われているのかもしれません。

また、C#などでは__ComObjectの型は指定できないため注意が必要です。

powershell

1# 以下の型宣言ならどれでも動作する 2[__ComObject]$AP = New-Object -ComObject "Excel.Application" 3[Microsoft.Office.Interop.Excel.Application]$AP = New-Object -ComObject "Excel.Application" 4[Microsoft.Office.Interop.Excel.ApplicationClass]$AP = New-Object -ComObject "Excel.Application" 5 6# 以下の場合(型を明示しない場合含む)は動作しない 7[object]$AP = New-Object -ComObject "Excel.Application"

New-Objectを使わない

New-Objectの代わりに以下の記述でもExcelのインスタンスを生成できます。

powershell

1$AP = [Activator]::CreateInstance([type]::GetTypeFromProgID('Excel.Application'))

New-Objectの結果を直接使わない

以下のように、New-Objectの結果のApplicationプロパティを参照することでもエラーは発生しなくなりました。

powershell

1$AP = (New-Object -ComObject "Excel.Application").Application

投稿2019/02/06 10:33

imihito

総合スコア2166

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kamikazelight

2019/02/06 11:35

エラーを言葉のままに受け取っていました 言われてみれば powershellだった気がするのですが メソッドは引数の型違いで定義出来ましたね..... 今回も非常に助かりました。 これからもよろしくお願い致します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問