Excel2007 ファイルに ADO.NET でデータを書き込む

検証環境 Fujitsu FMV-W630(Pen4(530)3.4GHz/3GB)
WindowsVista Ultimate(6.0.6002 SP2,v.659 Build 6002)
VisualStudio2008Pro(VB) 9.0.30729.1SP/.NET Framework 3.5SP1

本エントリは、猿頁 » Blog Archive » Excel ファイルに PIA でデータを書き込むの続きです。


さて、今度は別アプローチ。
ADO.NET を使って Excel2007ファイル(.xlsx)にデータを書き込んでみます。

1. プロバイダの指定と接続 → 切断

このへんもセオリーなので、さらっと記述します。

Const EX_PATH = "C:\Users\salvage\Book1.xlsx"
Const ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" _
    & EX_PATH & "; Extended Properties=""Excel 12.0; HDR=No;"""
Const ConnectSheetScript = "CREATE TABLE [Sheet1$] " _
    & "(c1 Decimal, c2 Decimal, c3 Decimal, c4 Decimal, c5 Decimal" _
    & ", c6 Decimal, c7 Decimal, c8 Decimal, c9 Decimal, c10 Decimal)"

Using xlConn = New System.Data.OleDb.OleDbConnection(ConnectionString)
    xlConn.Open()
    Using xlCmd = New OleDb.OleDbCommand("", xlConn)
        xlCmd.CommandText = ConnectSheetScript
        xlCmd.ExecuteNonQuery()

        '(A)

    End Using
    xlConn.Close()
End Using

ConnectionString は、Excel へのDB接続に使用するプロバイダを記述します。
Excel2003 までは Jet4.0 プロバイダでよかったんですが、2007 からは ACE プロバイダ(Accessのエンジンです)を使うことになります。
また、今回は書き込みのみの目的ですので Extended Properties のあたりは「Excel」「HDR」しか記述していません。読み込みも行う場合は IMEX とか ReadOnly とかの設定も必要になったりするらしいですが、まあ今回はユルめな感じで。

どんな設定項目があるのかの公式な資料は、ガンバったんですがどうしても見つけることができませんでした。
今回の情報は、主に

CodeProject: Working with MS Excel(xls / xlsx) Using MDAC and Oledb. Free source code and programming help

を参考にしています。

HDR は 「No」な設定にしてみました。こうしとくと、1 行目のデータをテーブルにおける項目名とみなしません。
でもこの場合、新規の Excel だと空白のセル自体をフィールドとして見なさなくなり例外が発生してしまいますので、CREATE TABLE で書き込む列に項目名を付けてやる必要があります。そうすると、シートの 1 行目にはつけた項目名そのものが格納されてしまいます。
HDR=Yes であらかじめ 1 行目に項目名を埋め込んでいた時とまったく同じ出力結果になってしまうので、正直あまり使い分ける意味がないような気がします。

このように CREATE TABLE で項目名を明示的に付けた場合、実際に書き込むロジックを記述する (A) の部分は、以下のようになります。

For i As Integer = 1 To 10000
    xlCmd.CommandText = "INSERT INTO [Sheet1$] (1.000000000,1.1,1.12,1.123," _
        & "1.1234,1.12345,1.123456,1.1234567,1.12345678,1.123456789);"
    xlCmd.ExecuteNonQuery()
Next

結果は

…うーん、微妙。
ヘタな PIA よりは十分速いですが、上手に組んだ PIAよりは遅いと。
1 行目が常に見出し行になってしまう制限も含め、あまり使い勝手のいいものではなさそうです。


ついでに。

CREATE TABLE も使わず、あらかじめ Excel ファイルの 1 行目に項目名を設定もせずに、直接 INSERT INTO 文だけで書き込むこともできます。
この場合は、INSERT INTO 文そのものに列名を表す「F1, F2, …」を記述します。

Const InsertString = "INSERT INTO [Sheet1$] (F1, F2, F3, F4, F5"
    & ", F6, F7, F8, F9, F10) VALUES " _
    & "(1.000000000,1.1,1.12,1.123,1.1234,1.12345,1.123456," _
    & "1.1234567,1.12345678,1.123456789);"

こんな感じですね。

ただし、あらかじめ使用する Excel ファイル-シートの一番右側の列に何か書き込んでおかないと列そのものが存在しない、というエラーになります。
かといって書き込んでおくと、その次の行から INSERT されることになりますので、どっちにせよ最低 1 行は INSERT には使えないという制限は健在なわけです。

もひとつ。
ADO.NET でデータが書き込まれた列は、書式設定が初期値に戻ります。表示形式を「日付」にしようが、文字色・背景色・罫線を設定しておこうが、データが書き込まれるとすっぴんの「標準」に戻ってしまいます。
ので、装飾等を入れる必要がある場合には、ADO,NET は選択肢にならないということになりそうです。


ということで、調べてはみましたが、あまりメリットが感じられない結果になってしまいました。ACE プロバイダを使った Excel への書き込み。

どう使い分ければいいかなー、と考えてみたんですが、Excel がインストールされたマシンで動作させるなら、制限もなく上手に組めば速度も確保できるという点で、Excel PIA がベストなのではないかと。

Excel がインストールされていない環境で Excel ファイルを生成したい場合には、1 行目制限はあきらめて ADO,NET(ACE プロバイダ)という選択肢もあると思います。

「ACE プロバイダは Access2007 がインストールされていないと使えない」という記述もどこかで読みましたが、それはちょっと調べが浅いような気もします。
確かに Windows 標準では提供されていませんし、Access2007 と同時にインストールされるエンジンではありますが、この ACE エンジン(+ Office2007 対応 ODBC ドライバのセット)は、単体無償でダウンロード提供されています。

ダウンロードの詳細 : 2007 Office system ドライバ: データ接続コンポーネント

ので、このコンポーネントをインストールすれば、Office なしでも ACE プロバイダを使った Excel ファイルへの書き込みは可能になります、と。
かなりリーズナブルに動作環境を構築できますので、予算と併せ考えた場合は意外とニーズは高いかもしれません。

Excel2007 ファイルに PIA でデータを書き込む

検証環境 Fujitsu FMV-W630(Pen4(530)3.4GHz/3GB)
WindowsVista Ultimate(6.0.6002 SP2,v.659 Build 6002)
VisualStudio2008Pro(VB) 9.0.30729.1SP/.NET Framework 3.5SP1
Microsoft Office  Excel 2007(12.0.6504.5001) SP2 MSO(12.0.6425.1000)

VB.NET から Excel2007ファイル(.xlsx) にデータを書き込むには、大きく 2 つの方法があります。

  1. PIA で書き込む
  2. ADO.NET(OLE DB) で書き込む

DB プロバイダ系の書き込み方法としてはもう一つ、ODBC があるんですが、以前やった仕事で 64KB 制限の壁に泣かされたことがあるので、まともに調べる気になりませんでした。のでパス。


PIA は、昔の VB / VBA の時代に、Object library として提供されていた OLE インターフェイスを、.NET 用にラップしたものです。
Object Library は Office 最新の 2007 でも提供されていますので、未だ現役の技術ではあります。.NET でも、Object Library を参照設定して使うことはできます。
.NET から Object Library を直接参照設定かけた場合は、型の制限等が違いますので、自動的に .NET の型に合わせたラッパーが生成されます。これを IA と呼ぶんですが、どうも一部うまく機能しないような生成になってしまうらしいです。
で、そのへんを正常に動作するように手動で調整した IA が提供されているわけです。これが PIA 。

Object Library にしても PIA にしても、本質は「OLE による Office ソフトウェアの外部からの制御」です。ので、制御される対象の Office ソフトウェアそのものがインストールされている必要があります。
また、外部から Office インターフェイス ( VBA と Office ソフトウェアのやり取りなどに使われています) をいじるという動作ですので、多機能低性能。ざっくばらんに言うと、「VBA にできることは全部できるが超ノロい」ということですね。

使い方は割と簡単。

1. PIA の参照設定とコード記述の準備。

ソリューションエクスプローラから VB プロジェクトを右クリック → [参照の設定]で「参照の追加」ダイアログを表示させます。
で、[.NET]タブ → 「Microsoft.Office.Interop.Excel(12.0.0.0)」を選択 → [OK]。

適当に Button コントロールを Form に載せ、以下 Click イベントへいろいろ記述していきます。

2. 常套句を記述。

基本は、「使ったオブジェクトは全部変数に取っておいて、後できちんと解放する」こと。
このへんは決まり文句なので、あまり深く考える必要もないような気がします。
今回は既存ファイルへの上書きを例にしたいので、Workbook は Open で生成しています。(新規作成時には Add を使います。)

Const EX_PATH = "C:\Users\salvage\Book1.xlsx"

Dim xlApp = New Microsoft.Office.Interop.Excel.Application
Dim xlBooks As Microsoft.Office.Interop.Excel.Workbooks = xlApp.Workbooks
Dim xlBook As Microsoft.Office.Interop.Excel.Workbook = xlBooks.Open(EX_PATH)
Dim xlSheets As Microsoft.Office.Interop.Excel.Worksheets = xlBook.Worksheets
Dim xlSheet As Microsoft.Office.Interop.Excel.Worksheet = xlSheets("Sheet1")
Dim xlRange As Microsoft.Office.Interop.Excel.Range

'(A)

System.Runtime.InteropServices.Marshal.ReleaseComObject(xlRange)
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlSheet)
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlSheets)
xlBook.Close()
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBook)
xlBooks.Close()
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBooks)
xlApp.Quit()
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp)

と一気に書いといて、あとは実装したいコードを (A) の部分に記述すれば OKOK 。

3. ダミーデータを 10 列 × 1 万行書き込むロジックを記述。

まあとりあえずこんな感じで。

'(A)
For i = 1 To 10000
    xlRange = xlSheet.Range(xlSheet.Cells(i, 1), xlSheet.Cells(i, 10))
    xlRange(1, 1).value = i
    xlRange(1, 2).value = "1.1"
    xlRange(1, 3).value = "1.12"
    xlRange(1, 4).value = "1.123"
    xlRange(1, 5).value = "1.1234"
    xlRange(1, 6).value = "1.12345"
    xlRange(1, 7).value = "1.123456"
    xlRange(1, 8).value = "1.1234567"
    xlRange(1, 9).value = "1.12345678"
    xlRange(1, 10).value = "1.123456789"
Next
xlBook.Save()

4. 上書きするための Excel ファイルを用意。

とりあえず書式設定が保持されることを確認したいので、A ~ J 列に「数値(小数点以下 9 桁)」を設定しておきます。
ビジュアルに確認したいのであれば、文字色や罫線などを設定しておいた方がわかりやすいかもしれません。

5. 時間計測用のロジックを追加。

あとで ADO.NET と動作時間を比較したいので、イベントの最初と最後に時間計測用のコードをちょろりと書いておきます。

Dim startTime = Now
  …
MsgBox((Now - startTime).ToString)

まあ簡単にこんな感じで。

5. 実行 → 確認。

2. で常套句を記述した際に、「きちんと解放すること」と書きました。これは、解放を忘れると Excel が終了せずに残ってしまうからです。
ので、ほんとに解放されるかどうか、Windwows タスクマネージャを起動しておいて確認できるようにしておきます。タスクマネージャは、[Shift]+[Ctrl]+[Esc]一発で起動できます。

実行結果。

10 列 × 1 万行 = 10 万セル分のデータ挿入で 7 分 35 秒ほどでした。
仕事場のマシンで同様の確認をした時には 3 分程でしたので…自宅マシンのスペックが低いんだよなーやっぱり(;-;)。

いやいや、今回のテーマは「私のマシンのスペックの低さを嘆く」ではないので。

6. まとめて挿入する方法

3. の方法だと、1 セルずつ 10 万回のデータ挿入を行うわけですから、オーバーヘッド(この場合は Excel ~ VB 間でデータ挿入以外の制御のために使う時間)も大変なものになります。
1 回の通信で 10 万データを一気に挿入できたら、このオーバーヘッドにかかる時間は 10 万分の 1 になるんではないでしょうか。

ということで、(A)を書き直してみました。

'(A)'
Dim xlArray(9999, 9) As Object
For i = 0 To 9999
    xlArray(i, 0) = New Object : xlArray(i, 0) = i + 1
    xlArray(i, 1) = New Object : xlArray(i, 1) = "1.1"
    xlArray(i, 2) = New Object : xlArray(i, 2) = "1.12"
    xlArray(i, 3) = New Object : xlArray(i, 3) = "1.123"
    xlArray(i, 4) = New Object : xlArray(i, 4) = "1.1234"
    xlArray(i, 5) = New Object : xlArray(i, 5) = "1.12345"
    xlArray(i, 6) = New Object : xlArray(i, 6) = "1.123456"
    xlArray(i, 7) = New Object : xlArray(i, 7) = "1.1234567"
    xlArray(i, 8) = New Object : xlArray(i, 8) = "1.12345678"
    xlArray(i, 9) = New Object : xlArray(i, 9) = "1.123456789"
Next
xlRange = xlSheet.Range("A1").Resize(10000, 10)
xlRange.Value = xlArray
xlBook.Save()

わずか 3 秒。ってなんですかこの速さは。
Object 型の 2 次元配列を用意しとかなきゃならないメモリの圧迫っぷりがいまいちですが、十分実用的な速度は確保できますね。


次、ADO.NET でのデータ挿入。
長くなったので、続きます


参考資料

[HOWTO] Visual Basic または VBA から ADO を Excel データで使用する
Visual Basic .NET を使用してデータを Excel ブックに転送する方法
Visual Basic .NET を使用して Microsoft Excel を自動化する方法
Visual Basic: リフレクションを使用して COM オブジェクトを検査する

(26) K4で一部メールが文字化ける

メール回りをいじり出すと、やっぱこの際我慢していた不満もなんとかしたいってのが人情ってもんではないでしょうか。

K4 使ってて困るのは、一部のメールが文字化けること。

アメリカあたりからやってくる UTF-8 形式のメールの一部が、EUC(?) とかに認識されてすごいことになります。
アルファベットだけの奴ならそれなりに読めるんですが、中途半端に漢字が混ざっているともう泣けてくるような化けっぷりで。

たぶんヘッダが少々ラフになってしまっているんではないかと推測し、向こうさんは漢字までちゃんと表示されるかどうかなんか確認しないからなー、しょうがないかなーとあきらめ気味だったんですが。
でも Facebook からのメッセージメールや米国 Microsoft からのあれこれメールが化けると、まじでけっこう不便です。

つことで、なんとか対処策はないものかと探してみたら、XMailのBBSでビンゴなスレッドが。

UTF8のメールが文字化けする

「ActivePerl5.8 対応拡張モジュール」ってなんだよ知らないよそんなの、とこちらも探してみると、

K4 のダウンロード

にちゃんとあるではないですか。がーん知らんかったー。

私の使っている XMail は 1.25、XMailCFG は 2.35d なので、K4 0.91b 用の対応モジュールをダウンロード → cgi フォルダに上書き。
なんか config.cgi とかも上書かれるので動作不良起こされるのが怖く、上書き対象の現行のファイルを全部バックアップ取ってから、とちょっと慎重に行ってみました。

メールの中を表示する操作をすると警視庁のサイトに飛んだりして少々焦りましたが、再ログインを何度か行ったら動作が安定しました。
K4 の初期設定では、不正なアクセスと認識されると全部警視庁のサイトに飛ぶように設定されているんですよね。調整入れるたびにまま飛ぶので、すっかりピーポ君と顔なじみになったような気がします。

さて、たぶんこれで大丈夫だと思うんですが、こんな時に限って文字化けメールがやってきません。
まあそのうち何かしらやってくるでしょうから、その時にでも確認、ダメだったらまた次の手を考えてみようかと思います。

(25) メーラで振り分けフォルダのメールを受信できない

ここしばらく Web サーバも安定し、特に手を入れることもなくのんびり日常を過ごしてきていたわけですが。

外出先等からも確認できるように、ここ数年私はメールをサーバに置きっぱなしにするようになってまして。Web メーラも K4 って奴をわざわざ入れまして。

Web サーバからメールをローカルに落とさない設定にしておいたら、気がつくとけっこうな量のメールがたまるようになってきました。

メーリングリストなどが容量圧迫の主な原因なんですが、このへんはローカルのメーラに落としてしまってもかまわないんですよね考えてみれば。

つことで、K4 の振り分け機能でメーリングリストフォルダに格納されたメールを、Becky! のリモートメール機能を使ってローカルに落としてしまおうとしたんですが。

リモート接続ではサブフォルダを認識しない。

Becky! や K4 の設定をどうひっくり返しても、サブフォルダを認識させるオプションが見つかりません。

まいったなー、どうすれば認識するのかなーとあちこち引っかき回していたら、K4 の「受信メッセージの振り分け」設定ページで、

振り分けられたメッセージは、それを XMail の受信用フォルダ(mailbox)に戻さない限りメーラからは受信できなくなります。

との説明文を見つけてしまいました。うわーん。

受信フォルダには一番たくさんサーバに残しておきたいメールがたまってるんだよー。


しかたがないので、自動振り分けの対象とならないメールを退避する専用のサブフォルダをサーバに作り、従来受信フォルダに残しておくことにしていたメールをすべて退避フォルダに移動させることにしました。
「その他」という振り分け条件は作れないので、「To が自分のメールアドレスなら」という、ほとんどのメールに該当する条件を作成し、一番低い優先度で振り分けルールに追加登録。今、既にあるメールは手動で退避フォルダに移動しました。

受信フォルダを、メーラとやりとりするためだけのインターフェイスという役割と考えるようにしたわけですね。

あとは、K4 のページあたりメール表示件数を 100 件に拡張して。振り分けフォルダの内容を受信フォルダに移動して。Becky! でダウンロード受信(サーバ側からは削除)して。
メールを削除しても K4 側からはまだ一覧が表示できてしまうので、[最新情報に更新]をクリックして削除されたことを確認して。

おお、少々めんどくさいけどイケるじゃないですか。

まあたぶん整理は月に一度くらいでしょうし、自分以外の人が使うわけでもないので、それほど使いやすさにこだわる必要もありません。
しばらくこれで運用してみたいと思います。

IE8 で IE7Pro を使うには

まとめ。

IE8 に IE7ro を組み込んだ時にいくつかの機能が正常に動作しなくなります。
これを IE7 と同様に正常に動作させるには、

HKEY_CURRENT_USER\SOFTWARE\Microsoft\Internet Explorer\MAIN に TabProcGrowth を DWord で作って「1」を設定すれば OK 。

すべての不具合が解消するかどうかは未確認ですが、マウスジェスチャの「タブを閉じる」などの動作は正常になりましたよ。


詳細。

猿頁 » Blog Archive » (138) 転びブラウザ を見ると、私が Sleipnir を使い出したのは 2005 年のようです。
IE のよけいな機能をそぎ落とし+Webブラウズに便利な機能を多数追加した Sleipnir は、当時の私のニーズにかなりマッチしていたように思います。

が。

IE8 が高速性やアクセラレータ等のオモシロい機能をひっさげて登場してきたんですが、Sleipnir がどうもそれらをうまく吸収できないわけです。
あたらしもん好きな私としましては、IE8 のメリットもぜひ満喫してみたい。
そもそも Sleipnir とかそのへんに乗り換えたのはタブブラウザだってのが一番の理由だったわけですから。だったら IE8 も十分候補にできるんじゃね?

みたいな。


てことでひさびさに IE8 を直接起動してみたんですが、5 秒で挫折。

マウスジェスチャがありません。

いろんなページをざくざくと開きまくってざくざくと閉じまくる使い方に慣れてしまった私にとって、いちいちタブ領域までマウスを運ばないとページを閉じられない、というのはなかなかツラいものがあります。

ので、IE7Pro を導入してみることにしました。
おおお、これで IE でもマウスジェスチャが。と思ったんですが。

だめだ「タブを閉じる」が変な動きをする。

正確には、表示されていたページは確かに閉じるんですが、タブそのものは残って「空白のページ」(または「新しいタブ」を起こしたときに表示される初期ページ)になってしまうんですね。
たまに望み通りタブ自体が閉じられることもあり、どうも不安定な動作に思えます。

IE7Pro のフォーラムを読むと、やはり同じ状況になっている方はけっこういらっしゃるようで、「だからはやく IE8Pro をリリースしてくれ」「いや、俺んとこではちゃんとタブも閉じるよ?」とかなかなか活発で不毛な議論がせめぎ合っておりまして。

対処法は、littlegirls さんが提示してくださっておりました。

IE7Pro Forum / IE7pro + IE8 + Loosely Coupled IE = IE7pro does not always load


IE8 では、タブごとに別プロセスが起動するようになっています。
これで、どこかのページがフリーズ起こしても、そのタブだけを落として他のタブは生き残るというハングアップ対策になっていたりするんですが。

一方で、IE7 まではすべてのタブが同じプロセスで起動されていました。
この状態でタブを閉じ続けると、最後のタブを閉じたときに IE のウィンドウそのものも閉じるという動作になります。
IE7Pro はこの IE7 の動作を前提に作られているアドオンでして、「タブを閉じる」動作にはどうも「タブがひとつしかない場合にはページは消すがタブそのものは残す」という制御が入っているようです。これで、連続してタブを閉じていっても、IE ウィンドウ自体は終了させない、という状況を実現しているみたいなんですね。

別ブラウザの某アドオンではこの制御が組み込まれておらず、連続でタブを閉じる操作をするとうっかりブラウザ自体を終了させてしまうことがあり、そのつど再起動させなければならないわずらわしさにうんざりしたことがあったので、これはこれでナイス制御だとは思います。

が、この「最後のひとタブ」を、IE7Proではどうも「プロセス内にタブがひとつだけある場合」という条件で判定しているようなんですね。
IE7 であればこれはほんとに最後のひとタブを判別できるんですが、IE8 ではタブがそれぞれ独立したプロセスの「最後のひとタブ」になっているために、「ページは閉じるがタブは残す」という動作になってしまっている、ということわけです。

加えて、IE8 ではタブごとに「必ず」別プロセスを持つ、というわけではありません。
原則として別プロセスになりますが、同じサイトの別ページだったりした場合には同一プロセス下に複数タブを担当させることもあるようです。
この場合は1プロセスに複数タブが存在しますので、IE7Proの「タブを閉じる」動作は、ほんとにタブを閉じたりします。
ページ内リンクを別タブで開くとサイトが違っても同じタブグループになったりもしますので、グループが同じであっても必ずしもプロセスが同じというわけではありません。よって「同じタブグループだからタブごと閉じるだろう」など見た目から判断することができず、「タブが閉じたり残ったり、動作が安定しない」ように見えてしまうために、納得できない感がいや増したりします。

ソースをたどったわけではないので、いろんな条件で試して観察してみた結果としての推測でしかありませんが、まあたぶん合っているんではないかと思います。


で、どうすればいいかというと。
ひとつのIE ウィンドウの中のタブを、すべて同じプロセス内で管理するように IE8 の設定を調整すればいい。ということになります。つまり、

HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Main に DWord で TabProcGrowth を作って、値を 0 または 1 にしろ

ということですね。

0 と 1 の違いは、私は正直よくわかっていません。0 だと IE のメニューや各種ボタンの動作まで同一プロセス、1 だとタブのみが同一プロセス(IE の操作系は別プロセス)みたいな感じらしいんですが、具体的に明確な説明をしているページを見つけることはできませんでした。
0 だと保護モードが有効な時に設定が無効になるとか、デバッグの際には 0 にしろとか(1 ではダメな理由に言及しているサイトは見つけられませんでした。このへん、無責任な伝言ゲームになっている可能性があります)ちょっと裏が取れない情報が散見されます。
このややこしさの元となる IE8 の新機能は LCIE と呼ばれており、IE開発チームが割と早い段階で概念について blog で言及されています。
原文はこちら、日本語訳版はこちら

でまあ、とりあえず 1 で十分 IE7Pro は従来の動作になるようです。0 にまでする必要はなさそうですね。
ただ、IE7Pro のすべての動作を確認したわけではありませんので、あるいは 1 では正常に動作しない機能もあるのかもしれません。
そんな場合には、0 に切り替えて試してみるのもひとつの手だとは思います。


おまけ。

マウス中クリックでリンク先をタブで開くことはできるんですが、アクティブは元タブのままであり、開いた側のタブがアクティブになりません。
私の場合は開いた側をすぐ見たいことの方が多いので、アクティブが移動してほしいわけです。

これは拡張の必要はなく、IE8 そのものの [インターネットオプション] → [全般]タブのタブの[設定] → [タブブラウズの設定]ダイアログの [タブブラウズを有効にする]と[新しいタブの作成時には常に新しいタブへ移動する]にチェックをつければ OK でした。

ついでに、検索プロバイダは現在 Bing がどこまでツカエるかお試し中です。

もう少し調べものや blog 書きに便利な機能を組み込んでおきたいので、しばらくいろいろとイジってみようと思います。

つくるためのWindows7

ここ1年ほど本業がすっかり上流工程で、「作る」からとんとごぶさたになってしまっておりますが。

でもやはり自分の本質はプログラマなのだと。思いたいわけです。

つことで、今度出るぞ出るぞな雰囲気になっているWindows7も、「どう作るのか」「何が作れるのか」が知りたいわけです。

マイクロソフトでは、Tech Fieldersな皆さんが、そこらへんのツボを抑えたコラムの展開を始めているようです。

開発者のための Windows 7 ~まずはここから~ | Tech Fielders コラム

を筆頭に全6回予定だそうで。

ついでに、北海道では7/4に

Windows 7 コミュニティ勉強会 with Tech Fielders 北海道編

も行われるようです。
「知りたいところばかりギュッと濃縮」されたようなセッションの塊。
あいかわらずすごいなー、CLR/H。


てなことを、松崎さんのblogで知ってみたり。

松崎 剛 Blog : あの UAC (ユーザーアカウント制御)、「回避」 したいですよね ?

VS2010も日本語版ベータが公開されましたし、

ディベロッパー製品開発統括部 Blog : ダウンロードセンターに Visual Studio 2010 日本語版 Beta1 をリリースしました

またしばらく楽しい日々になっていきそうです。

(186) さらばニフティ

たったいま、@nifty を解約しました。
長い間、ありがとうございました。

NiftyServe の頃から数えて、10 数年のお付き合いとなりました。
技術的にも文化的にも、目から鱗が落ちまくるような体験でした。
NiftyServe がなければ、プログラムで喰っていく技術力もモチベーションも、私の手には入らなかったと思います。

インターネットの普及とともに、NiftyServe は @nifty へと、パソコン通信事業者からプロバイダへと変化していきました。
私にとっては必要のないサービスの提供が主軸となり、少しずつ求めるものと与えられるものがずれていってしまったように思います。

すでにサイトもメールサーバも、独自のものに移行しました。
解約を決意してから、移行の完了まで数年かかりました。いや実際なかなか難しいものですねえ。
告知期間も設けた…つもりだったんですが、ドメインの移行と同時にサーバの中身ごとばっさりイカれました。
いっそすがすがしいといいますか、たもとを分かつ相手にふさわしい対応だなあと妙に感心したりもしました。

それでも。
お世話になりました。ありがとうございました。

…やっぱり、ちょっぴり寂しいなあ。

手軽にグラフを描いてみた

昔だったら何万も出してグラフパーツを購入したり、むりむり Excel を制御してチャートシートを起こしたりしたんですが。
もっと昔だったら座標とってひとつずつプロットして自力で描いたりしたんですが。

時代はオープンソースで WPF でかなり気合の入ったビジュアルの図表が描き起こせるってほんとですかそうですか。

つことでモノは試しと実際に入手 → 試してみることにしました。
今回使ってみたのは Visifire。英語圏のサイトからの配布ですが、英語読めないことなんか気にしない。

Silverlight & WPF Chart

Download ページへ行って、とりあえず現行最新 v2.2.2 を落としてみました。
ざっと 973KB の zip ファイルで。マニュアルも落として。って説明書きのほうが 5.81MB で。それぞれざっとダウンロードフォルダに展開して。

ダウンロードフォルダのままでは使い勝手がちょいと悪いので、ドキュメントの Visual Studio 2008 フォルダに Components\visifire フォルダを作って、visifire_v2.2.2.zip の bin フォルダの中の 4 ファイルをコピーして。

これで準備完了というかインストール完了というかなんかそんな感じで。


こっから先は、先ほどダウンロードしたマニュアルを見ながらの作業となります。

Visual Studio 2008 IDE で、WPF アプリケーションを新規作成します。マニュアルは C# で解説されていますが、あえて VB で作成します。

次に、WPFVisifire.Charts.dll を参照設定します。
ソリューションエクスプローラからプロジェクト名を右クリック → [参照の追加]をクリックして「参照の追加」ダイアログを表示、[参照]タグで先ほどのフォルダへ → WPFVisifire.Charts.dll を選択して [OK] をクリック。

どうも visifire はコントロールではなく純粋なコンポーネントみたいなので、ツールボックスには何も表示されません。[アイテムの選択...] で追加しようとしても、「ツールボックスに追加できるコンポーネントは何もありません。」とか言われてしまいます。
なので、コードでゴリゴリ書いていくしかなさそうですねー。

まずは Windows1.xaml を少々書き換えます。

<Window x:Class="Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="350" Width="450">
    <Grid x:Name="LayoutRoot">

    </Grid>
</Window>

ウィンドウサイズを少し大きくして、<Grid> に名前を付けただけですが。

で、Windows1.xaml のコード側、Windows1.xaml.vb でコンストラクタを追加。

Public Sub New()

    InitializeComponent()

    '*** Call function to create chart
    Call CreateChart()

End Sub

これも、CreateChart メソッドを呼び出しているだけですが。

最後に、CreateChart メソッドを書きます。

Private Sub CreateChart()

    '*** Create
    Dim _chart As New Visifire.Charts.Chart
    Dim _dataSeries As New Visifire.Charts.DataSeries
    Dim _numberOfDataPoints As Integer = 10
    Dim _random As New System.Random

    '*** Set chart width and height
    _chart.Width = 400 : _chart.Height = 300

    '*** Loop and add a few DataPoints
    For loopIndex As Integer = 0 To _numberOfDataPoints - 1
        Dim _dataPoint As New Visifire.Charts.DataPoint
        _dataPoint.YValue = _random.Next(1, 100)
        _dataSeries.DataPoints.Add(_dataPoint)
    Next

    '*** Add
    _chart.Series.Add(_dataSeries)
    Me.LayoutRoot.Children.Add(_chart)

End Sub

マニュアルの C# コードを VB に焼き直しただけです。
これは簡単に言ってしまえば、乱数 10 個をデータとして Chart インスタンスに割り当てて、xaml の LayoutRoot と名付けた描画空間に組み込んだ、というところですね。

これだけでおしまいです。下が実行結果。

おおぅ、意外と簡単できれいなものが。

Windows Vista Service Pack 2、本日公開

Microsoft(R) Windows Vista(R)およびMicrosoft Windows Server(R) 2008 Service Pack 2日本語版を5月27日より提供開始

つことでひとつ。


ようやっと正式版が公開されましたので、まあ入れてみようかなと思ったわけです。
しかし、私のメインマシンの Vista には、現在なんだかプレリリース版が既に入っていたりもするわけです。
[コントロールパネル]-[プロパティ]とたどると、「Service Pack 2, v.659」とか表示されています。

のでまずこいつのアンインストから始めねば。

そんな時にお役に立つのがこちら。

Windows Vista Service Pack 2 および Windows Server 2008 Service Pack 2 に関する情報

このページの「SP2 のプレリリース バージョンの削除」の項を確認、その通りに操作してみます。

まずはスタートメニューの[検索の開始]ボックスに「appwiz.cpl」を入力 → Enter で検索。
ってさっそく何も見つかりません。なんでこんな回りくどい書き方をしてるんだろう。
これは単純に、スタートメニューから[コントロールパネル]-[プログラムと機能]を選択すればいいだけなのに。

で、[インストールされた更新プログラムを表示] をクリック → [Service Pack for Microsoft Windows (KB948465)] が表示されません。ええー?

私のマシンでは、「Microsoft Windows (KB948465) の Service Pack」と表示されました。
それっぽい更新プログラムが見つからない場合は、「KB948465」を頼りに探してみると見つけやすいかもしれません。

見つかったら、アンインストール。
私の環境では 24 分ほどかかりましたが無事成功、「Service Pack 1」と表示されるようになりました。


アンインストが成功したら、Service Pack 2 インストーラを入手。

Windows Server 2008 とVista (ともに x86 )の 5か国語(英蘭独日・スペイン語)版 exe タイプはこちら。

ダウンロードの詳細 : Windows Server 2008 Service Pack 2 および Windows Vista Service Pack 2 (5 言語用スタンドアロン版) (KB948465)

でもって Windows Server 200 (x86・x64・IA-64) と Vista (x86・x64) 5か国語版 DVD イメージ (.iso) タイプはこちら。

ダウンロードの詳細 : Windows Server 2008 Service Pack 2 および Windows Vista Service Pack 2 (5 言語用スタンドアロン版) DVD ISO (KB948465)

32 ビット版の Vista であれば、exe タイプのほうがファイルサイズが小さくてお勧めです。っても 348 MB あるわけですが。
どちらも必要要件は、SP1 が当たっていること。

インスト自体は、何のトラブルもなく完了しました。
[コントロールパネル]-[プロパティ]とたどると、今度は「Service Pack 2」と表示。内部バージョンとかの表記のない、なんともそっけない感じで。

バージョン情報を表示されると、6.0.6002 になっているみたいですね。

VB で超簡単 MySQL アクセス

検証環境 Fujitsu FMV-W630(Pen4(530)3.4GHz/3GB)
WindowsVista Ultimate(6.0.6002 SP2,v.659 Build 6002)
VisualStudio2008Pro(VB) 9.0.30729.1SP/.NET Framework 3.5SP1

猿頁 » Webサーバ構築記 からの派生です。

まあいろいろありまして、いま私の机の横には、メインマシンとサーバマシンが縦に積み重なっています。サーバマシンの中では WordPress という PHP 製の blog システムが稼働し、この猿頁は WordPress 上で運用されています。
WordPress はエントリやユーザー、アクセス状況といった情報の保持に MySQL という DB エンジンを使っています。

ふつー、このWordPresに関する機能を自作するなら WordPress プラグインの仕様に則って PHP で作成するのが筋なんですが。
Woopra というアクセス解析サービスが、解析結果の表示に ローカルの EXE を使うことを知った時に、

なんだ別にどんなアプローチでもアリじゃん。

と目から鱗が。

つことで、VB から MySQL を直接読んで WordPress のデータをイジってみようとか思ってみました。
読むだけなら意外とちょー簡単でちょーびっくり。


0. 参考資料

MySQL は、サイト内にリファレンスマニュアルが用意されています。
英語版は 3.23/4.0/4.1、5.0、5.1、5.4、6.0 とバージョンごとに用意されていますが、日本語版は 4.1 と 5.1 の 2 バージョンだけのようです。
また、日本語版の 5.1 と英語版の 5.1 では記載内容が微妙に違います。どうも日本語版は 4.1 から 5.1 を派生して起こした時に旧版の内容や構成が残ってしまっているような感じです。

私のサーバマシンでは 5.0 が稼働していますので、日本語でさっくり調べたい時は

  MySQL :: MySQL 5.1 リファレンスマニュアル

で。
なんか実装と説明が合わなくて「?」となった時は、英語がめんどくさいですが

  MySQL :: MySQL 5.0 Reference Manual

で調べていけばなんとかなりそうな気がします。
chm(Windows Help)ファイルでも提供されていますので、いちいち Web で検索するのがめんどい方はそっちを入手してもいいかもしれません。

1. Connector/Net 6.0 の入手とインストール

VS2008 では、DB へのアクセスは ADO.NET という仕組みを使って行うのが一般的です。
ADO.NET は、簡単に言っちゃうと、いろんな DB へアクセスするプログラミングの手順やコードをなるべく統一しようよ?という仕組みなわけですね。
一方で、実際に各種 DB へのアクセス方法は意外とさまざまでして、これを 統一っぽくするには、DB ごとに、ADO,NET と実際の DB を橋渡しするプログラムが必要になります。
このプログラムをデータプロバイダと呼びます。まあ、特定の DB をお使ったプログラムを作成するためのプラグインとかアドインとかアドオンとか、なんかそんな感じでイメージしていただければいいのではないかと思います。

つことで MySQL 用のデータプロバイダ。
まずはこいつを Visual Studio IDE に組み込むことにします。

MySQL 用のデータプロバイダは「MySQL Connector/NET」という名前で、

  MySQL :: Download Connector/Net 6.0

で提供されています。今日の時点では、6.0.3 が最新ですね。
このページから、「Windows Binaries (ZIP)」をダウンロードします。
入手できたファイルは mysql-connector-net-6.0.3.zip 、これを解凍すると mysql.data.msi というインストーラが出てきますので、ダブルクリックで実行、さっくりインストールしてしまいます。

実行できない場合は、Windows インストーラを最新にする必要があるのかもしれません。
Vista では標準で 4.0 が組み込まれているはずですが、Windows Server 2003 や XP な方は、3.0 とかそのへんを探してインストールしてみるといいように思います。

また、VS2008 Express Edition では、SQL Server / Access 以外のデータプロバイダは使用できませんので、そのへんもご注意ください。

2. サーバエクスプローラの調整

Connector/NET のインストールが終わったら、次。
Visual Studio IDE が、MySQL サーバにアクセスできるよう設定します。

今回の私の場合は、VS IDE はメインマシン (salvage-PC)、MySQL はサーバマシン (MiscnotesWebSer) にそれぞれインストールされています。
ので、VS IDE から MiscnotesWebSer というコンピュータを見に行けるような設定が必要となります。
MySQL と 開発環境が同じマシンの場合は、たぶんこの項は省略できます。

  1. VS IDE を起動します。
     
  2. サーバエクスプローラが表示されていない場合は、メニューから[表示]-[サーバーエクスプローラ]で表示させます。


     

  3. サーバーエクスプローラのツリーから[サーバー]を右クリック、[サーバーの追加...]をクリックします。


     

  4. 「サーバーの追加」ダイアログが表示されますので、[コンピュータ]にコンピュータ名を入力します。

    サーバマシンにアクセスするには、メインマシンとは違うユーザ名/パスワードが必要となりますので、コンピュータ名を入力し終わったら[OK]ではなく、「別の名前で接続…」リンクをクリックします。
     

  5. 「接続するユーザー」ダイアログが表示されますので、サーバマシンに登録してあるユーザー名とパスワードを入力して[OK]をクリックします。


     

  6. 「サーバーの追加」ダイアログに戻りますので、[OK]をクリックします。
    このタイミングで初めて、5)で入力したユーザ名とパスワードを使ってサーバマシンに接続に行きます。ユーザ名やパスワードの登録が間違っている場合は、ここで初めてエラーが表示されます。

    エラーが表示されてしまった場合は、再度「接続するユーザー」ダイアログを表示させて正確なユーザ名/パスワードを入力し直します。
     

  7. 正常に追加できると、サーバエクスプローラの[サーバ]ノードの下に、[MiscnotesWebSer]が追加表示されます。


     

  8. 続いてサーバエクスプローラのツリーから[データ接続]を右クリック、[接続の追加...]をクリックします。


     

  9. 9) 「データソースの選択」ダイアログが表示されますので、「MySQL Database」を選択し、[続行]をクリックします。


     

  10. 「接続の追加」ダイアログへ移行します。ここで、「サーバ名」「ユーザ名」「パスワード」を入力します。

    サーバ名は~7)までで作成したサーバ名を入力。ユーザ名とパスワードはサーバマシンのではなく、MySQL のユーザ名とパスワードを入力します。
    この 3 つを入力したら、[テスト接続]をクリックして接続を試してみます。「テスト接続に成功しました」と表示されれば成功です。

    「テスト接続に成功しました」メッセージボックスは[OK]をクリックして閉じ、「接続の追加」ダイアログに戻ります。
    今回は個人的なツール作成が目的なのでセキュリティなどは斟酌しません。ですから、めんどくさくないように[Save my password]にチェックをつけます。これで、何かとパスワード入力を求められたりすることがなくなります。
    テスト接続に成功すると、[Database name]のコンボボックスには接続可能なデータベース名の一覧が表示されるようになっているはずです。今回は WordPress のデータをイジりたいので、「wordpress」を選択します。

    で、最後に[OK]をクリックします。 
     

  11. 正常に追加できると、サーバエクスプローラの[データ接続]ノードの下に、[MiscnotesWebSer(wordpress)]が追加表示されます。

    [MiscnotesWebSer(wordpress)]ノードを広げてみると、その下に MySQL - wordpress データベースの中身が取得表示されていることがわかります。

3. データセットの作成

VS IDE の設定が完了したら、新しく Windows フォームアプリケーションプロジェクトを作成します。
このへんの操作説明は省略しますはっはっは。

引き続き、MySQL へのアクセスをするデータセットを作成します。

  1. ソリューションエクスプローラのプロジェクト名(この例であれば[smpl001_AccessMySQL])を右クリック、[追加]-[新しい項目]と選択します。


     

  2. 「新しい項目の追加」ダイアログが表示されますので、[カテゴリ]から[データ] → [テンプレート]から[データセット]を選択し、[追加]をクリックします。

    VS IDE に作成されたデータセットが表示されます。


     

  3. サーバエクスプローラから、アクセスしたいテーブルをデータセットウィンドウにドラッグ & ドロップします。
    すると、確認ダイアログが表示されます。

    何を言っているのかわかりにくいんですが、要は、DB のユーザ名やパスワードなどをプロジェクトの中に埋め込んじゃうけどいいかい?という確認です。
    なんでそんなことを聞いてくるかというと、テキストエディタなどで簡単に見れるようになってしまうのでセキュリティがちょいやばになってしまうからなんですね。
    今回はセキュリティとかあまり気にしませんので、気軽に[はい]をクリックします。
    業務上のアプリケーションだったり、不特定多数への公開を前提とする場合には、このへんは少し考えたほうがいいかもしれません。
     

  4. ドラッグしたテーブルのデータテーブルが作成されます。


     

  5. タブ表示欄右端の[×]をクリックします。
     
  6. 「以下の項目への変更を保存しますか?」というダイアログが表示されますので、[はい]をクリックします。

    VB2005 の頃の話になりますが、データセットは保存まわりが少々不安定だったような思い出があります。Ctrl+S では修正の一部が保存されなかったり、修正を繰り返していくうちにファイルが再読み込みできないような状態になったりしたんですね。
    VB2008 になってからはまだそんな被害には遭遇していませんが、私はなるべくこまめに保存、Ctrl+Sではなく必ずファイルを閉じて完全に保存するようなクセがついています。
     

  7. 作成したデータテーブルが、正常に MySQL にアクセスできるかどうかを確認します。
    ソリューションエクスプローラから[DataSet1.xsd]をダブルクリックし、もう一度データセットウィンドウを表示させます。
     
  8. データセットウィンドウの[wp_session_manager]を右クリックし、[データのプレビュー]をクリックします。


     

  9. 「データのプレビュー」ダイアログが表示されますので、[プレビュー]をクリックします。
    MySQL テーブルの内容が表示されれば、正常にアクセスできていることの確認となります。

    [閉じる]をクリックして、 「データのプレビュー」ダイアログを閉じます。

4. DataGridView への接続

せっかくですので、作成したデータセットを使って Windows フォームにデータを表示するプログラムも作ってみます。

  1. Form1 に、ツールボックスから DataGridView コントロールを載せます。


     

  2. DataGridView コントロールを Form1 に載せると、[DataGridView タスク]というタイトルのスマートタグが自動的に表示されます。


     

  3. [DataGridView タスク]スマートタグの[データソースの選択]コンボボックスをプルダウンし、[他のデータソース]-[プロジェクトデータソース]-[DataSet1]-[wp_session_manager]をクリックします。


     

  4. [データソースの選択]コンボボックスに[WpsessionmanagerBindingSource]と表示され(全部表示されず「Wpsessionmanager」のような表示になっているかもしれません)、DataGridView コントロールに MySQL のテーブル wp_session_manager の各フィールドが列として表示され、フォームデザイナウィンドウの下の方に「DataSet1」「WpsessionmanagerBindingSource」「Wp_session_managerTableAdapter」の 3 つのコンポーネントが表示されますが、別になんのことだかわからなくてもかまいません。


     

  5. あとついでに、追加/編集/削除をチェックをはずしておきます。

    今回はデータの表示を確認したいだけですので、まちがって書き換えたりしないようにしておきたい、ということですね。
    さらについでに、[親コンテナにドッキングする]も一度クリックし、DataGridView コントロールがフォーム全体に広がるようにしておきます。

5. 実行

以上でプログラミング完了。1 行もコードを書いていませんが、これだけで DB の中身を表示できるプログラムが完成しました。
F5 を押して、実行してみます。

おおー、ちゃんと表示されるではないですか。

6. UnixTimeの変換

ここからおまけ。

MySQL では、日時の管理によく UnixTime という考え方を使うようです。
最初「UnixTime という型なのか?」と思ったんですが、内部的にはただの int(11) のようでよくわかりません。

でもまあ WordPress でも日付は UnixTime 管理みたいですし、いろいろ調べてみると MySQL を使ったアプリケーションではセオリーとしてよく使われているみたいですし、MySQL そのものに UnixTime を対象とした変換関数も用意されているという、なんとなく中途半端な対応となっているようです。

上記の作成例でも UnixTime フィールドはがっちり表示されているわけですが、実際に何月何日なのかがよくわかりません。

ので、データテーブルを少し修正して、人間にわかる形式での表示に差し替えてみます。

  1. 先ほど作成した「DataSet1.xsd」のウィンドウを表示させます。
     
  2. [wp_session_manager]を右クリックし、[構成...]をクリックして「TableAdpter構成ウィザード」ダイアログを表示させます。


     

  3. [クエリビルダ]ボタンをクリックして、「クエリビルダ」ダイアログを表示させます。
     
  4. Select 文の「unixtime」を、「FROM_UNIXTIME(unixtime) as vistime」に書き換えます。
     
  5. [クエリの実行]ボタンをクリックして、無事に表示できれば成功です。


     

  6. [OK]をクリックして「クエリビルダ」ダイアログを閉じ、[完了]を押して「TableAdpter構成ウィザード」ダイアログを閉じます。
     
  7. Form1 をデザイナウィンドウで開き、DataGridViewの[DataGridViewタスク]スマートタグの[データソースの選択]を、一度「なし」に選択し、再度「WpsessionmanagerBindingSource」を選択し直します。
     

これで完了。実際に実行して表示を確認してみます。

よーし。ちゃんとわかりやすい表記になりましたね。


MySQL のマニュアルを読むと、Connector/Net の上で動作する「MySQL Visual Studio プラグイン」なるものがあるそうなんですが。

  MySQL :: MySQL 5.1 リファレンスマニュアル :: 24.3 MySQL Visual Studio プラグイン 

これ、実際にはどこにも見つかりません。
ガンバって探してみたんですが、見つかったのは古いミラーサイトでの古いバージョンのみでした。

  MySQL AB :: MySQL Visual Studio Plugin

どうも Connector/Net が5 → 6 になった時に統合されたか、あるいは単に提供をやめてしまったかな感じです。
実際、Connector/Net で十分用は足りるので、なくてもかまわないような気もします。