「窓を開けたり閉じたり」では、一定幅の列で構成されたひとつの窓をワークシートの左側に開けたり閉じたりしましたが、もうちょっと複雑な窓を複数開閉してみようと、がんばってみました。 まず、その使い方から説明します。
次に、窓を開けるワークシートに、窓の内容を作り込みます。
まず、窓を開け閉めするタブを窓を設ける場所の左端に貼り付けます。エクセルの標準図形として用意されている ShapeRound1Rectangle(「四角形: 1 つの角を丸める」)を回転させて使いました。中の文字は任意ですが、Shape名は Tab-1、Tab-2・・・のようにしておきます。ここでは3個の窓のために3個のタブをつけましたが、窓の個数も任意です。番号は連番にしておいたほうがよいでしょう。
すべてのタブにマクロ ToggleWindow() を登録しておきます。
タブのプロパティは「セルに合わせて移動やサイズ変更をしない」にしておきます。
タブの Shape名の接頭語 "Tab-" は同じように定数 tabNamePrefix として宣言しています。タブをクリックすると、Shape名はプログラム内では tabName として、その番号部分は index として取得されます。
タブの右側に窓をつくっていきます。必要な列を構成して中に必要な表を作り、できあがったら、その列の範囲を選択して、Shift キーを押しながら該当するタブをクリックします。そうすると、その列構成などが先に用意した一覧表に登録されます。
窓の中に挿入する画像や図形などは、プロパティを「セルに合わせて移動やサイズ変更をする」にしておきます。
以下が、プログラムの全体です。本体は途中にある ToggleWindow() で、これだけが Public となっています。
標準モジュール ToggleWindow()
'----- キー押し下げ状態取得のための API 使用宣言 #If Win64 Then Declare PtrSafe Function GetAsyncKeyState Lib "User32.dll" (ByVal vKey As Long) As Integer #Else Declare Function GetAsyncKeyState Lib "User32.dll" (ByVal vKey As Long) As Integer #End If '----- タブ名の接頭語、ウィンドウ属性一覧表の場所 Private Const tabNamePrefix = "Tab-" Private Const tableSheetName = "Const" Private Const tableCellName = "DaftarWindow" '----- タブの色を指定 Private Const openTabColor = &HC47244 Private Const closeTabColor = &HFFFFFF '----- タブをクリックした時の実行マクロ Public Sub ToggleWindow() Dim index, tabName tabName = Application.Caller index = Val(Replace(tabName, tabNamePrefix, "")) If shiftKeyDown Then resisterWindow tabName, index: Exit Sub If Not confirmTabSetting(index) Then Exit Sub If isOpen(index) Then closeWindow tabName, index Else openWindow tabName, index End If End Sub '----- ウィンドウのサイズなどの登録 Private Sub resisterWindow(tabName, index) Dim openClose, columnStart, columnsCount, columnWidth() Dim i openClose = True With Selection columnStart = .Cells(1).column columnsCount = .Columns.count ReDim columnWidth(columnsCount) For i = 1 To columnsCount columnWidth(i) = .Columns(i).columnWidth Next End With With ThisWorkbook.Worksheets(tableSheetName).Range(tableCellName) .Offset(0, index) = openClose .Offset(1, index) = columnStart .Offset(2, index) = columnsCount For i = 1 To columnsCount .Offset(2 + i, index) = columnWidth(i) Next End With MsgBox tabName & " の登録終了", vbOKOnly, "" End Sub '----- ウィンドウの開閉動作 Private Sub openWindow(tabName, index) Dim columnStart, columnsCount, columnWidth() Dim i If isOpen(index) Then Exit Sub With ThisWorkbook.Worksheets(tableSheetName).Range(tableCellName) columnStart = .Offset(1, index) columnsCount = .Offset(2, index) ReDim columnWidth(columnsCount) For i = 1 To columnsCount columnWidth(i) = .Offset(2 + i, index) Next End With With ActiveSheet.Columns(columnStart) For i = 1 To columnsCount .Offset(0, i - 1).columnWidth = columnWidth(i) Next End With isOpen(index) = True changeTabColor tabName, index End Sub Private Sub closeWindow(tabName, index) Dim columnStart, columnsCount Dim i If Not isOpen(index) Then Exit Sub With ThisWorkbook.Worksheets(tableSheetName).Range(tableCellName) columnStart = .Offset(1, index) columnsCount = .Offset(2, index) End With With ActiveSheet.Columns(columnStart) For i = 1 To columnsCount .Offset(0, i - 1).columnWidth = 0 Next End With isOpen(index) = False changeTabColor tabName, index End Sub '----- ウィンドウの開閉状況の取得/設定 Private Property Get isOpen(index) isOpen = Range(tableCellName).Offset(0, index) End Property Private Property Let isOpen(index, sw) Range(tableCellName).Offset(0, index) = sw End Property '----- タブの色を変える Private Sub changeTabColor(tabName, index) With ActiveSheet.Shapes(tabName) If isOpen(index) Then .Fill.ForeColor.RGB = openTabColor .Fill.Visible = True .Line.Visible = False .TextFrame.Characters.Font.Color = RGB(255, 255, 255) Else .Fill.ForeColor.RGB = closeTabColor .Fill.Visible = True .Line.ForeColor.RGB = openTabColor .Line.Visible = True .TextFrame.Characters.Font.Color = openTabColor End If End With End Sub '----- Shift キーが押されているかどうかの判定 Private Function shiftKeyDown() As Boolean shiftKeyDown = (GetAsyncKeyState(vbKeyShift) And &H8000) End Function '----- 設定がなかった場合の警告表示 Private Function confirmTabSetting(index) confirmTabSetting = Not IsEmpty(Range(tableCellName).Offset(0, index)) If confirmTabSetting Then Exit Function MsgBox tabNamePrefix & index & vbCrLf & vbCrLf & _ "設定するには、必要な列の並びを選択して" & vbCrLf & _ "SHIFT キーを押しながら" & vbCrLf & _ "再度該当するタブをクリックしてください。", _ vbOKOnly, "設定がありません" End Function