環境:WinXP、VB.NET
いつもお世話になっています。
選択されたテーブル(MDB)項目の内容をExcelのセルに入力する処理を初めて作成しました。
流れとしては入力処理終了後にExcelを表示(wApp.Visible=True)したら
そのまま閉じる(wApp.Quit)ことはせずにwApp,wBook…等を解放して終了。
あとはExcel側で名前を付けて保存するなり閉じるなり…といった感じです。
この時Excel画面はフォームの上に表示されExcel画面を閉じればフォーム
が最前面になるのかなというイメージだったんですがそうではなく
タスクバーでフォームを選択しないと前面に来ない状態です。
これを最前面にさせる方法はあるでしょうか?
そもそも何か思い違いをしてるかもしれませんがよろしくお願いします。
APIのSetActiveWindowとか?
Excelに限らずWordとか外部アプリを起動して閉じた時に真下にあった
フォームが一瞬見えたあとにエクスプローラとか別ウィンドウが
立ち上がってるとしてそのうしろに隠れちゃうとか・・・って事ですか?
単純に最前面はTopMostプロパティをTrueだと思いますが
それだとExcelを表示してもフォームが上になっちゃうから
フォームがアクティブになったときにActivatedとかで
TopMost = True
TopMost = False
とかはダメでしょうか?
>フォームがアクティブになったときにActivatedとかで
外部アプリを閉じた時にうしろに隠れちゃうんだからActivatedイベントは
検出されないのかな・・?ダメっぽいですね。
やはり初心者ごときが回答するもんじゃないですね。忘れて下さいm(_ _)m
初心者ですがさんありがとうございます。
>フォームがアクティブになったときにActivatedとかで
念のため試してみましたが、ご想像の通りでした。
通ってみたさんありがとうございます。
>APIのSetActiveWindowとか?
APIの使用法がよく分からずまだきちんとは試せていません…すいません。
なにかサンプルコードのようなものはないか調査中です。
あとアクティブにするタイミングはアプリケーション(Excel)が終了したら
という事になると思い、ProcessクラスであればExitedイベントで終了を
検出できるという事までは調べたんですが…
元々今回は「セルにデータを入力する」が勉強課題で現在は下記のような
コードになっているのですが、終了を検出する方法はあるでしょうか?
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
'中略(テーブル接続等)
'※テスト(テーブル内容をExcelのセルへ)
If mDataTable.Rows.Count > 0 Then
Dim i, j As Integer
Dim wRowCnt As Integer = mDataTable.Rows.Count - 1
Dim wColCnt As Integer = mDataTable.Columns.Count - 1
Dim wSetItem(wColCnt) As String
Dim wCol1, wCol2 As String
'
Dim wAppli As New Excel.Application
Dim wBooks As Excel.Workbooks
Dim wBook As Excel.Workbook
Dim wSheets As Excel.Sheets
Dim wSheet As Excel.Worksheet
Dim wCells, wRange, wRange1 As Excel.Range
'
wBooks = wAppli.Workbooks
wBook = wBooks.Add
wSheets = wBook.Worksheets
wSheet = CType(wSheets.Item(1), Excel.Worksheet)
wCells = wSheet.Cells
'配列にセット:見出し(フィールド名)
For i = 0 To wColCnt
wSetItem(i) = mDataTable.Columns(i).Caption
Next
'配列内容をExcelのセルへ
wRange1 = CType(wCells(1, 1), Excel.Range)
wCol1 = wRange1.Address(False, False)
ReleaseComObj(CType(wRange1, Excel.Range))
wRange1 = CType(wCells(1, wColCnt + 1), Excel.Range)
wCol2 = wRange1.Address(False, False)
wRange = wSheet.Range(wCol1 & ":" & wCol2)
wRange.Value = wSetItem
'
ReleaseComObj(CType(wRange1, Excel.Range))
ReleaseComObj(CType(wRange, Excel.Range))
For i = 0 To wRowCnt
'配列にセット:1レコード分(フィールド値)
wSetItem.Initialize()
For j = 0 To wColCnt
wSetItem(j) = mDataTable.Rows(i)(j).ToString
Next
'配列内容をExcelのセルへ
wRange1 = CType(wCells(i + 2, 1), Excel.Range)
wCol1 = wRange1.Address(False, False)
ReleaseComObj(CType(wRange1, Excel.Range))
wRange1 = CType(wCells(i + 2, wColCnt + 1), Excel.Range)
wCol2 = wRange1.Address(False, False)
wRange = wSheet.Range(wCol1 & ":" & wCol2)
wRange.Value = wSetItem
'
ReleaseComObj(CType(wRange1, Excel.Range))
ReleaseComObj(CType(wRange, Excel.Range))
Next
'表示
wAppli.Visible = True
ReleaseComObj(CType(wCells, Excel.Range))
ReleaseComObj(CType(wSheet, Excel.Worksheet))
ReleaseComObj(CType(wSheets, Excel.Worksheets))
'wBook.Close(False)
ReleaseComObj(CType(wBook, Excel.Workbook))
ReleaseComObj(CType(wBooks, Excel.Workbooks))
'wAppli.Quit()
ReleaseComObj(CType(wAppli, Excel.Application))
'
Else
MessageBox.Show("該当データなし!")
End If
End Sub
やろうと思えば今ある知識(↑)だけでも何とかなるのでは?
[入力後のファイルを保存]
Dim wPath As String = 保存ファイル名
wAppli.DisplayAlerts = False
wSheet.SaveAs(wPath)
wAppli.DisplayAlerts = True
[Process.Startメソッドで起動]
Process.Start("Excel.exe", wPath)
とか。
まぁそれなりの仕様もあるだろうし、あくまでそれっぽく動くのでは?
程度のものでとてもいい手法とは言えないけどね。
いずれにせよ質問に沿ったコードを載せた方が良いよ。
↑だと、あれっ?このスレ「Excelにデータを吐くには」だっけ?て感じが・・・
こちらのサイトのTipsにありましたがどうですか?
< SAMPLE >
'標準モジュール
Public Declare Function SetActiveWindow Lib"USER32" (ByVal hWnd&) As Long
'ここからはフォームの処理
Private Sub Command1_Click()
Dim Ret As Long
’Form1をアクティブにする
Ret=SetActiveWindow(Form1.hwnd)
End Sub
SetActiveWindowの(古い)MSDN
> この関数は、アプリケーションがバックグラウンドにあるときには (現在ユーザーがほかのアプリケーションで作業をしているときには) 、ウィンドウをアクティブ化しません
また代用品としてSetForegroundWindowなどがありますが、Win2k(?)あたりからWin9xと挙動が違います。
他にもSetWindowPosなどもあります
返事が遅れてすいません。皆様アドバイスありがとうございます。
んーさん回答有難うございます。
ご指摘の通りだなと思います。今回はExcelを起動し新規ファイルを開きデータを入力したら
>あとはExcel側で名前を付けて保存するなり閉じるなり…といった感じです。
つもりでしたので保存処理は入れませんでした。Excel表示後、加工するのか
しないのか、保存するのかしないのか…etc 全てその時の判断で自由にと。
ですがこの方法であればたしかに終了時にフォームを前面にすることも
できそうなので今の自分等にはいい方法だと思うのでやってみます。
Tipsさん、参考さん回答有難うございます。
いくつかのサンプルや社内でAPI関連の技本など見つけましたがVB6の頃の
もので.NETから始めた初級者チームなので.NETに置き換えて参考にするといった
ことが全くの未熟だということが正直なところです。ヘルプ等もですが…
ですがいい機会なので色々勉強してものにできればと思います。
また遅れてしまうかもしれませんが結果報告できれば書込みします。
ツイート | ![]() |