AutoFit Merged Cell Row Height

AutoFit Merged Cell Row Height

You’ve most likely heard this warning — “Avoid merged cells in your Excel worksheets!”, and that is excellent advice. Merged cells can cause problems, especially when they’re in a table that you’ll be sorting and filtering. You’ll run into more problems if you try to autofit merged cell row height.

Forced to Merge

Occasionally though, you might have no choice but to use one or more merged cells on a worksheet. As long as you avoid merging table cells, and proceed with caution, things might be okay.

In the example shown below, there is an order form, and space for a note about the order. If the note will always be short, there’s no need to merge the cells – just let the text flow across the columns.

mergecellsautofit01

However, if the notes will be two or more lines, you’ll need to merge the cells, and turn on Wrap Text. Adjusting the column width would affect the product list that starts in row 12, so that’s not an option.

Merged Cell Row Height

Usually, if you add more text to a single cell, and Wrap Text is turned on, the row height automatically adjusts, to fit the text.

When the cells are merged in row 10, the row height has to be manually adjusted when the text changes. That works well, as long as you remember to do it, but it can be a nuisance, if the text changes frequently.

And if you forget to adjust the row height, you might print the order form, while key instructions are hidden.

mergecellsautofit02

AutoFit Merged Cell Row Height

To fix the worksheet, so the merged cells adjust automatically, you can add event code to the worksheet.

[Update: The original code is below, and there are several modified versions of the code in the comments. There is also an updated version of Smallman’s code in this December 2015 blog post.]

The merged cells are named OrderNote, and that name will be referenced in the event code.

mergecellsautofit03

Code to AutoFit Merged Cell Row Height

We want the row height to adjust if the OrderNote range is changed, so we’ll add code to the Worksheet_Change event.

The code that I use is based on an old Excel newsgroup example, that was posted by Excel MVP, Jim Rech.

Note: As Jeff Weir pointed out in the comments below, this code will wipe out the Undo stack, so you won’t be able to undo any steps you’ve previously taken. So, instead of using the Worksheet_Change event, you could use the workbook’s BeforePrint event, to reduce the Undo problem.

  1. Right-click on the sheet tab, and paste the following code on the worksheet module. Note: Only one Worksheet_Change event is allowed in each worksheet module.
  2. Change the range name from “OrderNote”, to the named range on your worksheet.
  3. If your worksheet is protected, you can add code to unprotect and protect the worksheet.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim MergeWidth As Single
Dim cM As Range
Dim AutoFitRng As Range
Dim CWidth As Double
Dim NewRowHt As Double
Dim str01 As String
str01 = "OrderNote"
  If Not Intersect(Target, Range(str01)) Is Nothing Then
    Application.ScreenUpdating = False
    On Error Resume Next
    Set AutoFitRng = Range(Range(str01).MergeArea.Address)
    With AutoFitRng
      .MergeCells = False
      CWidth = .Cells(1).ColumnWidth
      MergeWidth = 0
      For Each cM In AutoFitRng
          cM.WrapText = True
          MergeWidth = cM.ColumnWidth + MergeWidth
      Next
      'small adjustment to temporary width
      MergeWidth = MergeWidth + AutoFitRng.Cells.Count * 0.66
      .Cells(1).ColumnWidth = MergeWidth
      .EntireRow.AutoFit
      NewRowHt = .RowHeight
      .Cells(1).ColumnWidth = CWidth
      .MergeCells = True
      .RowHeight = NewRowHt
    End With
    Application.ScreenUpdating = True
  End If
End Sub

How It Works

The event code checks to see if the changed cell is in the OrderNote range. If it is, the code runs, and does the following:

  1. Unmerge the cells
  2. Get the width of the first column in the OrderNote range
  3. Get the total width for all columns in the OrderNote range
  4. Add a little extra to the calculated width
  5. Set the first column to the calculated total width
  6. Autofit the row, based on the note next in the first column
  7. Get the new row height
  8. Change the first column to its original width
  9. Merge the cells
  10. Set the row height to the new height

Screen updating is turned off while the code runs, and it all happens in the blink of an eye.

Test the Event Code

To test the code, make a change to the text in the named merged cells, then press Enter. The row height should adjust automatically.

Is this code, to AutoFit merged cell row height, something that you’ll use in your workbooks? Please let me know in the comments.
__________________

135 thoughts on “AutoFit Merged Cell Row Height”

  1. Hi Smallman (and Debra who started the post),
    Many thanks for all your help, without which I would be pulling what’s left of my hair out.
    All the best,
    Simon

  2. i did create this little macro

    Private Sub Worksheet_Change(ByVal Target As Range)
    If Target.WrapText = True Then
        With Target
            .Select
            .RowHeight = 1
            .WrapText = True
            .UnMerge
            .EntireRow.AutoFit
            Selection.Merge
            'vNewHeight = (.Width * .Height) / Selection.Width
            vNewHeight = .Width * .Height / Selection.Width
            If vNewHeight < 16 Then vNewHeight = 16
            .RowHeight = vNewHeight
            .VerticalAlignment = xlCenter
        End With
    End If
    End Sub
  3. Yes!!!!!
    I love it. Well done Juan!
    This is a very minor point, the code would not run correctly on my machine as I use Option Explicit, I added the variable declaration:

    Dim vNewHeight As Single

    then it runs like a dream. This is an evolution in this technique. Once again Well done!!!!!!
    I have to add this to my site but will credit your work. I am not easily this impressed – simply wonderful.
    Take care
    Smallman

    Option Explicit
    Private Sub Worksheet_Change(ByVal Target As Range)
    Dim vNewHeight As Single
        If Target.WrapText = True Then
            With Target
                .Select
                .RowHeight = 1
                .WrapText = True
                .UnMerge
                .EntireRow.AutoFit
                Selection.Merge
                vNewHeight = .Width * .Height / Selection.Width
                If vNewHeight < 16 Then vNewHeight = 16
                    .RowHeight = vNewHeight
                    .VerticalAlignment = xlCenter
            End With
        End If
    End Sub
  4. Hi Smallman,
    I am very new to codes but have read the posts & trying my luck to combine the following codes from your post (on automating the autofit of rows height for merged cells, maintaining the unlocked ‘status’ of merged cells etc) & Suzi’s (on protected worksheet). However the codes don’t seem to work for my worksheet. Would really appreciate if you can help.

    Option Explicit
     Option Base 1
    Private Sub Worksheet_Change(ByVal Target As Range)
     If Not Intersect(Target, Range("C37,C38,C39,C40,C41,C42,C43,C44,C45,C46,C47,C48,M37,M38,M39,M40,M41,M42,M43,M44,M45,M46,M47,M48,W37,W38,W39,W40,W41,W42,W43,W44,W45,W46,W47,W48")) Is Nothing Then
     FixMerged
     End If
     End Sub
     Sub FixMerged()
     Dim mw As Single
     Dim cM As Range
     Dim rng As Range
     Dim cw As Double
     Dim rwht As Double
     Dim ar As Variant
     Dim i As Integer
     ActiveSheet.Unprotect "password" ', userinterfaceonly:=True
    Application.ScreenUpdating = False
     ar = Array("C37", "C38", "C39", "C40", "C41", "C42", "C43", "C44", "C45", "C46", "C47", "C48", "M37", "M38", "M39", "M40", "M41", "M42", "M43", "M44", "M45", "M46", "M47", "M48", "W37", "W38", "W39", "W40", "W41", "W42", "W43", "W44", "W45", "W46", "W47", "W48")
     For i = 1 To UBound(ar)
     On Error Resume Next
     Set rng = Range(Range(ar(i)).MergeArea.Address)
     With rng
     .MergeCells = False
     cw = .Cells(1).ColumnWidth
     mw = 0
     For Each cM In rng
     cM.WrapText = True
     mw = cM.ColumnWidth + mw
     Next
     mw = mw + rng.Cells.Count * 0.66
     .Cells(1).ColumnWidth = mw
     .EntireRow.AutoFit
     rwht = .RowHeight
     .Cells(1).ColumnWidth = cw
     .MergeCells = True
     .RowHeight = rwht
     End With
     Next i
     Application.ScreenUpdating = True
     Range("C37:AF48").Locked = False
     ActiveSheet.Protect "password"
     End Sub
  5. Hi Olivia
    This method is good if you have say one column of cells where you want fitted. However, when you have the same row in two or more columns then the last columns being evaluated will affect the earlier columns as Excel will evaluate Column C, then M the way your coding is written.
    Also you don’t need to put every cell you want evaluated down in the coding. You can just put your ranges like so:
    Range(“C37:C48, M37:M48”) etc etc or [C37:C48, M37:M48] etc
    The following is an example using your first two ranges.

    Private Sub Worksheet_Change(ByVal Target As Range)
    Dim vNewHeight As Single
    ActiveSheet.Unprotect "password"
    If Not Intersect(Target, [C37:C48, M37:M48]) Is Nothing Then
        If Target.WrapText = True Then
            With Target
                .Select
                .RowHeight = 1
                .WrapText = True
                .UnMerge
                .EntireRow.AutoFit
                Selection.Merge
                vNewHeight = .Width * .Height / Selection.Width
                If vNewHeight < 16 Then vNewHeight = 16
                .RowHeight = vNewHeight
                .VerticalAlignment = xlCenter
            End With
        End If
    ActiveSheet.Protect "password"
    End If
    End Sub
    

    Just so we are clear – if Column M is a larger bit of text say in Row 37 then this will have an adverse affect on C37. This method is best for rows which don’t have another cell being evaluated in the same column.
    Hope that helps Olivia. You can email me directly if you want me to take a look at your file but pretty sure this is the issue. Just test on one column, then 2 then 3 and you will get the idea. OR I could send you a file with the above code working beautifully.
    Take care
    Smallman

  6. Hi Smallman,
    Thank you for your reply! My merged cells is made up of a few columns in each row (total 12 rows, from Row 37 to 48), eg C37:L37, M37:V37, W37:AF37.
    Have tried your codes and encountered the following message:
    Compile error: Syntax error
    After I clicked ‘Ok’,
    ‘Private Sub Worksheet_Change(ByVal Target As Range)’ is highlighted in yellow &
    ‘If vNewHeight < 16 Then vNewHeight = 16’ is in red font.
    Not sure what these mean. Will you be able to help?
    Thanks so much!! It’s really great to have you guys around!! =)
    Olivia

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.