2013-07-20 154 views
0

我刚刚开始使用VBA for Excel。大约十年前,我在大学使用了VB和Java,并且当时有能力胜任这项工作,但实质上是从头开始。 (嗯,不是像骑自行车。)如何基于单元格内容构建不连续的行范围?

我想了解的方法来建立一个范围,不只是宣布为A1:J34或其他。我的谷歌搜索面临的挑战是,当搜索“范围”和表示我所寻找的术语时,我会得到比我需要的更高级的命中,大部分命中甚至不能解决我所需的基本总结信息。

因此,下面是它的基础知识: Excel 2011在Mac上。 工作表的数据从A到M,一直到1309. 这是标题行和数据行的重复模式。啊。似乎创建工作表的人更多地考虑从工作表打印而不是数据的组织。我需要清理它和3更喜欢它在一个数据透视表中使用,并且它在这个愚蠢的重复布局中是无用的。

标题行如下: 姓氏,名字,然后是10个日期单元格。 当然,标题下的数据行是名称,然后是出席的1或0。 每个标题下有20到30个名字。然后它重复。日期每改变一次,就会从最后一次离开的地方开始。

我现在需要做的事情: 我试图通过添加以特定值开始的所有行(在列A中)将范围组装到范围变量中。在我的情况下,该值是字符串“Last Name”,所以我可以使用范围变量来保存以“Last Name”开头的所有行中的所有单元格。这将捕获所有需要使用日期格式的单元格。 (我做的,所以我就可以确保日期标题都是实际的日期格式 - 因为他们是不是所有的日期格式现在,很多都只是“常规”细胞。)

我的问题:

  1. 当告诉范围对象它的范围是什么时,你如何给它提供单元/行/列不仅仅是由编写代码的人员根据行标准输入的开始和结束单元定义的块?例如:根据A中“First Name”的存在情况,创建一个范围,其中列A到行中的行数为1,34,70,133和128.
  2. 最常用的方法是什么?
  3. 其中哪些最适合我的需要,为什么?

回答

1

下面是一个工作示例,演示如何查找“姓氏”行,构造包含所有这些行的范围对象,然后遍历该对象以搜索非日期值。通过将数据范围读入变体数组,然后在数组中搜索姓氏行和这些行内的“错误日期”,可以大大提高代码的速度。如果您有大量的行需要检查,尤其如此。

Sub DisjointRng() 

    Dim checkCol As String, checkPattern As String 
    Dim dateCols() 
    Dim lastCell As Range, usedRng As Range, checkRng As Range 
    Dim cell As Variant 
    Dim usedRow As Range, resultRng As Range, rngArea As Range 
    Dim i As Long, j As Long 

    checkCol = "A"    'column to check for "Last Name" 
    checkPattern = "Last*" 
    dateCols = Array(3, 5)  'columns to check for date formatting 

    With Worksheets("Sheet1") 
     'find the bottom right corner of data range; we determine the used range 
      'ourselves since the built-in UsedRange is sometimes out-of-synch 
     Set lastCell = .Cells(.Cells.Find(What:="*", SearchOrder:=xlRows, _ 
      SearchDirection:=xlPrevious, LookIn:=xlFormulas).Row, _ 
      .Cells.Find(What:="*", SearchOrder:=xlByColumns, _ 
      SearchDirection:=xlPrevious, LookIn:=xlFormulas).Column) 
     Set usedRng = .Range("A1:" & lastCell.Address) 
     'the column of values in which to look for "Last Name" 
     Set checkRng = .Range(checkCol & "1:" & checkCol & usedRng.Rows.Count) 
    End With 
    'step down the column of values to check for last name & add 
     'add found rows to range object 
    For Each cell In checkRng 
     If cell.Value Like checkPattern Then 
      'create a range object for the row 
      Set usedRow = Intersect(cell.EntireRow, usedRng) 
      If resultRng Is Nothing Then 
       'set the first row with "Last Name" 
       Set resultRng = usedRow 
      Else 
       'add each additional found row to the result range object 
       Set resultRng = Union(resultRng, usedRow) 
      End If 
     End If 
    Next cell 
    For Each rngArea In resultRng.Areas 
     'if found rows are continguous, Excel consolidates them 
      'into single area, so need to loop through each of the rows in area 
     For i = 1 To rngArea.Rows.Count 
      For j = LBound(dateCols) To UBound(dateCols) 
       If Not IsDate(rngArea.Cells(i, dateCols(j))) Then 
        'do something 
       End If 
      Next j 
     Next i 
    Next rngArea 
End Sub 
+0

太棒了,谢谢! 1)dateCols变量设置是否通过3,4和5数组中的位置指示列C,D和E?似乎很明显,但想要确认(noob),所以我可以将其更改为N. 2)“.Cells.Find(What:=”部分中的通配符符号(*) - 这是干什么的? 3)你把我的位置编码非嵌套的Fors内的非日期单元格的行为 - 为什么是这种情况,而不是一个rngArea.whatever后外部For语句关闭? (只是试图理解逻辑不仅仅是代码) 再次谢谢你。比我预期的代码更明智。 – user2601892

+0

顺便说一句,我会给一个+1,但我是全新的在这里,我不能投票。 – user2601892

+0

当然,如果你愿意,你可以接受答案。 1)是的,3,4,5是列号2)Find中的*是通配符 - 声明中说“找到一个包含任何内容的单元格”3)我推测你想对每个单元执行一些操作非格式化的日期单元格。外'For'循环遍历resultRng中的区域,可能看起来像(A3:X3,A7:X14,A15:X15等);对于包含多于一行的块(区域)的行,例如A7:X14;内部'For'行中的每个单元格。如果rngResult只是单个行的集合,您只需要2 For的 – chuff

0

可以使用Union操作,这样

Dim r As Range 

Set r = Range("A1, A3, A10:A12") 

或本

Set r = Union(Range("A1"), Range("A3"), Range("A10:A12")) 

您可以在迭代这个范围内像这样

Dim cl as Range 
For Each cl in r.Cells 
    ' code cell cl 
Next 

或本

Dim ar as Range 
For each ar in r.Areas 
    ' code using contiguous range ar 
    For each cl in ar.Cells 
     ' code using cell cl 
    Next 
Next 
+0

谢谢,克里斯,但不是我所得到的。 在上面的内容中,您明确指定了定义范围的单元格。我想知道如何通过扫描表单来查找范围的单元格以查找完整的行,但只有当行的第一个单元格与设置的条件匹配时才将其包括在范围的范围内。 我将不得不谷歌这是.Cells是什么。 请记住,我是一名新秀! – user2601892

相关问题