1

I have a very large set of data that includes start and stop times for aircraft in the NAS. I want to create a macro to make a visual representation of this data in excel, like the following:

(note: this image uses fake data)

As you can see I've done the first 7 rows by hand, but there are several data files with as many as 2500+ rows each which makes the process tedious. I've tried to create a macro but I'm confused how to search for and select the appropriate range to highlight.

Here's what I have so far:

Sub autofill()

    Dim rng As Range
    Dim row As Range
    Dim cell As Range

    'set the range of the whole search area
    Set rng = Range("A2:HJ121")

    For Each row In rng.Rows
        Dim callsign As Variant
        Set callsign = cell("contents", "A" & row)
        Dim valstart As Variant
        Set valstart = cell("contents", "E" & row)
        Dim valstop As Variant
        Set valstop = cell("contents", "F" & row)

        'now select the range beginning from the column whose header matches the
        'time in valstart and ends at the time which matches the time in valstop

        Selection.Merge
        Selection.Style = "Highlight"
        Selection.Value = callsign
    Next row

End Sub

What's the easiest way of selecting the rows I need?

I'm not a programmer by profession; apologies in advance if my code demonstrates sloppy technique or violates some holy programming principles. :P

Thanks!

Community
  • 1
  • 1
Sarah
  • 13
  • 1
  • 4

2 Answers2

1

Here's my go at VBA for this.

Option Explicit

Public Sub fillSchedule()
    Dim startCol As Long
    Dim endCol As Long
    Dim i As Long
    Dim j As Long

    Dim ws As Excel.Worksheet
    Dim entryTime As Single
    Dim exitTime As Single
    Dim formatRange As Excel.Range

    Set ws = ActiveSheet

    startCol = ws.Range("H:H").Column
    endCol = ws.Range("HJ:HJ").Column

    Call clearFormats

    For i = 2 To ws.Cells(1, 1).End(xlDown).Row
        entryTime = ws.Cells(i, 5).Value
        exitTime = ws.Cells(i, 6).Value
        Set formatRange = Nothing

        For j = startCol To endCol
            If (ws.Cells(1, j).Value > exitTime) Then
                Exit For
            End If

            If ((entryTime < ws.Cells(1, j).Value) And (ws.Cells(1, j).Value < exitTime)) Then
                If (formatRange Is Nothing) Then
                    Set formatRange = ws.Cells(i, j)
                Else
                    Set formatRange = formatRange.Resize(, formatRange.Columns.Count + 1)
                End If
            End If
        Next j

        If (Not formatRange Is Nothing) Then
            Call formatTheRange(formatRange, ws.Cells(i, "A").Value)
        End If
    Next i
End Sub

Private Sub clearFormats()
    With ActiveSheet.Range("H2:HJ121")
        .clearFormats
        .ClearContents
    End With

End Sub
Private Sub formatTheRange(ByRef r As Excel.Range, ByRef callsign As String)

    r.HorizontalAlignment = xlCenter
    r.Merge

    r.Value = callsign

    ' Apply color
    With r.Interior
        .Pattern = xlSolid
        .PatternColorIndex = xlAutomatic
        .ThemeColor = xlThemeColorLight2
        .TintAndShade = 0.799981688894314
        .PatternTintAndShade = 0
    End With

    ' Apply borders
    With r.Borders(xlEdgeLeft)
        .LineStyle = xlContinuous
        .ColorIndex = 0
        .TintAndShade = 0
        .Weight = xlThin
    End With
    With r.Borders(xlEdgeTop)
        .LineStyle = xlContinuous
        .ColorIndex = 0
        .TintAndShade = 0
        .Weight = xlThin
    End With
    With r.Borders(xlEdgeBottom)
        .LineStyle = xlContinuous
        .ColorIndex = 0
        .TintAndShade = 0
        .Weight = xlThin
    End With
    With r.Borders(xlEdgeRight)
        .LineStyle = xlContinuous
        .ColorIndex = 0
        .TintAndShade = 0
        .Weight = xlThin
    End With
End Sub
Joseph
  • 5,070
  • 1
  • 25
  • 26
  • Thanks so much! This is so close to perfect. The only problem is that it encounters a runtime error at some point on all my sheets, although at different times. Some sheets it processes about half way, others only the first 10 rows. `Run-time error '91': Object variable or With block variable not set`, pointing to the line `r.HorizontalAlignment = xlCenter`. Also, it doesn't select the first cell that it should, but I think that should be easily fixable if I look at the code a bit :) – Sarah Nov 16 '12 at 18:38
  • Glad to help! :) Also, I see what's going wrong. When the code returns false for this line: "If ((entryTime < ws.Cells(1, j).Value) And (ws.Cells(1, j).Value < exitTime)) Then" then it never sets a range, which then "Nothing" gets passed into the formatTheRange() procedure. I've updated the code to check for a valid range before it calls the procedure. Please let me know if this works. – Joseph Nov 16 '12 at 19:39
  • 1
    Great minds think alike! I made the exact code change myself, and also a small change to move all the columns over to the left one (because I prefer conceptualize the start of the time at the beginning of the cell rather than the end :P). The only other thing I did was change your styling code to simply `formatRange.Style = "Highlight"` :P Btw, I would upvote this but I can't -- not enough rep! :( Need 10 more... – Sarah Nov 16 '12 at 20:36
  • I'm glad you got it working :) and yes, great minds think alike lol. No worries about the upvote. I'm happy to have helped! – Joseph Nov 16 '12 at 21:21
0

How about a conditional formatting solution?

Highlight all the cells from H2 to (last bottom right cell).

Use this formula:

=IF(AND((H$1>$E2),(H$1<$F2)),TRUE)

Then apply a fill. And if you're willing to give up the border and the name inside the filled range, it will work for you :).

Also, you may want to Freeze Panes from G2 so you can scroll all the way to the HJ column and still see the Callsign column.

Hope this helps

Joseph
  • 5,070
  • 1
  • 25
  • 26
  • Unfortunately, I do need the name and border :\ -- but thanks for the tip about freeze panes which I hadn't used before, even though I couldn't get it to work -- to freeze the 3 needed columns (callsign, entry, exit) plus the first row. The easier solution for me was to hide columns B, C, D, and G and split at H2. – Sarah Nov 15 '12 at 22:40
  • Surprised you couldn't get freeze panes to work. If you click on D2 (click D2 by itself, then click View->Freeze Panes->Freeze Panes) it should work i would think. – Joseph Nov 15 '12 at 22:46