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

Tips08_2: RefEdit 代替手法 ( Excel97 は不可 )

[ Tips08 油断のならないRefEdit へ戻る ]

(お知らせ) RefEdit アイコンをオリジナルアイコンに変更しました (Ver 2.40 , 2011/7/1)
              (左から Excel , OOo.Calc , オリジナル

1. RefEditコントロールを使わないでRefEdit動作を実現する方法
2. RefEdit 代替手法(クラスモジュール版)  Ver 2.40  【 Excel2010(64bit)動作確認済 】
        ・ プロパティ/メソッド 一覧
        ・ 利  用  例
        ・ F  A  Q

  ローカル作業時の閲覧用に、このページを PDF化 しました。
          (A4 で 2頁/枚 の割付印刷し、山折りして綴じると小冊子になります)
      [ RefEdit_Support_Class.pdf  ( 786 KB ) ]    ( 2011/7/1 Ver 2.40 )

この RefEdit代替手法では、セル選択の際に[CTRL+SHIFT+↓]等のショートカットキーが利用できます。
RefEdit コントロールでショートカットキーを有効にするには【レジストリの修正】が必要です。
[ KB291110 : Excel の RefEdit コントロールでショートカット キーを使用して範囲を選択できない ]


[ この場所へのリンク ]
-------------------------------------------------------------------------
(2009/5/23 追記 , 2010/3/30 修正, 2010/4/13 修正, 2010/4/18 修正 , 2010/4/20 修正 , 2011/7/1 修正)
RefEditコントロールを使わずにRefEdit動作を実現する方法  (Excel97は不可)
( 2010/4/14 クラスモジュール化しました。 実際に利用する場合は クラスモジュール版を使って下さい )

RefEdit コントロールは上記の解説のように様々な問題を抱えており、使わないで済めば、それに
越したことは無いコントロールです。しかし、セル選択のユーザーインターフェースとして、このコン
トロールに代わるものが無い現状では、問題事項に引っ掛からないよう留意しつつ慎重に使うしか
ありませんでした。

ここでは、モードレスフォームを利用してRefEditコントロールと同じ動作をさせる方法を解説します。
先ず、簡単に説明すると、
    ・ 一旦、ユーザーフォームをHideモードで閉じて、呼び出し元の標準モジュールに戻る。
    ・ 標準モジュールからモードレスのRefEdit 代替フォームを表示。
    ・ 同時に、ブックのセル選択監視イベントをスタートさせ、セル範囲を取得。
    ・ セル選択の間(RefEdit 代替フォームの表示中)、呼び出し元の標準モジュールではループ待機。
    ・ RefEdit 代替フォームを閉じた通知を受けたらループ待機を抜け、取得したセル範囲を設定して
      ユーザーフォームを再表示(Hideなので、前回内容が残っている)。
という手順になります。

モードレスフォームを使う為、Excel97では利用できません。Excel2000以上のバージョンが対象です。





  (左記の RefEdit ボタンは通常のコマンドボタンに
    画像を載せて作ってあります。)

         

  (左記は RefEdit コントロールではありません。
    Label & CommandButton の UserFormです。
    RefEdit ボタンは、通常のコマンドボタンに
    画像を載せて作ってあります。)

         


手順詳細フローチャート


フローチャートに従って実行手順を順に説明します。
(1) UserForm1にあるRefEditボタンをクリックすると、RefEdit実行フラグをオンにしてUserForm1は
    [Hide]で閉じます。閉じるボタン[X] or マクロでのUnLoad の場合には、RefEdit実行フラグは
    オフになるようにします。
(2) UserForm1.Show の次ステップでは、RefEdit実行フラグのオン/オフで分岐します。
(3) RefEdit実行フラグがオフの場合は、通常クローズなので、後の処理に進みます。
(4) RefEdit実行フラグがオンの場合は、RefEditフォームをモードレスで表示した後、実行フラグが
    オフになるまでループ待機します。
(5) RefEdit実行フラグがオンになると、ThisWorkbook内でのセル範囲選択の監視が始まり、範囲
    選択するとRefEditフォームへそのセル範囲が渡されます。
(6) RefEditフォームを閉じる([X]ボタン or RefEditボタン)と実行フラグがオフとなり、ループ待機を
    終了します。
(7) ループ後のステップで、セル範囲をUserForm1に設定して、UserForm1を再表示して戻ります。
    (Hideで閉じているので、UserForm1の内容は保持されており、前回の内容で表示されます)

補:RefEditフォーム入力中でのシート切り替えも可能です。但し、シート切り替え後は、一度、
    RefEditフォーム上をクリックして、フォームをアクティブにしてからセルを選択して下さい。
    そうしないと、切り替え後の「シート名」が正しく取得できない場合があります。

【  サンプルブックRefEdit_Dialog_Basic.xls  】
      2010/3/30 修正
          ・ RefEdit ボタンのアイコン画像を OpenOffice.org で使われているのアイコンに変更。
          ・ 画面遷移時の描画レスポンス向上の為に [ frmRefEdit.Show ] の後に DoEvents を追加。
          ・ サンプルブック内に RefEdit.dll への参照設定が誤って残っていたので、その参照設定を削除。
      2010/4/13 修正
          ・ RefEdit実行フラグがオフの場合に記述してあった [ Unload UserForm1 ] は不要でしたので削除しました。
      2010/4/18 修正
          ・ セルアドレスの編集形式をオプションの 「A1形式/R1C1形式」 に合せました。
      2010/4/20 修正
          ・ RefEditフォームの表示位置を呼出元フォームの左上端とする修正をしました。
          ・ マウスカーソルが砂時計のままとなる場合がある事への対処をしました。
      2011/7/1 修正
          ・ RefEdit アイコン を オリジナルアイコンに変更しました(機能の変更はありません)。

    この手法を利用するブックへは、RefEdit 代替フォーム(frmRefEdit) を
          このサンプルブックからエクスポート&インポート
    で、そのままコピーして使ってください( frmRefEdit のフォーム名は変更しないでください)。

    利用側のUserFormで使う『アイコン付きコマンドボタン』は、
          このサンプルブックのVBE上から、UserForm1のコマンドボタンをコピー
    すればアイコン画像と一緒に取り込めます。

  ---- 標準モジュール ----

#If VBA7 And Win64 Then    '64bit版対応
  Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#Else
  Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
#End If

Public blnRefEditExecute As Boolean
Public strRefEditFieldName As String
Public strRefEditRangeValue As String
Public rngRefEditRangeObject As Range
'------------------------------------------------------
Public Sub RefEditFormTest()
  blnRefEditExecute = False
  Load UserForm1
L1:
  UserForm1.Show

  If (blnRefEditExecute = TrueThen
    '[UserForm1] は Hide 状態
    strRefEditRangeValue = ""
    Load frmRefEdit
    With frmRefEdit
      .StartUpPosition = 0
      .Top = UserForm1.Top
      .Left = UserForm1.Left
      .Caption = "RefEdit ( " & UserForm1.Caption & " )"
      .Show vbModeless
    End With

    'マウスカーソルが砂時計のままとなる場合がある事への対処
    ActiveSheet.Activate

    DoEvents

    Do While blnRefEditExecute      'RefEdit実行中はループ継続
      Sleep 250   'Wait(0.25sec)
      DoEvents
    Loop

    UserForm1.Controls(strRefEditFieldName) _
        .Caption = strRefEditRangeValue
    GoTo L1
  End If
  blnRefEditExecute = False

  '〜〜 UserForm1 入力後の処理 〜〜

End Sub

  ---- RefEditを使うUserFormモジュール(UserForm1) ----

Private Sub cmdRefEdit1_Click()
  strRefEditFieldName = "lblRefEdit1"
  blnRefEditExecute = True
  Me.Hide
End Sub
'--------------------------------------------------------
Private Sub cmdRefEdit2_Click()
  strRefEditFieldName = "lblRefEdit2"
  blnRefEditExecute = True
  Me.Hide
End Sub

  ---- RefEdit代替フォーム(frmRefEdit) ----

Private Sub cmdRefEdit_Click()
  Unload Me
End Sub
'-------------------------------------------------------
Private Sub UserForm_QueryClose _
        (Cancel As Integer, CloseMode As Integer)
  blnRefEditExecute = False
End Sub

  ---- ThisWorkbook モジュール ----

Private Sub Workbook_SheetSelectionChange _
        (ByVal Sh As ObjectByVal Target As Range)
  If (blnRefEditExecute = TrueThen
    If (Application.ReferenceStyle = xlA1) Then
      strRefEditRangeValue = Sh.Name & "!" _
                & Target.Address(False, False, xlA1)
    Else
      strRefEditRangeValue = Sh.Name & "!" _
                & Target.Address(True, True, xlR1C1)
    End If
    frmRefEdit.lblRefEdit.Caption = strRefEditRangeValue
  End If
End Sub


[ この場所へのリンク ]
-------------------------------------------------------------------------
(2010/4/14 追記, 2010/4/18 修正 , 2010/4/20 修正 , 2010/4/23 修正 , 2010/5/ 2 修正 ,
 2010/5/14 修正 , 2010/12/15 修正 , 2010/12/25 BUG修正 , 2011/7/1 修正)

RefEdit 代替手法(クラスモジュール版)  (Excel97は不可)  【 Excel2010(64bit) 動作確認済(Ver2.40) 】
  (この代替手法の仕組みの解説は こちら を参照。ローカル用に PDF もあります)

クラスモジュール & サンプル ブックRefEdit_Support_Class.xls 】  ( Ver. 2.40  2011/7/1 )
      2010/4/14 Ver 1.00
      2010/4/18 Ver 1.10
          a) セルアドレスの編集形式をオプションの 「A1形式/R1C1形式」 に合せました。
      2010/4/20 Ver 1.20
          a) Clear メソッドを追加しました。
          b) RefEditフォームの表示位置を呼出元フォームの左上端とする修正をしました。
          c) マウスカーソルが砂時計のままとなる場合がある事への対処をしました。
      2010/4/23 Ver 2.00
          a) TargetRange プロパティに[値の設定]を追加しました。
          b) TargetBook/TargetSheet/TargetAddrプロパティ,Terminateメソッドを追加しました。
          c) RefEdit復帰イベントの代替としてActivateイベントを利用する為の[ActivateInfo]プロパティを追加しました。
      2010/5/ 2 Ver 2.10
          a) 標準モジュール名を変更しました。 [ mdlRangeSelect  ⇒  mdlRangeSelection ]
          b) 代替手法利用時の排他制御に関する修正を行ないました。これに伴い、標準モジュール( mdlRangeSelection )
             が 必須 となりましたので、一緒に インポート してください。
          c) 排他制御の判断用に RefEditActive プロパティ と IsRefEditActive 関数を追加しました。
          d) [ TargetRange ] プロパティ (値の設定)で、指定の Range オブジェクト が処理対象 ブック か否かの チェック が
             抜けていたのを修正しました。
      2010/5/14 Ver 2.20
          a) SelectionChangeイベントが常時稼働(RefEdit入力中か否かをフラグで判別してスキップ)していたのを、RefEdit
             フォーム表示中のみに変更(監視ワークブックオブジェクトを、RefEditフォーム表示直前に設定し、RefEditフォーム
             消去直後に破棄(Nothing)します)しました。
          b) RefEditフォームにブック切替機能を追加しました。これに伴い、Showメソッドにブック切替機能用の引数を追加し、
             ReleaseBookReferenceメソッドを追加しました。
          c) TargetAddrプロパティにCellOnly引数を追加しました。
          d) StartUpBookプロパティを追加しました。
          e) 結合セルを選択した場合に「セル範囲」となっていたのを「結合セルの先頭セル」が取得セルとなるように修正しました。
      2010/12/15 Ver 2.30
          a) SetRefEditメソッドのRangeType引数に [3: 1つ以上の単一セルを選択] を追加しました。
          b) TargetRange(設定プロパティ)にて、指定のRangeTypeと異なるRangeオブジェクトが設定できてしまう不具合を修正しました。
          c) InitRefEditメソッドを追加しました。
          d) API呼び出しの 64bit対応を行ないました。
      2010/12/25 Ver 2.31 (BUG修正)
          a) 隣接するセルを CTRL を押しながら選択した場合に 「セル範囲」 に纏められてしまう不具合を修正しました。
          b) RangeType [3: 1つ以上の単一セルを選択] で隣接セルを選択できない不具合を修正しました。
      2011/7/1 Ver 2.40
          a) RefEdit ボタンのアイコンをオリジナルアイコンに変更しました(機能の変更はありません)。


RefEdit コントロールを使わない上記手法の
    ・ ループ制御ロジック
    ・ RefEditフォーム呼び出し時のRefEdit実行フラグの設定処理
等をクラスモジュール( clsRangeSelection )にしてブラックボックス化しました(ThisWorkbook モ
ジュールは使いません)。ループ制御などのマクロをコピーする等の手間も無くなり、非常に利用
し易くなりました(実行マクロも視覚的に判り易くなりました)。

このクラスには【Range オブジェクト】を取得するプロパティを用意してありますので、RefEdit コント
ロールでは必要だった「セルアドレス文字→Rangeオブジェクト」変換処理を行なう必要がありません。

また、RefEdit コントロールの場合、TextBox 部が修正可能である為、選択したセル範囲のアドレス
文字列が手入力により壊される(変更される)可能性もあります(Evaluate による Range オブジェクト
変換の際にエラーチェックが必須)。しかし、RefEdit 代替手法では、セルアドレス表示部は表示専
用である為、セル選択した内容が保障されます。

さらに、RefEdit コントロールでは出来なかった
    ・ 他ブックのセル選択
    ・ 「単一セルのみ選択可」といった制限の設定
    ・ [Ctrl + Shift + ↓]などのショートカットキーの使用
が可能です。




〜〜 RefEdit代替手法を利用するUserFormの表示手順(上図の解説) 〜〜
(1)  clsRangeSelection クラスオブジェクトについて排他制御の確認を行なう(下記解説参照)。
(2)  clsRangeSelection クラスのインスタンスを作成します。この時点の ActiveWorkbook が RefEdit
      による選択対象ブック(StartUpブック)となります(Showメソッドで[BookChange=True]を指定した
      場合は他のブックのセルも選択可能です)。
(3)  [ Load UserForm1 ] でユーザーフォームをロードする(ユーザーフォームの初期処理が必要
     な場合は、この後に記述するか、もしくは UserForm_Initialize に記述する)。
(4)  clsRangeSelection クラスの [ Show ] メソッドを実行してRefEdit代替手法の制御ルーチンを起
     動する。ユーザーフォームは、この Showメソッド内から表示されます。
     (ユーザーサイドでUserForm1.Show は使用しません)
(5)  RefEdit ボタンクリック時に、clsRangeSelection クラスの [ SetRefEdit ] メソッドを実行します。
     その後に 【 Me.Hide 】 でユーザーフォームを閉じると RefEdit 代替フォームが表示されます。

     SetRefEdit メソッドには、選択セルアドレスを表示する【ラベルコントロール】と、選択セルの制限
     条件(単一セルのみ可 or 複数セル範囲が可 等 )を指定します。
    (注) この条件設定機能は、Ver2.30より InitRefEditメソッド(UserForm_Initialize内で実行)にて
          行なうようになりました。尚、SetRefEditメソッドでも引き続き指定可能ですので、InitRefEdit
          メソッドを使わなくても問題なく動作します。

(6)  RefEdit 代替フォームを閉じると、ユーザーフォームを再表示して、指定のラベルコントロールに
     選択セルアドレスが設定されます。
(7)  Activateイベントと[ActivateInfo]プロパティを使って【RefEditからの復帰イベント】を構築できます。
(8)  通常クローズ(閉じるボタン/マクロの Unload )すると、Show メソッドを抜けるので、クラスオブ
     ジェクトを解放して終了してください。
(9)  選択セルの Range オブジェクトは [ TargetRange ] プロパティで取得できます。セルアドレス文字
     は [ TargetAddr ] プロパティから取得します。
(10) セル選択内容をクリアする場合は Clear メソッドを実行します(ラベル上のセルアドレス文字を
     消去し、TargetRange プロパティの値を Nothing にします)。クリアボタン または ラベルのマウ
     スイベント等で実行してください。

(注-1) モードレスフォームを使用していますので、ユーザーフォームから「子フォーム」を起動する事に
        は利用できません(モーダルフォーム内からモードレスフォームは表示不可)。標準モジュールか
        らの起動に限ります。

(注-2) RefEdit 代替フォームでセル選択中にはシート切り替えが可能です。但し、シート切り替え直後
        には、「シート」が正しく取り込まれない場合があります。その場合には、RefEdit 代替フォーム上を
        クリックしてから再度セルを選択して下さい。


〜〜 RefEdit 代替手法を利用する際に排他制御が必要な理由 〜〜
  RefEdit 代替手法を使用する場合には、clsRangeSelection クラスオブジェクトが稼働中か否かを判断
してユーザーフォーム表示マクロの排他制御を行なってください(サンプルマクロ参照)。

  RefEdit 代替フォームは通常のモードレスフォームです。したがって、セル選択操作だけではなく、
      ・ メニュー(コマンドバー/リボン , 右クリックメニュー)
      ・ シート上に配置したボタン等
の操作も可能です。それ故に、
      ・ メニュー/ボタン等に登録されているマクロが呼出し可能な状態
      ・ [メニュー > マクロの実行] からもマクロを呼出す事が可能な状態
      ・ 上記の呼出し可能なマクロに、現在実行中の自分自身のマクロが含まれていれば、
         それも呼出し可能(この場合は[再帰呼出し]になります)
という問題が出て来ます(RefEdit コントロールの場合には、メニュー/ボタン等の操作はできません)。

  この問題を回避する為に、RefEdit 代替手法を利用するプロジェクト(ブック)では、各プロシジャーの
先頭で排他チェックを行なう必要があります。

  この排他チェックを行なう為に IsRefEditActive 関数を用意してあります。Type 引数を以下のように
使い分けて判定します。
    (1) RefEdit 代替手法を利用する プロシジャーの場合
            [ Type = False ] として RefEdit 代替手法の重複実行 ( clsRangeSelection クラス
            オブジェクトのバッティング ) を回避します。
    (2) 上記(1)以外の Sub プロシジャー で、メニュー登録されているプロシジャー、
        または、[マクロの実行]から呼出し可能なプロシジャーの場合
            [ Type = True ] として、セル選択操作中 ( RefEdit フォーム 表示中 ) に メニュー
            から実行されないようにします。
    (3) 上記 (1) (2) 以外の プロシジャーの場合
            IsRefEditActive 関数による排他制御処理の組み込みは必要ありません。

  この排他制御管理を行なう為に、
        clsRangeSelection クラスオブジェクト変数は
                                プロジェクト(ブック)内に ただ1つだけ
としてください。複数の ユーザーフォーム で RefEdit 代替手法を利用する場合、その1つの オブジェ
クト変数を共用して使用するようにしてください。

(注) Excel2000〜2003 では、
            ・ 『待機ループ(DoEvents あり)』の最中に
            ・ [メニュー/マクロの実行] からマクロを実行する
      と、【そのマクロが ”2度” 連続して実行されてしまう】という不具合があります。メニュー or ボタン等
      に登録して実行されるものは大丈夫です。また、Excel2007/Excel2010 では、この不具合はありま
      せん(リボンシステムとして新たにメニュー系が作り直された為と思われます)。したがって、排他制御
      により実行抑止する際には Beep による警告に留め、MsgBox 表示は行なわないで下さい。


〜 ブック切替機能とブック参照の解放 〜
  通常(ShowメソッドでBookChangeを省略 or False )は、
        StartUpブック : クラスオブジェクト生成時点のActiveWorkbook
に対してのみセル選択操作が可能です。

  Showメソッドで[BookChange = True]とすると、RefEditフォーム上でブックを切り替えるコンボボック
スが有効となり、オープン中のブックがリストに載ります。そのコンボボックスでブックを切り替えると、
切替後のブックに対してセル選択が可能となります。なお、ブックのリストにはアドインブック・個人用
マクロブック・テンプレートブックは含まれません。


  このコンボボックスでブックを指定すると、そのブックがActiveになります。RefEditフォームを閉じて
ユーザーフォームへ戻る際にはStartUpブック(クラスオブジェクト生成時点のActiveWorkbook)へ自
動的に切り替わります。また、ブック切り替え機能を有効にした場合には、セルアドレス文字に「ブック
名」が付きます(TargetAddrプロパティ、ユーザーフォームのRefEditラベルも同様です)。

  ここで、ブック切替機能を有効にしている場合に注意を要する点がひとつあります。それは、
        RefEditでセル選択をしたブックをユーザーフォーム側でCloseする
という場合です。例としては、
        「データブック」が別個にあるとして、ユーザーフォームマクロから「データブック」
        を開き、RefEditで取り込みセル範囲を指定し、その範囲のデータを取り込んだ後に
        「データブック」を閉じる。
というものが考えられます。

  Clearメソッド、またはTargetRangeプロパティにNothingを代入しない限り、クラスオブジェクト内には、
選択したセルのオブジェクト参照が残っています。このオブジェクト参照を残したままそのセルが属す
るブックをCloseすると、俗に言う『幽霊プロジェクト(エクセル上からも、タスクバーからもブックが消えて
いるのに、VBE上には残っている)』の状態になります。


  これを回避する為に、ブックをCloseする前に、ReleaseBookReferenceメソッドを実行してく
ださい。

  ReleaseBookReferenceメソッドは、指定したブックのセルを選択しているRefEditを探して一括して
Clear(オブジェクト参照を解放します)します。ユーザーサイドで「どのRefEditが、そのブックのセル
を選択しているか」といった事を気にする必要はありません。一度のメソッドで対象となるRefEditを
全てClearします。

(例)    Workbooks.Open “ABC.xls”
              :
          〜 ABC.xls に関する処理、ABC.xlsのセルをRefEdit選択 等 〜
              :
          RefEditSupport.ReleaseBookReference Workbooks (“ABC.xls”)
          Workbooks (“ABC.xls”).Close

  なお、ブック切替機能を使わない場合にはこの処理は必要ありません。また、ユーザーフォーム
終了後に行なう「クラスオブジェクト = Nothing」により、クラス内の全てのオブジェクト参照は解放
されます。


〜〜 利用ブックに サンプルブックからコピー(インポート)するもの 〜〜
(1) クラスモジュール : clsRangeSelection をインポートする。
(2) 標準モジュール : mdlRangeSelection をインポートする。
(3) ユーザーフォームモジュール : frmRefEdit をインポートする。
    ( ※ frmRefEdit のフォーム名は変更できません)
(4) UserForm1 上の RefEdit ボタンを、利用するユーザーフォームにコピー&ペーストする。
    (アイコン画像が一緒にコピーされます)
    Excel の RefEdit アイコン画像に変更したい場合には、以下のファイルのアイコン画像と
    差し替えてください。  
    【 アイコン画像ファイル : RefEdit_Icon.zip  



〜〜 アドイン運用など、他ブックから参照設定して利用する場合 〜〜
(1) プロパティウィンドウで、clsRangeSelection クラスモジュールの [ Instancing ] プロパティを
    Private → PublicNotCreatable に変更する。
(2) クラスを利用するブックでは、クラスオブジェクト作成の際、
          Set RefEditSupport = New clsRangeSelection
    の代わりにインスタンス作成関数を使います。
          Set RefEditSupport = CreateRangeSelectClass ()



〜 RefEdit 代替手法( RefEdit Support )の 二次配布について 〜
    本機能の二次配布については、カレンダークラスアドイン( clsPasteCal )で規定している
    ルールに準じます(詳細は上記リンク先を参照して下さい)。





=======================================================================
  [ clsRangeSelection ] クラス    メソッド/プロパティ一覧
=======================================================================
      下記で[ object ]の部分には、clsRangeSelection クラスを定義したオブジェクト変数を記述します。

定  義
  標準 モジュールの宣言セクション(モジュールの先頭)で、下記のように定義します。

    Public  object  As  clsRangeSelection

    このクラスオブジェクトは、必ず Public で宣言してください。
    なお、宣言時に New キーワード を付けないでください。
          OK    Public  object  As  clsRangeSelection
          NG    Public  object  As  New  clsRangeSelection

    ( object )
      任意の名前を指定して下さい。

    RefEdit 代替手法を利用する ユーザーフォーム を表示する前に、下記のようにしてクラスのインスタンスを
    作成します。
        Set  object  =  New  clsRangeSelection

    複数の ユーザーフォーム でこの機能を使う場合、個々の ユーザーフォーム ごとに クラスオブジェクトを
        用意せず、1プロジェクト(ワークブック) にクラスオブジェクトは1つのみとし、複数のユーザーフォー
        ム で共有するようにしてください(排他制御の判定の為)。

    通常は、StartUpブック(クラスオブジェクト作成時の ActiveWorkbook)RefEdit 代替フォームで
        選択可能なブックとなります。もし、ユーザーフォームのマクロ で アクティブブック を他の ブック に切り替え
        たとしても、その ブック に対しては機能しません(選択セルは取り込まれません)。なお、シート は切り替えは
        可能です。

    上記StartUpブック 以外のブックのセル選択を行ないたい場合には、Show メソッドの[BookChange] にTrue
        を指定します。

    アドイン運用など、参照設定でクラスを利用している場合は、New キーワードを使わずに下記のようにします。
             Set  object  =  CreateRangeSelectClass ( )
        (CreateRangeSelectClass 関数は、mdlRangeSelection モジュール に用意してあります)


メソッド
object .Show    MsForms ユーザーフォーム オブジェクト , [ BookChange ]

    RefEdit 代替手法の制御ルーチンを起動するメソッドです。ユーザーフォームは、このメソッド内から
    表示されます(ユーザーサイドで UserForm1.Show 等とする必要はありません)。尚、この Show メソッド
    を実行する前に ユーザーフォームを Load してください。
    ( 例 )
        Set RefEditSupport = New clsRangeSelection
        Load UserForm1
        ' 〜 UserForm1 の初期処理が必要な場合は、この場所、もしくは UserForm_Initialize に記述する 〜
        RefEditSupport.Show UserForm1 , False
        Set RefEditSupport = Nothing

    ( MsForms ユーザーフォーム オブジェクト )
      RefEdit 代替手法を利用する ユーザーフォームオブジェクトを指定します。

    ( BookChange )
      StartUpブック(クラスオブジェクト生成時点のActiveWorkbook )以外のブックへ切り替えを行 なってセル
      選択を行なうか否かを指定します。
      省略が可能です。
          False : StartUpブックに対してのみセル選択可能です。(既定値)
          True : StartUpブック以外のブックに切り替えてセル選択が可能です。

      ブック切替機能を使用する場合、以下の点が変わります。
          ・RefEditフォームに『ブック切替コンボボックス』が表示されます。このコンボ ボックスでブックを切り替え
           てからセルを選択します。
          ・セルアドレス表示にブック名が加わります(TargetAddr プロパティも同様)。

 

object .InitRefEdit    RefEditLabel , RangeType

    RefEdit 対象コントロール(選択したセルアドレスを表示するラベル)の初期設定を行なうメソッドです。
    UserForm_Initialize 等で実行します。

    [単一セル] のみ許すのか、[セル範囲] も可とするのかという制限を指定できます。
    ( 例 )
        Private Sub UserForm_Initialize ()
          With RefEditSupport
              .InitRefEdit Me.lblRefEdit1 , 0    ‘ 複数セル範囲可
              .InitRefEdit Me.lblRefEdit2 , 2    ‘ 単一セルのみ可
          End With

    ( RefEditLabel )
      RefEdit 対象コントロールオブジェクト(選択したセルアドレスを表示する ラベル) を指定し ます。
      ラベル のみ指定できます。テキストボックスなどは指定できません。

    ( RangeType )
      セルを選択する際の制限を指定します。
          0 : 制限なし ( 複数セル範囲 or 単一セル範囲 or 単一セル )
          1 : 単一セル範囲 or 単一セル が可能
          2 : 単一セル のみ可能
          3 : 複数の単一セル が可能
      なお、結合セルは1セル(結合セルの先頭セル) として扱います。

      InitRefEdit メソッドで指定したRangeType属性はSetRefEdit メソッドで変更する事が可能です。
      InitRefEdit/SetRefEdit メソッドにて設定したRangeType属性はTargetRangeプロパティでセル範囲を
      設定する際の妥当性チェックにも使用されます([単一セルのみ可] としているコントロールに対して
      セル範囲を設定しようとした場合など。この場合にはセル範囲の先頭セルのみが設定されます)。


object .SetRefEdit    RefEditLabel , [ RangeType ]

    RefEdit 対象コントロール(選択したセルアドレスを表示するラベル) を指定するメソッドです。
    このメソッドの後で [ Me.Hide ] でフォームを閉じると、RefEdit 代替フォームが表示されます。

    [単一セル] のみ許すのか、[セル範囲] も可とするのかという制限を指定できます。
    ( 例 )
        Private Sub cmdRefEdit3_Click ()
            RefEditSupport.SetRefEdit Me.lblRefEdit3 , 2    '単一セルのみ
            Me.Hide
        End Sub

    セルアドレスは Excel のオプション設定にしたがって
          "Sheet2!A1:B5" (A1形式)  or  "Sheet2!R1C1:R5C2" (R1C1形式)
    の形式で表示されます。なお、ブック切替機能を有効にしている場合にはセルアドレスにブック名 が
    付きます。
        "[Book1.xls]Sheet2!A1:B5" (A1形式)  or  "[Book1.xls]Sheet2!R1C1:R5C2" (R1C1形式)

    選択したセルが結合セルの場合には「結合セルの先頭セル」が取得されます(結合セルを含むセル範囲
    の場合にはセル範囲全体が取得されます)。

    ( RefEditLabel )
      RefEdit 対象コントロールオブジェクト(選択したセルアドレスを表示する ラベル) を指定します。
      ラベル のみ指定できます。テキストボックスなどは指定できません。

    ( RangeType )
      セルを選択する際の制限を指定します(省略が可能です)。実行の都度、変更しても構いません。
         省略 : 前回の設定が継続。初回設定時は [ 0 ] と解釈します。
              0 : 制限なし ( 複数セル範囲 or 単一セル範囲 or 単一セル )
              1 : 単一セル範囲 or 単一セル が可能
              2 : 単一セル のみ可能
              3 : 複数の単一セル が可能
      なお、結合セルは1セル(結合セルの先頭セル)として扱います。

      InitRefEdit/SetRefEdit を一度も実行していないRefEdit 対象コントロールに対して、RangeType を
      省略した場合(初回設定)には [0 :制限なし] となります。
 

object .Clear    RefEditLabel

    セル選択情報をクリアするメソッドです。クリアボタン押下 または RefEdit 対象コントロール(ラベル)
    のマウスイベント等で実行してください。

    指定した RefEdit 対象コントロール(選択したセルアドレスを表示するラベル)上に表示されている
    セルアドレスを消去します。また、このメソッド実行後、指定した RefEdit 対象コントロールに対する
    TargetRange プロパティは Nothing を返します。

    TargetRange プロパティに Nothing を代入しても同じ効果が得られます。

    ( 例 )
        Private Sub lblRefEdit1_MouseDown ( ByVal Button As Integer, ByVal Shift As Integer, _
                                                       ByVal X As Single, ByVal Y As Single )
            If ( Button = 2 ) And ( Shift = 4 ) Then
                ' [ Alt + 右Click ] 操作でクリアする
                RefEditSupport.Clear  Me.lblRefEdit1
            End If
        End Sub

    ( RefEditLabel )
      RefEdit 対象コントロールオブジェクト(選択したセルアドレスを表示する ラベル) を指定します。
      ラベル のみ指定できます。テキストボックスなどは指定できません。
 

object .Terminate

    RefEdit 利用フォーム の Terminateイベントで必ず実行してください。

    クラスオブジェクト内からUserForm(コントロール)参照を完全に削除して、UnLoadを確実に行なえるように
    する為に必要です。

 

object .EndRefEdit

    [ frmRefEdit : QueryClose ] で RefEdit 終了通知(ループ停止指示) に使用しています。
    【ユーザーサイド】では使用しません。
 

object .BookChange  Index

    [ frmRefEdit : cmbBook_Change ] で 対象ブック切替に使用しています。
    【ユーザーサイド】では使用しません。

  ( Index )
    ブック切替コンボボックスの ListIndex 値を指定します。
 

object .ReleaseBookReference  Book

    ブック切替機能を使用している場合に使用します(ブック切替機能を使用していない場合は 無効です)。
    これから Close しようとしているブックのセルを選択している RefEdit 情報を 一括してクリアして、そのブック
    へのオブジェクト参照を解放する為に使用します。 詳細は「ブック切替機能とブック参照の解放」 を参照し
    てください。

    ( Book )
      Workbookオブジェクトを指定します。
      StartUpブック(クラスオブジェクト生成時点のActiveWorkbook)を指定した場合は無効です。
 

プロパティ
object .StartUpBook  ( ) [ = Workbook ]

    StartUpブック(クラスオブジェクト生成時のActiveWorkbook)のオブジェクトを取得します。
    値の取得のみ可能です。

    ( 値の取得 )
      StartUpブック(クラスオブジェクト生成時のActiveWorkbook)のオブジェクトを返します。
 

object .TargetRange  ( RefEditLabel ) [ = Range ]

    RefEdit ボタンから選択したセルの Range オブジェクトを取得します。逆に RefEdit ボタンへ Range
    オブジェクト を設定する事もできます(RefEdit ラベル上への セルアドレス文字の設定も同時に行な
    われます)。
    値の取得/設定が可能です。

    このプロパティを使うと、RefEdit コントロールの場合に必要だった 「セルアドレス文字 → Range オブ
    ジェクト」 の変換処理(Evaluate 等による変換)が必要ありません。

    Nothing を代入する操作は Clear メソッド と同じ効果です(RefEdit ラベルのセルアドレス文字は消去
    されます)。

    ( RefEditLabel )
      RefEdit 対象コントロールオブジェクト(選択したセルアドレスを表示する ラベル) を指定します。
      ラベル のみ指定できます。テキストボックスなどは指定できません。

    ( 値の取得 )
      指定の RefEdit 対象コントロールについて、セル選択済みの場合は、その Range オブジェクト を
      返します。セル未選択の場合は Nothing を返します。

      初期値(セル選択 or TargetRange (値の設定) を一度も行なっていない状態)は Nothing です。

    選択したセルが結合セルの場合には「結合セルの先頭セル」が取得されます(結合セルを含むセル
    範囲の場合にはセル範囲全体が取得されます)。

    ( 値の設定 )
      指定の RefEdit 対象コントロールに対して、Range オブジェクト を設定できます(その Range オブ
      ジェクト は、この TargetRange プロパティで再び取得できます)。Range オブジェクトのセルアドレス
      文字が RefEdit ラベル に設定されます(Nothing を設定した場合は、消去になります)。

      InitRefEdit/SetRefEdit にて設定したRangeType に合わないセル範囲を渡した場合には、RangeType
      に沿うように渡されたセル範囲を整形してから設定されます。
          例: RangeType = 2 (単一セルのみ可)と指定されているRefEdit対象コントロールに
               「セル範囲」を渡した場合には、そのセル範囲の先頭セルだけが設定されます。

      InitRefEdit/SetRefEdit を一度も実行していないRefEdit対象コントロールに対して、TargetRange プロパ
      ティでセル範囲(or 単一セル)を設定する場合には、そのRefEdit対象コントロールのRangeType は
      [0:制限なし] と見做されます。

      ブック切替機能を使わない場合、そのRangeオブジェクトがStartUpブック(クラスオブジェクト 生成時の
      ActiveWorkbook)と異なる時は無効です。

      セルアドレス文字のフォーマット(A1形式 , R1C1形式)は Excel のオプションの設定に従います。
          A1形式    : "Sheet2!B2:C5"
          R1C1形式 : "Sheet2!R2C2:R5C3"
      ブック切替機能を有効にしている場合には、セルアドレスにブック名が付きます。
          A1形式 : "[Book1.xls]Sheet2!B2:C5"
          R1C1形式 : "[Book1.xls]Sheet2!R2C2:R5C3"
 

object .TargetBook  ( RefEditLabel ) [ = Workbook ]

    RefEdit ボタンから選択したセルの Workbook オブジェクト を取得します。
    値の取得のみ可能です。

    ( RefEditLabel )
      RefEdit 対象コントロールオブジェクト(選択したセルアドレスを表示する ラベル) を指定します。
      ラベル のみ指定できます。テキストボックスなどは指定できません。

    ( 値の取得 )
      指定の RefEdit 対象コントロールについて、セル選択済みの場合は、そのセルの Workbook
      オブジェクト を返します。セル未選択の場合は Nothing を返します。

      初期値(セル選択 or TargetRange (値の設定) を一度も行なっていない状態)は Nothing です。
 

object .TargetSheet  ( RefEditLabel ) [ = Worksheet ]

    RefEdit ボタンから選択したセルの Worksheet オブジェクトを取得します。
    値の取得のみ可能です。

    ( RefEditLabel )
      RefEdit 対象コントロールオブジェクト(選択したセルアドレスを表示する ラベル) を指定します。
      ラベル のみ指定できます。テキストボックスなどは指定できません。

    ( 値の取得 )
      指定の RefEdit 対象コントロールについて、セル選択済みの場合は、そのセルの Worksheet
      オブジェクト を返します。セル未選択の場合は Nothing を返します。

      初期値(セル選択 or TargetRange (値の設定) を一度も行なっていない状態)は Nothing です。
 

object .TargetAddr  ( RefEditLabel , [ ReferenceStyle ] , [ CellOnly ] ) [ = String ]

    RefEdit ボタンから選択したセルの セルアドレス文字 を取得します。
    値の取得のみ可能です。

    ( RefEditLabel )
      RefEdit 対象コントロールオブジェクト(選択したセルアドレスを表示する ラベル) を指定します。
      ラベル のみ指定できます。テキストボックスなどは指定できません。

    ( ReferenceStyle )
      セルアドレスの編集形式(A1形式/R1C1形式)を xlA1 または xlR1C1 で指定します。
      省略可能です。省略した場合は Excel のオプション設定に従います。

    ( CellOnly )
      セルアドレスにブック名/シート名を含めるか否かを指定します。 省略可能です。
            False : ブック名/シート名を含めます。既定値。
            True : ブック名/シート名を含めずに、セルアドレスのみの編集

    ( 値の取得 )
      指定の RefEdit 対象コントロールについて、セル選択済みの場合は、そのセルのアドレスを文字列で
      返します。セル未選択の場合は 空文字( "" ) を返します。
          A1形式    : "Sheet2!B2:C5"
          R1C1形式 : "Sheet2!R2C2:R5C3"
      ブック切替機能を有効にしている場合には、セルアドレスにブック名が付きます。
          A1形式    : "[Book1.xls]Sheet2!B2:C5"
          R1C1形式 : "[Book1.xls]Sheet2!R2C2:R5C3"

      CellOnly=Trueとした場合には、ブック名/シート名は付きません(セルアドレスのみ)。
      初期値(セル選択 or TargetRange (値の設定) を一度も行なっていない状態)は 空文字 です。
 

object .ActivateInfo  [ = String ]

    UserForm_Activate イベント内で使用します。このプロパティには Activate イベントの発生理由が
    文字列で返ります。値の取得のみ可能です。

    この ActivateInfo プロパティは、値を一度取得すると、値が 空文字( "" ) に リセット されます
        したがって、Activate イベントの先頭で 変数に取り込み、その変数で処理を行ってください。


    a) UserForm_Initialize イベント直後の Activate イベントでは "Initialize" の文字列が返ります。
    b) RefEdit 入力から復帰する際にも、ユーザーフォームの再表示によって Activate イベントが発生
        します。この場合には、RefEdit ラベルのオブジェクト名が返ります。
    c) 上記以外の Activate イベントでは 空文字( "" ) が返ります。
          ・ 子フォームを表示し、その子フォームを閉じて戻って来た時(Excel2000(SR無)のみ)
          ・ RefEdit 処理以外で Hide した後に再表示した時

    "Initialize" / 空文字( "" ) 以外の場合が、RefEdit 入力の AfterUpdate イベント に相当します。
    RefEdit 項目が複数ある場合は、その項目名で分岐させてください。

    ( 値の取得 )
      "Initialize" or RefEdit ラベルオブジェクト名 or 空文字("") が 返ります。
 

object .RefEditActive  ( ) [ = Boolean ]

    RefEdit フォーム表示中(セル選択操作中) か否かの状態を取得します。
    値の取得のみ可能です。

    [ IsRefEditActive ] 関数内で使用しています。
    【ユーザーサイド】 では使用しません。

    ( 値の取得 )
      True  : RefEdit フォーム表示中(セル選択操作中)
      False : RefEdit フォームは表示されていない(利用元の ユーザーフォーム を表示中)
 

関  数 】  ( mdlRangeSelection に収録 )
IsRefEditActive  ( object , [ Type ] ) [ = Boolean ]

    RefEdit 代替手法によるユーザーフォーム処理が実行中か否かの状態を返します( clsRangeSelection クラス
    オブジェクトのインスタンス作成済か否か )。
    [ Type = True ] とすると、範囲を狭めて『RefEdit フォーム表示中(セル選択操作中) か否か』の状態を返します。

    この関数の使用目的については前述 『RefEdit 代替手法を利用する際に排他制御が必要な理由』 を参照。

    Type 引数の使い分けは以下のようにしてください。
        (1) RefEdit 代替手法を利用する プロシジャー
              [ Type = False ] として RefEdit 代替手法の重複実行 ( clsRangeSelection クラスオブジェクトの
              バッティング ) を回避します。
        (2) 上記(1)以外の Sub プロシジャー で、メニュー登録されているもの/[マクロの実行] から呼出し可能なもの
              [ Type = True ] として、セル選択操作中 ( RefEdit フォーム 表示中 ) に メニュー から実行
              されないようにします。
        (3) 上記(1)(2)以外の プロシジャー
              IsRefEditActive 関数による排他制御処理の組み込みは必要ありません。

    ( object )
      clsRangeSelection クラスのオブジェクト変数 を指定します。
      この排他制御管理を行なう為に、clsRangeSelection クラスオブジェクト変数はプロジェクト(ブック)内に
      ただ1つだけとしてください。複数の ユーザーフォーム で RefEdit 代替手法を利用する場合、その1つ
      の オブジェクト変数を共用して使用するようにしてください。

    ( Type )
      省略 or False : RefEdit 代替手法を利用する プロシジャー が実行中か否かの状態
      True            : RefEdit フォーム表示中(セル選択操作中) か否かの状態

    ( 返却値 )
      Type = False の場合
            True  : RefEdit 代替手法を利用する プロシジャーが実行中
            False : 上記以外(未実行状態)

      Type = True の場合
            True  : RefEdit フォーム表示中 (セル選択操作中)
            False : 上記以外
                        ・ RefEdit 代替手法を利用する プロシジャー が実行中ではない
                        ・ RefEdit フォームは表示されていない (利用元の ユーザーフォーム を表示中)
 

CreateRangeSelectClass  ( ) [ = clsRangeSelection オブジェクト ]

    VBA では外部の クラス の インスタンス(オブジェクト) を New キーワード によって生成する事ができません
    ので、clsRangeSelection クラス を アドイン 運用する場合には、New キーワードの代わりに、この関数によって、
    インスタンス(オブジェクト) を生成します。
        Set object = CreateRangeselectClass ( )

    RefEdit 代替手法を利用する ワークブック 内に clsRangeSelection クラスモジュール を 収録して使用する
    場合には、この関数は必要ありません。

    補: クラス を アドイン 運用する場合には、clsRangeSelection クラスモジュール の [ Instancing ] プロパティ
        を 【 PublicNotCreatable 】 とする必要があります。

    ( 返却値 )
      clsRangeSelection クラス の 新規インスタンス (オブジェクト) を作成して返します。
 

利 用 例

'==== 標準モジュール(Sample) ====

'RefEdit制御クラスオブジェクト(Public),プロジェクト内で共有して使用する
Public RefEditSupport As clsRangeSelection
'----------------------------------------------------------
Sub Test_RefEdit_1()
  '===================================================================
  ' RefEdit入力中(モードレス)はメニュー操作も可能になります。その為、
  ' ・[メニュー/マクロの実行]から[Public]マクロの実行
  ' ・コマンドメニュー/右クリックメニューに登録されたマクロの実行
  ' が可能な状態になっています。そこで、安全性の面から上記のマクロ等
  ' が起動しないように、以下のように排他制御を行なってください。

  If IsRefEditActive(RefEditSupport, FalseThen
    Beep
    Exit Sub
  End If
  '===================================================================

  'StartUpブック:[クラスオブジェクト作成時のActiveWorkbook]
  Set RefEditSupport = New clsRangeSelection

  Load UserForm1  '[UserForm1.Show]は使用しない

  '〜 UserForm1の初期処理が必要な場合は、この場所か、UserForm_Initialize に記述する 〜
  With UserForm1
    .Caption = "RefEdit 代替テスト(ブック切替 無)"
    .cmdBook1Open.Enabled = False
    .cmdBook2Open.Enabled = False
  End With

  'UserForm表示とRefEdit処理の制御
  '[BookChange=False] : StartUpブックのみRefEditでセル選択可
  RefEditSupport.Show UserForm1, False

  Set RefEditSupport = Nothing
End Sub
'----------------------------------------------------------
Sub Test_RefEdit_1_BookChange()
  If IsRefEditActive(RefEditSupport, FalseThen
    Beep
    Exit Sub
  End If

  Set RefEditSupport = New clsRangeSelection

  Load UserForm1
  With UserForm1
    .Caption = "RefEdit 代替テスト(ブック切替 有)"
    .cmdBook1Open.Enabled = True
    .cmdBook2Open.Enabled = True
  End With

  '[BookChange=True] : StartUpブック以外もRefEditでセル選択可
  RefEditSupport.Show UserForm1, True

  Set RefEditSupport = Nothing
End Sub
'--------------------------------------------------------------
'RefEditSupport を使用するマクロはRefEditSupportの有無で判断
'
'Sub Test_RefEdit_2()
'  If IsRefEditActive(RefEditSupport, False) Then
'    Beep
'    Exit Sub
'  End If
'
'  Set RefEditSupport = New clsRangeSelection
'  Load UserForm2
'  RefEditSupport.Show UserForm2, False
'  Set RefEditSupport = Nothing
'End Sub
'--------------------------------------------------------------
'RefEditSupport を使用しないマクロはRefEditフォームの入力中か否かで判断
'
'Sub Test_Other()
'  If IsRefEditActive(RefEditSupport, True) Then
'    Beep
'    Exit Sub
'  End If
'
'  UserForm3.Show
'End Sub


'--------------------------------------------------------------
' ※ アドイン運用など、別ブックから参照設定して利用する場合 ※
'    (1) clsRangeSelectionのInstancingプロパティを"PublicNotCreatable"にする。
'    (2) [ Set RefEditSupport = New clsRangeSelection ] の代わりに
'        インスタンス作成関数を使って
'            Set RefEditSupport = CreateRangeSelectClass
'        としてインスタンスを作成する。


'==== UserForm1 モジュール ====

Private Wkbk1 As Workbook   'New Book[1]
Private Wkbk2 As Workbook   'New Book[2]
'----------------------------------------------------------
Private Sub UserForm_Initialize()
' [InitRefEdit] メソッド
' arg1: 呼出元Label(選択セル範囲のアドレス文字を受取ります)
' arg2: 0(複数セル範囲可,既定値), 1(単一セル範囲可), 2(単一セルのみ), 3(1つ以上の単一セル)

  With RefEditSupport
    .InitRefEdit Me.lblRefEdit1, 0    '複数セル範囲可
    .InitRefEdit Me.lblRefEdit2, 1    '単一セル範囲可
    .InitRefEdit Me.lblRefEdit3, 2    '単一セルのみ
    .InitRefEdit Me.lblRefEdit4, 3    '1つ以上の単一セル
  End With
End Sub
'----------------------------------------------------------
Private Sub UserForm_Activate()
Dim strActivateInfo As String
  'ActivateInfoプロパティの取得は1回のみ有効です(取得後は空文字にリセットされる)。
  '直接参照せずに変数に取り出してから利用します。
  strActivateInfo = RefEditSupport.ActivateInfo

  Select Case strActivateInfo
    Case ""
      '[RefEdit呼出]以外で Hide した後に再表示した場合は空文字です。
      'その際のActivateイベント処理は、ここに記述します。

    Case "Initialize"
      'Initializeイベント直後のActivateイベント処理は、ここに記述します。

    Case Else
      'RefEditからの復帰イベント処理は、ここに記述します。
      '(AfterUpdate イベントの代替になります)
      '[ActiveInfo]には RefEdit代替Label名が入っているので、
      '複数のRefEdit使用時にはラベル名で分岐させます。

      lblInfo.Caption = strActivateInfo & " から復帰"
  End Select
End Sub
'----------------------------------------------------------
Private Sub UserForm_Terminate()
  RefEditSupport.Terminate      '※Terminateイベントで必ず実行する
End Sub
'----------------------------------------------------------
'============== RefEdit 呼び出し ===========================
'呼出元のRefEdit代替Labelを設定してHideすると、RefEditフォームが呼び出されます。
' [SetRefEdit] メソッド
'   arg1: 呼出元Label(選択セル範囲のアドレス文字を受取ります)
'   arg2: 0(複数セル範囲可), 1(単一セル範囲可), 2(単一セルのみ)), 3(1つ以上の単一セル)
'         省略時は[InitRefEdit]メソッドでの設定値で実行される。
'         [SetRedEdit]メソッドにて[RangeType]の変更は可能。

Private Sub cmdRefEdit1_Click()
  RefEditSupport.SetRefEdit Me.lblRefEdit1   '省略により [0]複数セル範囲可
  Me.Hide
End Sub
'----------------------------------------------------------
Private Sub cmdRefEdit2_Click()
  RefEditSupport.SetRefEdit Me.lblRefEdit2   '省略により [1]単一セル範囲可
  Me.Hide
End Sub
'----------------------------------------------------------
Private Sub cmdRefEdit3_Click()
  RefEditSupport.SetRefEdit Me.lblRefEdit3   '省略により [2]単一セルのみ
  Me.Hide
End Sub
'----------------------------------------------------------
Private Sub cmdRefEdit4_Click()
  RefEditSupport.SetRefEdit Me.lblRefEdit4   '省略により [3]複数の単一セル可
  Me.Hide
End Sub
'----------------------------------------------------------
'===========================================================
'入力内容をクリアする場合は、クリアボタン もしくは ラベルの
'マウスイベント等で Clear メソッドを実行します。
Private Sub lblRefEdit1_MouseDown(ByVal Button As Integer, _
                                  ByVal Shift As Integer, _
                                  ByVal X As SingleByVal Y As Single)
  If (Button = 2) And (Shift = 4) Then
    '[Alt+右Click]操作でクリアする
    RefEditSupport.Clear Me.lblRefEdit1

    '下記でも同じクリア操作になります
    '[ RefEditSupport.TargetRange(Me.lblRefEdit1) = Nothing ]
  End If
End Sub
'----------------------------------------------------------
Private Sub lblRefEdit2_MouseDown(ByVal Button As Integer, _
                                  ByVal Shift As Integer, _
                                  ByVal X As SingleByVal Y As Single)
  If (Button = 2) And (Shift = 4) Then
    RefEditSupport.Clear Me.lblRefEdit2
  End If
End Sub
'----------------------------------------------------------
Private Sub lblRefEdit3_MouseDown(ByVal Button As Integer, _
                                  ByVal Shift As Integer, _
                                  ByVal X As SingleByVal Y As Single)
  If (Button = 2) And (Shift = 4) Then
    RefEditSupport.Clear Me.lblRefEdit3
  End If
End Sub
'----------------------------------------------------------
Private Sub lblRefEdit4_MouseDown(ByVal Button As Integer, _
                                  ByVal Shift As Integer, _
                                  ByVal X As SingleByVal Y As Single)
  If (Button = 2) And (Shift = 4) Then
    RefEditSupport.Clear Me.lblRefEdit4
  End If
End Sub
'----------------------------------------------------------
'===========================================================
' RefEdit入力後には[TargetRange]プロパティで Range オブジェクトを取得できます。
' [TagetRange] プロパティ
'   arg1: 呼出元Label を指定します
Private Sub cmdMsgBox1_Click()
Dim rngSelect As Range
  Set rngSelect = RefEditSupport.TargetRange(Me.lblRefEdit1)
  If (rngSelect Is NothingThen
    MsgBox "Nothing"
  Else
    MsgBox rngSelect.Parent.Parent.Name & vbCrLf & _
           rngSelect.Parent.Name & vbCrLf & _
           rngSelect.Address(FalseFalse)

'    TargetBook/TargetSheetプロパティでも Book/Sheetオブジェクトを取得できます。
'    TargetAddrプロパティでも セルアドレス文字を取得できます。
'    MsgBox RefEditSupport.TargetBook(Me.lblRefEdit1).Name & vbCrLf & _
'           RefEditSupport.TargetSheet(Me.lblRefEdit1).Name & vbCrLf & _
'           RefEditSupport.TargetAddr(Me.lblRefEdit1, xlA1, True)
  End If
End Sub
'----------------------------------------------------------
Private Sub cmdMsgBox2_Click()
Dim rngSelect As Range
  Set rngSelect = RefEditSupport.TargetRange(Me.lblRefEdit2)
  If (rngSelect Is NothingThen
    MsgBox "Nothing"
  Else
    MsgBox rngSelect.Parent.Parent.Name & vbCrLf & _
           rngSelect.Parent.Name & vbCrLf & _
           rngSelect.Address(FalseFalse)
  End If
End Sub
'----------------------------------------------------------
Private Sub cmdMsgBox3_Click()
Dim rngSelect As Range
  Set rngSelect = RefEditSupport.TargetRange(Me.lblRefEdit3)
  If (rngSelect Is NothingThen
    MsgBox "Nothing"
  Else
    MsgBox rngSelect.Parent.Parent.Name & vbCrLf & _
           rngSelect.Parent.Name & vbCrLf & _
           rngSelect.Address(FalseFalse)
  End If
End Sub
'----------------------------------------------------------
Private Sub cmdMsgBox4_Click()
Dim rngSelect As Range
  Set rngSelect = RefEditSupport.TargetRange(Me.lblRefEdit4)
  If (rngSelect Is NothingThen
    MsgBox "Nothing"
  Else
    MsgBox rngSelect.Parent.Parent.Name & vbCrLf & _
           rngSelect.Parent.Name & vbCrLf & _
           rngSelect.Address(FalseFalse)
  End If
End Sub
'----------------------------------------------------------
Private Sub cmdBook1Open_Click()
  If (Wkbk1 Is NothingThen
    'Book[1] Open
    Set Wkbk1 = Workbooks.Add

    cmdBook1Open.Caption = "Close"
    cmdBook1Open.ForeColor = vbRed
  Else
    'Book[1] Close , Closeする前にBook[1]のセル選択を全て解放する
    RefEditSupport.ReleaseBookReference Wkbk1
    Wkbk1.Close SaveChanges:=False
    Set Wkbk1 = Nothing

    cmdBook1Open.Caption = "Open"
    cmdBook1Open.ForeColor = vbBlack
  End If
End Sub
'----------------------------------------------------------
Private Sub cmdBook2Open_Click()
  If (Wkbk2 Is NothingThen
    'Book[2] Open
    Set Wkbk2 = Workbooks.Add

    cmdBook2Open.Caption = "Close"
    cmdBook2Open.ForeColor = vbRed
  Else
    'Book[2] Close , Closeする前にBook[2]のセル選択を全て解放する
    RefEditSupport.ReleaseBookReference Wkbk2
    Wkbk2.Close SaveChanges:=False
    Set Wkbk2 = Nothing

    cmdBook2Open.Caption = "Open"
    cmdBook2Open.ForeColor = vbBlack
  End If
End Sub


F A Q

Q1. VBEの実行ボタンでUserFormを表示するとエラーになります。
A1. clsRangeSelectionを使用しているUserFormを、VBEの実行ボタンで直接表示させる事はできません。
        また、UserFormをShowメソッドで表示させた場合も同様にエラーになります。標準モジュールのプロシ
        ジャーからclsRangeSelectionのShowメソッドで表示させてください。

Q2. RefEditボタン(CommandButton)のアイコン画像は、どのように設定しますか?
A2. サンプルブックのUserForm1にあるRefEditボタンをコピー&ペーストすれば、アイコン画像付きで作成
        できます。Excelのアイコン画像に変更したい場合は、アイコン画像ファイルをダウンロードして、その中
        にある画像ファイルをVBEのプロパティウィンドウからCommandButtonのPictureプロパティに読み込めば
        差し替えられます。
        [ アイコン画像ファイル ] : RefEdit_Icon_zip  

Q3. RefEditをUserFormに複数配置したいのですが、クラスオブジェクトはRefEditの数だけ定義
      するのですか?

A3. clsRangeSelectionのクラスオブジェクトは、1プロジェクト(ワークブック)に1つだけ定義して、その1つの
        クラスオブジェクトを全てのRefEdit(プロジェクト内にRefEditを使うUserFormが複数ある/UserForm上に
        RefEditが複数ある)で共有して使用します。

Q4. RefEditを使うUserFormがブックに複数あるのですが、クラスオブジェクトはUserFormごとに
      定義するのですか?

A4. A3.を参照

Q5. シートを切り替えてからセルを選択しても、セルアドレスのシート表示が変わりません。
A5. その場合には、一旦、RefEditフォームをクリックしてからセル選択を行ってください。

Q6. UserForm_Activateイベントを使っていますが、RefEditフォームを閉じる度にActivateイベ
      ントの処理が実行されてしまいます。

A6. UserForm.Hide → RefEditフォーム表示 → UserForm.Show の流れで作り上げていますのでRefEdit
        フォームを閉じる度にActivateイベントが発生します。ActivateInfoプロパティの値でInitialize後のActivateか、
        RefEdit入力後のActivateかが判断できます。判定方法の詳細はActivateInfoプロパティを参照してください。

Q7. RefEdit入力後のイベント処理を行いたい。
A7. RefEditフォームを閉じる度にUserForm_Activateイベントが実行されます。Activateイベント内でActivateInfo
        プロパティの値を判断して、Initialize後のActivateか、RefEdit入力後のActivateか(どのRefEditか)が判断
        できます。判定方法の詳細はActivateInfoプロパティを参照してください。

Q8. 他のブックのセルを選択したい。
A8. ShowメソッドのBookChange引数にTrueを指定すると他のブックのセルを選択できます。なお、ブックの
        切り替えはRefEditフォーム上から行います。

Q9. UserForm表示の際にRefEdit に初期選択セルを設定しておきたい。
A9. ActivateイベントでActivateInfoプロパティ="Initialize"の際に、TargetRangeプロパティへ初期選択セル
        のRangeオブジェクトを設定(Set)します。セルアドレス文字は自動的に編集されてRefEditラベルに表示
        されます。

Q10. RefEditで選択したセル範囲のRangeオブジェクトを取得したい。
A10. TargetRangeプロパティで取得します。

Q11. RefEditで選択したセル範囲のセルアドレス文字を取得したい。
A11. TargetAddrプロパティで取得します。

Q12. RefEditで選択したセル範囲のセルアドレス文字のシートとセルを分割したい。
A12. TargetBookプロパティ/TargetSheetプロパティでブックとシートオブジェクトが取得できますので、
          そのNameプロパティから取得できます。セルアドレス部分はTargetAddrプロパティで[ CellOnly
          = True ]とします。

Q13. RefEditで選択した内容をクリアしたい。
A13. RefEdit入力で何もセルを選択しないで戻ればクリアされます。マクロで行うには、Clearメソッドを
          実行するか、TargetRangeプロパティにNothing を設定するとクリアされます。

Q14. RefEditでの選択を単一セルに制限したい。
A14. SetRefEditメソッドで[ RangeType = 2 ]とするとセル範囲を選択しても取得されるのは、その先頭
          セルのみになります。

Q15. ブック切替機能を使用していて、セル選択していたブックをマクロからクローズしても
        大丈夫ですか?

A15. そのブックを選択しているRefEdit を残したままでブックをクローズすると、エクセル上では消えても、
          VBE上ではVBAプロジェクトが残ってしまいます。ブックをクローズする前に、そのブックを選択し
          ているRefEdit を全てクリアする必要があります。ReleaseBookReferenceメソッドに、そのクローズする
          ブックオブジェクトを指定すれば、そのブックのセルを選択しているRefEditを一括してクリアします。
          ユーザーサイドで「どのRefEditが、そのブックを選択しているか」を調べる必要はありません。

Q16. 排他制御が何故必要なんですか?
A16. 「RefEdit代替手法を利用する際に排他制御が必要な理由」 を参照。






[ Home へ戻る ] [ Tips08 油断のならないRefEdit へ戻る ]
ロゴ(ゴールド)   ロゴ(ゴールド)

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