実用的アプリケーションの開発(Outlook編)
何を作るか?
連絡先にWebページアドレスが指定されていた場合は、アイテム表示ウインドウ内でWebページを表示できるようにします。
プロジェクトの作成
[ファイル]⇒[新規作成]⇒[プロジェクト]から、[Outlook 2007 アドイン]を作成します。
[プロジェクト]⇒[新しい項目の追加]を開き、[Outlookフォーム領域]を選択します。
その後、[新しいフォーム領域のデザイン]、[分離]を選択し、WebSitePreviewという名前を付けておきます。
最後に、フォーム領域を表示するメッセージクラスを[連絡先]のみに変更し、完了を押します。
フォーム領域のデザイン画面が開くので、フォームの大きさを適当に広げてから、WebBrowserコントロールを配置します。
連絡先の取得
フォーム領域のコードを表示し、連絡先からURLを取得してブラウザコントロールに渡す部分を実装します。
追加したコードは以下の通りです。
Outlook.ContactItem myItem = (Outlook.ContactItem)this.OutlookItem; if ((myItem != null) && (myItem.BusinessHomePage != null)) { webBrowser1.Navigate(myItem.BusinessHomePage); }
[デバッグ]⇒[デバッグの開始]を行うと、Outlookが起動するので、左下のボタンを使って、連絡先表示に切り替えます。
ダブルクリックして連絡先アイテムを表示させます。リボンの[表示]の部分に、[WebSitePreview]というボタンが追加されています。
[WebSitePreview]ボタンをクリックすると、ウインドウ内にWebサイトが開きます。
この例においても、使用しない場合は、アドインを削除しておく必要があります。
実用的アプリケーションの開発(Excel編)
プロジェクトの作成
[ファイル]⇒[新規作成]⇒[プロジェクト]から、[Excel 2007 ブック]を作成します。
ドキュメントは新規に作成します。
[プロジェクト]⇒[ユーザーコントロールの追加]⇒[新しい項目の追加]⇒[ユーザーコントロール]を選択し、追加を押します。
ユーザーコントロールのデザイナが開きますが、ここでは何もしません。
ThisWorkBook.csのコードを表示し、Startupイベントハンドラ(ThisWorkbook_Startup)内に、カスタム作業ウインドウを表示するためのコードを記述します。
実際のコードは以下となります。
UserControl1 uc = new UserControl1(); this.ActionsPane.Controls.Add(uc); this.Application.CommandBars["Task Pane"].Position = Microsoft.Office.Core.MsoBarPosition.msoBarRight;
カスタム作業ウインドウの編集
ユーザーコントロールのデザイナを開き、「帳票作成」、「クリア」、「全てクリア」のボタンを作成します。
「全てクリア」ボタンをダブルクリックし、イベントハンドラを生成させます。
ここでは、全てのシートをクリアする必要があります。追加するコードは以下となります。
private void button3_Click(object sender, EventArgs e) { Globals.ThisWorkbook.ClearAllSeets(sender, e); }
実際にクリア作業を行うのは、ThisWorkbookのClearAllSeetsです。以下のように実装します。
public void ClearAllSeets(object sender, System.EventArgs e) { foreach (Excel.Worksheet workSheet in this.Worksheets) { workSheet.Cells.Clear(); } }
ユーザーコントロールのデザイナを開き、「クリア」ボタンをダブルクリックして、イベントハンドラを生成させます。
ここでは、アクティブなシートのみクリアする必要があります。追加するコードは以下となります。
private void button2_Click(object sender, EventArgs e) { Globals.ThisWorkbook.ClearActiveSeets(sender, e); }
実際にクリア作業を行うのは、ThisWorkbookのClearActiveSeetsです。以下のように実装します。
public void ClearActiveSeets(object sender, System.EventArgs e) { ((Excel.Worksheet)this.ActiveSheet).Cells.Clear(); }
帳票の作成
ユーザーコントロールのデザイナを開き、「帳票作成」ボタンをダブルクリックして、イベントハンドラを生成させます。追加するコードは以下となります。
private void button1_Click(object sender, EventArgs e) { Globals.ThisWorkbook.MakeFormatedSeet(sender, e); }
帳票の作成そのものは、ThisWorkbookのMakeFormatedSeetが行います。
まずはひな形を示します。
public void MakeFormatedSheet(object sender, EventArgs e) { }
作成する帳票は、以下のようなものにします。
まずは、外枠部分を描画します。
記述したコードは以下となります。
#region 外枠の描画 // 1ページ目外枠 Excel.Worksheet activeSheet = (Excel.Worksheet)this.ActiveSheet; Excel.Range temp = ((Excel.Range)activeSheet.get_Range( activeSheet.Cells[1, 1], activeSheet.Cells[59, 9])); temp.BorderAround(missing, Excel.XlBorderWeight.xlThin , Excel.XlColorIndex.xlColorIndexAutomatic, missing); // 2ページ目外枠 temp = ((Excel.Range)activeSheet.get_Range( activeSheet.Cells[60, 1], activeSheet.Cells[118, 9])); temp.BorderAround(missing, Excel.XlBorderWeight.xlThin , Excel.XlColorIndex.xlColorIndexAutomatic, missing); #endregion
次に、タイトル周りの表部分を描画します。
記述したコードは以下となります。
#region タイトル周りの描画 // 配布先 temp = ((Excel.Range)activeSheet.get_Range( activeSheet.Cells[1, 1], activeSheet.Cells[4, 2])); temp.BorderAround(missing, Excel.XlBorderWeight.xlThin , Excel.XlColorIndex.xlColorIndexAutomatic, missing); temp.Merge(true); temp.Merge(false); temp.VerticalAlignment = Excel.Constants.xlTop; // タイトル temp = ((Excel.Range)activeSheet.get_Range( activeSheet.Cells[1, 3], activeSheet.Cells[4, 7])); temp.BorderAround(missing, Excel.XlBorderWeight.xlThin , Excel.XlColorIndex.xlColorIndexAutomatic, missing); temp.Merge(true); temp.Merge(false); temp.HorizontalAlignment = Excel.Constants.xlCenter; temp.VerticalAlignment = Excel.Constants.xlCenter; // 文書番号、日付、所属、氏名 for (int i = 0; i < 4; ++i) { temp = ((Excel.Range)activeSheet.get_Range( activeSheet.Cells[1 + i, 8], activeSheet.Cells[1 + i, 9])); temp.BorderAround(missing, Excel.XlBorderWeight.xlThin , Excel.XlColorIndex.xlColorIndexAutomatic, missing); temp.Merge(true); temp.HorizontalAlignment = Excel.Constants.xlCenter; } #endregion
更新履歴表を描画します。
記述したコードは以下となります。
#region 更新履歴表の描画 for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { temp = (Excel.Range)activeSheet.Cells[7 + i, 2 + j]; temp.BorderAround(missing, Excel.XlBorderWeight.xlThin , Excel.XlColorIndex.xlColorIndexAutomatic, missing); temp.HorizontalAlignment = Excel.Constants.xlCenter; } temp = ((Excel.Range)activeSheet.get_Range( activeSheet.Cells[7 + i, 5], activeSheet.Cells[7 + i, 8])); temp.BorderAround(missing, Excel.XlBorderWeight.xlThin , Excel.XlColorIndex.xlColorIndexAutomatic, missing); temp.Merge(true); } #endregion
各部分の文字列を描画します。
記述したコードは以下となります。
#region 文字列を書く // Excel.Range.Valueは未サポート、Excel.Range.set_Valueは引数が不明で使えず。 ((Excel.Range)activeSheet.Cells[1, 1]).Value2 = "配布先"; ((Excel.Range)activeSheet.Cells[1, 3]).Value2 = "Excel仕様書テンプレート"; ((Excel.Range)activeSheet.Cells[1, 8]).Value2 = "IJ-XXXXXX"; ((Excel.Range)activeSheet.Cells[2, 8]).Value2 = "2008/5/21"; ((Excel.Range)activeSheet.Cells[3, 8]).Value2 = "情報技術開発部"; ((Excel.Range)activeSheet.Cells[6, 2]).Value2 = "改版履歴"; ((Excel.Range)activeSheet.Cells[7, 2]).Value2 = "バージョン"; ((Excel.Range)activeSheet.Cells[7, 3]).Value2 = "日付"; ((Excel.Range)activeSheet.Cells[7, 4]).Value2 = "作成者"; ((Excel.Range)activeSheet.Cells[7, 5]).Value2 = "内容"; #endregion
[デバッグ]⇒[デバッグの開始]を行うと、カスタム作業ウインドウが表示された状態で起動します。カスタム作業ウインドウにある[帳票作成]ボタンを押すと、以下のように枠線などが描画されます。
Sheet2、Sheet3に切り替えても、同様のことが行えます。
最後に、[全てクリア]ボタンを押すと、全てのシートが白紙に戻ります。
実用的アプリケーションの開発(Word編)
プロジェクトの作成
[ファイル]⇒[新規作成]⇒[プロジェクト]から、[Word 2007 ドキュメント]を作成します。
ドキュメントは新規に作成します。
[プロジェクト]⇒[ユーザーコントロールの追加]⇒[新しい項目の追加]⇒[ユーザーコントロール]を選択し、追加を押します。
デザイン画面が開きますが、ここでは何もしません。
次に、ソリューションエクスプローラでWebNewsReaderプロジェクトを右クリックし、[追加]⇒[新しい項目]を開きます。[リボン(ビジュアルデザイナ)]を選択し、追加を押します。
リボンのデザイン画面が開くので、タブとグループのLabelプロパティを設定します。
フィードの選択、登録を行うためのインタフェースを追加します。
フィードの取得を行うインタフェースを追加します。
フィードの初期値を設定しておくために、コードを編集します。
現在選択しているURLを保持するためのプロパティを追加します。
イベントハンドラを実装します。
フィードの取得を行うイベントハンドラ(button2_Click)については、後で実装します。
XMLの取得
XMLを取得して、Wordドキュメントに書き出す部分を実装します。
XMLファイルを読む部分が出来たので、フィードの取得を行うイベントハンドラ(button2_Click)から呼び出せるようにします。
XMLの解析
現時点で、以下のようなドキュメントが生成されます。
しかし、これは生のXMLを直接表示しているだけなので、非常に読みづらいです。
そこで、XMLのタグを元に、必要な情報のみを抽出します。
プロジェクト名で右クリックして、[追加]⇒[新しい項目]⇒[クラス]を選択します。
この新しいクラスの実装イメージは次ページの図のようになります。これから順に説明していきます。
まず、XMLファイルの構造を見てみましょう。
サイトの名前が、<rss><channel><title>の位置に記述されています。サイトのURLは、<rss><channel><link>の位置にあります。以下、同様にして、必要な情報をXPathで記述してみると、以下のようになります。
情報の種別 | XPath |
---|---|
サイトの名前 | /rss/channel/title |
サイトのURL | /rss/channel/link |
エントリのタイトル | /rss/channel/item/title |
エントリのURL | /rss/channel/item/link |
エントリの更新時刻 | /rss/channel/item/pubDate |
エントリの内容 | /rss/channel/item/description |
まず、サイトの名前とURLを抽出します。ここでは、サイトの名前とURLは1つしか存在しないことを前提としています。
次に、各エントリの情報を抽出します。エントリは複数ある可能性が高いので、List<>を使って受けています。
ここまでで、XMLから必要な情報が取り出せました。
ドキュメントを単独で開けないようにする
VSTOを使用したOfficeアプリケーションを、より大きなアプリケーションの一部で使うようになった場合、生成されたOfficeドキュメントに直接触られると困ることがあります。
ここでは、Excelにアドインでパスワード認証をつけておき、上位アプリケーションからパスワードを指定して開く、ということを行います*1。
名前を付けて保存と印刷を無効化する
Excelアドインプロジェクトを新規作成し、ThisAddIn.csのコードを開きます。
名前を付けて保存、及び、印刷機能を無効化するため、WorkbookのBeforeSaveとBeforePrintのイベントハンドラを実装します。
private void ThisWorkBook_BeforeSave(bool b, ref bool Cancel) { if (b == true) { Cancel = true; MessageBox.Show("保存はキャンセルされました。"); } } private void ThisWorkBook_BeforePrint(ref bool Cancel) { Cancel = true; MessageBox.Show("印刷はキャンセルされました。"); }
BeforeSaveは、ファイル選択ダイアログが出るケース(引数bがtrueの場合)のみキャンセルし、上書き保存は通るようになっています。
これらのイベントハンドラは、ファイルオープン時に設定出来るように、Openイベントハンドラ内に実装します*2。
private void ThisAddIn_Open(Excel.Workbook wb) { this.Application.ActiveWorkbook.BeforePrint += new Excel.WorkbookEvents_BeforePrintEventHandler( ThisWorkBook_BeforePrint); this.Application.ActiveWorkbook.BeforeSave += new Excel.WorkbookEvents_BeforeSaveEventHandler( ThisWorkBook_BeforeSave); MessageBox.Show("名前を付けて保存、印刷、の機能を無効化しました。"); }
最後に、Openイベントハンドラを登録します。
private void ThisAddIn_Startup(object sender, System.EventArgs e) { this.Application.WorkbookOpen += new Excel.AppEvents_WorkbookOpenEventHandler(ThisAddIn_Open); }
これは、Startupイベントハンドラ中で行います。
パスワードを設定する
Excelブックにパスワードを設定するため、上書き保存時に処理を追加します。上書き保存は、BeforeSaveイベントハンドラの第一引数がfalseの場合に相当するので、以下のように実装します。
private void ThisWorkBook_BeforeSave(bool b, ref bool Cancel) { if (b == true) { Cancel = true; MessageBox.Show("保存はキャンセルされました。"); } else { this.Application.ActiveWorkbook.Password = "hogehoge"; MessageBox.Show("ドキュメントにパスワードを設定しました。"); } }
これで、既存のExcelファイルを開いて上書き保存すると、常にパスワードが付加されるようになります。
パスワード付きドキュメントを開くと、次のようなダイアログが表示され、パスワードを入力する旨を知らせます。
アプリケーションからExcelファイルを開く
新規にWindowsフォームプロジェクトを作成し、フォームにボタンを配置します。
ソリューションエクスプローラの[参照設定]を右クリックし、[参照の追加]を選択します。
この画面から、以下を全て選択し、OKを押します。
- Microsoft.Office.Interop.Excel
- Microsoft.Office.Tools.Common.v9.0
- Microsoft.Office.Tools.v9.0
- Office
さらに、Form1.csのusing宣言に以下を追加します。
using Excel = Microsoft.Office.Interop.Excel; using Office = Microsoft.Office.Core;
フォームデザイナ上のボタンをダブルクリックして、イベントハンドラを生成します。イベントハンドラ内では、ファイル選択ダイアログを表示し、選択されたファイルをExcelで開く処理を実装します。この時、パスワード認証を回避するためにExcelワークブックのOpenメソッドでパスワードを指定します。
コードを以下に示します。
private void button1_Click(object sender, EventArgs e) { OpenFileDialog dialog = new OpenFileDialog(); if (dialog.ShowDialog() == DialogResult.OK) { Excel.Application app = new Excel.Application(); try { this.Visible = false; app.Visible = true; Excel.Workbook wb = app.Workbooks.Open( dialog.FileName, Type.Missing, Type.Missing, Type.Missing, "hogehoge", Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing); while (app.Visible) ; this.Visible = true; } catch { app.Workbooks.Close(); } finally { System.Runtime.InteropServices.Marshal.ReleaseComObject(app); GC.Collect(); } } }
これにより、このアプリケーションを用いれば、同じパスワードのついた文書を開くことができるようになります。
なお、この例においても、登録されたCOMアドインを削除しておく必要があります。
カスタム作業ウインドウのリサイズに応じてスクロールバーを出す
カスタム作業ウインドウはリサイズ可能ですが、内部のコントロールを考慮してはくれないので、そのままでは問題が出る場合があります。これを回避するための方法を示します。
Excelアドインプロジェクトを新規に作成し、カスタム作業ウインドウを実装します。
カスタム作業ウインドウには、Panelコントロールとボタンを配置します。
ユーザーコントロールを選択し、プロパティから、Resizeイベントのイベントハンドラ名を入力し、イベントハンドラのひな型を生成します。
生成されたイベントハンドラは、以下のように実装します。
private void uc1_Resize(object sender, EventArgs e) { panel1.Width = Globals.ThisAddIn.CustomTaskPanes[0].Width; panel1.Height = Globals.ThisAddIn.CustomTaskPanes[0].Height - 20; // これを忘れるとスクロールバーが不可視になるので注意! }
これにより、UserControl1のResizeイベントが生じた際には、カスタム作業ウインドウの全体をPanelが占有している状態になります。また、初期値については、
ThisAddIn_Startup内で、以下のように指定します。
customTaskPane.Width = 210;
ユーザーコントロールのデザイナで、Panelコントロールを選択し、以下を指定します。
プロパティ | 値 |
---|---|
AutoScroll | true |
AutoScrollMinSize | 200, 500 |
この状態で、デバッグして実行すると、カスタム作業ウインドウが表示された状態で起動します。カスタム作業ウインドウの幅を狭めていくと、途中からスクロールバーが出ることが確認できます。また、ウインドウを縦方向に狭めていったときも、同様に、スクロールバーが出ることが確認できます。
なお、この例においても、登録されたCOMアドインを削除しておく必要があります。
印刷不可にする
印刷不可にする(Excel編)
Excelアドインプロジェクトを新規に作成します。
ThisAddIn.csのコードを開き、スタートアップイベントハンドラ(ThisAddIn_Startup)に、印刷をキャンセルするコードを追加します。
変更を加えたコードは以下となります。
private void ThisAddIn_Startup(object sender, System.EventArgs e) { this.Application.ActiveWorkbook.BeforePrint += new Excel.WorkbookEvents_BeforePrintEventHandler( ThisWorkBook_BeforePrint); } ... private void ThisWorkBook_BeforePrint(ref bool Cancel) { Cancel = true; MessageBox.Show("印刷はキャンセルされました。"); }
実行して、印刷を行うと、以下のダイアログが表示され、印刷がキャンセルされます。印刷プレビューについても、同様にキャンセルされます。
なお、この例においても、登録されたCOMアドインを削除しておく必要があります。
印刷不可にする(Word編)
Wordアドインプロジェクトを新規に作成します。
ThisAddIn.csのコードを開き、スタートアップイベントハンドラ(ThisAddIn_Startup)に、印刷をキャンセルするコードを追加します。
変更を加えたコードは以下となります。
private void ThisAddIn_Startup(object sender, System.EventArgs e) { this.Application.Application.DocumentBeforePrint += new Word. ApplicationEvents4_DocumentBeforePrintEventHandler( ThisDocument_BeforePrint); } ... private void ThisDocument_BeforePrint(Word.Document document, ref bool Cancel) { Cancel = true; MessageBox.Show("印刷はキャンセルされました。"); }
実行して、印刷を行うと、以下のダイアログが表示され、印刷がキャンセルされます。
なお、この例においても、登録されたCOMアドインを削除しておく必要があります。