お絵かきロジックアナライザ開発記   その5

それっぽい形のロジックシートが完成したので、早速ヒントを入力して自動解析させてみたいところですが、ここではもう少し今後のプログラム発展に対応する準備を進めていきましょう。

現在NewLogicSheetプロシージャ内のフィールドサイズに関する保存情報はプロシージャ内で宣言されたローカルな変数(HintXHintYFieldXFieldYの各変数)に収められ、このプロシージャ内でのみ参照しています。しかしこれらの内容は解答を求めるための分析プロシージャなどでも参照したい情報であることは明らかです。ローカル変数のままではダメで、他のプロシージャからも利用できるようにしなければなりません。それではということで、モジュール内の各プロシージャで共通して使えるように、DimステートメントやPublicステートメントを宣言部に置いてグローバル化する方法が考えられますが、先述の通りマクロリセット操作で中身が消えてしまうという危うさもはらんでいます。使用時にワザワザVBEを起動し、故意にマクロリセットをするユーザーがいるのかは疑問ですが、例えば実行エラーが発生した場合にユーザーがそれとは気付かずリセットを実行してしまう場合もあります。どのような操作が行われても内容が失われることのない、“強い”情報保存先は無いのでしょうか。

システムワークシート

そのような要求に対する回答の一つとして「セルに保存する」というのはどうでしょう。マクロリセットしたところで、ワークシートのセル内容が消去されてしまうようなことはありません。もちろん操作する人間が故意にセルを編集すれば、その後のマクロ実行内容に支障がありますが、操作時には見えない、あるいはロックされていて編集できないような形にできれば内容が編集されることもないでしょう。

このようにブックが開いている間中、何が起きても内容を失わないで欲しい情報というものは、VBAを長く使っていると結構多いものです。またセル内容はモジュール外でも共用できる上、他ブックからの参照でさえ、それほど難しい手順を覚えることもなく可能です。そこでこのような“超”グローバルな情報保存先として、専用の「システム情報保存ワークシート」を定義し、このシートの各セルに必要な情報を収めるようにすれば、マクロリセットにすら耐える保存先として便利に利用できます。ワークシートならキーボード入力からロックしたり、ユーザーに見えないようにすることも容易なので、ある程度の秘匿性も確保できます。

それでは早速‘システムワークシート’を作成していきましょう。

ワークシートを隠す

ワークシートを見えなくするのに最も手軽なのは、メニューバーから[書式]→[シート]→[表示しない]を選ぶ方法です。これで選択されているシートが非表示になりますが、[書式]→[シート]→[再表示]で簡単に戻るので‘見えない状態’とは言えません。1枚目のワークシートを非表示にする操作は以下のコードに相当します。


Sub Macro1()
  ThisWorkbook.Sheets("sheet1").Visible = False
End Sub

シートオブジェクトのVisibleプロパティがTrueなら表示、Falseなら非表示になるのですが、実はこのプロパティにxlVeryHiddenをセットすると、[書式]→[シート]メニューで[再表示]が選択できなくなります。つまりマウスやキーボードの操作からは非表示を解除できません。VBAでTrueをセットしないと再表示できないので、かなり‘見えない状態’と言えるでしょう。

Excelでは新規ワークシート作成時に3枚のワークシートを準備するようになっていますので(オプション設定を変更しているとこの限りではありませんが)、1枚目の‘Sheet1’をシステム情報保存用シートとしましょう。1枚目のワークシート名を‘System’に、2枚目は‘Nonogram’にそれぞれ変更し、標準モジュールのNonoModule内に以下のコードを作成して、SystemSheetDisableを実行してみて下さい。3枚目のワークシートは不要なので、シートを削除しておきましょう。


Sub SystemSheetDisable()
' システムシート非表示
  ThisWorkbook.Sheets("Nonogram").Activate        'ロジックシートアクティブ
  ThisWorkbook.Sheets("System").Visible _
    = xlSheetVeryHidden                           'システムシート非表示
End Sub

Sub SystemSheetEnable()
' システムシート表示
  With ThisWorkbook.Sheets("System")              'システムシート表示
    .Visible = xlSheetVisible
    .Activate
  End With
End Sub

これでマクロからワークシートの表示/非表示を操作できるようになりました。この見えなくなったシートに、マクロで必要な情報を保存、参照することとします。‘System’シートになった‘Sheet1’は、今までテストしてきたときに描かれたロジックシートの残骸があるので、キレイに消しておいてあげましょう。簡単な方法としてはA列を選択し、ShiftCtrlを押したままキーを押して選択範囲上で右クリックし、削除コマンドを実行すればOKです。

ちなみにシステムシート表示プロシージャではVisibleプロパティにxlSheetVisibleという値をセットしていますが、この定数は&hFFFFでありTrueと同値です。「表示させる」という意味合いでこのxl定数名を使っただけです。

セルへの情報保存

システムシートに保存する情報としてはNewLogicSheetプロシージャのFieldXFieldYHintXHintYです。これらは新規作成時に設定した後、分析作業でも参照する情報となります。

ところで、せっかく「マクロが中断してもコケない」保存領域を確保したので、起動時の状態を保存し、終了時に戻すようなものに利用するテを考えます。今回作ろうとしているプログラムでは表示画面をできるだけ広くしたいので、数式バーや各種ツールバー、ステータスバーなどを表示しないようにして、シート表示部分を増やす工夫をしてみましょう。例えば数式バーを非表示にする場合、通常は表示されているはずだからと「ブックアクティブ時に非表示化し、非アクティブになったら表示する」と固定的に処理しても良いのですが、数式バーを非表示で使用しているユーザーが皆無であるという保証はありません。できれば「ブックアクティブ時には非表示にするが、非アクティブ時には元の状態に戻す」という処理がしたいものです。つまりブックが開かれた時点での数式バーの表示有無を取得し、ブックが非アクティブになる時にはその状態を復元するようなコードが必要になってきます。ここで‘ブッククローズ時’ではなく、‘非アクティブ時’に戻すというのは、例えば他のブックを同時に開いている状態を想像すれば理由が理解できるでしょう。つまりお絵かきロジックアナライザでは数式バーを消して表示画面を少しでも拡げるのですが、他のブックをアクティブにした際、数式バーは必要になるコトでしょう。

それでは数式バーの非表示と復元のため、ThisWorkbookモジュール内に以下のコードを入力して下さい。


Private Sub Workbook_Activate()
' ブックアクティブイベント
  ThisWorkbook.Sheets("System").Range("A1").Value _
    = Application.DisplayFormulaBar
  Application.DisplayFormulaBar = False
End Sub

Private Sub Workbook_Deactivate()
' ブック非アクティブイベント
  Application.DisplayFormulaBar = _
    ThisWorkbook.Sheets("System").Range("A1").Value
End Sub

入力が終わったらSystemSheetEnableプロシージャを実行してSystemワークシートを一旦表示させ、アクティブにした状態でワークシートを上書保存した上でブックを閉じます。再度ブックを開くと数式バーは非表示になり、SystemワークシートのA1セルに、Excel起動時の数式バー表示有無がTrueまたはFalseで保存されているはずです。新規ワークブックを開くなりしてNonogram.xlsが非アクティブになると数式バーは元の状態にもどります。新規ブック側で[表示]→[数式バー]をクリックし、数式バーの表示/非表示を切替ながらNonogramワークブックと新規ブックとでアクティブブックを切替えることで、目的通りの動きをするかが確認できます。

今後A列にはこのような内容の情報を取得していくコトとし、FieldXなどはB列に保存します。NonoModuleに以下のコードを入力したらSystemSheetDisableを実行した上でFieldSizeDialogを実行して下さい。


Sub NewLogicSheet()
' 新規ロジックシート作成
  Dim HintX As Integer                            'ヒントサイズ
  Dim HintY As Integer
  Dim FieldX As Integer                           'フィールドサイズ
  Dim FieldY As Integer
  Dim StartPos As Integer                         '太線描画ポインタ
  Dim EndPos As Integer
  FieldX = SetFieldSize.FieldWidth.Value          'フィールドサイズ取得
  FieldY = SetFieldSize.FieldHeight.Value
  HintX = (FieldX + 1) \ 2                        'ヒントサイズ算出
  HintY = (FieldY + 1) \ 2
  With ThisWorkbook.Sheets("System")
    .Range("B1").Value = FieldX                   'フィールドサイズ取得
    .Range("B2").Value = FieldY
    .Range("B3").Value = HintX                    'ヒントサイズ算出
    .Range("B4").Value = HintY
  End With
  Unload SetFieldSize                             'フォーム消去
  Cells.Delete                                    '編集領域クリア
    ....

やっていることは見た目に何も変わっていませんが、FieldXなどのローカル変数に取得した内容をセルに書込んでいます。普通ならこれらのローカル変数をグローバル変数化するだけで、他のプロシージャからも利用できるようにするのですが、このセルを参照する方式なら、仮に実行エラーなどでマクロリセットされることがあっても、支障なく再処理が行えます。SystemSheetEnableプロシージャを実行してSystemワークシートを表示させ、指定したサイズの数値が設定されたかを確認してみて下さい。

テスト実行の度にシステムシートの表示切替をしているのも煩わしいので、せめて非表示にする処理は新規作成に先立って毎回実行するようにしましょう。FieldSizeDialogプロシージャの先頭から先程作成したSystemSheetDisableプロシージャを呼出すようにします。


Sub FieldSizeDialog()
' フィールドサイズ設定ダイアログ
  NonoModule.SystemSheetDisable                   'システムシート非表示
  SetFieldSize.Show                               '新規作成フォーム表示
End Sub

オプション情報の保存

前節では数式バーだけでしたが、他にも同様に扱われる色々な設定があります。メニューバーから[ツール]→[オプション]で開くオプションダイアログ設定には、ブックに保存されるものもありますが、多くはシステムに設定が記憶されるものです。つまり何らかの保存操作をしなくても、変更した設定がその後も継続される項目があり、これらは現状を保存した上で設定変更し、ブック非アクティブ時に復元することが望まれます。

ここでは「数式バー」「行列番号」「シート見出し」を非表示にして、「入力後にセルを移動する」のチェックマークを外します。ただし行列番号とシート見出しはシステム記憶ではないので現状取得は不要ですが、セル移動に関しては数式バーと同様にその後の状態に影響があるので、セルに保存した上で設定変更し、ブック非アクティブ時に復元する手順を要します。

それではブックのActivateイベントとDeactivateイベントを書替えてみましょう。


Private Sub Workbook_Activate()
' ブックアクティブイベント
  NonoModule.SystemSheetDisable                   'システムシート非表示
  With ThisWorkbook.Sheets("System")              'オプション情報取得
    .Range("A1").Value = Application.DisplayFormulaBar
    .Range("A2").Value = Application.MoveAfterReturn
    .Range("A3").Value = Application.MoveAfterReturnDirection
  End With
  With Application                                'オプション情報設定
    .DisplayFormulaBar = False
    .MoveAfterReturn = False
  End With
  With ActiveWindow                               'シートオプション設定
    .DisplayHeadings = False
    .DisplayWorkbookTabs = False
  End With
End Sub

Private Sub Workbook_Deactivate()
' ブック非アクティブイベント
  With ThisWorkbook.Sheets("System")              'オプション情報復元
    Application.DisplayFormulaBar = .Range("A1").Value
    Application.MoveAfterReturn = .Range("A2").Value
    Application.MoveAfterReturnDirection = .Range("A3").Value
  End With
End Sub

ブックアクティブ(ブックオープン時を含む)の度に念のためシステムシートを非表示にしています。数式バーの表示有無はApplicationオブジェクトのDisplayFormulaBarプロパティで設定されています。同様にセル移動設定はMoveAfterReturnプロパティに、移動方向はMoveAfterReturnDirectionプロパティでそれぞれ設定されているので、ブックアクティブ時にこの内容を取得、保存し、ブックが非アクティブになったところで元に戻しています。

また現在状況の保存を要しないシートオプションに関してだけは、念のためロジックシート新規作成時にも設定しておきましょう。


Sub FieldSizeDialog()
' フィールドサイズ設定ダイアログ
  NonoModule.SystemSheetDisable                   'システムシート非表示
  With ActiveWindow                               'シートオプション設定
    .DisplayHeadings = False
    .DisplayWorkbookTabs = False
  End With
  SetFieldSize.Show                               '新規作成フォーム表示
End Sub
← 前へ   → 次へ ▲ ページトップ