Excelの起動
Excelのアプリケーションを起動するサンプルを確認していきましょう。今回のサンプルは、Silverlight連載の月間ページビューをExcelに表示してグラフを表示するためのものです。図3に実行イメージを示します。

Excelのオートメーションオブジェクトを利用すれば、グラフを作成したり、セルに色をつけることも可能ですが、表示したいイメージがある程度決まっているのなら、あらかじめExcelのテンプレートを作成し、Silverlight側では単に動的に変動する値を埋める、といった単純なものにした方がいいでしょう。
今回は、グラフの範囲設定と、ヘッダー行に色をつけた図4のExcelブックを図4のようにWebサーバーの「~/ExcelTemplate/テンプレート.xlsx」に作成しておきます。Silverlight側は、Excel起動ボタンが押されたタイミングでテンプレートをダウンロードし、ページビューのセルに値を設定してExcelを起動して、グラフを表示します。

まずはコードの全体をリスト2に示します。
// Excelの起動ボタンのクリック時のイベントハンドラ
private void btnExecExcel_Click(object sender, RoutedEventArgs e)
{
// 1.Excelテンプレートのダウンロード
var client = new WebClient();
client.OpenReadCompleted += client_OpenReadCompleted;
client.OpenReadAsync(new Uri(@"http://localhost:1348/ExcelTemplate/テンプレート.xlsx"));
}
// ダウンロード終了時のイベントハンドラ
void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
if (e.Error != null)
return;
// 2.Excelテンプレートファイルの保存
var filePath = System.IO.Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
"テンプレート.xlsx");
var s = new BinaryReader(e.Result);
var b = s.ReadBytes((int)e.Result.Length);
File.WriteAllBytes(filePath, b);
// オートメーションが利用出来るかの確認
if (!AutomationFactory.IsAvailable) return;
// 3.Excel オートメーションを作成して値を書き込む
using (dynamic excel = AutomationFactory.CreateObject("Excel.Application"))
using (var books = excel.Workbooks)
using (var book = books.Open(@"C:\temp\テンプレート.xlsx"))
using (var sheets = book.Worksheets)
using (var sheet = sheets[1])
using (var cells = sheet.Cells) {
// 2010/08 - 2011/01 のページビュー
var pageViews = new List<int>() { 1034, 6809, 2093, 1776, 1248, 1326 };
var baseRowIndex = 3;
var baseColIndex = 3;
for (var index = 0; index < pageViews.Count; index++)
{
var cell = cells[baseRowIndex, baseColIndex + index];
cell.Value = pageViews[index];
}
excel.Visible = true;
}
}
簡単にプログラムを確認していきましょう。このサンプルには、大きく分けて下記の3つの手順があります。
- Excelテンプレートのダウンロード
- Excelテンプレートファイルの保存
- Excel オートメーションを作成して値を書き込む
1. Excelテンプレートのダウンロード
WebClientクラスのOpenReadAsyncメソッドを利用して、Webサーバーに配置されたExcelファイルをダウンロードします。同時に、ダウンロード終了時のイベントハンドラを登録しておきます。
2. Excelテンプレートファイルの保存
ダウンロードしたデータをオートメーションから読み込むために、ユーザーのドキュメントフォルダにテンプレート.xlsxという名前で保存します。Silverlightでは、ファイルをユーザーのストレージに保存する場合はSaveFileDialogクラスを通じてユーザーがアクションを起こす必要がありますが、信頼されたアプリケーションでは特定ディレクトリであればユーザーの同意は必要ありません。詳しくは、前回の連載を確認してください。
3. Excelオートメーションを作成して値を書き込む
前述の通り、Excelのオートメーションオブジェクトを作成し、ExcelのC3のセル(2010/08の実績)からH3(2011/01の実績)に対しそれぞれのページビューを設定して、最後にVisibleプロパティをtrueにすることで、Excelを起動してグラフを表示しています。
単なるオートメーションの呼び出しであれば、CreateObjectメソッドで取得したオブジェクトのみをDisposeすればよいのですが、暗黙オブジェクトを生成するオートメーションには注意が必要です。
例えば、リスト3の例では、bookオブジェクトからWorkSheets、WorkSheet、Cells、Cellの4つのオブジェクトが暗黙的に参照され、生成されています。
book.Worksheets[1].Cells[3, 3] = "1";
このような例では、Silverlightアプリケーションが終了するまで、Excelのプロセスが残ってしまうことがあります。多くのクライアントを相手にしたり、再起動の間隔が長いWebサイトのアプリケーション程に気を尖らすことも無いのかもしれませんが、メモリリークの原因にもなるので、暗黙のオブジェクトにも注意して廃棄を行うようにしましょう。
WMIを使ったプリンタ一覧の取得
よく使いそうな例として、WMI(Windows Management Instrumentation)を使ったサンプルも見ておきましょう。WMIはコンピューターの情報を簡単に管理するためのライブラリで、現在のプロセスの情報やプリンタの情報などをSQLに似た言語で簡単に取得、管理できます。WMIに関する情報は、TechNetのスクリプトセンターを参照してください。
リスト4は、現在コンピュータにインストールされているプリンタの一覧を取得する例です。
var printerList = new StringBuilder();
using (dynamic wmi = AutomationFactory.CreateObject("WbemScripting.SWbemLocator"))
{
wmi.Security_.ImpersonationLevel = 3;
wmi.Security_.AuthenticationLevel = 4;
using (var service = wmi.ConnectServer(".", @"root\cimv2"))
{
foreach (var printer in service.ExecQuery("Select * from Win32_Printer"))
{
printerList.AppendFormat("プリンタ名: {0} ポート名:{1}\n", printer.Name, printer.PortName);
}
}
}
MessageBox.Show(printerList.ToString());
WMIのプログラムIDは、WbemScripting.SWbemLocatorです。Excelの例と同様に、CreateObjectメソッドでオートメーションオブジェクトを取得し、プリンタ情報を管理するWin32_Printerに対してクエリーを行っています。
このサンプルを実行すると、図5のような画面が表示されます。

現在のところ、Silverlight単体ではローカルコンピューターにインストールされたプリンタの情報を取得できません。プリンタに限らず、デバイスに関係する情報を取得するためには、多くの場合オートメーションオブジェクトに頼る必要があります。
