「窓を開けたり閉じたり」では、一定幅の列で構成されたひとつの窓をワークシートの左側に開けたり閉じたりしましたが、もうちょっと複雑な窓を複数開閉してみようと、がんばってみました。 まず、その使い方から説明します。
次に、窓を開けるワークシートに、窓の内容を作り込みます。
まず、窓を開け閉めするタブを窓を設ける場所の左端に貼り付けます。エクセルの標準図形として用意されている 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