0

我刚刚开始使用 VBA for Excel。近十年前,我在大学里使用过 VB 和 Java,那时我已经能胜任了,但基本上是从头开始。(嗯,不像骑自行车。)

我试图了解构建一个不只是声明为 A1:J34 或其他的范围的方法。我的谷歌搜索面临的挑战在于,在搜索“范围”和表明我所寻求的术语时,我得到的点击量远远超过我所需要的,其中大部分点击量甚至没有解决我需要的基本摘要信息。

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

标题行如下:姓氏、名字,然后是 10 个日期单元格。标题下的数据行当然是姓名,然后是 1 或 0 代表出勤率。每个标题下有 20 到 30 个名称。然后它重复。并且每隔几组日期就会改变一次,从上一组停止的地方开始。

我现在需要做的是:我正在尝试通过添加以特定值开头的所有行(在 A 列中)将一个范围组合成一个范围变量。在我的情况下,该值是字符串“姓氏”,因此我可以让范围变量保存所有以“姓氏”开头的行中的所有单元格。然后,这将捕获所有需要采用日期格式的单元格。(我这样做是为了确保日期标题实际上都是日期格式 - 因为它们现在不都是日期格式,许多只是“常规”单元格。)

我的问题:

  1. 当告诉一个范围对象它的范围是什么时,你如何给它提供单元格/行/列,这些单元格/行/列不仅仅是由编写代码的人输入的开始和结束单元格定义的块,而是基于行标准?例如:根据 A 中“名字”的存在,创建一个 Range,其中包含从 A 到 I 列的第 1、34、70、93 和 128 行。
  2. 最常见的方法是什么?
  3. 其中哪一个最适合我的需要,为什么?
4

2 回答 2

1

您可以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
于 2013-07-20T10:47:34.653 回答
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
于 2013-07-23T17:48:30.797 回答