ExcelとAccessに独自のリボンを追加する

Officeにて業務用アプリケーションを構築する時に、いつも課題になるのが「ボタンや入力用UIをどうするか?」で悩みます。Accessの場合には、フォームを作るのが定石なので、それほど困らないのですが、Excelの場合はシートの上にボタンを置くというのも、格好が悪いのと、列が多い場合、置き場所に困ります。

また、複数ウィンドウがあると、ボタンへのアクセスがしにくくなります。そこで利用するのが色々悪名高いリボン。しかし、登場からもう10数年経過して割りと受け入れられてきてるとも思います。今回は、このリボンに自分が作ったVBAコマンドなどを割り当てて動かせるように構築しようと思います。

今回使用するファイル

WYSIWYGでリボンを作成するOffice2010 RibbonCreatorというソフトウェアもありますが、こちらはシェアウェアとなっています。また、Visual Studio for OfficeでもGUIでリボンを作成できるようです。

Excelにリボンを追加する

Excelファイルにリボンを追加するのは少々厄介です。まずリボンが追加出来るのは、VBAが利用出来る拡張子がxlsm形式やxlam形式である事が必要です。事前にxlsm形式等でファイルを保存しておきましょう。また、XMLファイルが必要ですが、xlsmをLhazなどのアーカイバで解凍すると色々出てきます。この中に「customUI」というフォルダを作り、その中に「customUI.xml」と「customUI14.xml」の2つのファイルを作るのですが、最期はZIPで固め直すという面倒が作業が必要です。

そこで利用するのが、Custom UI Editor Toolです。まずはこれを使えるようにしましょう。

※なおこのツールは、WordやPowerPointにも使えるので、pptmファイルにリボンを付けることも可能です。

Custom UI Editor Tool

Custom UI Editor Toolをまずはインストールしましょう。以下の手順で準備します。このエディタは、Excel、Word、PowerPointに対応しているのは確認しています。

  1. サイトに行きClone or Downloadをクリックする
  2. Download ZIPをクリックする
  3. ダウンロードされたZIPファイルを解凍する
  4. 解凍された中のフォルダ「Publish」⇒「Application Files」⇒「CustomUIEditor_4_0_0_0」を開く
  5. CustomUIEditor.exe.deployというファイルがあるので、名前変更で、.deployを削る
  6. CustomUIEditor.exeに対するショートカットをデスクトップにでも作る
  7. ちょっと日本語入力にオカシナ点がある・・・・

Setup.exeがあるのですが、ビルドに失敗してるのか!?起動しても何もおきないのでこの方法でexeファイルを起動します。

図:Custom UI Editor Toolを起動してみた

起動時初期化のコード

リボンを定義する前に、初期化する為のコードなどをExcel側に用意しておきましょう。標準モジュールを追加して、以下のコードを用意しておきます。

OnLoadという関数が肝です。リボン初期化時にこのコードが読み込まれ、リボンのインスタンスを取得します。ここでしか取得できず、取得しておかないと後でリボンをコントロール出来なくなります。また、今回は自作リボンを起動時にアクティブにしています。

また、リボンのボタンが直接叩く「hello」という関数を作っておきました。

リボンを作成する

早速リボンを作成します。Custom UI Editor Toolを起動し、Openでxlsmファイルを開きましょう。開いた初期の状態では何も入っていない状態のはずです。メニューより「Insert」⇒「office2010 Custom UI Part」をクリックしましょう。これでXMLが書けるようになります。作成したら、以下のサンプルコードを貼り付けてみましょう。

サンプルコード

リボンはボタンだけでなく、テキストボックスやドロップダウンなど色々なパーツを作り込むことができますが、今回はまずシンプルに1個のタブと1個のグループ、1個のボタンだけで構成しています。1行目ラストにはonLoad="OnLoad"を追加し、初期化コードを実行させます。

また、buttonのonActionには作成済み関数であるhelloを指定してあげています。

imageMsoについて

imageMsoはボタンなどで使う予め用意されているアイコン画像です。アイコン名を入れる事で予め用意されてるアイコン類を使えるのですが、imageMso Gallaryにてどんな画像があるのか調べる事が可能です(但し、Office2010とOffice2016ではアイコンのデザインが大分異なります)

また、ここに独自の画像(PNGファイルなど)を使う事も可能です。もちろん、Custom UI Editorから画像を挿入し、ファイル名の拡張子を除いたものをimageに指定することで独自画像をボタンに使用する事が可能です。

  1. Custom UI Editorでxlsmファイルを開く
  2. リボンを追加し、Insert Iconでjpgやpngファイルを開く
  3. 左のパネルにあるcustom14UI.xmlの中に画像が登録される
  4. imageMso=ではなく、image="tomato"といった形で指定する。拡張子は付けない。

図:Custom UI Editorで簡単に独自画像が追加できる

主に使うパーツ

自分がよく使うパーツをピックアップしてみました。上記では必要最低限度のパーツのみでXMLに記述しましたが、主に今後開発を進めていくに当たってよく使うパーツのコードを記述してみました。

チェックボックスやテキストボックスなどもありますが、あまりリボンで作り込む時には適さないので、自分は使用していません。

気をつけなければならない点は

  1. 各パーツ類のidは重複してはなりません。
  2. menu属性の場合、その親のitemSizeに従うので、Buttonにはsize属性は付けない

この2点はコピペ時にしょっちゅう引っかかるポイントです。きちんと確認しましょう。

図:サブメニューなどを追加してみた

Accessにリボンを追加する

Accessの場合、WordやExcel、PowerPointとはアプリケーションの構造自体が異なり、リボン自体の組み込み方も異なります。XML形式で定義するのは同じなのですが、この組み込み部分がややこしいです。

図:サブメニューや大きなメニューを使うと雰囲気アップ

Usysribbonsテーブルを作る

リボンはテーブルで作ります。まずは以下の形式でテーブルを隠しオブジェクトとして作ります。

  • IDはオートナンバー(値は1)
  • RibbonNameは短いテキスト型(値は適当にリボン名を入力)
  • RibbonXmlは長いテキスト型(XML構造定義をここに記述)

作成後に、以下の手順で起動時にこのリボンが表示されるように設定します。

  1. メニューより「ファイル」⇒「オプション」を開く
  2. 現在のデータベースを開く
  3. リボンとツールバーのオプションの項目に移動する
  4. リボン名のドロップダウンリストに上記で設定したリボン名が出て来るので選択する。
  5. OKボタンを押して、Accessを再起動

Usysribbonsテーブルは隠しオブジェクトにしておくべきですので、左サイドバーより

  1. Usysribbonsテーブルを右クリック
  2. テーブルのプロパティを開く
  3. 属性の隠しオブジェクトにチェックを入れてOKボタンをクリック

図:Usysribbonsテーブルの構造

起動時初期化のコード

リボンを定義する前に、リボンを初期化する為のコードを事前に用意しておきましょう。標準モジュールを追加しておいて、以下のコードを用意しておきます。また、Accessで独自リボンを使う場合には、Microsoft office15 Object Libraryへの参照設定が必要です。

とりわけ、onLoadはリボン読み込み時にだけ実行される特別な関数で、ここでリボンのインスタンスを取得しておかないと、移行リボンのコントロールが出来ないので必須のコマンドです。また、Accessの場合はオリジナルのリボンをまず表示するのが定石なので、この段階で自作リボンをアクティブにしています。

リボンを作成する

基本的にはExcelの場合と同じです。少し異なる点は、onActionにマクロを指定できる点です。マクロを指定する場合は、onActionにマクロ名を入れるだけです。関数を直接叩く場合には、関数名を入れますがその関数はExcelの場合と同じ様式で作成します。

起動時に初期化する

onLoadという関数を事前に用意しましたが、XML内でこれを読み込み時に実行するように追加します。

1行目のcustomUIの項目に、onLoad="onLoad"として追加します。これで自動で実行されるようになります。

ボタンの実行に関数を割り当て

idにはButtonXを指定。onActionにはtestribbonを指定しました。testribbonという名前のマクロを用意した場合には、そちらが実行されるようになります。

実行用のコード

上記のときの直接実行コードは以下のように作ります。

control.IDで押されたボタンのIDを取得しています。この時、ButtonXならばメッセージボックスを表示してくれます。

ボタンの幅などのTips

普通にそのまま、リボンを作ってると、ボタンの幅が狭く、リボンのラベルが妙な所で改行!?されたような不細工な表示になることがままあります。自分としては綺麗に表示したいのに制御が出来ません。これを制御する方法は、ラベルの改行したい場所に「
」という文字を入れることで、改行が可能になります。

すると綺麗に幅が調整されてボタンの見た目もGoodになります。

チェックボックスを利用する

業務でどうしても設定ダイアログではなく、リボンでオプション切り替えできるようにして欲しいという事でしたので、計算や実行をする際に切り替える為のオプションとして「チェックボックス」をリボンに追加し、チェック内容をフラグにして条件分岐し計算結果を変動させる仕組みを作りました。ボタンと違って、オンオフのロジックが必要となるので、少々難易度が高いです。

もちろん、ExcelやPowerPointなどでも利用する事は可能です。

図:ラジオボタンは存在しない

リボンXMLについて

チェックボックスのリボン自体はそこまで難しくはありません。しかし、チェック状態の取得やチェックされた時のアクション、そしてその値を格納する変数等が必要になるので、単純ではありません。

  • getPressedがチェック状態を取得するイベントになります。引数がその関数となる
  • onActionがチェックした時のイベントになり、引数がその関数となる。
  • 今回初期値や、その後チェックされた場合にはiniファイルへとチェック状態を保存するようにしています。
チェックボックスのロジック

チェックボックスは、リボンが読み込まれた時にチェック状態を取得する為のgetPressedというアクション、そしてその後のチェックをした時のonActionの2つで構成されています。

今回、前述のXMLのうち、chksagakuonlyにあるアクションについて、以下に記してみました。それぞれ、chkSagaku_getPressed関数chkSagaku_onAction関数が担当しています。前者はリボン読み込み時の初回のみ、後者は随時実行されることになります。

  • リボンロード時にまず、ribbonmanが呼び出され、チェック状態をiniファイルから読み込み
  • チェック状態を取得したら、returnedValとして対象のチェックボックスへ値を返して上げる
  • チェック時はiniファイルへ書き込みをすると同時に、管理している変数へ保存する

実際にメインとなるルーチンで使う場合には、リボンの状態を取得するのではなく、この変数に格納されている値を利用して、条件分岐させプログラムを書く事になります。今のリボンのコントロールの状態を随時読み出すのは非常に厄介なので。

トグルボタンを利用する

チェックボックスの場合、見ての通り小さいコントロールなので、今オンなのかオフなのかわかりにくいという特性があります。なので、頻繁に切り替えて使うようなシーンでは、ミスを生む可能性が非常に高いです。そこで利用するのがトグルボタンコントロールで、オンオフ状態をスイッチのように切替える事を表現したコントロールになります。

今回このコントロールのオンオフ時に於ける「画像」と「ラベル」も同時に変更して、モードチェンジを実現してみたいと思います。結構複雑なロジックになります。

トグルボタンのXML

今回のケースでは、トグルの状態やトグル変更時の他に、その際のトグルのラベルや画像も動的に切り替える必要があるため殆どの項目にアクションを付けてあげる必要があります。

  • getLabelが動的にその時点でのラベルを取得して表示します。
  • getImageが動的にその時点でのボタンの画像を取得します
  • onActionがトグルボタンクリック時のアクション(関数)を指定しています。
  • getPressedがロード時に呼び出される関数です。
トグルボタンのロジック

トグルボタンのロジックはチェックボックスのロジックに加えて画像やラベルも切り替える必要がある点です。でないと、チェックボックスと変わらない。しかし、特にこの画像の切り替えなのですが、通常のプログラミングのように動的に切り替える事は出来ないので、変数を変更しリボンをリロードする事で実現しています。

  • 実際にプログラム内でトグルボタンの状態を利用して条件分岐する場合には、rbPressed変数の状態を利用して分岐させます。
  • 今回はフラグの状態によって、getButtonImageにて分岐し、LoadImageにて実際のpngファイルをロードしています。imagemsoも同様の処理で切り替える事が可能です。その場合はimagemsoの文字列だけを指定し、LoadImageは利用しません。
  • XML上のラベルでは、文字の位置調整で「
」という文字を使って改行位置を決定していましたが、VBA内でそれを実現する場合、単にvbLfを入れるだけで同じ事が実現可能です。そして文字を切り替えるためにreturndValで返しています。
  • onActionにてラベルの変更、画像の変更、状態の変更を行い、UpdateTheLabelにてリボンをリロード(InvalidateControlメソッド)させて反映し直しています。
  • 今回は状態の設定をiniファイルではなくsettingというテーブルを用意して、そこに状態を保存するようにしました。そのため、状態取得や読み書きはDlookupやDAOを使って読み書きしています。

アイコンに独自の画像を使う

Excelとは違い、Accessの場合にはimageMso以外の独自の画像を簡単に割り当てる事が出来ません。また、xlsmファイルとは違い画像ファイルをAccessファイル内に盛り込めないので、画像は同じフォルダ内にある画像を参照する形にする必要があります。

Accessに於けるボタンに独自のアイコンを割り当てる方法についてはこちらのサイトに詳しく解説がありますが、32bit版でなければ利用ができないコードになっています。しかし、海外のこちらのサイトにあるサンプルである「ExternalImages.zip」は64bit版にも対応したコードになっており、VBAにて外部イメージを使えるようにしています。

XML部分のコードもちょっと特殊。imagesで指定するのではなく、getImage属性にて指定し、画像ファイルを指定するのではなく、VBA内のサブプロシージャを参照するようになっています。ちょっと面倒ですね。シンプルな方法は以下の手順です。

  1. 以下のコードを標準モジュールを作って取り込んでおく
  2. XML内のimageMso=部分を「getImage="myButton_getImage" 」としておく。=以下は呼び出す関数名
  3. 呼び出す関数側は、対象の画像までのフルパスをsetするようにコードを記述する

図:オリジナルの画像を適用できた。

図:Accessでも独自のアイコンは使えるよ

関連リンク

コメントを残す

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

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