【发布时间】:2014-03-14 06:25:37
【问题描述】:
我在工作表中有一个用户窗体。 在这种形式中,我有 6 个组合框。
这个组合框由一个有 6 列的工作表填充,每列进入一个组合框。 选择每个组合框后,我在此表上创建一个过滤器并重新填充下一个。
我给你举个例子,让你更清楚。
我有一张有 6 列的表格:
大陆 |国家 |状态 |城市 |街道 |建筑物名称
此表包含所有这些项目的所有可能组合。 例如: 对于街道上的每一栋建筑,我都有一排所有相同的 5 个第一个项目,最后一个发生变化。
当用户打开表单时,我使用工作表的第一列填充第一个组合框(我执行例程来获取唯一项目)。 当用户更改第一个组合框时,我将过滤器应用于第一列中的工作表,然后用过滤后的工作表填充第二个组合框。
我的问题是如何获得过滤范围。 我正在这样做:
lastRow = Sheets("SIP").Range("A65536").End(xlUp).Row
lFiltered = Sheets("SIP").Range("A2:F" & lastRow).SpecialCells(xlCellTypeVisible).Cells
它工作正常。但是,当我应用过滤器并且它仅隐藏第 10 行时,lFiltered 变量将仅返回到第 9 行。 它在第一个隐藏行上中断,之后不再返回任何行。
我想出的解决方案是对每一行执行一次 foreach 并检查其是否可见,但代码变得非常非常慢。填充每个组合框最多需要 10 秒。
有人知道我该如何解决这个问题吗?
非常感谢。
-- 编辑--
这是代码的重要部分
Dim listaDados As New Collection
Dim comboList() As String
Dim currentValue As String
Dim splitValue() As String
Dim i As Integer
Dim l As Variant
Dim lFiltered As Variant
Dim lastRow As Integer
'Here I found the last row from the table
lastRow = Sheets("SIP").Range("A65536").End(xlUp).Row
'I do this because when the filter filters everything, lastRow = 1 so I got an erros on lFiltered range, it becames Range("A2:F1")
If lastRow < 2 Then
lastRow = 2
End If
'Here I get an array with all the visible rows from the table -> lFiltered(row, column) = value
lFiltered = Sheets("SIP").Range("A2:F" & lastRow).SpecialCells(xlCellTypeVisible).Cells
'I have duplicated entries, so I insert everything in a Collection, so it only allows me to have one of each value
on error resume next
For i = 1 To UBound(lFiltered)
currentValue = Trim(lFiltered(i, column))
If currentValue <> 0 Then
If currentValue <> "" Then
'Cammel case the string
currentValue = UCase(Left(currentValue, 1)) & LCase(Mid(currentValue, 2))
'Upper case the content in between "( )"
splitValue = Split(currentValue, "(", 2)
currentValue = splitValue(0) & "(" & UCase(splitValue(1))
'Insert new item to the collection
listaDados.Add Item:=currentValue, Key:=currentValue
End If
End If
Next i
i = 1
'Here I copy the collection to an array
ReDim Preserve comboList(0)
comboList(0) = ""
For Each l In listaDados
ReDim Preserve comboList(i)
comboList(i) = l
i = i + 1
Next l
'Here I assign that array to the combobox
formPerda.Controls("cGrupo" & column).List = comboList
--- 编辑---
这是我如何管理代码以按我想要的方式工作。
'Get the last row the filter shows
lastRow = Sheets("SIP").Range("A65536").End(xlUp).Row
'To avoid to get the header of the table
If lastRow < 2 Then
lastRow = 2
End If
'Get the multiple range showed by the autofilter
Set lFilteredAux = Sheets("SIP").Range("A2:F" & lastRow).Cells.SpecialCells(xlCellTypeVisible)
'Check if there is more than 1 no contiguous areas
If Sheets("SIP").Range(lFilteredAux.Address).Areas.Count > 1 Then
'If Yes, do a loop through the areas
For i = 1 To Sheets("SIP").Range(lFilteredAux.Address).Areas.Count
'And add it to the lFiltered array
ReDim Preserve lFiltered(i - 1)
lFiltered(i - 1) = Sheets("SIP").Range(lFilteredAux.Address).Areas(i)
Next i
Else
'If there is only one area, it goes the old way
ReDim lFiltered(0)
lFiltered(0) = Sheets("SIP").Range(lFilteredAux.Address)
End If
现在我的 lFiltered 数组与我使用的方式有点不同,但我调整了我的 foreach 以像这样工作:
For i = 0 To UBound(lFiltered)
For j = 1 To UBound(lFiltered(i))
currentValue = Trim(lFiltered(i)(j, columnNumber))
next j
next i
非常感谢! =D
【问题讨论】:
-
lFiltered 只返回第 9 行时 lastRow 的值是多少?
-
lastRow 值始终正确。例如,我现在做了一个测试,我几乎隐藏了每一行,除了第 79 行和从 763 到 929 的行。lastRow 的值为 929,但 lFiltered 变量只得到了第 79 行。这就像“范围”方法停在第一个间隙。而且我不知道如何解决它。
-
您是否将 lFiltered 声明为 Range 变量?该名称令人困惑,因为它暗示它是一个 Long 类型的变量,但这在您的代码中不起作用 - 您需要使用 Gary 的学生所指出的 Set。
-
我将 lFiltered 变量声明为 Variant。交互后的 lFiltered 值是一个二维数组。第一个是行,第二个是列 例如: lFiltered(1,2) 给出了第一行和第二列中单元格的值。 lFiltered 不返回范围。它是值的数组。你认为我应该这样做不同吗?我将编辑我的问题并添加我的一部分代码来向您展示我在做什么。还有表格的一部分,值在哪里。
-
我想我明白你在说什么,它开始工作得很好。我更改了我的代码来执行此操作: Set lFilteredAux = Sheets("SIP").Range("A2:F" & ultimaLinha).Cells.SpecialCells(xlCellTypeVisible) 但我不能这样做: lFiltered = Sheets("SIP") .Range(lFilteredAux.Address) 因为当我有时它不起作用,例如: lFilteredAux = "$A$2:$F$4,$A$8:$F$10" 只有当我有一个范围时它才会起作用,而不是多个范围。我可以做些什么来转换我在数组中的范围,以便我可以执行 foreach?