Excel 创建范围时xlCellTypeVisible不起作用

Excel 创建范围时xlCellTypeVisible不起作用,excel,vba,Excel,Vba,我试图在Excel 2010中使用VBA创建一个范围,仅用于可见的行。我已经过滤掉了我不想要的值,并且我使用了关键字xlCelltypeVisible,但是,当我测试它时,该范围仍然显示该范围内应该隐藏的字段 我尝试了几种不同的创建范围的方法,但似乎没有任何效果。似乎xlCellTypevisible不起作用 这不是我正在使用的实际工作表,但出于演示目的,这正好总结了我的问题: Sub create_range() ActiveSheet.Range("$A$3:$C$8").Auto

我试图在Excel 2010中使用VBA创建一个范围,仅用于可见的行。我已经过滤掉了我不想要的值,并且我使用了关键字xlCelltypeVisible,但是,当我测试它时,该范围仍然显示该范围内应该隐藏的字段

我尝试了几种不同的创建范围的方法,但似乎没有任何效果。似乎xlCellTypevisible不起作用

这不是我正在使用的实际工作表,但出于演示目的,这正好总结了我的问题:

Sub create_range()

    ActiveSheet.Range("$A$3:$C$8").AutoFilter Field:=3, Criteria1:="North"
    Set a = Range("A3", Range("A" & Rows.Count).End(xlUp)).SpecialCells(xlCellTypeVisible)

    MsgBox (a(3))



End Sub
在这种情况下,我有三列,A3=optA,B3=optB,C3=optC

在选项A字段下,我有A、B、C、D、E 在选项B字段下,我有1,2,3,4,5 在选项C字段下,我有北、东、西、南、北

正如您在上面的代码中所看到的,我已经在Opt C字段中过滤了North的值。因此,在a列中,我看到了Opt a、a、E

我的期望是,当我创建一个范围时,我可以选择这些选项,并且只能选择这些选项。但这是行不通的。如果选择a1,我正确地将选项A视为A3,这就是我所期望的。但当我选择第三个,应该是a3范围内的最终值时,我看到的是B而不是E


它的最佳实践是始终在VBA中限定所有对象。否则,意外的结果就会发生

试试这个:

Option Explicit 'always include this at top of your modules; it forces variable declaration and saves you from massive headaches :)

Sub create_range()

    Dim mySheet as Worksheet
    Set mySheet = Worksheets("Sheet1") 'change as needed

    With mySheet

       .Range("$A$3:$C$8").AutoFilter Field:=3, Criteria1:="North"

        Dim a as Range 'you need to declare as a range, since you are setting it to a range object
        Set a = .Range("A3", .Range("A" & Rows.Count).End(xlUp)).SpecialCells(xlCellTypeVisible)

       MsgBox a.Areas.Item(1).Cells(1,1).Value 'first cell

       Dim lastA as Range 'in case the last area is contiguous
       Set lastA = a.Areas.Item(a.Areas.Count)
       Msgbox lastA.Cells(lastA.Rows.Count,1) 'last cell

   End With

End Sub

它的最佳实践是始终在VBA中限定所有对象。否则,意外的结果就会发生

试试这个:

Option Explicit 'always include this at top of your modules; it forces variable declaration and saves you from massive headaches :)

Sub create_range()

    Dim mySheet as Worksheet
    Set mySheet = Worksheets("Sheet1") 'change as needed

    With mySheet

       .Range("$A$3:$C$8").AutoFilter Field:=3, Criteria1:="North"

        Dim a as Range 'you need to declare as a range, since you are setting it to a range object
        Set a = .Range("A3", .Range("A" & Rows.Count).End(xlUp)).SpecialCells(xlCellTypeVisible)

       MsgBox a.Areas.Item(1).Cells(1,1).Value 'first cell

       Dim lastA as Range 'in case the last area is contiguous
       Set lastA = a.Areas.Item(a.Areas.Count)
       Msgbox lastA.Cells(lastA.Rows.Count,1) 'last cell

   End With

End Sub

这个问题是由Excel处理两件事的方式引起的:定义范围之外的单元格和非连续范围

对于第一个:如果我定义rng=RangeA1:B2,然后调用MsgBox rng.Cells3,3.Address,它将给我C3,即使这不是范围的一部分。Excel会自动超出范围

对于第二个:在您的示例中,MsgBox a.Address将给出A3:A4、A8—一个包含2个A3:A4和A8的范围。当您尝试在不指定区域的情况下引用它时,它将默认为第一个区域A3:A4,然后根据out first point扩展范围以查找值

下面是一个粗略函数,用于返回非连续列中的第n个单元格:

Function NthCellInColumn(ByRef Target As Range, ByRef Cell As Long) As Range
    Dim DiscardedCells As Long, WhichArea As Long

    DiscardedCells = 0
    For WhichArea = 1 To Target.Areas.Count
        'Is the cell in this area?
        If Cell <= DiscardedCells + Target.Areas(WhichArea).Cells.Count Then
            'Yes, so let's find it
            Set NthCellInColumn = Target.Areas(WhichArea).Cells(Cell - DiscardedCells, 1)
            Exit For 'Stop looping through areas
        Else
            'No, so Discard the Cells
            DiscardedCells = DiscardedCells + Target.Areas(WhichArea).Cells.Count
        End If
    Next WhichArea
End Function

按如下方式使用:MsgBox NthCellInColumna,3.Value

此问题是由Excel处理两件事情的方式引起的:定义范围之外的单元格和非连续范围

对于第一个:如果我定义rng=RangeA1:B2,然后调用MsgBox rng.Cells3,3.Address,它将给我C3,即使这不是范围的一部分。Excel会自动超出范围

对于第二个:在您的示例中,MsgBox a.Address将给出A3:A4、A8—一个包含2个A3:A4和A8的范围。当您尝试在不指定区域的情况下引用它时,它将默认为第一个区域A3:A4,然后根据out first point扩展范围以查找值

下面是一个粗略函数,用于返回非连续列中的第n个单元格:

Function NthCellInColumn(ByRef Target As Range, ByRef Cell As Long) As Range
    Dim DiscardedCells As Long, WhichArea As Long

    DiscardedCells = 0
    For WhichArea = 1 To Target.Areas.Count
        'Is the cell in this area?
        If Cell <= DiscardedCells + Target.Areas(WhichArea).Cells.Count Then
            'Yes, so let's find it
            Set NthCellInColumn = Target.Areas(WhichArea).Cells(Cell - DiscardedCells, 1)
            Exit For 'Stop looping through areas
        Else
            'No, so Discard the Cells
            DiscardedCells = DiscardedCells + Target.Areas(WhichArea).Cells.Count
        End If
    Next WhichArea
End Function

像这样使用:MsgBox NthCellInColumna,3.Value

您得到的具体错误是什么?为什么你没有定义一个-它是一个范围,还是一个数组?如果您没有指定内容,那么可能会出现未指定的错误。然而,我怀疑主要的问题是Excel正在“填充”您的非连续范围以生成一个连续范围,我没有收到错误。我只是得到了一个不同于我预期的值。在我定义变量时,这似乎不是一个问题。我也试过了,没什么区别。我正在寻找的是一种方法,使一个范围内的只是可见的细胞,使我只能访问他们的其他原因。你得到什么具体的错误?为什么你没有定义一个-它是一个范围,还是一个数组?如果您没有指定内容,那么可能会出现未指定的错误。然而,我怀疑主要的问题是Excel正在“填充”您的非连续范围以生成一个连续范围,我没有收到错误。我只是得到了一个不同于我预期的值。在我定义变量时,这似乎不是一个问题。我也试过了,没什么区别。我正在寻找的是一种方法,使一个范围内的只是可见的细胞,使我只能访问他们的其他原因。谢谢你,斯科特。当我运行该代码时,我确实看到地址中列出的值是A3、A4和A8,但是,我仍然无法按我想要的方式访问它们。例如,假设我想取该范围内的最后一个值,即字母E,并将其移动到字段E1。我将如何通过代码实现这一点?这正是我真正想表达的意思。在应用过滤器之前,我需要一种方法来识别第一个和最后一个可见值,而不知道它们在工作表上的显示位置。谢谢。我在工作簿中创建了一个新模块,并复制和粘贴了您的代码。对于行MsgBox a.Areas.Item1.value,我得到一个错误:运行时错误'13':
类型不匹配。在获取E值的最后一行方面,这是非常有效的。尝试我的新编辑,我忘了放置.Cells1,1部分谢谢,但这将返回Opt A。我希望获得第一个值A。我只是想澄清一下,我并不总是知道它将是过滤器开始处下方的第一个值。它可能是256行中的第103行,最后一个值可能是202。我只是为了简单起见才做了这个例子。@Robbie,从Ank you中排除标题行,Scott。当我运行该代码时,我确实看到地址中列出的值是A3、A4和A8,但是,我仍然无法按我想要的方式访问它们。例如,假设我想取该范围内的最后一个值,即字母E,并将其移动到字段E1。我将如何通过代码实现这一点?这正是我真正想表达的意思。在应用过滤器之前,我需要一种方法来识别第一个和最后一个可见值,而不知道它们在工作表上的显示位置。谢谢。我在工作簿中创建了一个新模块,并复制和粘贴了您的代码。对于行MsgBox a.Areas.Item1.value,我得到一个错误:运行时错误“13”:类型不匹配。在获取E值的最后一行方面,这是非常有效的。尝试我的新编辑,我忘了放置.Cells1,1部分谢谢,但这将返回Opt A。我希望获得第一个值A。我只是想澄清一下,我并不总是知道它将是过滤器开始处下方的第一个值。它可能是256行中的第103行,最后一个值可能是202。我做这个例子只是为了简单。@Robbie,从aI中排除标题行我很困惑。当我不知道该范围内有多少行时,如何告诉此函数查找该范围内的最后一个单元格。例如,NthCellInColumna,*最后一个cell*@ScottHoltzman工作表function.Counta?它只是一个快速/粗略的函数,可以抓取第n个项目,如果您通过了第n个项目,则不会返回任何内容end@Chronocidal-明白了,我很困惑。当我不知道该范围内有多少行时,如何告诉此函数查找该范围内的最后一个单元格。例如,NthCellInColumna,*最后一个cell*@ScottHoltzman工作表function.Counta?它只是一个快速/粗略的函数,可以抓取第n个项目,如果您通过了第n个项目,则不会返回任何内容end@Chronocidal-明白了。