はじめまして.[VB6.0 Windows2000pro office2002]
VBで作成したメニュー画面より,コモンダイアログを表示し,
そこでユーザが選択したエクセルファイルを読み取り専用としてオープンしたいと思っています.
VB側としては,エクセルファイルが立ち上がっている状態の場合は,メニュー画面をいじることは出来ないように死体のです.(複数のエクセルファイルを起動させないために)
実際に,エクセルオブジェクトを作成し,エクセルファイルを立ち上げることが出来ましたが,VBとオープンされたエクセルファイルと別々に動作してしまいます.
ご存知の方がいらっしゃいましたらぜひご教授願います.
単純にExcelが起動されているかどうか であれば、APIを使用し、現在実行中のプロセスを調べて、Excel.exeがあればそのメニューをいじらない というロジックにすればできるのではないでしょうか??
起動されているExcelのファイル名までチェックしたいのであれば、VBでExcelを起動した時にファイル名を覚えておいて、それでチェックするとか。
でもコレだと、VB以外から起動したExcelファイルについてはダメですけどね(^^;)
ほんとは、Excel起動の有無+起動されているファイル名 まで取得してやるのが一番なんでしょうけど…ちょっと私にはわからないです。すみませんm(_ _)m
ハナクソース様
早速の回答ありがとうございます.
> 起動されているExcelのファイル名までチェックしたいのであれば、VBでExcelを起動した時にファイル名を覚えておいて、それでチェックするとか。
> でもコレだと、VB以外から起動したExcelファイルについてはダメですけどね(^^;)
ということで,VB側でオープンさせたエクセルに対してウィンドウハンドラを取得しその値を保持するようにしてみましたが,思うように処理が出来ませんでした.
(技術の無さです)
また,エクセルオブジェクトに対してユーザが何らかのイベントを起こした際に
VB側から取得できるでしょうか?
よろしくお願いします.
たびたびすみません.
以下のようにエクセルファイルの制御を行ってみました.
読みにくいソースかもしれませんがよろしくお願いします
他に良い方法がございましたら,ご教授お願いします.
メニュー画面(menu.frm)
'------------------------------------------------------
'実行ボタンが押下された際の処理
'------------------------------------------------------
private sub cmdActionMenu_click()
・・・・
' コモンダイアログを表示
dlgCmnDialog.ShowOpen
' 選択されたファイル名を取得
If dlgCmnDialog.FileName = "" Then ' ファイルが選択されていない場合は終了
Exit Sub
End If
cmdActionMenu.Enabled = False ' 「実行」ボタンを非表示
bSelectFile = dlgCmnDialog.FileName
' ファイルオープン
Call FileReadForExcel(bSelectFile, bCaption)
' エクセルアプリケーションが終了するまで待機
Call WatchExcelHandle(bCaption)
dlgCmnDialog.FileName = "" ' ファイル名の初期化
cmdActionMenu.Enabled = True ' 「実行」ボタンを非表示
Exit Sub
private Sub FileReadForExcel(ByVal pSelectFile As String, ByRef pCaptionTitle As String)
Dim xlApp As Excel.Application
Dim xlBook As Excel.Workbook
Dim xlSheet As Excel.Worksheet
On Error GoTo ErrFileReadForExcel
Set xlApp = CreateObject("Excel.Application")
Set xlBook = xlApp.Workbooks.Open(pSelectFile)
Set xlSheet = xlBook.Worksheets(1)
pCaptionTitle = xlApp.Caption ' キャプション名取得
xlSheet.Application.Visible = True
Set xlSheet = Nothing ' オブジェクトの解放\
Set xlBook = Nothing
Set xlApp = Nothing
ErrFileReadForExcel:
If Err.Number <> 0 Then
Call MsgBox("エラーが発生しました。", vbCritical, App.Title)
End If
Exit Sub
End Sub
private Sub WatchExcelHandle(ByVal pCaptionTitle As String)
Dim wkHwnd As Long
'参考キャプション名を与えてハンドルを取得する
wkHwnd = FindWindow(vbNullString, pCaptionTitle)
' エクセルファイルが起動中の場合
If wkHwnd <> 0 Then
Sleep (2000) ' いったんプログラムを停止
' 再度このプロシージャを呼ぶ
Call WatchExcelHandle(pCaptionTitle)
End If
End Sub
遅くなりましたm(_ _)m
あんぶーさんのソースを参考に私の環境で実行してみましたが、動作しました。
(あるウィンドウのハンドルを取得し、そのウィンドウが閉じられるまではループしてました)
>思うように処理が出来ませんでした.
↑↑↑具体的に、意図する動きと現状の動きはどのようなものでしょうか?↑↑↑
とりあえず、ステップ実行してみてはどうでしょうか??
それと、WatchExcelHandle内でウィンドウハンドルの戻り値を聞いて再度自分自身(WatchExcelHandle)をCALLしていますが、特別な理由がないのであれば、ロジック的には以下のようにしたほうが望ましいのではないかと思います。
①WatchExcelHandleをFuncitionにする。(戻り値:ウィンドウハンドル)
②cmdActionMenu_click()プロシージャでウィンドウハンドルの戻り値を聞いて、待ち合わせ or 処理続行の判断をする。
↓↓こんな感じ↓↓
wkHwnd =WatchExcelHandle
Do While(wkHwnd <>0)
Sleep(2000)
wkHwnd =WatchExcelHandle
Loop
おそらくここが問題ではないと思いますし、まぁ好みの問題(^^;)な気もしますので、よかったら参考程度に。
ハナクソースさまご確認ありがとうございます.
>>思うように処理が出来ませんでした.(2004/04/20(火) 13:27:45)
>↑↑↑具体的に、意図する動きと現状の動きはどのようなものでしょうか?↑↑↑
というのは,
このアプリケーションを実行している際は,他のエクセルが起動しない.
画面を移動させると残像(?)が残ってしまう.
といった点です.
結局Shell関数を使用して以下のように修正しようと思います.(すみません)
同じような起動方法なのに,エクセルの立ち上がり状態が違うのはなぜなのでしょうか?
・・・とかいた時点で気づいたのですが,ウィンドウハンドラの解放って結構重要なことですよね?
Public Function FileReadForExcel(ByVal pSelectFile As String, ByRef pCaptionTitle As String) As Boolean
Dim xlApp As Excel.Application
Dim xlPath As String
Dim wkProcID As Long
Dim wkHandle As Long
Dim wkStatus As Long
Dim Buffer As String
On Error GoTo ErrFileReadForExcel
FileReadForExcel = False
Set xlApp = CreateObject("Excel.Application") ' オブジェクトの作成
pCaptionTitle = xlApp.Caption
xlPath = xlApp.Path & "\" & m_Excel_Name ' Excel実行ファイル名取得
Set xlApp = Nothing ' オブジェクトの解放
xlPath = xlPath & " " & pSelectFile ' 起動させたいファイルを追加
wkProcID = Shell(xlPath, vbNormalFocus) ' プロセス実行,ID取得
If wkProcID = 0 Then
' IDが取得できない
Call CmLog(g_SystemName, "modViewr(FileReadForExcel)", _
"以下のコマンドが実行できませんでした。" & xlPath, _
"", CmGetFilePath(g_LogDir, g_LogFileName))
Exit Function
End If
' ハンドル取得
wkHandle = OpenProcess(SYNCHRONIZE, True, wkProcID)
If wkHandle = Null Then
Buffer = Space(300)
FormatMessage FORMAT_MESSAGE_FROM_SYSTEM, ByVal 0&, GetLastError(), LANG_NEUTRAL, Buffer, 300, ByVal 0&
Buffer = Left$(Buffer, InStr(1, Buffer, vbNullChar & vbNullChar) - 1)
Call MsgBox("エラーが発生しました。Err:" & Buffer, vbCritical, App.Title)
End If
' プロセス待機
wkStatus = WaitForSingleObject(wkHandle, INFINITE)
If wkStatus <> WAIT_OBJECT_0 Then
Buffer = Space(300)
FormatMessage FORMAT_MESSAGE_FROM_SYSTEM, ByVal 0&, GetLastError(), LANG_NEUTRAL, Buffer, 300, ByVal 0&
Buffer = Left$(Buffer, InStr(1, Buffer, vbNullChar & vbNullChar) - 1)
Call MsgBox("エラーが発生しました。Err:" & Buffer, vbCritical, App.Title)
End If
' ハンドルの解放
If wkHandle <> 0 Then CloseHandle (wkHandle)
wkHandle = 0
FileReadForExcel = True
Exit Function
ErrFileReadForExcel:
If Err.Number <> 0 Then
Call MsgBox("エラーが発生しました。Err:" & Err.Description, vbCritical, App.Title)
End If
Exit Function
End Function
最後に,ハナクソースさま,回答どうもありがとうございました.
また何か行き詰まったときはよろしくお願いします.