Uncategorized

VSTO を使った Microsoft Office 開発における Cached によるデータ永続化の実装

【環境】
Visual Studio 2005 Tools for the Microsoft Office system
Microsoft Office 2003
または、
Visual Studio Codename Orcas March 2007 CTP 以降 (Trinity Beta 1 以降)
the Microsoft Office system 2007

こんにちは。

今日は、Office 開発における Cached という仕組みと、それをどのようなビジネスアプリケーションの中でどう応用していくかを簡単に説明します。(Microsoft On などでスマートクライアントのセミナーを聞かれたことのある方は、既にご存知の内容です。)

以下、Microsoft Office 2003 を例に説明します。

【Cached を使わないとどうなってしまうのか】

まず、その効果を理解してもらうため、以下のようなアプリケーションを作成してみましょう。Visual Studio 2005 で [Visual C#] – [Office] の [Excel ブック] プロジェクトを作成します。

  1. メニューの [データ] – [新しいデータソースの追加] で、データベースに接続して、何某かのテーブルをデータソースとして追加してください。
  2. メニューの [データ] – [データソースの表示] でデータソースのペインを表示して、取り込んだテーブルをワークシート上にドラッグアンドドロップしましょう。(ワークシート上に、Excel 用の ListObject コントロールが取り込まれます。)
  3. この状態でそのまま実行しても良いですが、今回は、データアイランドを理解してもらうため、検索ボタンを付けて、ボタンを押したら検索をおこなうようにしてみましょう。
    ツールボックスからワークシート上にボタンをドラッグアンドドロップして配置しましょう。
    (実際の開発では、ワークシート上ではなく、アクションペインなどに配置しましょう。ペインを使った開発については、ここ に記載しています。)

  4. Sheet1.cs のコードファイルを表示してください。Sheet1_Startup メソッドで、データのロード(アダプターのFill)を実行していますので、ここのコードを削除します。
  5. 上記で配置した検索ボタンをダブルクリックしてボタンのクリックイベントとして、上記で削除した Fill の処理を実装します。(以下、アダプター名を productTblTableAdapter、データテーブルをhol_DBDataSet.ProductTblとした場合のサンプルです。)
private void button1_Click(object sender, EventArgs e){Globals.Sheet1.productTblTableAdapter.Fill(Globals.Sheet1.hol_DBDataSet.ProductTbl);}
では、ビルドして実行してみましょう。
F5 によるデバッグ実行ではなく、ビルドされた xls ファイル (binDebugの下のxlsファイル) を直接起動して実行してみてください。(これから「保存」の確認をおこないますが、F5 の場合、デフォルトでは、プロジェクトのリソースがコピーされ上書きされてしまいます。)
  1. 検索ボタンを押して、データベースからデータが検索され、Excel のシート上に表示されることを確認してみましょう。
  2. つぎに、1つ実験をしてみましょう。
    開いている Excel のブックを保存して終了し、再度、このExcelファイルを表示してみてください。データは保存されていますか?

結果は、一瞬データが表示されて、すぐに空っぽになってしまったはずです。

なぜこのような動作をするのでしょうか?
理由を説明しましょう。

検索ボタンを押して取得したデータは、メモリ内のデータセット(またはデータテーブル)と呼ばれるオブジェクトに格納され、格納されたメモリ上のデータとコントロールの間でバインドがおこなわれているからです。つまり、メモリ上のデータは、Excel を終了した段階で空になってしまうのです。(ADO.NET の非接続型アーキテクチャについて、こちら が参考になるでしょう。)

尚、Microsoft Office 2007 の Word のコンテンツコントロールでお試しの方は、ドキュメントを保存するとデータはページ上に保存されますが、内部のデータセット (もしくはデータテーブル) はやはりクリアされています。

起動時にデータをデータベースに毎回接続して自動で取得するようなアプリケーションであれば問題ありませんが、このように [検索] ボタンなどでデータを取得した場合にはデータを永続化しておく必要があるのです。

【では、Cached を使ってみましょう】

データセット (DataSet) やデータテーブル (DataTable) は、XML にシリアライズすることが可能です。このため、 このような状況に対処するには、デスクトップアプリケーションであれば、通常、XML として保存するためのボタンなどを設けて対処しますが、Office アプリケーションの場合、ユーザはOffice文書とやりとりをしていますから、別途XMLとしてファイル保存などしたくはないでしょう。
こうしたことに対処するため、VSTO では、データに Cached 属性を指定しておくことで、Office のバイナリの文書内にシリアライズして保存しておくというテクノロジーがあります。

使い方は、簡単です。

  1. 先ほどのソースを開いて、Sheet1.cs のデータセット (またはデータテーブル) の上に、以下のように Cached 属性を宣言します。(ソリューションエクスプローラ上の [すべてのファイルを表示] のツールボタンをクリックして、表示される Sheet1.Designer.cs ファイルを開いて、下記の該当箇所に属性を設定します。)

    [Microsoft.VisualStudio.Tools.Applications.Runtime.Cached()]
    public ExcelWorkbook2.HOL_DBDataSet hol_DBDataSet;

    宣言も、internal から public などに変更しておいてください。

  2. では、再度ビルドして上記の通り実行してみましょう。
    今度はどうでしょう?

今度は、ちゃんと保存できるようになりましたね。シリアライザブルなものであれば、こうして処理をすることが可能になります。

この XML によるシリアライズの仕組みは大変利口にできています。データセットオブジェクトは、ユーザが情報の編集をおこなっている際も、どのデータが挿入され、どのデータが変更されたかといった情報(RowState)や、変更・削除されたものについては編集前の情報も含め保持しています。この仕組みによって、データベースへ Update をおこなう際には、更新されたレコードだけを対象にデータベースに書き込むなどの利口な処理をおこなっています。また、UI 上で編集をロールバックするといった処理も可能です。
実は、上記のシリアライズでは、こうした RowState などの状態も含め保存をおこなっています。ですから、日にちをまたがって編集処理をおこなうようなシナリオでも、この仕組みを有効に活用することができるようになっています。

Categories: Uncategorized

Tagged as:

1 reply»

Leave a Reply