連載
» 2014年06月19日 00時00分 公開

WinRT/Metro TIPS:PowerPointやExcelの資料をアプリに同梱するには?[ユニバーサルWindowsアプリ開発]

アプリにOfficeドキュメントを同梱し、アプリ内からこれを開く方法と、Windows PCにOfficeがインストールされていない場合に、Office Onlineを使って対処する方法を解説する。

[山本康彦(http://www.bluewatersoft.jp/),BluewaterSoft]
WinRT/Metro TIPS
業務アプリInsider/Insider.NET

powered by Insider.NET

「WinRT/Metro TIPS」のインデックス

連載目次

 Windows Phoneには標準でOfficeが搭載されている。ならば、WordやExcelやPowerPointのファイル(以降、Office文書ファイル)をアプリに格納しておいて、アプリから開けないだろうか? 例えば、操作マニュアルをWordファイルで提供するといった用途が考えられる。そこで本稿では、ユニバーサルWindowsアプリに同梱したOffice文書ファイルをアプリから開く方法と、OfficeがインストールされていないWindows環境での対策を解説する。なお、本稿のサンプルは「Windows Store app samples:MetroTips #79」からダウンロードできる。

事前準備

 ユニバーサルプロジェクトを使ってユニバーサルWindowsアプリを開発するには、以下の開発環境が必要である。本稿では、無償のVisual Studio Express 2013 for Windowsを使っている。

  • SLAT対応のPC*1
  • 2014年4月のアップデート*2適用済みの64bit版Windows 8.1 Pro版以上*3
  • Visual Studio 2013 Update 2*4適用済みのVisual Studio 2013(以降、VS 2013)*5

*1 SLAT対応ハードウェアは、Windows Phone 8.1エミュレーターの実行に必要だ。ただし未対応でも、ソースコードのビルドと実機でのデバッグは可能だ。SLAT対応のチェック方法はMSDNブログの「Windows Phone SDK 8.0 ダウンロードポイント と Second Level Address Translation (SLAT) 対応PCかどうかを判定する方法」を参照。なお、SLAT対応ハードウェアであっても、VM上ではエミュレーターが動作しないことがあるのでご注意願いたい。

*2 事前には「Windows 8.1 Update 1」と呼ばれていたアップデート。スタート画面の右上に検索ボタンが(環境によっては電源ボタンも)表示されるようになるので、適用済みかどうかは簡単に見分けられる。ちなみに公式呼称は「the Windows RT 8.1, Windows 8.1, and Windows Server 2012 R2 update that is dated April, 2014」というようである。

*3 Windows Phone 8.1エミュレーターを使用しないのであれば、32bit版のWindows 8.1でよい。

*4 マイクロソフトのダウンロードページから誰でも入手できる。

*5 本稿に掲載したコードを試すだけなら、無償のExpressエディションで構わない。Visual Studio Express 2013 Update 2 for Windows(製品版)はマイクロソフトのページから無償で入手できる。Expressエディションはターゲットプラットフォームごとに製品が分かれていて紛らわしいが、Windowsストアアプリの開発には「for Windows」を使う(「for Windows Desktop」はデスクトップで動作するアプリ用)。


用語

 本稿では、紛らわしくない限り次の略称を用いる。

  • Windows:Windows 8.1とWindows RT 8.1(2014年4月のアップデートを適用済みのもの)
  • Phone:Windows Phone 8.1

サンプルコードについて

 Visual Studio 2013 Update 2のRTMがリリースされたが、残念なことに本稿執筆時点ではVB用のユニバーサルプロジェクトのテンプレートがまだ含まれていない*6。そのため、本稿で紹介するコードはC#のユニバーサルプロジェクトだけとさせていただく。別途公開しているサンプルコードには、ユニバーサルプロジェクトに似せた形のVBのコードも含めてある*7

*6 VB用のユニバーサルプロジェクトも近い将来に提供されるものと思われる。例えば、Windowsストアアプリ用のVBプロジェクトのCommonフォルダーに自動生成される「NavigationHelper.vb」ファイルには、Phoneの[戻る]ボタン(ハードウェアボタン)からの割り込みを処理するためのコードがUpdate 2ですでに追加されている。これはユニバーサルプロジェクトのために必要になるコードであり、ユニバーサルプロジェクトを提供する予定がないのなら不要なものだ。

*7 プロジェクト間のファイルリンクを使えば、VBでもユニバーサルプロジェクトに似たソリューション構成にできる。別途公開のサンプルコードでは、VBでもWindows用/Phone用/共通コードの3プロジェクトに分けてユニバーサルプロジェクトに似せて書いてみた。ただし、このような形にするにはかなりの手間が掛かった(説明するには本連載の1回分では足りないほどだ)。ユニバーサルプロジェクトテンプレートの形にこだわらず、素直に作った方がよさそうである。なお、ユニバーサルプロジェクトで作らなくてもユニバーサルWindowsアプリはリリースできるので、お間違えなきよう(「WinRT/Metro TIPS:ユニバーサルプロジェクトで開発するには?」参照)。


Office文書ファイルをアプリに同梱するには?

 プロジェクト内に置いて、「コンテンツ」にすればよい。ユニバーサルプロジェクトの場合は、共有プロジェクトに置ける。

 例として適当なPowerPointのファイルを作り、ファイル名を「sample.pptx」とする(ソリューションとは別のフォルダーに作成したとする)。VS 2013のソリューションエクスプローラーで、まず共有プロジェクトに適当なフォルダー(ここでは「Assets」とする)を作る。続いて、作成した「Assets」フォルダーを右クリックして[追加]−[既存の項目]を選び、「sample.pptx」ファイルを指定する。そうしたら、「sample.pptx」ファイルのプロパティで、[ビルド アクション]を「コンテンツ」にする(次の画像)。画像やフォントを同梱するのと同じである。

プロジェクトに追加したOffice文書ファイルを[コンテンツ]にする(VS 2013) プロジェクトに追加したOffice文書ファイルを[コンテンツ]にする(VS 2013)
プロジェクトに追加したOffice文書ファイルのプロパティで、[ビルド アクション]を[コンテンツ]にする(赤枠内)。
その下の[出力ディレクトリにコピーする]は、[コピーしない]のままにしておく。
なお、ソリューションエクスプローラーで[追加]−[既存の項目]を選ぶ代わりに、エクスプローラーからファイルをソリューションエクスプローラーのフォルダーにドラッグ&ドロップしてもよい。

同梱したOffice文書ファイルをアプリから開くには?

 LaunchFileAsyncメソッド(Windows.System名前空間のLauncherクラス)を使えばよい。ただし、アプリに同梱したファイルは他のアプリ(ここではPowerPoint)からアクセスできないので、一時フォルダーにコピーしてから開く(デバッグ実行時はインストール場所が違うのでアクセス可能だ。気を付けよう)。

 まず、アプリに同梱したファイルを一時フォルダーにコピーするコードは次のようになる。

// アプリに同梱するOfficeファイル
const string SampleFolder = "Assets";
const string SampleFileName = "sample.pptx";

// アプリに同梱したOfficeファイルを一時フォルダーにコピーして、それを返す
private static async System.Threading.Tasks.Task<Windows.Storage.StorageFile> 
  GetOfficeFileAsync()
{
  var tempFolder = Windows.Storage.ApplicationData.Current.TemporaryFolder;
  var tempFile = (await tempFolder.TryGetItemAsync(SampleFileName))
                  as Windows.Storage.StorageFile;
  // すでにコピー済みなら、それを返す
  if (tempFile != null)
    return tempFile;

  // 一時フォルダーにコピーしてそのファイルを返す
  var installedFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
  var sampleFolder = await installedFolder.GetFolderAsync(SampleFolder);
  var srcFile = await sampleFolder.GetFileAsync(SampleFileName);
  return await srcFile.CopyAsync(
                         tempFolder, SampleFileName,
                         Windows.Storage.NameCollisionOption.ReplaceExisting
                       );
}

アプリに同梱したファイルを一時フォルダーにコピーするコード(C#)
共有プロジェクトに新しく「AttachedOfficeFiles.cs」ファイルを作り、その中の「AttachedOfficeFiles」クラスに記述する。
PhoneにはTryGetItemAsyncメソッドが存在しないため、このままではビルドできない(すぐ次に述べる)。

 ただし、PhoneのAPIにはTryGetItemAsyncメソッド(Windows.Storage名前空間のStorageFolderクラス)が存在しないので、新しくStorageFolderExtensionsクラスを作って、そこに拡張メソッドとして実装する(次のコード)。

#if WINDOWS_PHONE_APP
  public static class StorageFolderExtensions
  {
    public static async System.Threading.Tasks.Task<Windows.Storage.IStorageItem> 
      TryGetItemAsync(this Windows.Storage.StorageFolder folder, string name)
    {
      var files = await folder.GetItemsAsync().AsTask().ConfigureAwait(false);
      return files.FirstOrDefault(p => p.Name == name);
      // FirstOrDefaultメソッドの使用には、ファイル冒頭に「using System.Linq;」が必要
    }
  }
#endif

Phone用のTryGetItemAsyncメソッド(C#)
PhoneのAPIにはTryGetItemAsyncメソッドが存在しないので、自前で実装しなければならない。Phone専用なので「#if」ディレクティブで切り分ける。
この程度の短いクラスなら、既存のファイルに記述してしまってもそれほど混乱しないだろう。ここでは、上記の「AttachedOfficeFiles.cs」ファイルに同居させた。

 先のGetOfficeFileAsyncメソッドで得られたファイルを開くコードは次のようだ。

public static async System.Threading.Tasks.Task OpenOfficeDocumentAsync()
{
  var officeFile = await GetOfficeFileAsync();
  var opt = new Windows.System.LauncherOptions();
  await Windows.System.Launcher.LaunchFileAsync(officeFile, opt);
}

ファイルの関連付けを利用してファイルを開く(C#)
GetOfficeFileAsyncメソッドで得られるのはPowerPointのファイルなので、このコードでPowerPointが起動してファイルが開かれる。
ここではLauncherOptionsオブジェクト(=ローカル変数「opt」)を使っていないが、後ほどOfficeのインストールされていないWindowsへの対処で使用する。

 あとは画面にボタンを配置し、そのClickイベントで上述のOpenOfficeDocumentAsyncメソッドを呼び出せば、アプリに同梱したOffice文書ファイルが表示される(次の画像)。OpenOfficeDocumentAsyncメソッドは非同期メソッドなので、ボタンのClickイベントハンドラーにasyncキーワードの追加を忘れずに(次のコード)。

private async void Button_Click(object sender, RoutedEventArgs e)
{
  await AttachedOfficeFiles.OpenOfficeDocumentAsync();
}

ボタンのイベントハンドラーで上述のメソッドを呼び出す(C#)

アプリに同梱したOffice文書ファイルが表示された
アプリに同梱したOffice文書ファイルが表示された アプリに同梱したOffice文書ファイルが表示された
上はWindows。デスクトップに切り替わり、PowerPointが立ち上がる。なお、PowerPoint(または、PowerPointのファイルを表示できるアプリ)がインストールされていない環境では表示できないが、その対処は次項で述べる。
下はPhone(VS 2013 Update 2付属のエミュレーター)。Phone版のPowerPointに切り替わる。

OfficeがインストールされていないWindowsでは?

 上記のコードは、Office(あるいは、Office文書ファイルを表示するアプリ)がインストールされていないWindowsではうまくいかない(PhoneにはOfficeが標準なので心配はない)。その対策として、同じOffice文書ファイルをOneDriveに置いておき、Office Onlineで開くようにするとよい。

 まず、前述の「sample.pptx」ファイルをOneDriveの公開可能なフォルダーにコピーし、[表示のみ可能]にしておく(次の画像)。

OneDriveに置いた「sample.pptx」ファイル(Internet Explorer) OneDriveに置いた「sample.pptx」ファイル(Internet Explorer)
共有範囲は公開だが、他の人には[表示のみ可能]となるフォルダーに置こう(赤枠内)。
アクセス許可の設定は上位のフォルダー単位になる。詳しくは「ファイルとフォルダーを共有しアクセス許可を変更する」を参照してほしい。
なお、アクセス許可の設定を行うにはInternet Explorerを使う。WindowsストアアプリのOneDriveからはできないようである。

 続いて、Internet ExplorerでOneDriveに置いた「sample.pptx」ファイルをクリックする(上の画像の画面でクリックする)。すると「PowerPoint Online」に切り替わって、PowerPointのファイルが表示されるので、そのURLをコピーしてどこかにメモしておく(次の画像)。

PowerPoint Onlineで「sample.pptx」ファイルを表示(Internet Explorer) PowerPoint Onlineで「sample.pptx」ファイルを表示(Internet Explorer)
前の画像で「sample.pptx」ファイルをクリックすると、このようにPowerPoint Onlineで表示される。このときのURLをメモしておく。
この画像では、上部のメニューに[プレゼンテーションの編集]がある(赤枠内)。これは、編集可能なアカウントでサインインしているためだ。サインアウトしてこのメニューが[POWERPOINTで開く]に変わることを確かめておこう(変わらなければ、前述した[表示のみ可能]の設定ができておらず、誰でも編集できる状態だ)。

 さて、OfficeがインストールされていないWindowsでは、上記のPowerPoint OnlineのURLを開いてやればよい。そのために利用できるのが、LauncherOptionsオブジェクトのFallbackUriプロパティだ。ファイルの関連付けでは開けなかったとき、FallbackUriプロパティに指定したWebページを自動的に開いてくれるのだ。

 前述のOpenOfficeDocumentAsyncメソッドを、次のコードのように変更する。

// OneDriveにアップロードしたOfficeファイルのURL
const string SampleUrl
  = "https://onedrive.live.com/view.aspx?cid=1F……省略…31&app=PowerPoint";

public static async System.Threading.Tasks.Task OpenOfficeDocumentAsync()
{
  var officeFile = await GetOfficeFileAsync();
  var opt = new Windows.System.LauncherOptions();
#if WINDOWS_APP
  // 表示できるアプリがインストールされていないときの代替Uri
  opt.FallbackUri = new Uri(SampleUrl); 
#endif
  await Windows.System.Launcher.LaunchFileAsync(officeFile, opt);
}

ファイルの関連付けを利用してファイルを開く(改良版)(C#)
LauncherOptionsオブジェクト(=ローカル変数「opt」)のFallbackUriプロパティへの設定を追加した(太字の部分)。定数のSampleUrlには、さきほどメモしておいたURLを記述する。
これで、Officeを表示できるアプリがインストールされていないWindowsでは、ブラウザでPowerPoint Onlineが表示されるようになる。

 これで実行してみると、PowerPointがインストールされていないWindowsでは、次の画像のようにPowerPoint Onlineで表示される。なお、厳密にテストするにはPowerPointをアンインストールすべきであろうが、「sample.pptx」ファイル(および、コード内の定数)の拡張子を関連付けのないもの(例えば「.notpptx」など)に変更してしまえば動作を確認できる。

FallbackUriの指定によってPowerPoint Onlineが表示された(Windows) FallbackUriの指定によってPowerPoint Onlineが表示された(Windows)
画面の左半分は本稿で作ったアプリ、右半分はアプリから起動されたInternet Explorerである。
なお、別途公開のサンプルコードのWindowsプロジェクトには、直接PowerPoint Onlineで表示するためのコードも入れてある。

まとめ

 PhoneにはOffice ハブが標準だ。これを利用しない手はないだろう。また、OfficeがインストールされていないWindowsでも、OneDriveとPowerPoint Onlineを利用すればOffice文書を表示できる。

 ユニバーサルプロジェクトでは、それらのコードを共有プロジェクトに置ける。

 なお、本稿では筆者のOneDriveを使ったが、多数のアクセスが見込まれるアプリでは、ユーザーの許可を得た上でユーザーのOneDriveにアップロードした方がよいだろう。

「WinRT/Metro TIPS」のインデックス

WinRT/Metro TIPS

Copyright© 1999-2017 Digital Advantage Corp. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。