ゲーム馬鹿な日々
S | M | T | W | T | F | S |
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
タグ
PS3 ブレイブルー ネット対戦 PSP 私生活 アドホックパーティ PSPo2 世界樹の迷宮3 名古屋出張 DS TOV ライチ モンスターハンター3 ガンダム戦記 SSF4 VB2008 Wii DS お医者さんと禁煙しよう デモンズソウル09/11/18 VBでExcelファイル編集。プロセス解放について。
さすがに2~3年ぶりにコーディングしてると、
気づかないこともある。
念願叶って、VB.NETっていうかVB2008での仕事をしているのです。
そのための備忘録。
でも、VB2008だろうが、コテコテのクラサバアプリケーションだったり。
しかも、帳票はExcelファイルで出力といった
無駄にエコ仕様。
「必要なファイルだけ出力する」
「出力する必要がなければ、紙を無駄にしない」
と言っているわりには、
正直、Excelでの帳票のが、絶対、開発工数かかると思うんだよな。
帳票を未だにExcelで出そうしているユーザがいるってだけでも、
オレにとっては、レアなユーザなんですけど・・・。
----------------------------------------------
話を戻して・・・。
VBでExcelを弄るときは、以下の点を注意すること。
※というか、注意というより徹底しろ。
そうじゃないと、折角、動くものが出来ても、
編集後にExcelプロセスが落ちないから、
Windows側から直接Excelを起動できなくなる。
■Excelのマクロの記録でとったコードはそのまま使えない。
超常識。
よくあるのは、
例 誤り ActiveSheet 正解 xlBook.ActiveSheet
この間違え。
基本的に、バックグラウンドでファイルの中身を編集するので、
ActiveSheetオブジェクトを使うほうが珍しい。
逆に、ユーザに編集のExcelファイルの中身を見せたいなら、
ActiveSheetオブジェクトを使うはあり。
でも、あんまオススメしないし。オレが設計するならそんなんしない。
ちなみに、シート名が分かっているなら、直接取得したほうがいい。
xlSheet = xlBook.Worksheets("hoge")
■VB6.0との違い
VB2008触って初めて気づいた。
Excelを弄る際のオブジェクトの宣言記述が違う。
VB6.0 の場合
Dim xlApp As Excel.Application
Dim xlBook As Excel.Workbook
Dim xlSheet As Excel.Worksheet
Set xlApp = CreateObject("Excel.Application")
Set xlBook = xlApp.Workbooks.Add
Set xlSheet = xlBook.Worksheets(1)
VB.NET の場合
Dim xlApp As New Excel.Application
Dim xlBooks As Excel.Workbooks = xlApp.Workbooks
Dim xlBook As Excel.Workbook = xlBooks.Add
Dim xlSheets As Excel.Sheets = xlBook.Worksheets
Dim xlSheet As Excel.Worksheet = xlSheets.Item(1)
つまりは、CreateObjectしなくて良くなったってこと。
■オブジェクトの解放
ここから本題。
帳票をExcelしているという部分で、
オレが最もExcelがクソだと思っている部分。
宣言して使わなくなったオブジェクト変数は、
Marshal.ReleaseComObject() を実行して、
オブジェクトインスタンスの解放を必ず行わなければならない。
上の宣言の違い部分で記述した宣言であれば、
xlApp、xlBooks、xlBook、xlSheets、xlSheet
これらすべてを解放する必要がある。
ちなみに、Nothingを代入することによる解放は出来ない。
Marshal.ReleaseComObject() してから、その結果のオブジェクトに対して、
Nothingを代入べき。
こうしないと、Excelファイルを弄っている側のアプリケーションを終了しても、
Excelプロセスが残り続けるというクソバカ仕様なので、
絶対に解放を忘れないこと。
※余談:Excelプロセスが残ったままだと何が起きるか?
その状態で、Excelを起動しても、Excelのメニューしか表示されない。
しかも、メニュー自体も固まっているように見える。
つまり、Excelは、同時2つ以上のプロセスを動かすことができない?
■Excel関連オブジェクトへのアクセス方法
こんなところにまで頭を回す必要がある。
上でも述べたように、VBAのコードはそのまま使えないが、
大抵、罫線を引いたり、セルの書式を変更するロジックを調べるのに、
マクロの記録を使うが、VBAのマクロの記述のままでは、VB2008は、
「動く場合もあるが、Excelプロセスが居残り続ける」
といった罠がある。
たとえば、あるセルの色を指定するコードをマクロで記録してから、
VB用に書き換えたとする。
※ここでは、sheetオブジェクトの取得等は省く。
xlRange = xlCells(1,1)
xlRange.Interior.Color = RGB(0, 255, 0)
マクロの記録ではこのようにオブジェクトの取得を省いて、
1lineでプロパティまでアクセスする傾向にある。
この後、xlRangeオブジェクトの解放を行えば、いいように見えるが、
それだけでは、Excelプロセスは落ちない。
実際、コンパイルでもエラーにならなければ、
Excelファイル側でもちゃんとセルに色は塗られるから質が悪い。
何故xlRangeオブジェクトの解放では、ダメなのか。
xlRange = xlCells(1,1)
xlRange.Interior.Color = RGB(0, 255, 0) ←原因はココ
ここにxlRangeオブジェクト以外の、もう1つのオブジェクトが隠れている。
そのオブジェクトを解放しないといけない。
xlRange = xlCells(1, 1)
Dim xlInterior As Excel.Interior
xlInterior = xlRange.Interior
xlInterior.Color = RGB(0, 255, 0)
VB上では、このように記述して、xlRangeオブジェクトとxlInteriorオブジェクトを
解放しなければならない。
つまり、あるオブジェクトの下にぶら下っているオブジェクトや
プロパティにアクセスする際は、
その親オブジェクト⇒子オブジェクト⇒孫オブジェクト⇒・・・⇒プロパティ
と、すべてのオブジェクトを変数に取得していって、
アクセスする必要があるということ。
まぁ、というか、コンパイルエラーにしろよなって話なんだが。
ループ処理で、同じRangeオブジェクトに上書きしてアクセスしている場合でも、
ループを抜けてから、Rangeオブジェクトを解放してもダメ。
1ループの終わる時点でその都度解放しないとハマる。
参考リンク:VBレスキュー
とりあえず、アレだ。
VBできる人間が、VBでExcelファイルの編集が
できると思われてるのがおかしい。
簡単だと思っている人間に限って、
この組み合わせでアプリ作ったことない人間だとオレは思う。
気づかないこともある。
念願叶って、VB.NETっていうかVB2008での仕事をしているのです。
そのための備忘録。
でも、VB2008だろうが、コテコテのクラサバアプリケーションだったり。
しかも、帳票はExcelファイルで出力といった
無駄にエコ仕様。
「必要なファイルだけ出力する」
「出力する必要がなければ、紙を無駄にしない」
と言っているわりには、
正直、Excelでの帳票のが、絶対、開発工数かかると思うんだよな。
帳票を未だにExcelで出そうしているユーザがいるってだけでも、
オレにとっては、レアなユーザなんですけど・・・。
----------------------------------------------
話を戻して・・・。
VBでExcelを弄るときは、以下の点を注意すること。
※というか、注意というより徹底しろ。
そうじゃないと、折角、動くものが出来ても、
編集後にExcelプロセスが落ちないから、
Windows側から直接Excelを起動できなくなる。
■Excelのマクロの記録でとったコードはそのまま使えない。
超常識。
よくあるのは、
例 誤り ActiveSheet 正解 xlBook.ActiveSheet
この間違え。
基本的に、バックグラウンドでファイルの中身を編集するので、
ActiveSheetオブジェクトを使うほうが珍しい。
逆に、ユーザに編集のExcelファイルの中身を見せたいなら、
ActiveSheetオブジェクトを使うはあり。
でも、あんまオススメしないし。オレが設計するならそんなんしない。
ちなみに、シート名が分かっているなら、直接取得したほうがいい。
xlSheet = xlBook.Worksheets("hoge")
■VB6.0との違い
VB2008触って初めて気づいた。
Excelを弄る際のオブジェクトの宣言記述が違う。
VB6.0 の場合
Dim xlApp As Excel.Application
Dim xlBook As Excel.Workbook
Dim xlSheet As Excel.Worksheet
Set xlApp = CreateObject("Excel.Application")
Set xlBook = xlApp.Workbooks.Add
Set xlSheet = xlBook.Worksheets(1)
VB.NET の場合
Dim xlApp As New Excel.Application
Dim xlBooks As Excel.Workbooks = xlApp.Workbooks
Dim xlBook As Excel.Workbook = xlBooks.Add
Dim xlSheets As Excel.Sheets = xlBook.Worksheets
Dim xlSheet As Excel.Worksheet = xlSheets.Item(1)
つまりは、CreateObjectしなくて良くなったってこと。
■オブジェクトの解放
ここから本題。
帳票をExcelしているという部分で、
オレが最もExcelがクソだと思っている部分。
宣言して使わなくなったオブジェクト変数は、
Marshal.ReleaseComObject() を実行して、
オブジェクトインスタンスの解放を必ず行わなければならない。
上の宣言の違い部分で記述した宣言であれば、
xlApp、xlBooks、xlBook、xlSheets、xlSheet
これらすべてを解放する必要がある。
ちなみに、Nothingを代入することによる解放は出来ない。
Marshal.ReleaseComObject() してから、その結果のオブジェクトに対して、
Nothingを代入べき。
こうしないと、Excelファイルを弄っている側のアプリケーションを終了しても、
Excelプロセスが残り続けるというクソバカ仕様なので、
絶対に解放を忘れないこと。
※余談:Excelプロセスが残ったままだと何が起きるか?
その状態で、Excelを起動しても、Excelのメニューしか表示されない。
しかも、メニュー自体も固まっているように見える。
つまり、Excelは、同時2つ以上のプロセスを動かすことができない?
■Excel関連オブジェクトへのアクセス方法
こんなところにまで頭を回す必要がある。
上でも述べたように、VBAのコードはそのまま使えないが、
大抵、罫線を引いたり、セルの書式を変更するロジックを調べるのに、
マクロの記録を使うが、VBAのマクロの記述のままでは、VB2008は、
「動く場合もあるが、Excelプロセスが居残り続ける」
といった罠がある。
たとえば、あるセルの色を指定するコードをマクロで記録してから、
VB用に書き換えたとする。
※ここでは、sheetオブジェクトの取得等は省く。
xlRange = xlCells(1,1)
xlRange.Interior.Color = RGB(0, 255, 0)
マクロの記録ではこのようにオブジェクトの取得を省いて、
1lineでプロパティまでアクセスする傾向にある。
この後、xlRangeオブジェクトの解放を行えば、いいように見えるが、
それだけでは、Excelプロセスは落ちない。
実際、コンパイルでもエラーにならなければ、
Excelファイル側でもちゃんとセルに色は塗られるから質が悪い。
何故xlRangeオブジェクトの解放では、ダメなのか。
xlRange = xlCells(1,1)
xlRange.Interior.Color = RGB(0, 255, 0) ←原因はココ
ここにxlRangeオブジェクト以外の、もう1つのオブジェクトが隠れている。
そのオブジェクトを解放しないといけない。
xlRange = xlCells(1, 1)
Dim xlInterior As Excel.Interior
xlInterior = xlRange.Interior
xlInterior.Color = RGB(0, 255, 0)
VB上では、このように記述して、xlRangeオブジェクトとxlInteriorオブジェクトを
解放しなければならない。
つまり、あるオブジェクトの下にぶら下っているオブジェクトや
プロパティにアクセスする際は、
その親オブジェクト⇒子オブジェクト⇒孫オブジェクト⇒・・・⇒プロパティ
と、すべてのオブジェクトを変数に取得していって、
アクセスする必要があるということ。
まぁ、というか、コンパイルエラーにしろよなって話なんだが。
ループ処理で、同じRangeオブジェクトに上書きしてアクセスしている場合でも、
ループを抜けてから、Rangeオブジェクトを解放してもダメ。
1ループの終わる時点でその都度解放しないとハマる。
参考リンク:VBレスキュー
とりあえず、アレだ。
VBできる人間が、VBでExcelファイルの編集が
できると思われてるのがおかしい。
簡単だと思っている人間に限って、
この組み合わせでアプリ作ったことない人間だとオレは思う。
by arc1230
| 2009-11-18 18:39
| プログラミング
LINK
■ゲーム実況ページ
すでに手遅れ・・・w
☆RO関連
■アンテナサイト
Favor'sRagnarok
RO.Engine
俺の美女アンテナ
■よく見るページ
騎士スレテンプレ
DanceParty
ROラトリオ
■Bijou鯖の人々
りちぇちっく☆わーるど
明日は明日の風が吹く♪
星座の戦士達
The boundless sky
天使の微笑み
■他鯖の人々
Load of the SAKAGE
Midnight Twilight Days
人生平々凡々。
時計で眠るものの日記
√Pri LOG+
烏黒堂
もっさり☆RO日記(仮)
すでに手遅れ・・・w
☆RO関連
■アンテナサイト
Favor'sRagnarok
RO.Engine
俺の美女アンテナ
■よく見るページ
騎士スレテンプレ
DanceParty
ROラトリオ
■Bijou鯖の人々
りちぇちっく☆わーるど
明日は明日の風が吹く♪
星座の戦士達
The boundless sky
天使の微笑み
■他鯖の人々
Load of the SAKAGE
Midnight Twilight Days
人生平々凡々。
時計で眠るものの日記
√Pri LOG+
烏黒堂
もっさり☆RO日記(仮)