Excel 允许您使用
Outline.ShowLevels
建立显示轮廓的级别。
有什么方法可以知道当前方案中显示的级别吗? 像
levels = Outline.Levels
之类的东西
似乎没有这方面的任何信息。
鉴于官方帮助页面上令人困惑的信息,我进行了自己的测试,之后我得出以下结论:
'OUTLINE OF GROUPINGS OF A RANK:
'===============================
'In the Excel ribbon:
'Data/Scheme/Group-Ungroup-Subtotal
'In VBA:
'ActiveSheet.Outline
'Show/Hide outline bar:
'----------------------
'ActiveWindow.DisplayOutline = True 'False
'Expand or Collapse Groupings of the entire sheet:
'-------------------------------------------------
'ActiveSheet.Outline.ShowLevels([RowLevels], [ColumnLevels])
'Collapse Groupings of the entire sheet:
'--------------------------------------
'ActiveSheet.Outline.ShowLevels 1
'Group a range: _
The specified range must be a row or a column, _
or a range of rows or columns.
'---------------------------------------------------
'Range.Group
'Range.EntireRow.Group
'Range(Rows(r1), Rows(r2)).Group
'Reduce the grouping level of a range by one level. _
The specified range must be a row or a column, _
or a range of rows or columns.
'------------------------------------------------- --------
'Range.Ungroup
'Range.OutlineLevel = Range.OutlineLevel - 1
'Completely ungroup a range:
'---------------------------
'Range.ClearOutline 'Clears the outline of the specified range.
'Range.OutlineLevel = 1
'Rows.Hidden = False 'You need to show hidden rows after ungrouping!
'OUTLINE LEVEL OF A RANGE:
'-------------------------
'Returns or sets the schema level of a range:
'Moves a range (grouped or not) through the different levels of the outline.
'Read and write Variant.
'Range.OutlineLevel = level
'Range.EntireRow.OutlineLevel = level
'Rows(r).OutlineLevel = level
'Range(Rows(r1), Rows(r2)).OutlineLevel = level
'IMPORTANT: It seems that the maximum number of possible levels in a outline is 8
'Level 1:
'--------
'It is the default outline level of a range when it has no groupings.
'If we set the range outline level to 1, grouping is removed from the range.
'---------------------------------------------------------------------------
'Range.OutlineLevel = 1 'Remove range grouping!
'EXPAND AND COLLAPSE GROUPS (ShowDetail: show/hide detail of the grouped range)
'------------------------------------------------- ---------------------
'NOTE: only works if the range grouping level is within _
the visible levels set for the sheet by _
ActiveSheet.Outline.ShowLevels level
'------------------------------------------------- -------------------
'EXPAND GROUP: Show hidden rows within the group:
'Range.ShowDetail = True
'COLLAX GROUP: Hides the rows of the group except the first:
'Range.ShowDetail = False
'CHECK: Know if a group is contracted or expanded:
'expanded = Range.ShowDetail
'IMPORTANT: It can be applied to any row in the group.
'------------------------------------------------- ---------------------
'THE FOLLOWING DOES NOT WORK:
'-------------------------
'Locking and unlocking the outline bar when the sheet is protected:
'------------------------------------------------------------------
'ActiveSheet.EnableOutlining 'Reading and writing
'ActiveSheet.EnableOutlining = True 'Not working!!!!!
'Conditional formatting based on outline level:
'------------------------------------------------- ---
'Requires the use of a VBA helper function that _
we will use with the definition of the conditional format:
'=OutlineLevelFunc(CELL("row",A1)) = i
Function OutlineLevelFunc(ByVal r As Long) As Integer
On Error Resume Next
OutlineLevel = Rows(r).OutlineLevel
End Function 'OutlineLevelFunc
不同范围的分组顺序很重要,以及控制不同级别组的重叠也很重要。
由于解释起来有些复杂,我添加以下通用过程作为实际示例,以建立具有 3 个架构级别的范围的分组。
它需要一个列范围作为参数,其中每行的级别用字符串(“l1”,“l2”,“l3”)标记,以及用作数据引用的第二列范围(在本例中)文本),以及定义每个级别对应的标记的三个参数。
Sub MakeOutlineLevels(ByVal rangeRef As Range, _
ByVal levelsRange As Range, _
ByVal level1 As String, _
ByVal level2 As String, _
ByVal level3 As String)
'Use: _
MakeOutlineLevels rangeRef, levelsRange, "l1", "l2", "l3" '...
Dim wsheet As Worksheet
Dim selectedRange As Range
Dim currentCell As Range
Dim r As Long
Dim maxRow As Long
Dim level As String
Dim l1_start As Long
Dim l1_end As Long
Dim l2_start As Long
Dim l2_end As Long
Dim l3_start As Long
Dim l3_end As Long
On Error Resume Next
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual '-4135
Application.EnableEvents = False
Set wsheet = rangeRef.Worksheet
With wsheet
'Show all rows:
.Rows.ClearOutline
If .FilterMode Then .UsedRange.AutoFilter
Set selectedRange = Selection
.UsedRange.EntireRow.Select
Selection.EntireRow.Hidden = False
selectedRange.Select
ResetUsedRange rangeRef 'See below.
maxRow = ActiveSheet.UsedRange.Rows.Count
For r = .Range(CR_LímiteEdición).Row + 1 To maxRow
Set currentCell = Cells(r, rangeRef.Column)
currentCell.Select
ActiveWindow.ScrollRow = currentCell.Row - 1
level = Cells(r, levelsRange.Column)
'Level 1:
If level = level1 Then
'If there is level 3 pending grouping:
If l3_start <> 0 Then
'Add empty hidden row to close group:
If currentCell.Offset(-1) <> nStr Then
currentCell.EntireRow.Insert
ActiveCell.RowHeight = 0
End If
l3_end = r - 2
.Range(.Rows(l3_start), .Rows(l3_end)).Group
End If
'If there is level 2 pending grouping:
If l2_start <> 0 Then
'Add empty hidden row to close group:
If currentCell.Offset(-1) <> nStr Then
currentCell.EntireRow.Insert
ActiveCell.RowHeight = 0
End If
l2_end = r - 2
.Range(.Rows(l2_start), .Rows(l2_end)).Group
End If
'Start of level 1:
If l1_start = 0 Then
l1_start = r + 1
'End of level 1:
Else
l1_end = r - 1
.Range(.Rows(l1_start), .Rows(l1_end)).Group
l1_start = r + 1
End If
'When grouping level 1, reset counters of lower levels:
l2_start = 0
l3_start = 0
'Level 2:
ElseIf level = level2 Then
'If there is level 3 pending grouping:
If l3_start <> 0 Then
'Add empty hidden row to close group:
If currentCell.Offset(-1) <> nStr Then
currentCell.EntireRow.Insert
ActiveCell.RowHeight = 0
End If
l3_end = r - 2
.Range(.Rows(l3_start), .Rows(l3_end)).Group
l3_start = 0
End If
'Start of level 2:
If l2_start = 0 Then
'First level 2 group within level 1, group rows after the start of level 1:
'Add empty hidden row to close group:
If currentCell.Offset(-1) <> nStr Then
currentCell.EntireRow.Insert
ActiveCell.RowHeight = 0
End If
l2_start = l1_start
l2_end = r - 1
.Range(.Rows(l2_start), .Rows(l2_end)).Group
l2_start = r + 1
'End of level 2:
Else
l2_end = r - 1
.Range(.Rows(l2_start), .Rows(l2_end)).Group
l2_start = r + 1
End If
'When grouping level 2, we reset counters of the lower levels:
l3_start = 0
'Level 3:
ElseIf level = level3 Then
'Start of level3:
If l3_start = 0 Then
'First level 3 group within level 2, group rows after the start of level 2:
'Add empty hidden row to close group:
If currentCell.Offset(-1) <> nStr Then
currentCell.EntireRow.Insert
ActiveCell.RowHeight = 0
End If
l3_start = l2_start
l3_end = r - 1
.Range(.Rows(l3_start), .Rows(l3_end)).Group
l3_start = r + 1
'End of level3 (agrupar):
Else
l3_end = r - 1
.Range(.Rows(l3_start), .Rows(l3_end)).Group
l3_start = r + 1
End If
'Last row:
ElseIf r = maxRow Then
'If there is level 3 pending grouping:
If l3_start <> 0 Then
l3_end = r
.Range(.Rows(l3_start), .Rows(l3_end)).Group
End If
'If there is level 2 pending grouping:
If l2_start <> 0 Then
l2_end = r
'If there is level 3 pending grouping:
If l3_start <> 0 Then l2_end = l2_end + 1
.Range(.Rows(l2_start), .Rows(l2_end)).Group
End If
'If there is level 1 pending grouping:
If l1_start <> 0 Then
l1_end = r
'If there is level 3 pending grouping:
If l3_start <> 0 Then l1_end = l1_end + 1
'If there is level 2 pending grouping:
If l2_start <> 0 Then l1_end = l1_end + 1
.Range(.Rows(l1_start), .Rows(l1_end)).Group
End If
End If
Next
Application.CutCopyMode = False
.Calculate
End With
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic '-4105
Application.EnableEvents = True
End Sub 'MakeOutlineLevels
Sub ResetUsedRange(Optional ByVal ref As Range)
'Reset .UsedRange to adjust it to the area actually used in the active sheet!
Dim r As Long
Dim c As Integer
On Error Resume Next
Application.ActiveSheet.UsedRange
'NOTE: This do not clear blank rows at the end of the range used!
If ref Is Nothing Then Exit Sub
With ref.Worksheet
c = ref.Column
'Eliminar filas en blanco:
For r = .UsedRange.Rows.Count To 2 Step -1
If .Cells(r, c) = vbNullString Then
.Rows(r).Delete
Else
Exit For
End If
Next
End With
End Sub 'ResetUsedRange