48

I am looking to programmatically freeze the top row of an Excel worksheet from VBA. The end goal is to produce the same effect as the View > Freeze Panes > Freeze Top Row command in Excel 2007 so that the top row of the worksheet is frozen and users can see the top row of the worksheet even as they scroll through the data.

ashleedawg
  • 20,365
  • 9
  • 72
  • 105
LJ.
  • 875
  • 2
  • 9
  • 13

6 Answers6

45
Rows("2:2").Select
ActiveWindow.FreezePanes = True

Select a different range for a different effect, much the same way you would do manually. The "Freeze Top Row" really just is a shortcut new in Excel 2007 (and up), it contains no added functionality compared to earlier versions of Excel.

Tomalak
  • 332,285
  • 67
  • 532
  • 628
  • 6
    Seems like ScreenUpdating has to be on for this to work, but otherwise great. Thanks! – LJ. Jul 12 '10 at 23:25
  • 3
    I'm unclear on how you are freezing the top row by selecting the top row. To freeze the top row, the selection should be `Rows(2)` or `Rows("2:2")`. Selecting `Row("1:1")` results in a four quadrant split of the worksheet. –  Jul 29 '15 at 15:10
  • 7
    For a better solution see [This Answer](http://stackoverflow.com/a/34095034/445425) – chris neilsen May 23 '16 at 23:43
  • 2
    @chrisneilsen thanks for that, that other answer is actually much better. – hammythepig Jan 04 '17 at 21:57
22

Tomalak already gave you a correct answer, but I would like to add that most of the times when you would like to know the VBA code needed to do a certain action in the user interface it is a good idea to record a macro.

In this case click Record Macro on the developer tab of the Ribbon, freeze the top row and then stop recording. Excel will have the following macro recorded for you which also does the job:

With ActiveWindow
    .SplitColumn = 0
    .SplitRow = 1
End With
ActiveWindow.FreezePanes = True
Dirk Vollmar
  • 172,527
  • 53
  • 255
  • 316
  • 3
    Yes. This is the right answer. No need to select any part of the worksheet. – Joshua Stafford Feb 03 '15 at 16:58
  • 2
    Good answer but I'm curious why the last statement wasn't tucked into the With ... End With statement. –  Jul 29 '15 at 14:32
  • @Jeeped: This is just the raw output of the Excel macro recorder. Of course, you can include the line in the `With` block. – Dirk Vollmar Jul 29 '15 at 15:51
  • @Joshua Stafford: no this is not the "right" answer. One side effect of this technique is that it leaves the Split window state active so that, if you then decide to manually change the freeze-panes state to include a frozen column range on the left (for example), you can't do so unless you happen to notice that the Split state is active and know that you must first turn it off. In effect, that's a subtle "bug" in this technique, which can be very frustrating for the unaware or novice user. Some variation on Dannid's solution, below, avoids that problem. – pstraton Feb 03 '22 at 02:26
  • Man. I dealt with this 7 years ago. I no longer remember, so I'll defer to you. – Joshua Stafford Feb 04 '22 at 04:11
15

The problem with the recorded macro is the same as the problem with the built-in action: Excel chooses to freeze the top visible row, rather than the actual top row where the header information can be found.

The purpose of a macro in this case is to freeze the actual top row. When I am viewing row #405592 and I need to check the header for the column (because I forgot to freeze rows when I opened the file), I have to scroll to the top, freeze the top row, then find my way back to row #405592 again. Since I believe this is stupid behavior, I want a macro to correct it, but, like I said, the recorded macro just mimics the same stupid behavior.

I am using Office 2011 for Mac OS X Lion

Update (2 minutes later):

I found a solution here: http://www.ozgrid.com/forum/showthread.php?t=19692

Dim r As Range 
Set r = ActiveCell 
Range("A2").Select 
With ActiveWindow 
    .FreezePanes = False 
    .ScrollRow = 1 
    .ScrollColumn = 1 
    .FreezePanes = True 
    .ScrollRow = r.Row 
End With 
r.Select 
Dannid
  • 1,507
  • 1
  • 20
  • 17
  • 2
    For any other newbies like me: I was able to freeze the top 8 rows (where my report "dashboard" resides) by making the Range("A9") without changing anything else. – Sean Oct 24 '13 at 23:30
  • Beware: instead of **Range("A2").Select**, it may be tempting to to do something like **Range("1:1").Select** or **Rows(1).Select**, but doing so actually creates a quad-window freeze-panes state. (With no apparent usefulness, so maybe an old Excel bug?) – pstraton Feb 03 '22 at 01:45
9

Just hit the same problem... For some reason, the freezepanes command just caused crosshairs to appear in the centre of the screen. It turns oout I had switched ScreenUpdating off! Solved with the following code:

Application.ScreenUpdating = True
Cells(2, 1).Select
ActiveWindow.FreezePanes = True

Now it works fine.

Tom M
  • 91
  • 1
  • 1
7

To expand this question into the realm of use outside of Excel s own VBA, the ActiveWindow property must be addressed as a child of the Excel.Application object.

Example for creating an Excel workbook from Access:

Using the Excel.Application object in another Office application's VBA project will require you to add Microsoft Excel 15.0 Object library (or equivalent for your own version).

Option Explicit

Sub xls_Build__Report()
    Dim xlApp As Excel.Application, ws As Worksheet, wb As Workbook
    Dim fn As String

    Set xlApp = CreateObject("Excel.Application")
    xlApp.DisplayAlerts = False
    xlApp.Visible = True

    Set wb = xlApp.Workbooks.Add
    With wb
        .Sheets(1).Name = "Report"
        With .Sheets("Report")

            'report generation here

        End With

        'This is where the Freeze Pane is dealt with
        'Freezes top row
        With xlApp.ActiveWindow
            .SplitColumn = 0
            .SplitRow = 1
            .FreezePanes = True
        End With

        fn = CurrentProject.Path & "\Reports\Report_" & Format(Date, "yyyymmdd") & ".xlsx"
        If CBool(Len(Dir(fn, vbNormal))) Then Kill fn
        .SaveAs FileName:=fn, FileFormat:=xlOpenXMLWorkbook
    End With

Close_and_Quit:
    wb.Close False
    xlApp.Quit
End Sub

The core process is really just a reiteration of previously submitted answers but I thought it was important to demonstrate how to deal with ActiveWindow when you are not within Excel's own VBA. While the code here is VBA, it should be directly transcribable to other languages and platforms.

  • 1
    You could also use `Set xlApp = New Excel.Application`, or even `Dim xlApp As New Excel.Application`. – Zev Spitz Oct 10 '16 at 15:28
3
Rows("2:2").Select
ActiveWindow.FreezePanes = True

This is the easiest way to freeze the top row. The rule for FreezePanes is it will freeze the upper left corner from the cell you selected. For example, if you highlight C10, it will freeze between columns B and C, rows 9 and 10. So when you highlight Row 2, it actually freeze between Rows 1 and 2 which is the top row.

Also, the .SplitColumn or .SplitRow will split your window once you unfreeze it which is not the way I like.

ian0411
  • 4,115
  • 3
  • 25
  • 33