ロゴ(青) Excel/VBA Tips ロゴ(緑)

Tips23: CommandBar から リボンUI へ

        ( 2016/3/16 : 初版 , 2016/4/3 : 7項に回避方法を追記 , 2018/4/17 : 4-2 項を追記 , 2018/5/10 : 4-3 項を追記 ) 

1. リボンUI の定義情報 (XML) は何処に置く?
2. リボンUI と Excel バージョン
3. リボンUI を定義する XMLファイルについて
  3-2. リボンUI カスタマイズツール : Custom UI Editor
4. リボンメニューの定義
  4-2. 複数のアドインブックでカスタムタブを共有する    ( 2018/4/17 追記 )
  4-3. ウィンドウ 幅を縮小 した際の 「表示幅不足」 への対策    ( 2018/5/10 追記 )
5. 右クリックメニューの定義( リボンUI )  --- Excel2010以降 ---
6. 右クリックメニューの定義( CommandBar )  --- Excel2007用 ---
7. ノーマル ワークブック  と  アドイン ワークブック ( 呼び出しマクロ名の重複 )
8. リボンUI にしたい。でも xls の呪縛が…。その対処法は…

[ この場所へのリンク ]

1. リボンUI の定義情報(XML)は何処に置く?

わたしのアドインソフトでは、Excel2007がリリースされ、ユーザーインターフェースがコマンドバー
メニューからリボンに移行した後も、ずっとコマンドバーによるメニュー構築のままにしていました。

その理由は、リボンそのものが『何か、良く判らん』というのもありますが、一番の理由、それは・・・

      『 リボンのカスタマイズには、XML定義が必要

      この説明を見て、単純に
            xlam のアドイン本体とは別に
            XML のファイルを一緒に配布しなきゃいけない

      と思い込んでしまっていた事でした。そうすると、
            アドイン配布には
                ・ インストーラーを用意する
                ・ 手作業での個々のファイル( xlam , XML ) のコピー先を説明する
            の、どちらかが必要になってくるのだろう。

      という風に考え、その結果、
            そんなの、
            面倒くせ〜〜〜、リボンなんて止〜めた!
            CommandBar メニューのままにする!

      という方針になってしまいました。

ということでした。

ところが、今回、ようやく重い腰を上げて、リボンの勉強を始めたところ、大きな勘違いをしていた
ことに気付きました。それは、

( 誤 ) : リボン定義のXMLファイル と エクセルファイル( xlsx, xlsm, xlam ) は
          別個のファイル。
      ↓
( 正 ) : リボン定義のXMLファイル は エクセルファイル(xlsx, xlsm, xlam) の
          実態である ZIPファイルの中に収録されている構成ファイルのひとつ



( 誤 ) : リボン定義のXMLファイル と エクセルファイルの2つを配布する必要あり。
      ↓
( 正 ) : リボン定義のXML は エクセルファイルの中に梱包されているものなので、
          従来通りにエクセルファイルのみ配布すれば良い。なお、ユーザーアイコン
          を使う場合には、その画像ファイルも一緒に梱包される

ということです。

勘違いしたまま放っといて、間違いに気付くのに10年も掛かったとは、我ながら、なんともマヌケ
な話です。

そして、いざチャレンジしてみると、さすがに最初は戸惑いもありましたが、一度作り上げて、その
基本を理解した後では、「意外に簡単にカスタマイズできるものだな」という感がします。「10年、
勿体ない事をしたな」という思いです。

ここでは、kt関数アドインのリボン化に際して、気付いた事・疑問に思った事などを実例を基に
紹介します。


[ この場所へのリンク ]

2. リボンUI と Excel バージョン

リボンUI の機能と Excel バージョンの関係をまとめると以下のようになります。

--- Excel2003 以前 ---
    (a) ファイル形式は 97-2003形式の xls , xla 。
    (b) メニュー構築は全て CommandBar のみで構築。

--- Excel2007 ---
    (a) 2007形式 ( xlsx , xlsm , xlam ) の新ファイル形式を導入。
        従来の 97-2003形式( xls , xla )も引き続き利用可。
    (b) リボンUI の導入(CommandBar によるメニュー構築も引き続き利用可)。
    (c) 2007形式 ( xlsx , xlsm , xlam ) でのみ、リボンUI のカスタマイズが可能。
        但し、右クリックメニューのカスタマイズは不可。
    (d) CommandBar によるメニューは全てアドインタブに収録。
    (e) 右クリックメニューのカスタマイズには、引き続き CommandBar によるメニュー構築が必要。

--- Excel2010 ---
    (a) 大きな機能拡張が施され、右クリックメニューのカスタマイズもリボンUI で可能になる。
        なお、CommandBar によるものも引き続き右クリックメニューに組込まれる ( リボンUI に
        よるものと併存 )。
    (b) ひとつのワークブック内に、Excel 2007用 と Excel 2010用のリボン定義を「別々 且つ
        一緒」に収録する事ができる。
    (c) これにより、ひとつのワークブックを Excel 2007 / 2010 で開いた場合に
            Excel 2007 …… Excel 2007までのリボン機能のみ
            Excel 2010 …… Excel 2010で追加された機能も活用したリボン機能
        という風に分けて処理する事が可能。

--- Excel2013 以降 ---
    (a) SDI ( Single Document Interface ) へ移行。リボンUI の定義方法はExcel2010と同じ
    (b) 複数ワークブックを開いている際に各々のウィンドウメニューに対してカスタマイズを確実に
        反映させるためには、CommandBar によるメニュー構築を捨ててリボンUI へ完全に移行
        する事が望ましい。
    (c) SDI 環境(Excel2013 以降) で CommandBar によるメニュー作成を行なう場合の注意点を
        下記記事に整理してありますので参考にしてください」。
            [ Tips27: Excel 2013/2016 アドインブック によるCommandBar メニューとアドインタブ ]


[ この場所へのリンク ]

3. リボンUI を定義するXMLファイルについて

サンプルの RibbonTest.xlsm を例に、リボンUIを定義するXMLファイルが、どのように構成されて
いるか説明します。
      [ サンプルファイルRibbonTest.xlsm ]

RibbonTest.xlsmでは、下図のExcel 2007用/Excel 2010用のリボンUI を定義しています。


  右クリックメニューは改頁プレビュー用もカスタマイズ


  Excel2007では右クリックメニューは CommandBar



RibbonTest.xlsm の構成ファイルを展開すると下図のようになっています。
なお、ワークシート・VBAマクロなどは xl フォルダ内に収録されています。

  (1) customUI14.xml …… リボンUI 定義 (Excel2010 以降用), 右クリックメニュー定義も含む
  (2) customUI.xml  …… リボンUI 定義 (Excel2007 用)
  (3) _rels/customUI14.xml.rels …… 参照ファイルのID定義 (customUI14.xml 用)
  (4) _rels/customUI.xml.rels  …… 参照ファイルのID定義 (customUI.xml 用)
  (5) images/Icon_Cal_Large.png …… 万年暦アイコン
  (6) Images/Icon_Hata_Large.png …… 旗アイコン

上記のように、リボンUI定義ファイルには
      ・ customUI14 シリーズ ( Excel 2010 以降用 )
      ・ customUI    シリーズ ( Excel 2007 用 )
の2グループがあり、以下のような使い分けができます。

「customUI シリーズ」のみ収録
    Excel 2007以降の全て ( Excel2007, 2010, 2013 … ) に反映されます。

「customUI14 シリーズ」のみ収録
    Excel 2010以降の全て ( 2010, 2013 … ) に反映されます。
    Excel 2007 には反映されません。

「customUI シリーズ + customUI14 シリーズ」を一緒に収録
    Excel 2007
          customUI シリーズの定義に基づいて反映されます。
    Excel 2010以降の全て( 2010, 2013 … )
          customUI14 シリーズの定義に基づいて反映されます。


「customUI シリーズ」「customUI14 シリーズ」ではファイル名だけでなく、その XML定義の先頭
に記述する宣言ステートメントも異なります。

----- customUI.xml -----
<?xml version="1.0" encoding="utf-8"?>
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" >

----- customUI14.xml -----
<?xml version="1.0" encoding="utf-8"?>
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" >



----- _rels/customUI.xml.rels , _rels/customUI14.xml.rels -----
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
  <Relationship Id="Icon_Cal_Large"
    Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
    Target="images/Icon_Cal_Large.png"/>
  <Relationship Id="Icon_Hata_Large"
    Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
    Target="images/Icon_Hata_Large.png"/>
</Relationships>

参照ファイルの ID定義用 XMLでは 「customUI シリーズ」 「customUI14 シリーズ」 の違いはありません。
( 「customUI14 シリーズ」 でも 2006 です )




[ この場所へのリンク ]

3-2. リボンUI カスタマイズツール : Custom UI Editor

これらの リボンUI 定義ファイルの作成は、リボンUI カスタマイズ用のツール「Custom UI Editor
Tool
」を利用すれば簡単に行えます。[ 拡張子をZIPに変更⇒ZIP解凍⇒XML定義編集⇒ZIP圧縮
⇒拡張子を元に戻す] といった面倒な手順を踏む必要がありません。xlsm 等のエクセルファイルの
ままでリボンUI のXML定義を編集できます


ツールのインストール方法/利用方法の詳細は下記をご覧ください。
      【初心者備忘録 > リボン関連】  
      http://www.ka-net.org/ribbon.html

なお、「Custom UI Editor Tool」では、ツール上での編集で日本語が使えません (最新版では使えます)。
対処方法については下記をご覧ください。
      【初心者備忘録 > リボン関連 > Custom UI Editor Toolの弱点
      http://www.ka-net.org/ribbon/ri05.html
      最新版(Ver 4.0) の入手方法


もうひとつ、「Custom UI Editor Tool」で気付いた点として、「customUI シリーズ」 「customUI14
シリーズ」の両方で同じ画像ファイルをアイコンとして使う場合、一方の画像ファイルが 連番を
付けて別名保存 されてしまいます(2つの画像ファイルに同じIDが振られます)。



----- _rels/customUI.xml.rels -----
<Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
      Target="images/Icon_Cal_Large.png" Id="Icon_Cal_Large" />


----- _rels/customUI14.xml.rels -----
<Relationship Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"
      Target="images/Icon_Cal_Large0.png" Id="Icon_Cal_Large" />


そのまま、2ファイルとしておいても構いませんが、無駄に思われるなら、ZIP構成ファイルを開き、
連番付きの画像ファイルを削除して、Terapad 等のエディターで Target属性のファイル名を修正
してください。


[ この場所へのリンク ]

4. リボンメニューの定義

まずは、ウィンドウ上部のリボンメニューの定義について、サンプルに基づいて説明します。


このサンプルでは、アイコンとして、組み込みアイコンの他に独自画像を2つ使用しています。
                           
( Icon_Hata_Large.png )   ( Icon_Cal_Large.png )


アイコン画像には Largeサイズ(32×32)
と Normalサイズ(16×16) の2種が指定
できますが、このサンプルでは Largeサイ
ズを使います。


ここで定義するリボンメニューは「customUI シリーズ」 「customUI14 シリーズ」ともに同じ
内容です(ただし、先頭の xmlsns 属性の値は異なります。前項を参照)。

----- customUI.xml -----
<?xml version="1.0" encoding="utf-8"?>
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" >
  <ribbon>
    <tabs>
      <tab id="TestTab1" label="ktFuncAddin">
        <group id="TestGroup1" label="ktFuncAddin Tools">

          <button id="TestButton1" label="Calendar Form"
                  onAction="RibbonTest_onAction"
                  size="large" imageMso="HeaderFooterCurrentDate" />

          <button id="TestButton2" label="Clock Form"
                  onAction="RibbonTest_onAction"
                  size="large" imageMso="HeaderFooterCurrentTimeInsert" />

          <button id="TestButton3" label="Holiday List"
                  onAction="RibbonTest_onAction"
                  size="large" image="Icon_Hata_Large" />

          <button id="TestButton4" label="Year Calendar"
                  onAction="RibbonTest_onAction"
                  size="large" image="Icon_Cal_Large" />

          <button id="TestButton5" label="Help"
                  onAction="RibbonTest_onAction"
                  size="large" imageMso="Help" />
        </group>
      </tab>
    </tabs>
  </ribbon>
</customUI>


<tabs> <tab> <group> の関係は下図の通りです。



-- id 属性 --
個々のオブジェクトの識別名を指定します。

-- label 属性 --
個々のオブジェクトの表示名を指定します。
tab ならば タブ名(ホーム・挿入・ページレイアウト など)
group ならば グループ名(クリップボード・フォント など)
button ならば ボタンキャプション名(貼り付け など)


<customUI> 〜 </customUI> 要素
この間にリボン定義を記述します。
先に説明したように、customUI.xml と customUI14.xml では、xmlns 属性に指定する値が異
なります。
(注) customUI14.xml でも <customUI> 〜 </customUI> です。 '14' は付きません。

<ribbon> 〜 </ribbon> 要素
この間に記述される内容が 「ホーム」「挿入」などのトップメニューが並ぶ リボンUI の中に挿入
されます。

<tabs> 〜 </tabs> 要素
この中に タブ定義を記述します。
<tab> 〜 </tab>で括ったものを複数指定可能です。

<tab> 〜 </tab> 要素
この中にタブ内に配置する個々のコントロール定義を記述します。
label属性に指定した名称がリボン上部のタブ切り換えボタンに表示されます。
<tab …… insertAfterMso="TabHome"> という風に記述すると [ ホーム ] タブの次に挿入
されます。挿入位置を指定する属性には他に「insertAfterQ , insertBeforeMso , insertBeforeQ」
があります。位置指定を何も指定しなければ【一番後ろ】に挿入されます。

<group> 〜 </group> 要素
タブ内のコントロールをグループ分けします。
label属性に指定した名称がリボン下部にグループ名として表示されます。

<button> 要素
-- id 属性 --
コントロールの識別名を指定します。
onAction などのインターフェースルーチンでは、引数 『 control As IRibbonControl 』 で
コントロールオブジェクトが渡されますので、control.ID として、ここで指定したコントロール名
を利用できます。

-- label 属性 --
ボタンキャプションを指定します。半角空白位置で改行されます。
日本語キャプションが意図しない位置で改行されてしまう場合には下記を参考に対処して
ください。
      【初心者備忘録 > リボン関連 > ラベルが勝手に改行されてしまうときの対処法
      http://www.ka-net.org/ribbon/ri77.html

-- size 属性 --
アイコンの大きさを指定します。
大きいアイコン(32×32)の場合は "large" を指定します。
省略すると小さいアイコン(16×16)になります。

-- imageMso 属性 --
組込みアイコンの名称を指定します。
大きいアイコン・小さいアイコンで名称は同じです。
組込みアイコンは下記を利用すれば調べられます。
      【初心者備忘録 > Office関連
      http://www.ka-net.org/office.html
          ・ Office 2010 関連情報 > アイコン一覧(Office 2010)
          ・ 公開ソフト > Office 2007 Icon Viewer(Office 2007)
                            Office 2010 Icon Viewer(Office 2010)
                            Excel 2010 Icon Viewer(Excel 2010)

-- image 属性 --
独自の画像ファイルをアイコンとして使用する場合に _rels/customUI.xml.rels または
_rels/customUI14.xml.rels で定義してある識別名を指定します。

-- onAction 属性 --
コントロールをクリックした際に呼び出すインターフェースプロシージャーのマクロ名を記述
します。標準モジュールに下記のように用意します。このプロシージャーはワークブックの
外(Excel のリボンシステム)から呼び出されるものなので [ Public ] で定義します。

Public Sub マクロ名(control As IRibbonControl)

(参考) onAction などのイベントプロシージャー・コールバックプロシージャー の引数定義は
          コントロールによって異なりますので、下記を参照してください。
          2007 Office Fluent リボンをカスタマイズする (開発者向け) (パート 3/3)
          https://msdn.microsoft.com/ja-jp/library/aa722523

コントロールごとに対応するマクロを用意して各々のマクロ名を指定しても良いですが、サン
プルのように、全コントロールで共通マクロを指定して control.ID によって分岐するという方
法もあります。

Public Sub RibbonTest_onAction(control As IRibbonControl)
  Select Case control.ID
    '--- Ribbon Menu ---
    Case "TestButton1": Call CalendarForm_Proc1
    Case "TestButton2": Call ClockForm_Proc1
    Case "TestButton3": Call HolidayList_Proc
    Case "TestButton4": Call YearCalendar_Proc
    Case "TestButton5": Call Help_Proc
  End Select
End Sub



[ この場所へのリンク ]

4-2. 複数のアドインブックでカスタムタブを共有する  ( 2018/4/17 追記 )

下記は、kt関数アドイン / kt電話郵便アドイン という 2つのアドインブックで1つのタブ
(AddinBox メニュー)を共有
している例です。片方のアドインのみをアドイン登録している
状態では [タブ:AddinBox メニュー] には各々のメニューのみが表示されます。2つのアド
インを共にアドイン登録すると、1つのタブを共有して下記のように表示されます。



このように、複数のアドインブックでカスタムタブを共有する場合には『XML名前空間
という定義を利用します。

2つのアドインブックのリボン定義は下記のようになっています。
  ---- kt関数Addin.xlam の リボン定義 ----

  <customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" xmlns:nsAddinBox="AddinBox" >
    <ribbon>
      <tabs>
        <tab idQ="nsAddinBox:AddinBoxTab"  label="AddinBox メニュー">
          <group id="ktFuncGroup" label="kt関数アドイン (Ver 5.00)">


  ---- kt電話郵便Addin.xlam の リボン定義 ----

  <customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" xmlns:nsAddinBox="AddinBox" >
    <ribbon>
      <tabs>
        <tab idQ="nsAddinBox:AddinBoxTab"  label="AddinBox メニュー">
          <group id="ktTelPostGroup" label="kt電話郵便アドイン (Ver 3.00)">


ここでは、「customUI 要素」にて "AddinBox" という名前の「名前空間(Name Space)」
両方のアドインブックで同じように定義
し、その名前空間接頭辞を "nsAddinBox"
しています。

次に、「tab 要素」にてメニューを収容するタブを指定しますが、『名前空間接頭辞 + コロン( : )
+ ローカルID』という書き方によって、両方のアドインブックで「同一のタブ」を指し示します。
尚、名前空間接頭辞付きの修飾指定の場合には 「id 属性」の代わりに「idQ 属性」を使用します。


[ この場所へのリンク ]

4-3. ウィンドウ幅を縮小 した際の 「表示幅不足」 への対策  ( 2018/5/10 追記 )

リボンに沢山のコマンドを作成すると、当然ですが、それに見合った「表示幅」が必要になります。
エクセルを全画面表示にしている場合には問題ないでしょうが(全画面でも表示しきれないような
リボン設計は行わないでしょうから)、ウィンドウを縮小した場合に『表示しきれない』というケースも
有り得ます。 実際にウィンドウを縮小してみると下図のようになります。


この「四角に丸アイコン」では殺風景なので、代わりのアイコンを表示するようにしてみます。
下記のように <group>要素に imageMso または image 属性を指定すれば下図のようになります。

  ---- リボンアタッチメント for Addinbox の リボン定義 ----

  <customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" >
    <ribbon>
      <tabs>
        <tab id="AddinBoxTab" label="AddinBox ribbon">
          <group id="ktFuncGroup" label="kt関数アドイン by RibbonAttachment" imageMso="FunctionWizard" >
             :
          </group>

          <group id="ktTelPostGroup" label="kt電話郵便アドイン by RibbonAttachment" image="Icon_YubinFaceTel_Large" >
             :
          </group>





Excel 自体のリボンでは、ウィンドウ縮小時に 「コマンド名を消して、アイコンだけ」とすることで表示に
必要な幅を小さくしています。

カスタムリボンに同じ動きをさせるには、<group>要素へ下記のように autoScale 属性を指定します。
ただし、この機能は Excel 2010 以降でのみ利用できます ( Excel2007 では不可 )。

  ---- リボンアタッチメント for Addinbox の リボン定義 ( customUI14.xml のみ指定可 ) ----

  <customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" >
    <ribbon>
      <tabs>
        <tab id="AddinBoxTab" label="AddinBox ribbon">
          <group id="ktFuncGroup" label="kt関数アドイン by RibbonAttachment" autoScale="true" >
             :
          </group>

          <group id="ktTelPostGroup" label="kt電話郵便アドイン by RibbonAttachment" autoScale="true" >
             :
          </group>






[ この場所へのリンク ]

5. 右クリックメニューの定義(リボンUI)  --- Excel2010以降 ---

標準画面と改頁プレビュー画面の2つの【セル】右クリックメニューをカスタマイズします。




リボンUIによる右クリックメニューのカスタマイズは Excel2010 以降で利用できます。つまり、
「customUI14 シリーズ」にて定義します。
  メインメニュー 右クリックメニュー
Excel 2007 「customUI シリーズ」 CommandBar によって動的作成
Excel 2010 「customUI シリーズ」  or
「customUI14 シリーズ」
「customUI14 シリーズ」

補 : 「customUI シリーズ」 と 「customUI14 シリーズ」の両方が定義されている場合、
      Excel2007では「customUI シリーズ」が読み込まれ、
      Excel2010では「customUI14 シリーズ」が読み込まれます。


----- customUI14.xml -----
<?xml version="1.0" encoding="utf-8"?>
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"
          onLoad="RibbonTest_onLoad" >
  <ribbon>
    <tabs>
      <tab id="TestTab1" label="ktFuncAddin">
        <group id="TestGroup1" label="ktFuncAddin Tools">

          <button id="TestButton1" label="Calendar Form" onAction="RibbonTest_onAction"
                  size="large" imageMso="HeaderFooterCurrentDate" />

          <button id="TestButton2" label="Clock Form" onAction="RibbonTest_onAction"
                  size="large" imageMso="HeaderFooterCurrentTimeInsert" />

          <button id="TestButton3" label="Holiday List" onAction="RibbonTest_onAction"
                  size="large" image="Icon_Hata_Large" />

          <button id="TestButton4" label="Year Calendar" onAction="RibbonTest_onAction"
                  size="large" image="Icon_Cal_Large" />

          <button id="TestButton5" label="Help" onAction="RibbonTest_onAction"
                  size="large" imageMso="Help" />
        </group>
      </tab>
    </tabs>
  </ribbon>

  <contextMenus>
    <contextMenu idMso="ContextMenuCell">
      <menu id="contextCellTest" label="ktFuncAddin">

        <checkBox id="contextCellTestCheckBox1" label="Popup on Cell"
                  getPressed="contextCheckBoxTest_getPressed"
                  onAction="contextCheckBoxTest_onAction" />

        <menuSeparator id="contextCellTestSeparator1" />

        <button id="contextCellTestButton1" label="Calendar Form"
                onAction="RibbonTest_onAction" imageMso="HeaderFooterCurrentDate" />

        <button id="contextCellTestButton2" label="Clock Form"
                onAction="RibbonTest_onAction" imageMso="HeaderFooterCurrentTimeInsert" />

        <button id="contextCellTestButton3" label="Calendar Mark"
                onAction="RibbonTest_onAction" imageMso="DrawingNewClassic" />
      </menu>
    </contextMenu>

    <contextMenu idMso="ContextMenuCellLayout">
      <menu id="contextCellLayoutTest" label="ktFuncAddin">

        <checkBox id="contextCellLayoutTestCheckBox1" label="Popup on Cell"
                  getPressed="contextCheckBoxTest_getPressed"
                  onAction="contextCheckBoxTest_onAction" />

        <menuSeparator id="contextCellLayoutTestSeparator1" />

        <button id="contextCellLayoutTestButton1" label="Calendar Form"
                onAction="RibbonTest_onAction" imageMso="HeaderFooterCurrentDate" />

        <button id="contextCellLayoutTestButton2" label="Clock Form"
                onAction="RibbonTest_onAction" imageMso="HeaderFooterCurrentTimeInsert" />

        <button id="contextCellLayoutTestButton3" label="Calendar Mark"
                onAction="RibbonTest_onAction" imageMso="DrawingNewClassic" />
      </menu>
    </contextMenu>
  </contextMenus>
</customUI>


<customUI> 〜 </customUI> 要素
この間にリボン定義を記述します。先に説明したように、customUI.xml と customUI14.xml では、
xmlns 属性に指定する値が異なります。

-- onLoad 属性 --
このリボン定義を含むワークブックがオープンされた際に実行される初期設定プロシージャの
マクロ名を記述します。標準モジュールに下記のように用意します。このプロシージャーはワークブックの
外(Excel のリボンシステム)から呼び出されるものなので [ Public ] で定義します。

Public Sub マクロ名(ribbon As IRibbonUI)

(参考) [ ribbon As IRibbonUI ] という引数は、ここでカスタマイズ定義する リボンUI 全体 (*1) の
          オブジェクトを指し示すオブジェクト変数です。例えば、アイコン・ポップアップメニューの構造
          などを動的に変更する場合に、変更後の内容で更新/表示(Invalidate , InvalidateControl
          メソッド 等)する場合に必要となります。 下記に掲載されている利用例を参考にして下さい。
                【初心者備忘録 > リボン関連】  http://www.ka-net.org/ribbon.html
   (*1)  リボンメニュー、右クリックメニュー、QAT ( Quick Access Toolbar )
          Backstageビュー ( ファイル タブ の画面 ) など

このサンプルでは、チェックボックスの初期値(True)の設定に利用しています。
なお、このサンプルでは [ ribbon As IRibbonUI ] は使用していません。

<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui"
          onLoad="RibbonTest_onLoad" >



Private blnPopupPosition As Boolean    'True:セル位置に表示 False:中央に表示

Public Sub RibbonTest_onLoad(ribbon As IRibbonUI)    'リボンの初期処理
  blnPopupPosition = True
End Sub


<ribbon> 〜 </ribbon> 要素
この間に記述される内容が 「ホーム」「挿入」などのトップメニューが並ぶ リボンUI の中に挿入
されます。このサンプルでは customUI.xml の内容と同じです。

<contextMenus> 〜 </contextMenus> 要素
右クリックメニューはオブジェクト(セル・行・列・画像・グラフ etc )ごとに用意されています。各々の
メニューに対して <contextMenu> でカスタマイズします。

<contextMenu> 〜 </contextMenu> 要素
この間に右クリックメニューのカスタマイズ定義を記述します。

-- idMso 属性 --
対象のオブジェクトを示す組込み識別子を指定します。
  ・ 標準画面のセルの右クリックメニュー               :  "ContextMenuCell"
  ・ 改頁プレビュー画面のセルの右クリックメニュー  :  "ContextMenuCellLayout"

様々な右クリックメニューの識別子を調べる場合には下記で紹介しているツールが便利です。
初心者備忘録 > リボン関連
      > 右クリックメニューをカスタマイズする際に役立つアドイン(Office 2010)
      http://www.ka-net.org/ribbon/ri61.html

<menu> 〜 </menu> 要素
この間にポップアップメニューを構成するコントロール群を記述します。

<menuSeparator> 要素
ポップアップメニュー内の分離腺です。

<button> 要素
前項 「4. リボンメニューの定義」 を参照。


Public Sub RibbonTest_onAction(control As IRibbonControl)
  Select Case control.ID
    '--- Ribbon Menu ---
    Case "TestButton1": Call CalendarForm_Proc1
    Case "TestButton2": Call ClockForm_Proc1
    Case "TestButton3": Call HolidayList_Proc
    Case "TestButton4": Call YearCalendar_Proc
    Case "TestButton5": Call Help_Proc

    '--- Context Menu (標準 & 改頁プレビュー) ---
    Case "contextCellTestButton1", "contextCellLayoutTestButton1"
      If (blnPopupPosition = True) Then
        Call CalendarForm_Proc2    '【右クリックセル位置に表示】
      Else
        Call CalendarForm_Proc1    '【中央に表示】
      End If
    Case "contextCellTestButton2", "contextCellLayoutTestButton2"
      If (blnPopupPosition = True) Then
        Call ClockForm_Proc2    '【右クリックセル位置に表示】
      Else
        Call ClockForm_Proc1    '【中央に表示】
      End If
    Case "contextCellTestButton3", "contextCellLayoutTestButton3"
      Call CalendarMarkForm_Proc
  End Select
End Sub


(おまけ)
    このサンプルでは、右クリックメニューでの 『セル位置に表示 or 中央に表示』 指示によって、実際に UserForm の
    表示位置を切り換えるという マクロ は掲載していません(MsgBox 案内で代用)。
    表示位置の切り換えを実装する場合には ktCell2Position 関数というものを利用します。詳細は下記参照。
          Tips 22: セル位置をUserForm表示位置に変換する


<checkBox> 要素
-- getPressed 属性 --
チェックボックスの状態(オン or オフ)を指定するコールバックプロシージャーのマクロ名を記述します。
標準モジュールに下記のように用意します。このプロシージャーはワークブックの外(Excel のリボンシス
テム)から呼び出されるものなので [ Public ] で定義します。

Public Sub マクロ名(control As IRibbonControl, ByRef returnValue)


オブジェクトの右クリックによって、右クリックメニューが表示される直前に指定されたマクロが呼び出さ
れますので、引数を通して、チェックボックスのオン/オフ値を指定します。

<checkBox …… getPressed="contextCheckBoxTest_getPressed" ……/>



Private blnPopupPosition As Boolean    'True:セル位置    False:中央

Public Sub contextCheckBoxTest_getPressed _
            (control As IRibbonControl, ByRef returnValue)
  Select Case control.ID
    Case "contextCellTestCheckBox1", "contextCellLayoutTestCheckBox1"
      returnValue = blnPopupPosition
  End Select
End Sub


-- onAction 属性 --
チェックボックス コントロールをクリックした際に呼び出すインターフェースプロシージャーのマクロ名を
記述します。標準モジュールに下記のように用意します。このプロシージャーはワークブックの外(Excel
のリボンシステム)から呼び出されるものなので [ Public ] で定義します。

Public Sub マクロ名(control As IRibbonControl, ByRef pressed As Boolean)


引数 pressed でクリック後のチェックボックスの値(オン/オフ)が受け取れます。

<checkBox …… onAction="contextCheckBoxTest_onAction" />



Private blnPopupPosition As Boolean    'True:セル位置    False:中央

Public Sub contextCheckBoxTest_onAction _
            (control As IRibbonControl, ByRef pressed As Boolean)
Dim strStatus As String

  Select Case control.ID
    Case "contextCellTestCheckBox1", "contextCellLayoutTestCheckBox1"
      blnPopupPosition = pressed

      If (blnPopupPosition = True) Then
        strStatus = "セル位置にポップアップ"
      Else
        strStatus = "画面中央にポップアップ"
      End If
      MsgBox "[ " & strStatus & " ] に設定変更しました。  ", _
             vbInformation + vbOKOnly, "RibbonTest/右クリックメニュー設定変更"
  End Select
End Sub


(参考) onAction などのイベントプロシージャー・コールバックプロシージャー の引数定義は
          コントロールによって異なりますので、下記を参照してください。
          2007 Office Fluent リボンをカスタマイズする (開発者向け) (パート 3/3)
          https://msdn.microsoft.com/ja-jp/library/aa722523

          その他に参考になるリンク集が下記にまとめられています。
          【初心者備忘録 > リボン関連 > リボン関連のリンク
          http://www.ka-net.org/ribbon/link.html


[ この場所へのリンク ]

6. 右クリックメニューの定義( CommandBar )  --- Excel2007用 ---

Excel2007では、右クリックメニューをリボンUI でカスタマイズできませんので、従来通りに
CommandBar コントロールでカスタマイズします(下記マクロの解説は省略)。


--- ThisWorkbook モジュール ---
Private Sub Workbook_Open()
  If (Val(Application.Version) = 12) Then
    Call XL2007用コンテキストメニュー作成      'Temporary
  Else
    'Excel2010以降では右クリックメニューもリボンで作成する
  End If
End Sub


Private Sub Workbook_BeforeClose(Cancel As Boolean)
  If (Val(Application.Version) = 12) Then
    Call XL2007用コンテキストメニュー削除
  Else
    'Excel2010以降では右クリックメニューもリボンで作成する
  End If
End Sub



--- 標準モジュール ---
'================================================================
'  Excel2007用 右クリックメニューの作成 ( Temporary = True )
'================================================================
Public Sub XL2007用コンテキストメニュー作成()
Dim CB1 As CommandBar
Dim CB2 As CommandBar
Dim CB_Popup1 As CommandBarControl
Dim CB_Popup2 As CommandBarControl

  On Error Resume Next
  Call prv_GetCellMenu(CB1, CB2)

  Set CB_Popup1 = CB1.Controls.Add(Type:=msoControlPopup, Temporary:=True)
  Set CB_Popup2 = CB2.Controls.Add(Type:=msoControlPopup, Temporary:=True)

  Call XL2007用コンテキストサブメニュー作成(CB_Popup1)
  Call XL2007用コンテキストサブメニュー作成(CB_Popup2)

  Set CB_Popup1 = Nothing
  Set CB_Popup2 = Nothing
  Set CB1 = Nothing
  Set CB2 = Nothing
End Sub


Private Sub XL2007用コンテキストサブメニュー作成(ByRef CB_Popup As CommandBarControl)
Dim MyCBCtrl As CommandBarControl

  On Error Resume Next
  CB_Popup.Caption = "ktFuncAddin"

  Set MyCBCtrl = CB_Popup.Controls.Add(Type:=msoControlButton, Temporary:=True)
  With MyCBCtrl
    .Caption = "Popup on Cell"
    .OnAction = "XL2007用コンテキストメニュー変更"
    .FaceId = 1848    '[チェックボックス:オン]
  End With

  Set MyCBCtrl = CB_Popup.Controls.Add(Type:=msoControlButton, Temporary:=True)
  With MyCBCtrl
    .Caption = "Calendar Form"
    .OnAction = "CalendarForm_Proc2"
    .FaceId = 125
    .BeginGroup = True    '分離線
  End With

  Set MyCBCtrl = CB_Popup.Controls.Add(Type:=msoControlButton, Temporary:=True)
  With MyCBCtrl
    .Caption = "Clock Form"
    .OnAction = "ClockForm_Proc2"
    .FaceId = 33
  End With

  Set MyCBCtrl = CB_Popup.Controls.Add(Type:=msoControlButton, Temporary:=True)
  With MyCBCtrl
    .Caption = "Calendar Mark"
    .OnAction = "CalendarMark_Proc"
    .FaceId = 16
  End With

  Set MyCBCtrl = Nothing
End Sub


Public Sub XL2007用コンテキストメニュー変更()
Dim CB1 As CommandBar
Dim CB2 As CommandBar
Dim CB_Popup1 As CommandBarControl
Dim CB_Popup2 As CommandBarControl
Dim blnCheckBox As Boolean

  On Error Resume Next
  Call prv_GetCellMenu(CB1, CB2)

  Set CB_Popup1 = CB1.Controls("ktFuncAddin")
  Set CB_Popup2 = CB2.Controls("ktFuncAddin")

  With CB_Popup1.Controls("Popup on Cell")
    If (.FaceId = 1848) Then
      blnCheckBox = True
    Else
      blnCheckBox = False
    End If
  End With

  If (blnCheckBox = True) Then
    'ON→OFF; 画面中央に表示
    With CB_Popup1
      .Controls("Popup on Cell").FaceId = 0    '[チェックボックス:オフ]
      .Controls("Calendar Form").OnAction = "CalendarForm_Proc1"
      .Controls("Clock Form").OnAction = "ClockForm_Proc1"
    End With

    With CB_Popup2
      .Controls("Popup on Cell").FaceId = 0    '[チェックボックス:オフ]
      .Controls("Calendar Form").OnAction = "CalendarForm_Proc1"
      .Controls("Clock Form").OnAction = "ClockForm_Proc1"
    End With

    MsgBox "[ 画面中央にポップアップ ] に設定変更しました。    ", _
            vbInformation + vbOKOnly, "RibbonTest/右クリックメニュー設定変更"
  Else
    'OFF→ON; セル位置に表示
    With CB_Popup1
      .Controls("Popup on Cell").FaceId = 1848    '[チェックボックス:オン]
      .Controls("Calendar Form").OnAction = "CalendarForm_Proc2"
      .Controls("Clock Form").OnAction = "ClockForm_Proc2"
    End With

    With CB_Popup2
      .Controls("Popup on Cell").FaceId = 1848    '[チェックボックス:オン]
      .Controls("Calendar Form").OnAction = "CalendarForm_Proc2"
      .Controls("Clock Form").OnAction = "ClockForm_Proc2"
    End With

    MsgBox "[ セル位置にポップアップ ] に設定変更しました。    ", _
            vbInformation + vbOKOnly, "RibbonTest/右クリックメニュー設定変更"
  End If

  Set CB_Popup1 = Nothing
  Set CB_Popup2 = Nothing
  Set CB1 = Nothing
  Set CB2 = Nothing
End Sub


Public Sub XL2007用コンテキストメニュー削除()
Dim CB1 As CommandBar
Dim CB2 As CommandBar

  On Error Resume Next
  Call prv_GetCellMenu(CB1, CB2)

  CB1.Controls("ktFuncAddin").Delete
  CB2.Controls("ktFuncAddin").Delete

  Set CB1 = Nothing
  Set CB2 = Nothing
End Sub



'標準/改頁プレビューの2つの[ Cellメニュー ]を取得する
Private Sub prv_GetCellMenu(ByRef argCellMenu1 As CommandBar, _
                            ByRef argCellMenu2 As CommandBar)
Dim cnt As Integer
Dim wkCB As CommandBar

  Set argCellMenu1 = Nothing
  Set argCellMenu2 = Nothing

  cnt = 0
  For Each wkCB In Application.CommandBars
    If (UCase(wkCB.Name) = "CELL") Then
      cnt = cnt + 1
      If (cnt = 1) Then
        Set argCellMenu1 = wkCB
      Else
        Set argCellMenu2 = wkCB
        Exit For
      End If
    End If
  Next wkCB
End Sub



[ この場所へのリンク ]

7. ノーマル ワークブック  と  アドイン ワークブック ( 呼び出しマクロ名の重複 )

--- ノーマル ワークブック ( xlsx , xlsm )  ---
カスタマイズした リボンUI は、そのワークブックが
      ・ アクティブな状況でのみ表示され操作可
      ・ アクティブでない状況では非表示となり操作不可
となります。

カスタマイズしたリボンUI を持つ複数のノーマルワークブックを同時に開いている場合、
その時々でアクティブなワークブックのリボンのみが表示され操作可となります(他のワーク
ブックのリボンは非表示となります)。


--- アドイン ワークブック ( xlam ) ---
カスタマイズした リボンUI は、常に表示され操作可です。
一緒にオープンしている他のどのワークブックからでも操作可です。

カスタマイズしたリボンUI を持つ複数のアドインワークブックを同時に開いている場合、
その全てのリボンUI が表示されており、操作可です。


--- イベント/コールバック プロシージャー の名前が他ワークブックと同じ ---
サンプルを基に、以下のような「ありふれたマクロ名を持つ」定義をそのままコピーして、

 <customUI … onLoad="Ribbon_onLoad" >
 <button … onAction="Ribbon_onAction" … />
 <checkBox … getPressed="contextCheckBox_getPressed" onAction="contextCheckBox_onAction" />

幾つものワークブック(Book1 , Book2 , ……)でリボンUI をカスタマイズしたとします(勿論、各々の
ワークブックでボタンやチェックボックスをクリックした際の処理は皆異なります)。そのようなワークブック
を同時に開いた場合、以下のような動きとなります。

    ・ ノーマルワークブックが複数の場合
          その時々でアクティブなワークブックのマクロが期待通りに呼び出されます(リボン自体、
          そのワークブックのものしか表示されていません)。
          Book1.xlsm がアクティブならばBook1.xlsmのRibbon_onAction、Book2.xlsm がアクティブ
          ならばBook2.xlsmのRibbon_onAction が呼び出されます。互いのワークブックで同じ名前
          のマクロが登録されていても何ら支障はありません

    ・ アドインワークブックが複数の場合
          開いている全てのアドインのリボンが表示され有効となっていますが、各々のアドインの
          リボンをクリックした場合に、期待通りのマクロが呼び出されるとは限りません。
          Book1.xlamのリボンをクリックしたら Book2.xlam のマクロが呼び出されるという動きをする
          場合があります。試した限りでは、先にオープンしたアドインワークブックのマクロが呼び出
          されるようです。

    ・ ノーマルワークブック と アドインワークブックの場合
          リボン付きのBook1.xlam , Book2.xlsm とリボン無しのBook3.xlsx を同時にオープンして
          いる場合、以下のような動きとなります。
            〜 Book2.xlsm がアクティブ 〜
                Book1.xlam/Book2.xlsm両方のリボンが有効になっていますが、どちらのリボンをクリック
                しても Book2.xlsmのマクロが呼び出されます
            〜 Book3.xlsx がアクティブ 〜
                Book2.xlsmのリボンが非表示で、Book1.xlamのリボンのみ有効になっており、Book1.xlam
                のリボンをクリックするとBook1.xlamのマクロが呼び出されます。

          Book2.xlsm/Book3.xlsx のワークブックを交互に切り換えて、その都度試してみた限りでは、
          ノーマルワークブックのリボンが有効な状況ではノーマルワークブックのマクロが呼び出され、
          無効になるとアドインワークブックのマクロが呼び出されるという動きをします。

このような事を避ける為にも、各ワークブックに定義するリボンUI のイベント/コールバック プロシー
ジャー の名前は、他のワークブックの名前と重ならないよう、ユニークな名前を付ける(ワークブック
名をプリフィックスにする等)よう心掛けてください。


ネット上には、様々なサンプルコードが転がっていますが、サンプルの質が良ければ良いほど、
丸コピ してしまいがち
です。つまり、他の多くの人も同じように丸コピ していると思うべきでしょう。
当然、丸コピ 同士ならば【名前も同じ】です。サンプルを転用する際には注意して下さい。


( 2016/4/3 追記 )
--- 各ワークブックのプロシージャー名が同じままで重複を回避する方法 ---

onAction句などに記述するマクロ名は、下記のようにブック名による修飾付きで記述することが出来ます。

 ※ 修飾なし ※
 <button … onAction="Ribbon_onAction" … />

 ※ ブック名で修飾 ※ (ブック名+感嘆符+プロシージャー名)
 <button … onAction="Test1.xlam!Ribbon_onAction" … />

 ※ ブック名&モジュール名で修飾 ※ (ブック名+感嘆符+モジュール名+ピリオド+プロシージャー名)
 <button … onAction="Test1.xlam!Module1.Ribbon_onAction" … />


この方法を利用すれば、プロシージャー名が他ブック(アドイン)と重複していても、正しいマクロ
を呼び出せます。

(注) アドインを開発する場合、通常ブック( xlsm )で開発作業を行ない、完成後にアドインブック( xlam )
      として別名保存という作業過程を経ると思いますが、上記のブック名による修飾も、それに合わせる
      必要がありますので、忘れずに修正して下さい。


[ この場所へのリンク ]

8. リボンUI にしたい。でも xls の呪縛が…。その対処法は…

「リボンUI にしたい。でも xls の呪縛が…。」
これは kt関数アドイン( kt関数Addin.xla ) が抱えている問題でもあります。

kt関数アドインでは、長らく(Excel2007 リリース後も) xla 形式のみで提供してきましたが、kt関数
アドイン(Ver4.00) から xla / xlam の2形式で提供するようになりました(なお、メニューには従来
の CommandBar を使用していますので、メインメニューは「アドイン タブ」に収録されています)。

ただし、xlam 形式への積極的なお薦めはしていません。「これから (Excel2007以降で)初めて使
用する場合には、xlam 形式という選択肢もありますよ」という程度のものです。

kt関数アドインが 2001年から提供している関係上、既に「多くの場所・多くのワークブック・多く
のセルでのシート関数」として利用されています。その為、
      kt関数Addin.xla から kt関数Addin.xlam に切り換えた場合、ワークブックをオープン
      する際に、シート上で kt関数を使用している数だけ、リンクエラーが繰り返し出て来
      ます。そのエラーが出尽くした後に「リンクの更新」によって参照先を変更する必要が
      あります。この作業が kt関数を使用している全てのワークブックで必要となります。

という問題を考えると、SDI ( Single Document Interface ) に対応するためとはいえ、簡単に
『今後は kt関数Addin.xlam のみにする』とはできませんでした。


この リボンUI の勉強をしながら、
      『 xla のままに留めたい、xla のままでリボンUI が使えたらなぁ〜』
と何気なく考えていた時に、ふと閃きました。それは ……
    ・ リボンUI は CommandBar メニューの代わり。
    ・ メニューコマンドのマクロは、元々 CommandBar から
      呼び出されるものなので【 引数なしの Public Sub 】。
    ・ それならば、外から(他のワークブックから) Application.Run で呼び出せる
    ・ リボンUI の外見だけを作る簡単なアドイン(ここで紹介したサンプル程度のもの)を
      用意して、メニューボタンの onAction イベントに Application.Run を記述。
    ・ このアドインをkt関数アドインと一緒に利用する。

こうすることで、
    ・ シート関数やVBAマクロとして利用するのは 従来通り [ kt関数Addin.xla ] なので、
      既存のワークブックに対して「リンクの更新」などは一切不要。既存のワークブックは
      そのまま何も修正せずに使い続けられる。
    ・ それでいて、メニューコマンド操作は上記のリボン用アドインが展開するリボンUI を
      通して行えますし、当然、Excel2013以降のSDI 環境にも完全に対応できます。


この対処法で作ったのが 【 kt関数 リボンアタッチメント アドイン 】 です。




 Home   Back Page   Next Page

ロゴ(ゴールド)   ロゴ(ゴールド)

角田 桂一 Mail:addinbox@h4.dion.ne.jp CopyRight(C) 2016 Allrights Reserved.