【问题标题】:Select cells between bold cells using a loop使用循环选择粗体单元格之间的单元格
【发布时间】:2018-04-07 16:02:59
【问题描述】:

我正在处理数据,其中唯一的一致性是布局和粗体标题以区分新日期。

我试图在这些单元格之间以粗体查找单元格,在所选行中找到值“Individual”(在 A 列中),然后将 D 列中给定行的值相加(因为可以有更多然后 1 行带有“个人”),并将这个新值复制到不同的单元格。 由于粗体之间的单元格是一个日期,如果该值不存在,则输出单元格需要向下移动一个而不填写任何内容。 这是我目前所拥有的:

Sub SelectBetween()

Dim findrow As Long, findrow2 As Long

findrow = range("A:A").Find("test1", range("A1")).Row
findrow2 = range("A:A").Find("test2", range("A" & findrow)).Row
range("A" & findrow + 1 & ":A" & findrow2 - 1).Select

Selection.Find("Individual").Activate

range("D" & (ActiveCell.Row)).Select
Selection.copy
sheets("Mix of Business").Select
range("C4").Select
ActiveSheet.Paste

Exit Sub

errhandler:
MsgBox "No Cells containing specified text found"

End Sub

如何循环遍历数据,并且每次循环遍历一个范围时,无论它是否找到值(例如个人),都会在输出单元格上向下移动一行?另外,如何将 findrow 更改为格式(粗体)而不是值?

以下是一些数据供参考:

这就是我试图让它看起来像的样子:

【问题讨论】:

  • 查看一些数据和预期的输出可能会有所帮助。过滤“个人”不是一个选项吗?
  • 嗨 QHarr - 不幸的是,它不会过滤所有“个人”(例如)而不考虑日期。我已经包含了一些数据的屏幕截图以及我想要实现的目标。第二张图片是我手动输入数据。但是如果定期进行的话,只需要几个小时。

标签: vba excel loops format range


【解决方案1】:

因此,您有一个良好的开端来尝试处理您的数据。我有一些技巧要分享,希望能帮助你更接近。 (请在您完成工作时回来提出更多问题!)

首先,尝试avoid using Select or Activate in your code。当您查看录制的宏时,我知道您看到的就是这些。但这是您的击键鼠标点击(选择和激活)的记录。您可以在没有它的情况下访问单元格或区域中的数据(请参见下面的示例)。

为了处理您的数据,您的第一个问题是确定数据集的开始位置(哪一行)和结束位置。通常,您的数据位于具有 BOLD 数据的单元格之间。例外是最后一个数据集,它只有许多空白行(直到列的末尾)。因此,我创建了一个从给定行开始的函数,并检查其下方的每一行以查找粗体单元格或数据末尾。

Private Function EndRowOfDataSet(ByRef ws As Worksheet, _
                                 ByVal startRow As Long, _
                                 Optional maxRowsInDataSet As Long = 50) As Long
    '--- checks each row below the starting row for either a BOLD cell
    '    or, if no BOLD cells are detected, returns the last row of data
    Dim checkCell As Range
    Set checkCell = ws.Cells(startRow, 1)  'assumes column "A"
    Dim i As Long
    For i = startRow To maxRowsInDataSet
        If ws.Cells(startRow, 1).Font.Bold Then
            EndRowOfDataSet = i - 1
            Exit Function
        End If
    Next i
    '--- if we make it here, we haven't found a BOLD cell, so
    '    find the last row of data
    EndRowOfDataSet = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
End Function

为了向您展示如何将其用于您的特定数据,我创建了一个测试子例程,指示如何遍历所有不同的数据集:

Option Explicit

Public Sub DataBetween()
    Dim thisWB As Workbook
    Dim dataWS As Worksheet
    Set thisWB = ThisWorkbook
    Set dataWS = thisWB.Sheets("YourNameOfSheetWithData")

    '--- find the first bold cell...
    'Dim nextBoldCell As Range
    'Set nextBoldCell = FindNextBoldInColumn(dataWS.Range("A1"))

    '--- now note the start of the data and find the next bold cell
    Dim startOfDataRow As Long
    Dim endOfDataRow As Long
    Dim lastRowOfAllData As Long
    startOfDataRow = 3
    lastRowOfAllData = dataWS.Cells(ws.Rows.Count, "A").End(xlUp).Row

    '--- this loop is for all the data sets...
    Loop
        endOfDataRow = EndRowOfDataSet(dataWS, startOfDataRow)

        '--- this loop is to work through one data set
        For i = startOfDataRow To endOfDataRow
            '--- work through each of the data rows and copy your
            '    data over to the other sheet here
        Next i
        startOfDataRow = endOfDataRow + 1
    Do While endOfDataRow < lastRowOfAllData

End Sub

同时使用这两种方法,看看是否能让您更接近完整的解决方案。

编辑:我应该删除那段代码。这是我早期的一个概念,但它并没有完全奏效。我注释掉了这些行(为了以后在阅读 cmets 时更清楚)。下面,我将介绍该功能以及为什么它不能完全适用于这种情况。

所以这是有问题的函数:

Public Function FindNextBoldInColumn(ByRef startCell As Range, _
                                     Optional columnNumber As Long = 1) As Range
    '--- beginning at the startCell row, this function check each
    '    lower row in the same column and stops when it encounters
    '    a BOLD font setting
    Dim checkCell As Range
    Set checkCell = startCell
    Do While Not checkCell.Font.Bold
        Set checkCell = checkCell.Offset(1, 0)
        If checkCell.Row = checkCell.Parent.Rows.Count Then
            '--- we've reached the end of the column, so
            '    return nothing
            Set FindNextBoldInColumn = Nothing
            Exit Function
        End If
    Loop
    Set FindNextBoldInColumn = checkCell
End Function

现在,虽然这个函数工作得很好,但情况是不考虑最后一个数据集的结尾。换句话说,像这样的情况:

在这种情况下,函数FindNextBoldInColumn 将返回nothing,而不是数据的结尾。所以我(应该完全)删除了该功能并用 EndRowOfDataSet 替换它,这正是你所需要的。对此感到抱歉。

【讨论】:

  • 总是让我感到困惑,但为什么 ws 通过 ByRef 而不是 ByVal?
  • 作为参数传递给SubsFunctions 的变量可以用几种不同的方式来考虑。一个是它们是否“可变”。如果我们传入ByVal newValue As Long,那么在子内部我可以newValue = 1732354,并且该更改的范围将仅保留在该子内部。如果我们传入ByRef newValue As Long,现在我们对newValue 所做的任何更改都将发生在子外部的变量上。从技术上讲,您可以这样想:如果传递ByVal,则在子变量中创建值的副本;如果传递ByRef,那么你正在使用调用者的变量。
  • 决定使用哪个的另一个原因是参数是否为对象。对于您的问题,ws 是一个 Worksheet 对象。我们不一定需要创建工作表对象的完整内部副本,因此通常它通过ByRef 更多以提高效率。
  • 啊...好吧...我认为 ws 然后 ByVal 没有变化,但如果知道没有进行任何更改,则通过 ByRef 更有效是有意义的。
  • 谢谢彼得!非常感谢帮助!我现在无法运行代码 - 我收到“编译错误 - 未定义函数的子” 我该如何纠正这个问题?错误来自这一行 - FindNextBoldInColumn
猜你喜欢
  • 1970-01-01
  • 2019-05-14
  • 1970-01-01
  • 2011-10-28
  • 2023-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-24
相关资源
最近更新 更多