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.

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.

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.

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.
- 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.
- Change the range name from “OrderNote”, to the named range on your worksheet.
- 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:
- Unmerge the cells
- Get the width of the first column in the OrderNote range
- Get the total width for all columns in the OrderNote range
- Add a little extra to the calculated width
- Set the first column to the calculated total width
- Autofit the row, based on the note next in the first column
- Get the new row height
- Change the first column to its original width
- Merge the cells
- 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.
__________________
Yes I did mention that or did you miss that bit? It is just above in black and white.
Take care
Smallman
Yes I did miss the bit where you said “Run this code only once”, because also above in “black and white” is your statement With the example above you could use something like the following within your procedure to unlock the cells in question.
So if Suzi implemented your approach as you originally posted, then every nth time she runs her routine, your code addition does something that is not necessary.
Even had you not said that above, I don’t understand why someone should run a macro one time to do something so trivial. To my mind, it’s a bit like suggesting a VBA approach when someone asks “How do I make Cell A2 bold”
Hi Jeff and Smallman,
I apologize for the delay in replying. I was pulled onto another small project…
Anyway, I have read your posts and I understand how to unlock cells. This is a common routine used thoughout many forms I create.
I believe I may have missed out a part in my initial request. I noticed this when I looked at the code again. It seems the problem is happening because there are named ranges.
In the Array, rather than using cell names (i.e. C23, C24), I used named ranges. I have pasted my code below. The code works great but even though going into the code the cells are unlocked, by the time it finishes, the cells are locked up. I hope this helps. let me know if you need further clarifications. Thanks!
Option Explicit Option Base 1 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 'Cell Ranges below, change to suit. ar = Array("RAFDesc", "Summary", "AssExcRisks") 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 ActiveSheet.Protect "password" End SubHi Suzi
Welcome back. That was quite a break.
Before you protect your sheet you will need to unlock the cells in your named ranges. So in the lines before the protect statement include something like the following;
Range(“C47:J47”).Locked = False
Do this for each of your 3 named ranges. This will give you the restult you want.
Take care
Smallman
Hi Smallman! Everything is working fabulously! I was so close when I testing prior to my reply… I was trying to unlock the named ranges rather than the range of cells.DOH!! Thanks again! You have been invaluable!
Regards, Suzi
Hi Suzi
It becomes a little more complex when working with named ranges to unlock the cells. On testing I assumed your named ranges were 1 cell in length, from here you merged the cells. What you have to do is cycle through all of the merged cells and unlock them one at a time. Add the following to your code and it will unlock the cells of your named ranges. I would refer to this procedure just before you add the sheet protect button or just copy everything under the Sub line and before the End Sub line.
I have put the following in as a stand alone procedure. I hope you will be pointed in the right direction from here.
Take care
Smallman
Option ExplicitOption Base 1
Sub UnLockIt()
Dim arr As Variant
Dim r As Range
Dim i As Integer
arr = Array("RafDesc", "AssExcRisks", "Summary")
For i = 1 To UBound(arr)
For Each r In Range(arr(i))
r.MergeArea.Locked = False
Next r
Next i
End Sub
Hi Smallman, where does this go in the context of the larger chunk code? I can’t get this to work because I don’t know where the “Option Explicit” part goes… I have tried it at the end before End Sub, and as a separate thing, but neither works. I get an error message, a compile error: “Invalid inside procedure”. Can you help?