(This is not a required lesson, but Good Fun anyway.)
The procedure we used to find the end of a data range fails when there are blank cells, like this:
A line like this...
- Set rDataTable = Range(Cells(2, 1), Cells(2, 1).End(xlToRight).End(xlDown))
... would decide the data ends at row 7, the first blank cell in column 1.
It's a tricky problem to handle perfectly. The way I would do it is add a loop before the main loop that runs through the rows, finding the first row that is all blank.
It wouldn't be a counted loop (For), but a Do-Until loop. Instead of running a certain number of times, Do-Until loops run until a condition is met. For example, this...
- Dim tAnswer As String
- Do
- tAnswer = InputBox("Are goattos good?")
- tAnswer = LCase(Trim(tAnswer))
- Loop Until tAnswer = "yes"
... would loop forever until the user had acknowledged the goodness of goattos.
You can use a loop like that to look for the first row that is all blank. You have to check every cell that might have data in it.
- Do
- Next row
- Check if all the columns in the row that might have data are blank
- Loop Until there is a blank row
For example:
- Dim tCellValue As String
- Dim sRowToCheck As Single
- Dim tIsRowBlank As String
- Dim sLastDataRow As Single
- sRowToCheck = 1 ' Or 2... one less than wherever the data starts.
- Do
- ' Which row to check next?
- sRowToCheck = sRowToCheck + 1 ' First time through, this will point to the first data row.
- ' Init flag.
- tIsRowBlank = "yes"
- ' Check for col in row with data.
- tCellValue = Trim(Cells(sRowToCheck, 1))
- If tCellValue <> "" Then
- tIsRowBlank = "no"
- End If
- tCellValue = Trim(Cells(sRowToCheck, 2))
- If tCellValue <> "" Then
- tIsRowBlank = "no"
- End If
- tCellValue = Trim(Cells(sRowToCheck, 3))
- If tCellValue <> "" Then
- tIsRowBlank = "no"
- End If
- ' Loop until the flag has stayed at yes.
- Loop Until tIsRowBlank = "yes"
- sLastDataRow = sRowToCheck - 1
- MsgBox "Last data row: " & sLastDataRow
The flag pattern again.
If I was doing this for realsies, I'd replace the middle bit with a nested For loop:
- Sub FindLastDataRow()
- Dim tCellValue As String
- Dim sRowToCheck As Single
- Dim tIsRowBlank As String
- Dim sLastDataRow As Single
- Dim sCol As Single
- Const NUM_DATA_COLS = 3
- sRowToCheck = 1
- Do
- ' Which row to check next?
- sRowToCheck = sRowToCheck + 1
- ' Init flag.
- tIsRowBlank = "yes"
- ' Check all the cols that might have data.
- For sCol = 1 To NUM_DATA_COLS
- tCellValue = Trim(Cells(sRowToCheck, sCol))
- If tCellValue <> "" Then
- tIsRowBlank = "no"
- End If
- Next sCol
- ' Loop until the flag has stayed at yes.
- Loop Until tIsRowBlank = "yes"
- sLastDataRow = sRowToCheck - 1
- MsgBox "Last data row: " & sLastDataRow
- End Sub
Change NUM_DATA_COLS to check any number of cols, w/o changing the code. W00t!