- - PR -
VB.NETでClipBoardクラスを使用しつつ排他処理
投稿者 | 投稿内容 | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2007-03-07 18:17
こんばんは。
いま、VB.NETでExcel帳票作成アプリを作成しています。 環境はVS2003です。 直接Excelのセルに値を埋め込むと、処理に時間がかかってしまうため、 一度CSVを作成してからClipBoardを使用して Excelに貼り付けようとしました。 貼り付けまではうまくいき、処理にかかる時間も大幅に短縮したのですが、 このアプリはサーバーに置いておき、 複数同時アクセスを可能にしたいのです。 しかし同時にアプリを起動すると、タイミングによって前後のClipBoardの内容が 貼り付けられてしまいます。 そこで、ClipBoard使用時に排他処理をかませたいのですが、 何かいい方法はあるでしょうか。 アドバイスを頂けたらと思います。 以下、ソース。 ' Excelアプリ起動 xlsApp = CreateObject("Excel.Application") xlsApp.DisplayAlerts = False xlsBook = xlsApp.Workbooks.Open(m_xlsFilePath) xlsApp.Application.Visible = False ' シートを選択 With xlsBook.Worksheets(1) ' クリップボードにデータをコピーする System.Windows.Forms.Clipboard.SetDataObject(m_StrExcelData) ' 貼り付け先のシートをActivateにする .Activate() ' 貼り付け先のセル .Range("C13").Select() ' ペースト .Paste() ' クリップボードの内容をクリア(現在はコメントアウト) 'System.Windows.Forms.Clipboard.SetDataObject(NewSystem.Windows.Forms.DataObject) End With ' ファイルを保存 xlsBook.SaveAs(m_xlsFilePath) xlsBook.Close() : xlsBook = Nothing xlsApp.Application.Visible = False xlsApp.Quit() : xlsApp = Nothing [ メッセージ編集済み 編集者: Yakisoba 編集日時 2007-03-07 18:21 ] | ||||||||||||||||||||
|
投稿日時: 2007-03-07 19:09
二重で起動できなくする。 って書こうと思ったけどその前にこれが実行されるのってクライアント側なの?
これはひどいwこのサイトをReleaseComObject(だっけ?)で検索しなさい。 [ メッセージ編集済み 編集者: ぶさいくろう 編集日時 2007-03-07 19:10 ] | ||||||||||||||||||||
|
投稿日時: 2007-03-07 19:18
ツリーからExcelでもいいぞ
配列でコピー ODBC経由で流し込む ディレクトリだった [ メッセージ編集済み 編集者: Jitta 編集日時 2007-03-07 19:20 ] | ||||||||||||||||||||
|
投稿日時: 2007-03-07 21:31
早速のご返答ありがとうございます。
ぶさいくろうさんのおっしゃった通り、 xlsBook.Close() : xlsBook = Nothing xlsApp.Application.Visible = False xlsApp.Quit() : xlsApp = Nothing の部分を以下のように変えました。 Finally ' オブジェクトの解放 If Not (xlsRange Is Nothing) Then System.Runtime.InteropServices.Marshal.ReleaseComObject(xlsRange) End If If Not xlsSheet Is Nothing Then System.Runtime.InteropServices.Marshal.ReleaseComObject(xlsSheet) End If If Not xlsBook Is Nothing Then Try xlsBook.Close() Finally System.Runtime.InteropServices.Marshal.ReleaseComObject(xlsBook) End Try End If If Not xlsApp Is Nothing Then Try xlsApp.Quit() Finally System.Runtime.InteropServices.Marshal.ReleaseComObject(xlsApp) End Try End If End Try アプリが終了するまで、プロセスが残ったままなのですが、 この動きは正しいのでしょうか。 解放した時点で消えるものだと思っていたもので・・・ もちろんアプリ終了時にはプロセスは消えています。 最初の方で、複数同時アクセスと書きましたが、 サーバー上で複数同時実行される、ということです。 また、Jittaさんのおっしゃっていることですが、 オートメーションを使用してデータの配列をブックの特定のセル範囲に転送する ということでしょうか。 認識違いでしたら申し訳ないです。 [ メッセージ編集済み 編集者: Yakisoba 編集日時 2007-03-07 21:46 ] | ||||||||||||||||||||
|
投稿日時: 2007-03-07 23:04
http://www.atmarkit.co.jp/fdotnet/index/bbs/dir91.html
↑ 苦労しているんだ(笑)見てくれ。 モバイルからだった and 降りるバス停がすぐそこだったので簡単に書いてごめん。 方法は2つ。 1.Excel を“データベース”として扱い、ODBC 経由でデータを流し込む方法。 2.オートメーションで Excel を操作し、配列データで一気にデータを流し込む方法。 があります。どちらも過去ログにあるので、上の URL で、タイトルを一通り眺めてみてください。
いいえ。正しく解放されていれば、xlsApp.Quit() か、xlsApp をリリースした時点でプロセスが終了します。 _________________ | ||||||||||||||||||||
|
投稿日時: 2007-03-08 09:11
この部分以外のところも NG です。
Excel.Workbooks インスタンスの参照の取り忘れています。 取り忘れる == ReleaseComObject メソッドを使って参照カウントをデクリメントする機会を完全に失います。
意味のない参照カウントを増やすだけの実装になっています。 xlsApp は Application インターフェイス。 xlsApp.Application も Application インターフェイス。 そして、どちらも実体は同じものを示します。
Excel.Worksheets (Excel.Sheets) インスタンスの参照の取り忘れています。 取り忘れる == ReleaseComObject メソッドを使って参照カウントをデクリメントする機会を完全に失います。 With ステートメントを使っているため、With ブロック内はほとんど全滅です。
Excel.Range インスタンスの参照の取り忘れています。 取り忘れる == ReleaseComObject メソッドを使って参照カウントをデクリメントする機会を完全に失います。 で、Office PIA をここまでふんだんに使う方法を選択するのは賢明ではなく、
# Jitta さんの言う、"ODBC 経由でデータを流し込む" は、2. に当たる...? _________________ C# と VB.NET の入門サイト じゃんぬねっと日誌 | ||||||||||||||||||||
|
投稿日時: 2007-03-08 10:04
サーバー側で同時実行される可能性があるのであれば、
クリップボードを使う以上は無理だと思います。 仮に二重起動を防止したり、ロックファイルを使用したりして解決したとしても、 別のプログラムがクリップボードを使用したりする可能性もありますし、 保守作業中にコピーを行ってしまうこともあるかも知れません。 少なくとも安全とは言えないと思います。
CSVを作成とありますが、物理ファイルとして作成しているのでしょうか? 物理ファイルがあるならQueryTables.Add メソッドを使って取り込む手も使えるかも知れません。 当然CSVも排他を考慮して作成する必要がありますが。 | ||||||||||||||||||||
|
投稿日時: 2007-03-08 13:46
ご返答ありがとうございます。
ご指摘頂いた通り、Excelオブジェクトを細かく宣言し、 その1つ1つに対して解放することで Excelのプロセスが消えるようになりました。
様々な方法があるのですね。勉強になります。 とりあえず配列を使用しRangeで貼り付けるところから試してみようと思います。 |