Excelでの入出力について

タグの編集
投稿者 threecourse  (社会人) 投稿日時 2011/3/1 08:10:30
VBのプログラムの中で、Excelでの入出力をしたいと思っています。
Excelは基本的に入出力のみで、グラフを作ったりExcel特有の動作をさせなくても良いですが、
Excelで少し計算し、そのデータを用いてVBプログラムを実行して結果を見る、ということを行いたいです。
家でも会社(そこそこセキュリティが厳しい)でも使いたいです。

以下の方法を検討したのですが、調べ方が足りないのかいまいち決定打がなく、
欠点を解決する方法・さらなる良い方法があれば教えていただきたく、質問しました。

1.VBAでExcelからcsv出力し、VBのexeを実行させcsv読込・結果をcsv出力、それを再度VBAで読み込む。
(参考:Windows Scripting Hostによるexeファイルの実行)
http://officetanaka.net/excel/vba/tips/tips27.htm
-Formアプリケーションに対して使いにくい?

2.VSTO
-使用するExcelのバージョンが限られる(会社のExcelは2003なのですが、2003対応のVSTOプログラムの作成環境が構築できない?)
-通常どおりExcelを使うときと比べて使いにくい?(Excelの値を変えても、VBでコンパイルしたら元に戻ったり?)

3.Microsoft.Office.Interop.ExcelでExcelを開いて操作する
-Excelを開いているとき閉じているとき、対象ブックを開いているときも閉じているときも、適切に動作できるか?
-Excelのプロセスが残るらしい?
(参考)
http://techbank.jp/Community/blogs/nora/archive/2008/09/23/2365.aspx

4.VBでDLLを作成してVBAから使用する
-レジストリ登録が必要、使用可能になるまでに結構な準備が必要
-DLLのクラスの引数としてList(Of String)のようなものは渡せるか?
(参考)
http://www.sev.or.jp/ijupiter/world/dc_interrop/dotnet_com_interrop.html
投稿者 るきお  (社会人) 投稿日時 2011/3/1 13:22:13
こんにちは。

プログラム側でやりたいことが見えないのですが、すべてVBAで処理するわけにはいかず、.NETの力が必要ということでしょうか?
※VBと書いてあるのはVB6ではなく、VB.NETですよね?バージョンはいくつを想定しているでしょうか?
もし、VBAだけで済むのであればVBAが一番シンプルな解決方法と思います。

>1.VBAでExcelからcsv出力し、VBのexeを実行させcsv読込・結果をcsv出力、それを再度VBAで読み>込む。
>-Formアプリケーションに対して使いにくい?
Formアプリというのが何を指しているのかよくわかりません。
csvを中間ファイルとして使用するため汎用性はあり、個々のプログラムはシンプルにできるのではないかと思います。(その代りちょっと面倒ですね。)

VSTOは経験がないので割愛します。
バージョンは限られますが2003向けのVSTOはあったと思います。

>3.Microsoft.Office.Interop.ExcelでExcelを開いて操作する
>-Excelを開いているとき閉じているとき、対象ブックを開いているときも閉じているときも、適切に動作できるか?
できます。

>-Excelのプロセスが残るらしい?
適切に処理しないと残ります。

>4.VBでDLLを作成してVBAから使用する
>-レジストリ登録が必要、使用可能になるまでに結構な準備が必要
レジストリ登録は必要ですが、コマンド1つでできます。(regsvr32 or regasm)

>-DLLのクラスの引数としてList(Of String)のようなものは渡せるか?
よく状況がわからないです。
DLLを呼び出すもの → DLL
という構造と思います。今回は「DLLを呼び出すもの」 = Excel VBAなんですよね?
Excel VBAにはそもそもList(Of String)はないので、DLLにList(Of String)を渡すということはありえないと思います。


質問の雰囲気から私が勝手に現場のイメージを想像すると、以下の順でお勧めです。
1.VBAだけでつくる。
2.VBAでExcelからcsv出力し、…
3.Microsoft.Office.Interop.ExcelでExcelを開いて操作する
4.VBでDLLを作成してVBAから使用する
5.VSTO

この順位はプログラムのシンプルさと情報量の多さを重視しました。
どれもよく知っている人なら「VBでDLLを作成してVBAから使用する」を選ぶ状況かなと思います。
※あくまで、私が勝手に状況を想像して言っています。
投稿者 とくま  (社会人) 投稿日時 2011/3/1 19:45:22
>>3.Microsoft.Office.Interop.ExcelでExcelを開いて操作する
>>-Excelを開いているとき閉じているとき、対象ブックを開いているときも閉じているときも、適切に動作できるか?
>できます。
"適切に"っていうのが"ユーザの都合のいいように"といっているなら、
「できない」と言っておいた方が良いのかも?
Excel は排他でファイルを開くので、既に開いているファイルを
上書きはできません。Excel の仕様通りですが、実際のファイルを
開いて Excel.EXE に仕事をさせることになりますので、Excel の
都合いいような仕様通りの動作になります。

Excel ができることができ、できないことができません。
これを適切と言っているなら、できます。

>1.VBAでExcelからcsv出力し、VBのexeを実行させcsv読込・結果をcsv出力、それを再度VBAで読み込む。
VB と Excel の連携が気を使う必要があるので、VBA で実現できる
なら、VB の割り込む余地は無いでしょう。
>-Formアプリケーションに対して使いにくい?
VBA のユーザーフォームは特殊で、機能も VB のものに比べれば
機能が限定されている感はあります。
コントロールや描画系の処理がライブラリとして提供されている
かどうかなど、本格的なプログラミング開発環境と、1つの
アプリケーションのおまけとの違いはあるでしょう。

ただ、CSV 出力するだけの基本的なプログラムでそこまでの
差が重要か?作りこみ次第で本格的なプログラムが作成できる
VBA は、おまけとしては十分な機能は持っています。

>Excelからcsv出力し、VBのexeを実行させcsv読込・結果をcsv出力、それを再度VBAで読み込む
そもそも Excel は要るの?って気もします。
逆に CSV のデータを Excel で扱おうとすると、デフォルト
の動作では勝手に変換されたり、色々と問題が起こります。
データは CSV 管理でグラフもフォーム上に書いてしまう。
Excel 要らない選択もあると思います。
>Excelからcsv出力し、
シートそのままの形で保存するなら、この機能は Excel の
ファイル保存でできるし。
CSV からグラフを書く VB のプログラムだけ作れば、Excel
の勉強をしなくてよくなるかもしれません。

> どれもよく知っている人なら「VBでDLLを作成してVBAから使用する」を選ぶ状況かなと思います。
処理内容次第ですよね。簡単な処理を色々な Book に摘要したい
だけなら、Excel のアドインが都合がいい場合もあるかも。

結局、Excel を操作するなら Excel の構造を覚える必要が
あるわけで、VB や DLL はまた別の勉強が必要と考えると
VBA だけでいい気がします。

セキュリティはまた別の話。
マクロウィルスを警戒して Excel のマクロは使用禁止とか
なら VBA 自体できなくなる可能性もあるのでは?
どんなにプログラムで頑張っても本人がブログで個人情報
を公開すれば情報が漏れるのでは?
セキュリティが厳しいとだけ言われても分かりませんが、
会社のデータは家には持ち帰れないものでは?
そもそもプログラムと関係ないレベルの問題は無いのですか?
投稿者 threecouse  (社会人) 投稿日時 2011/3/1 23:29:11
るきおさん、とくまさん、ご回答どうもありがとうございます。
説明が不十分な部分があったので、追記させていただきます。

やりたいことは、金融商品の価格計算です。
会社での実務は(残念ながら)ExcelVBAですが、新しい商品の計算をするために新しいworkbookを作り、VBAコードをコピペするというプログラミングになっていて、修正する時が大変ですし、一貫性も保てません。
なので、実務は本当はVB.net等に移行すべきと考えていて、そのための勉強を行っているところです。
Visual Studio 2010で開発しています。

なぜVB.netがいるか?というと、
計算モデル部分が複雑なため、VBAだと力不足なのです。
うまくクラスを分割して、継承やラムダ式を使いながら共通部分・商品固有の部分と分けて計算したいのです。

なぜExcelがいるか?というと、
インプットの下準備としてExcelでの計算が必要な場合があること、
アウトプットの検証・分析はExcelで行うためです。
今はVB.netのみでcsv入出力で行っているのですが、少し面倒です。

というところで、入出力がExcel、計算はVB.netというのが理想なのです。

・Formアプリケーションに対して使いにくい?
Formアプリケーションは、Consoleアプリケーションに対しての対比です。
今はFormアプリケーションで作成しているのですが、
ちゃんとExcelからの呼び出しができれば、Consoleアプリケーションでも問題ないですね。。

・DLLのクラスの引数としてList(Of String)のようなものは渡せるか?
プログラムに渡したいものは、csvファイルないしList(Of String)で表せるデータということです。
ただ、引数は空でcsvをVB.netプログラムから読み込ませれば目的は達成できる気がしてきました。

・レジストリ登録が必要、使用可能になるまでに結構な準備が必要
少し試してみたのですが、 regasmの後にDLLの場所をExcel.exeの直下にする等の準備が必要なようで、今のところ上手くいっていないです。(regasm⇒VBA参照設定まではできたのですが、呼び出すとオートメーションエラーです。)
セキュリティは、 regasmが会社のPCで可能かどうかということを気にしています。(セキュリティ部門に申請すればできそうですが)
投稿者 パールマン  (社会人) 投稿日時 2011/3/2 13:20:17
Excel VBAでは、クラスモジュールも作成できます。
複数のWorkBookで使用することを考えるのであれば、アドイン( 拡張子:xla )を作りそれぞれのWorkBookでコールすれば解決できると考えます。

※ アドイン化は、Excelの‘Visual Basic Editor’で編集してから、ファイルの種類を‘アドイン’を選択して
  保存すればOK。

従いまして、中身はクラスモジュールの集合というアドインも作れるわけでして、わざわざVSを用意しなくてもと思うのですが・・・
投稿者 とくま  (社会人) 投稿日時 2011/3/2 17:24:56
>なぜVB.netがいるか?というと、
>計算モデル部分が複雑なため、VBAだと力不足なのです。
>うまくクラスを分割して、継承やラムダ式を使いながら共通部分・商品固有の部分と分けて計算したいのです。

VB6時代からプログラムをやっていますので、VBA だけのプログラムも
数多く組んできていますが、オブジェクト指向っぽい設計はできますし、
結局どう整理するかだけの気もします。
共通部分をモジュールに出して、商品固有の部分をクラス化するとか
できるので、VBA が力不足の理由としてはまだ弱い気はします。
ラムダ式も。。。逆に適用できなかった場合に泥臭い基本的な
文法(If文For文レベル)で書けないと要求を満たせないとかなったら
使わない方が分かり易くなる場合もあるのでは?

先の回答にあるように、複数の Book に共通して使うだけなら
アドインがありますし、VB がそれほど有効だとはまだ感じません。

ただ、VB.NET の方がやはりそれなりの進化と呼べる部分は
多いでしょうし、理想といわれる形があるならそれで良いのでは?
アドインを作るのと、VB のプログラムを作るのと。。。アドイン
の方がコードは8割コピペで済む気はするけど、Book を操作する
ような部分を作成すると考えれば、やりたい方でいいと思います。

Excel から VB の DLL 参照すると DLL のバージョン管理も力を
入れないといけなくないかな?VB から Excel を見た方が楽な
気はします。

実体は Excel ファイルのまま、拡張子を独自のものに変えて、
VB.NET の EXE が起動するようにして、EXE 起動時のコマンド
ライン引数からファイルパス取得で、VB.NET の制御下で Excel
ファイルを開いた方が色々と都合が良くないかなぁ。。。
投稿者 fshy  (社会人) 投稿日時 2011/3/2 22:34:03
Excel のデータをデータ セットに読み込んで、
http://msdn.microsoft.com/ja-jp/library/cc464080(v=vs.71).aspx

あとはLinqを使った集計、計算というのはいかがでしょう。

投稿者 とくま  (社会人) 投稿日時 2011/3/3 11:43:42
> Excel のデータをデータ セットに読み込んで、
上記手法は最近やってないので未確認情報でレスつけます。

読み込むだけで終わるならありかもしれませんが、
ADODB の時代から削除は面倒な手順が必要で、
http://support.microsoft.com/kb/257819/ja
ADO.NET でも微妙な感じの記事が引っ掛かりました。。。
http://genz0.blogspot.com/2009/05/netexceloledb.html
個人的にはお勧めしておりません。

データを管理する為の DataTable(DataSet) は優秀だと
思っていますが、私が使う場合はエクセルのオブジェクト
(Excel.Range.Value)から自前の処理で直接取得したセルの
値を DataSet に入れる手間を掛けてでも Excel と ADO.NET
の連携は避けたりしてます^^;
投稿者 threecourse  (社会人) 投稿日時 2011/3/3 21:00:25
パールマンさん、とくまさん、fishyさん、どうもありがとうございます。

クラスモジュールについては、時々使っています。
以下を参考にして研究したことがあります。
http://members3.jcom.home.ne.jp/daruma_kyo/
(ここ以外でWebや書籍で記載しているものをあまり見たことがないのですが・・)

アドインは業務では流行らないのですが、配布をきちんとしないと間違った値を出すのが怖いからかな。。
http://www.asahi-net.or.jp/~ef2o-inue/menu/menu06.html

クラスモジュールやアドインで頑張れば、ある程度まで何とかなるのは認識しているのですが、
そこで苦労するよりは、VB.netを使用したいというところです。(ただ入出力はExcelがいい)

頂いた意見を参考に、引き続き試行錯誤してみます。
oleDBによる方法も試してみます。どうもありがとうございます。