0

I am working with data where the only consistency is the layout and the bold headings to distinguish between a new date.

I am trying to find the cells in between these cells in bold, find the value "Individual" (in column A) in the selected rows, then sum the values of the given rows in column D (as there can be more then 1 row with "Individual"), and copy this new value to a different cell. Since the cells between the bold is one date, if the value is not there, the output cell needs to shift down one without filling in anything. Here is what I have so far:

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

How can I loop through the data and each time it loops through a range, no matter if it finds the value (e.g. individual) or not, shifts down one row on the output cell? Also, how can I change the findrow to be a format (Bold) rather then a value?

Here is some data for reference: enter image description here

This is what I am trying to get it to look like: enter image description here

Community
  • 1
  • 1
Gabriela
  • 85
  • 1
  • 1
  • 8
  • seeing some data and expected output might help. Is filtering on "Individual" not an option? – QHarr Apr 07 '18 at 16:24
  • Hi QHarr - unfortunately not since it would filter all "Individuals" (for example) without regarding the date. I've included some screenshots of the data and what I am trying to achieve. The second picture is me putting in the data manually. But if would just take hours to do on a regular basis. – Gabriela Apr 07 '18 at 16:32

1 Answers1

0

So you have a good start to trying to work through your data. I have a few tips to share that can hopefully help get you closer. (And please come back and ask more questions as you work through it!)

First and foremost, try to avoid using Select or Activate in your code. When you look at a recorded macro, I know that's all you see. BUT that is a recording of your keystrokes and mouseclicks (selecting and activating). You can access the data in a cell or a range without it (see my example below).

In order to approach your data, your first issue is to figure out where your data set starts (which row) and where it ends. Generally, your data is between cells with BOLD data. The exception is the last data set, which just has a many blank rows (until the end of the column). So I've created a function that starts at a given row and checks each row below it to find either a BOLD cell or the end of the data.

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

To show you how to use that with your specific data, I've created a test subroutine indicating how to loop through all the different data sets:

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

Use both of those together and see if that can get you closer to a full solution.

EDIT: I should have deleted that section of code. It was from an earlier concept I had that didn't completely work. I commented out those lines (for the sake of later clarity in reading the comments). Below, I'll include the function and why it didn't completely work for this situation.

So here's the function in question:

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

Now, while this function works perfectly well, the situation is DOES NOT account for is the end of the last data set. In other words, a situation like this:

enter image description here

The function FindNextBoldInColumn will return nothing in this case and not the end of the data. So I (should have completely) deleted that function and replaced it with EndRowOfDataSet which does exactly what you need. Sorry about that.

PeterT
  • 8,232
  • 1
  • 17
  • 38
  • always confuses me but why is ws passed ByRef and not ByVal? – QHarr Apr 07 '18 at 21:24
  • Variables passed as parameters to `Subs` or `Functions` can be thought of in a couple different ways. One is if they're "mutable". If we pass in `ByVal newValue As Long` then inside the sub I could `newValue = 1732354` and the scope of that change would only stay inside that sub. If we pass in `ByRef newValue As Long`, now any change we make to `newValue` will *also* happen to the variable outside of the sub. Technically you can think of it like this: if passing `ByVal` then a *copy* of the value is created in the sub's variable; if passing `ByRef` then you're using the caller's variable. – PeterT Apr 07 '18 at 21:39
  • 1
    The other reason to decide which to use is if the parameter is an object. In the case of your question, `ws` is a `Worksheet` object. We don't necessarily need to create a whole internal copy of the worksheet object, so usually it's passed `ByRef` more for efficiency. – PeterT Apr 07 '18 at 21:41
  • Ahh...ok...I thought as no change to ws then ByVal but makes sense if more efficient to pass ByRef if know no changes are made. – QHarr Apr 07 '18 at 21:42
  • Thanks Peter! Much appreciate the help! I am getting stuck on running the code now - I am getting the "Compile error - Sub of function not defined" How can I rectify this? The error is from this line - FindNextBoldInColumn – Gabriela Apr 08 '18 at 07:31
  • Updated the answer above. That code should have been deleted, but I've explained the function. In a way, you get to see how your thinking can evolve as you try to solve a problem. – PeterT Apr 08 '18 at 16:23
  • Thanks PeterT! I am getting closer to the answer, am in the process of filling in the code for the macro to copy the number of room nights to another cell in another sheet. I am stuck at the Finding part, which worked fine before. I also tweaked your code a little, as I was getting some synax errors. As far as I can tell, it loops fine through the WS but i haven't gotten it to copy the wanted cell and past to another yet. – Gabriela Apr 09 '18 at 18:53