VBAからBox APIを叩いてみる - 実践編

前回、Box APIを叩くための準備を行いました。社内で使う事を想定しWinHTTPRequestでプロキシーを超える為の設定も含めて、準備の紹介を行いました。すでにAccess Tokenは取得ができているのと、リフレッシュトークンを使った再取得の方法も紹介しています。

今回は、このAccess Tokenを使って、Box APIの中でもよく使うであろう、アップロード・ダウンロード・名前の変更・ファイルの削除・ファイルのロックをしてみたいと思います。また、加えてこのAPIを利用したアプリの使い所を研究してみたいと思います。

今回使用するファイルとライブラリ

ソースコード

ファイルのダウンロード

ファイルのダウンロードでは、ファイルのIDが必要です。ファイルのIDとは、「https://app.box.com/file/306826865097」とあった場合の「306826865097」の部分。これを指定します。BoxではContent PickerというGoogle Picker APIのようなものも用意されていますが、VBAから使うには厳しいので、直で指定しておく必要があります。

  • ファイル名の取得の行にて、帰ってくるファイル名(UTF8)をデコードする為に、DecodeURLMSHTMLという関数を利用しています。利用する為には、参照設定にて「Microsoft HTML Object Library」が必要です。
  • この項目の基本ですが、Tokenが生存してるかどうかの判定ルーチンにて、期限切れの場合リフレッシュトークンで取得し直し、ルーチンを続行させています。
  • ファイルはとりあえず、プログラムのある同じフォルダ内に生成されます。
  • ファイル名などの情報は、Content-Dispositionヘッダー内に含まれていて、ここから取り出します。ヘッダの内容は以下のような感じ
  • 使用するエンドポイントURLは、https://api.box.com/2.0/files/となります。

ファイルのアップロード

Box APIで最も面倒なルーチンは、ファイルのアップロードです。バイナリデータを送らなければならないため、様々な処理を追加しなければなりません。そのため、送信パラメータが複雑です。フォルダのIDおよびファイルのID、ファイル名、MIMETYPEが必要となります。今回はjpgファイルを送り込むので、ファイルのMIMETYPEは「image/jpeg」となります。ZIPならば「application/x-compress」ですね。

今回この部分については、大変よくできたルーチンがありますので、こちらを利用しました。

  • パラメータの構築では、SetNomarlParameter、SetFileParmater、SetEndParameter、GetSendParameter、ChangeStreamType、getBoundyをこちらのサイトのコードを利用させていただきました。
  • アップロードは上書きアップロードされます。バージョンが重なってる点で判別が可能です。
  • フォルダIDおよびファイルID、ファイルのパスは固定にしてしまってるので、ここを手直しする必要があります。
  • リクエストパラメータの設定に失敗すると文字化けしてアップロードされてしまいます。
  • HeaderリクエストにあるBoundaryとは、バウンダリ文字列と呼ばれるもので、適当な文字列なのですが、リクエスト文の境界線で用いられる文字列で必須です(文字種と文字数が一致していればUUIDのように生成して使って問題ない)。
  • ファイルの種類ごとにMIMETYPEは異なるので、より汎用的な関数にするには、拡張子などからMIMEを設定するルーチンが必要です。
  • 前述のダウンロードと組み合わせる事で、他のフォルダのバックアップファイルをマスターのファイルへ上書きで復元するといった事が実現します。単純なコピーでは上書きは出来ないので注意。

図:ファイルの版がアップデートされてることを確認

名前の変更

ファイル・フォルダの名前の変更には、新しいファイル名、ファイル・フォルダのIDが必要になります。また、今回は一つの関数でファイルとフォルダのリネームに対応させているので、フラグも必要(0ならばファイルのリネーム、1ならばフォルダのリネーム)。

  • 引数のflgでファイルのリネームか?フォルダのリネームかを判定しています。
  • ファイルとフォルダとで、それぞれ利用するエンドポイントURLが異なります。
  • ファイルの場合のエンドポイントURLは、https://api.box.com/2.0/files/となります。フォルダの場合のエンドポイントURLは、https://api.box.com/2.0/folders/となります。
  • パラメータの構築はJSON形式で作って送ってあげる必要があるため、VBA-JSONのJsonConverterを利用しています。
  • WinHTTPRequestでの送信メソッドは「PUT」ですので注意が必要です。

ファイルの削除

ファイルの削除はファイルのIDがあれば問題ありません。こちらも1つの関数でファイルとフォルダの削除に対応させているので、flgを引数に与えています。

  • ほぼファイルのリネームと同じルーチンですが、エンドポイントURLにつなげる項目がフォルダの場合の削除は少々異なります。
  • WinHTTPRequestでの送信メソッドは「DELETE」ですので注意が必要です。
  • 特に送信にあたってリクエスト文を組み立てる必要がないのでシンプルですね。

ファイルのロック

ファイルのロックはロックしている最中はファイルのダウンロードを阻止したり、編集の禁止をさせる為のものです。GUI上では誰でも簡単にロックは外せてしまうので、強力なものではないのですが、社内で使う上では必須です。ロックを掛けずにファイルの上書きがバッティングすると、あとから上書きしたファイルはファイルの整合性がズレ、別ファイルとして分離されてしまう仕組みなので、このロックは有効活用すべきですね。

  • パラメータの構築はJSON形式で作って送ってあげる必要があるため、VBA-JSONのJsonConverterを利用しています。
  • パラメータ上、いつまでロックするか?の時間は、そのままではexpire_atの時刻はGMTなのでここに常に9時間を足した時間で指定しないと、日本ではおかしなロックになってしまいます。
  • 今回のルーチンでは、expire_atの時刻指定(何時間後まで)の部分はしっかり作っていないので、実用する場合は、少し手直しが必要です。
  • WinHTTPRequestでの送信メソッドは「PUT」ですので注意が必要です。
  • ファイルに対してしかロックはできません。
  • is_download_preventedはFalseですとファイルのダウンロードもロックします。
  • 今回のメソッドはDictionaryオブジェクトを利用しているので、参照設定として「Microsoft Scripting Runtime」が必要です。
  • アンロックする場合は、JsonObjectにAddする部分で、JsonObject("lock").Add nullアンロックになるとのこと。

ファイルIDからBox Drive上のフルパスを構築する

Box APIを使って対象のファイルのIDから、Box Drive上のフルパスを構築する事が可能です。Box Driveはその場所が「C:¥Users¥ユーザ名¥Box」となっており、この下からがBox上のディレクトリ構造になっているので、APIでpath_collectionの部分を取得して構築すれば、IDのみで対象のファイルのドライブ上の在り処を突き止める事が可能です。ユーザ毎にフルパスが異なるので、少し工夫が必要です。

  • 普通にまず対象のファイルIDについての詳細な情報をリクエストする
  • path_collectionのentriesには1個ずつパスが入ってる。このうち一番最初の「すべてのファイル」は不要なので、次の配列から処理をする
  • また、同時にpath_collectionにはパスの個数が入ってるので(total_count)、これをループに利用する
  • CallByName関数を使ってJSONを取り出していく
  • ログインユーザ名はEnviron("USERNAME")で取得できるので、これを使い、Boxまでのフルパスを作成
  • 上記のBoxまでのフルパスとpath_collectionのパスを連結、最後にファイル名をつなげて完全なfullpathを構築したら返す

path_collectionは上から順番にディレクトリのルートからとなっており、最後にファイル名を付けてあげれば完成です。レスポンス的には以下のような感じになっています。

Box DriveのパスからファイルID逆引き

Box Drive上のExcelやAccessのファイルを開いた時に、そのファイルに割り当てられてるファイルのIDを調べたいことがあります(このファイルIDに基づいてロックされてるかどうかの自動チェックを続けて行う等の需要があります)。しかし、Box Drive上のファイルそのものにファイルIDの情報があるわけではないので、Box APIの「コンテンツ検索API」を用いて、逆引きしてあげる必要があります。

この時必要になる情報は

  • ファイル名および拡張子
  • そのファイルが存在するBox上でのフルパス

これら二つを持ってリクエストや判定を行って絞り込み、対象のファイルのIDを逆引きすることが可能です。

  • Box上にあるファイルじゃない場合には処理をしないように冒頭で判定させています
  • 現在開いてるファイル名およびその拡張子を取得し、リクエストを投げる為に利用しています。
  • リクエストエンドポイントは「https://api.box.com/2.0/search」になります。GETなので、パラメータをつなげてstrUriを生成します
  • 検索を絞り込む為に、queryはファイル名、content_typesをname、file_extensionに拡張子を、typeをfileを指定しています。
  • 複数の結果が返ってくると思われるので、ここで各ファイルのIDとBox上のフルパスを構築
  • 各ファイルのBox上のフルパスを連結させた値と、冒頭の自身のファイルのBox上のフルパスとを比較して同一のものであれば、それが逆引きされたファイルIDとなる(Boxは同じディレクトリ上に同一ファイル名のファイルが存在出来ない為
  • 最後に取得したファイルIDを返して終了

ただし注意点が1つ。アップロードしたてのファイルがBoxのインデックスに追加されるまで、企業で契約してる有償のBox Enterpriseであれば割と早く登録されますが(最大で10分くらい)、無償で利用できる個人のBoxの場合、相当長い間インデックスに登録されない為、実際にファイルを手動でアップロードして、検索してみるとなかなかヒットしません。ヒットしないということは、この逆引きでも検索で出てこないということなので要注意です。

合わせて以下のエントリーも参考にしてみてください。

Boxミニマニュアル

使い所を考える

実際にBox上では、Box editを使えばExcelファイルを開ける!また、保存した時に自動的に同期するといった謳い文句がありますが、まぁ、バグが酷いです。Box Toolが入ってるにも関わらず、Excelを開くアプリケーションが無い(実際には入ってる)と言われたり、同期ミスったり、PCを起動する度に勝手にファイルが増殖するなど、ちょっと使い物になりません。

また、Box DriveというGoogle Drive File Streamと同じような機能の仕組みもあるのですが、古い企業ではネットワークトラフィックが耐えられなかったり、プロキシーサーバ経由の場合不具合が出るなどの理由で、利用が制限されていることもあります。それ故ファイルサーバの代わりにはならず、そうなると「Excelのファイル間リンク」「Wordの差し込み印刷」などいった機能が使えなくなります。APIを利用することでこれらをカバーすることが可能です。

関連リンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)