根据Excel VBA中的combobox显示/隐藏WBS项目

我希望能够使用combobox过滤工作表的WBS数据。

select一个工作阶段应该导致只有具有该工作阶段的产品显示In progress的状态是可见的。 这个工作阶段,以及任何早期的工作阶段,也应该是可见的。

此外,如果具有所选工作阶段的产品具有“已Finished状态,但包含正在进行的任何早期工作阶段,则也应该可见。 那些早期的工作阶段也应该是可见的。 这个产品的选定的工作阶段可见。

如果一个产品根本没有select的工作阶段,那么也不应该看到它的任何工作阶段。

订单行只有在具有可见的产品时才可见。

select之前:

使用组合框过滤数据

select后:

例

这是我试图做的事情:

 Dim ws Worksheet Set ws = ThisWorkbook.Sheets("DataSheet") Dim lastRow As Long lastRow = ws.Cells(Rows.Count, 4).End(xlUp).row ws.Rows("2:" & lastRow).Select Selection.EntireRow.Hidden = True Dim SrchRng As Range, cel As Range Set SrchRng = ws .Range("A5", "I" & lastRow) For Each cel In SrchRng If cel.Range("C1").Text = ComboBox1.Text And cel.Range("E1").Value <> "In progress" Then cel.EntireRow.Hidden = False End If Next 

这段代码只能看到正在进行的选定工作阶段。 我希望产品行,订单行和所有先前正在进行的工作阶段行都可见。

编辑: (v0.3.2)添加了“显示所有”工作阶段选项。

似乎很容易做到,但事实certificate有点棘手。

循环访问行时,需要保存两行索引:当前订单行和当前产品行。 只有这样才能正确显示订单,如果任何产品显示。

请注意,常量声明和长variables名称使代码自我logging。

v0.3.2:

  • Show All – 如果将其他项目添加到不以“工作阶段”开头的combobox中,select它将显示所有行。 这个项目也可以是空白的。

码:

 Option Explicit 'v0.3.2 Private Sub ComboBox1_Change() Const l_Order_ As String = "Order " Const l_Work_stage_ As String = "Work stage " Const l_In_progress As String = "In progress" Const i_Orders As Long = 1 Const i_Products As Long = 2 Const i_WorkStages As Long = 3 Const i_Progress As Long = 5 Dim rngCurrentRow As Range Dim lngFirstDataRow As Long Dim lnglastDataRow As Long Dim lngCurrentOrderRow As Long Dim lngCurrentProductRow As Long Dim boolShowProduct As Boolean Application.ScreenUpdating = False ' No need for sheet name since Me = active sheet lngFirstDataRow = WorksheetFunction.Match(l_Order_ & "*", Me.Columns(i_Orders), 0) lnglastDataRow = WorksheetFunction.Match("*", Me.Columns(i_Progress), -1) With Range(Me.Rows(lngFirstDataRow), Me.Rows(lnglastDataRow)) If Not ComboBox1.Text Like l_Work_stage_ & "*" Then .EntireRow.Hidden = False GoTo ExitSub: Else .EntireRow.Hidden = True Set rngCurrentRow = .Rows(1) End If End With ' Loop through all data rows Do If rngCurrentRow.Columns(i_Orders) <> vbNullString Then lngCurrentOrderRow = rngCurrentRow.Row Set rngCurrentRow = rngCurrentRow.Offset(1) End If If rngCurrentRow.Columns(i_Products) <> vbNullString Then lngCurrentProductRow = rngCurrentRow.Row Set rngCurrentRow = rngCurrentRow.Offset(1) End If boolShowProduct = False ' Loop through consecutive non-empty progress/work stage rows Do Until rngCurrentRow.Columns(i_Progress) = vbNullString If rngCurrentRow.Columns(i_WorkStages) <= ComboBox1.Text _ And rngCurrentRow.Columns(i_Progress) = l_In_progress _ Then boolShowProduct = True Rows(rngCurrentRow.Row).Hidden = False Else ' Ignore End If Set rngCurrentRow = rngCurrentRow.Offset(1) Loop If rngCurrentRow.Columns(i_WorkStages).Offset(-1) < ComboBox1.Text Then ' Re-hide previous shown work stages for this product Range(Rows(lngCurrentProductRow), Rows(rngCurrentRow.Row)).Hidden = True ElseIf boolShowProduct Then Rows(lngCurrentOrderRow).Hidden = False Rows(lngCurrentProductRow).Hidden = False End If Loop Until rngCurrentRow.Row > lnglastDataRow ExitSub: Application.ScreenUpdating = True End Sub 

注意:如果您对我的variables命名惯例感到好奇,它基于RVBA 。

这是我的尝试。 我做了一些假设:

  1. 列A包含订单Order x格式的订单号,其中x是一个数字
  2. B列保留Product x格式的产品名称,其中x是xy
  3. 列C保存工作阶段Work stage x格式的工作阶段名称,其中x是一个数字
  4. D列将工作阶段状态保存为“已Finished或“ In progress
  5. ComboBox在Work stage x格式中包含工作阶段名称,其中x是一个数字
  6. 没有空行

     Sub ShowHideStages() Dim oW As Worksheet: Set oW = ThisWorkbook.Worksheets("Sheet9") Dim iLR As Long: iLR = oW.Cells(Rows.Count, 4).End(xlUp).Row Dim oCB As OLEObject: Set oCB = oW.OLEObjects("ComboBox1") Dim iC As Long Dim iA As Integer Dim iFirstRow As Integer Dim iOStartRow As Integer Dim iPStartRow As Integer Dim bStageFound As Boolean Dim bProdFound As Boolean Dim bHideRow As Boolean Dim sRowsToHide As String Dim aTemp As Variant ' Unhide all rows oW.Rows("2:" & iLR).EntireRow.Hidden = False ' Find the first instance of Order iFirstRow = Columns("A").Find(what:="*", After:=Columns("A").Cells(1, 1), LookIn:=xlValues).Row ' If dropdown value is empty then skip the process of hiding rows If Len(Trim(oCB.Object.Text)) > 0 Then With oW ' Loop through all rows For iC = iFirstRow To iLR ' Lets loop through current order bStageFound = False iOStartRow = iC Do iC = iC + 1 sRowsToHide = "" iPStartRow = iC bProdFound = False ' Now lets loop through each product Do iC = iC + 1 bHideRow = False ' Check if we need to hide the current row If CInt(Right(Trim(Range("C" & iC).Text), 1)) <= CInt(Right(Trim(oCB.Object.Text), 1)) And LCase(Trim(Range("D" & iC).Text)) = "finished" Then bHideRow = True ElseIf CInt(Right(Trim(Range("C" & iC).Text), 1)) > CInt(Right(Trim(oCB.Object.Text), 1)) Then bHideRow = True End If ' Check if work stage is the expected stage If Range("C" & iC).Text = oCB.Object.Text And LCase(Trim(Range("D" & iC).Text)) <> "finished" Then bProdFound = True bStageFound = True End If ' Set rows to hide string If bHideRow Then If Len(Trim(sRowsToHide)) = 0 Then sRowsToHide = CStr(iC) Else sRowsToHide = sRowsToHide & "," & CStr(iC) End If End If Loop While Len(Trim(Range("C" & iC).Offset(1, 0).Text)) <> 0 ' Check if product was found If Not bProdFound Then ' It wasn't so set the string to hide product sRowsToHide = CStr(iPStartRow) & ":" & CStr(iC) End If ' Hide specified rows .. if specified If Len(Trim(sRowsToHide)) > 0 Then If InStr(1, sRowsToHide, ":") > 0 Then Range(sRowsToHide).EntireRow.Hidden = True Else aTemp = Split(sRowsToHide, ",") For iA = 0 To UBound(aTemp) Rows(Trim(aTemp(iA))).EntireRow.Hidden = True Next End If sRowsToHide = "" End If Loop While Len(Trim(Range("A" & iC).Offset(1, 0).Text)) = 0 And iC < iLR ' Check if order was found If Not bStageFound Then ' It wasn't so lets set the string to hide the order sRowsToHide = CStr(iOStartRow) & ":" & CStr(iC) End If ' Hide the order if we need to If Len(Trim(sRowsToHide)) > 0 Then Range(sRowsToHide).EntireRow.Hidden = True End If End With End If End Sub 

注意 :UDF也适用于ComboBox中的空白select。 在这种情况下,所有行都显示出来