I have an AutoFitMergedCellRowHeight subroutine that takes a merged cell as an argument and then fixes its height so that all the text will be visible. The FixAll sub is activated when a button is pressed.
The problem is it's behavior is unstable. When a cell is selected that is in the same column as the merged cell (column 4) the height is one size (smaller, but the text is 100% visible); when a cell is selected outside that column but inside a table nothing happens; when a cell is selected outside the table the height is fixed but get too big.
Why is this happening? I can't see anything related to a selected cell in the sub.
Sub FitAll()
AutoFitMergedCellRowHeight (Cells(3, 4))
End Sub
Sub AutoFitMergedCellRowHeight(cell As Range)
Dim CurrentRowHeight As Single, MergedCellRgWidth As Single
Dim CurrCell As Range
Dim ActiveCellWidth As Single, PossNewRowHeight As Single
If cell.MergeCells Then
With cell.MergeArea
.WrapText = True
If .Rows.Count = 1 Then
cell = cell.MergeArea.Cells(1, 1)
MsgBox (cell.Row & "and" & cell.Column)
Application.ScreenUpdating = False
CurrentRowHeight = .RowHeight
ActiveCellWidth = cell.ColumnWidth
For Each CurrCell In Selection
MergedCellRgWidth = CurrCell.ColumnWidth +
MergedCellRgWidth
Next
.MergeCells = False
.Cells(1).ColumnWidth = MergedCellRgWidth
.EntireRow.AutoFit
PossNewRowHeight = .RowHeight
.Cells(1).ColumnWidth = ActiveCellWidth
.MergeCells = True
.RowHeight = IIf(CurrentRowHeight > PossNewRowHeight, _
CurrentRowHeight, PossNewRowHeight)
End If
End With
End If
End Sub
EDIT: I compare my results also to the same sub that doesn't use an argument but rather a selected cell. The results differ thought even after applying the changes CLR suggested..
Sub AutoFitMergedActiveCellRowHeight()
Dim CurrentRowHeight As Single, MergedCellRgWidth As Single
Dim CurrCell As Range
Dim ActiveCellWidth As Single, PossNewRowHeight As Single
If ActiveCell.MergeCells Then
With ActiveCell.MergeArea
.WrapText = True
If .Rows.Count = 1 Then
Application.ScreenUpdating = False
CurrentRowHeight = .RowHeight
ActiveCellWidth = ActiveCell.ColumnWidth
For Each CurrCell In Selection
MergedCellRgWidth = CurrCell.ColumnWidth + MergedCellRgWidth
Next
.MergeCells = False
.Cells(1).ColumnWidth = MergedCellRgWidth
.EntireRow.AutoFit
PossNewRowHeight = .RowHeight
.Cells(1).ColumnWidth = ActiveCellWidth
.MergeCells = True
.RowHeight = IIf(CurrentRowHeight > PossNewRowHeight, _
CurrentRowHeight, PossNewRowHeight)
End If
End With
End If
'MsgBox ("DONE")
MsgBox (ActiveCell.Row & "and" & ActiveCell.Column)
End Sub
For Each CurrCell In Selection is looking at selected cell, not cell passed in parameter.
I think you want to replace:
For Each CurrCell In Selection
MergedCellRgWidth = CurrCell.ColumnWidth + MergedCellRgWidth
Next
with something like:
For Each CurrCell In cell.MergeArea
MergedCellRgWidth = CurrCell.ColumnWidth + MergedCellRgWidth
Next
Related
I have a script that changes the cell color and a script to hide the cells that are not colored. The hide script works, but it hides ALL the cells, even the colored ones. I noticed that when I use the script that changes the cell color, it does not detect the changes in the excel interface(in the 'Fill Color' settings in 'Home' tab, under the 'font size' selection). I also noticed that when try to change the color of the cells (using the excel interface) that are colored from using the script, it does not change (the color seems to be fixed to whatever is set from the script).
Therefore, it seems like the interface does not detect the changes that are being made using the coloring script.
Also, I noticed the script below takes a while to check/hide all the cells. If there is a way to speed up the process, that would be great!
Any help will be greatly appreciated!
Thank you!
The script to hide uncolored cells:
Public Sub HideUncoloredRows()
Dim startColumn As Integer
Dim startRow As Integer
Dim totalRows As Integer
Dim totalColumns As Integer
Dim currentColumn As Integer
Dim currentRow As Integer
Dim shouldHideRow As Integer
startColumn = 1 'column A
startRow = 1 'row 1
totalRows = Sheet1.Cells(Rows.Count, startColumn).End(xlUp).Row
For currentRow = totalRows To startRow Step -1
shouldHideRow = True
totalColumns = Sheet2.Cells(currentRow, Columns.Count).End(xlToLeft).Column
'for each column in the current row, check the cell color
For currentColumn = startColumn To totalColumns
'if any colored cell is found, don't hide the row and move on to next row
If Not Sheet1.Cells(currentRow, currentColumn).Interior.ColorIndex = -4142 Then
shouldHideRow = False
Exit For
End If
Next
If shouldHideRow Then
'drop into here if all cells in a row were white
Sheet2.Cells(currentRow, currentColumn).EntireRow.Hidden = True
End If
Next
End Sub
The script that changes the color certain cells:
Range("A8").Select
Application.CutCopyMode = False
Range("A8").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.FormatConditions.Add Type:=xlExpression, Formula1:= _
"=COUNTIF(Name_Preps,A8)=1"
Selection.FormatConditions(Selection.FormatConditions.Count).SetFirstPriority
With Selection.FormatConditions(1).Font
.Bold = True
.Italic = False
.TintAndShade = 0
End With
With Selection.FormatConditions(1).Interior
.PatternColorIndex = xlAutomatic
.ThemeColor = xlThemeColorAccent3 'Changes the cell to green
.TintAndShade = 0.4
End With
Selection.FormatConditions(1).StopIfTrue = False
End Sub
Try to change your condition to follow
For currentColumn = startColumn To totalColumns
'if any colored cell is found, don't hide the row and move on to next row
If Sheet1.Cells(currentRow, currentColumn).Interior.ThemeColor = xlThemeColorAccent3 Then
shouldHideRow = False
Exit For
End If
Next
conditional formatting is not detected by Interior.ColorIndex and the likes
if you want to go on that way you can see here or here for relevant code
but I'd abandon conditional formatting as well as Select/Selection/Activate/ActiveXXX pattern and go simply this way:
Option Explicit
Sub HandleRowsColorAndVisibility()
Dim iRow As Long
With Range("A8", Cells(Rows.count, 1).End(xlUp)) '<--| reference cells from A8 down to column A last not empty cell
ResetRange .Cells '<--| first, bring range formatting and visibility back to a "default" state
For iRow = .Rows.count To 1 Step -1 '<--| then start looping through range
If WorksheetFunction.CountIf(Range("Name_Preps"), .Cells(iRow, 1)) = 1 Then '<-- if current cell matches your criteria ...
FormatRange .Cells(iRow, 1), True, False, 0, xlColorIndexAutomatic, xlThemeColorAccent3, 0.4 '<--| then format it
Else '<--| otherwise...
.Rows(iRow).Hidden = True '<--| hide it!
End If
Next
End With
End Sub
Sub ResetRange(rng As Range)
rng.EntireRow.Hidden = False
FormatRange rng, False, False, 0, xlColorIndexAutomatic, -4142, 0
End Sub
Sub FormatRange(rng As Range, okBold As Boolean, okItalic As Boolean, myFontTintAndShade As Single, myPatternColorIndex As XlColorIndex, myInteriorThemeColor As Variant, myInteriorTintAndShade As Single)
With rng
With .Font
.Bold = okBold
.Italic = okItalic
.TintAndShade = myFontTintAndShade
End With
With .Interior
.PatternColorIndex = myPatternColorIndex
.ThemeColor = myInteriorThemeColor
.TintAndShade = myInteriorTintAndShade
End With
End With
End Sub
My script moves data to excel template. Codewords is changed for relevant info.
All works well if TPLNR and AUFNR is filled. The cell is two rows in height. But if i leave AUFNR or TPLNR blank - cell height not ajusted. This is macro used to fill and adjust every row in table.
Sub Mac1()
'
' Mac1
'
Dim i As Integer
i = 12
'
Do While Range("L" & i).Value <> "THE END"
If Range("L" & i).Value = "M" Then
...
ElseIf Range("L" & i).Value = "T" Then
Range("A" & i & ":D" & i).Select
With Selection
.HorizontalAlignment = xlCenter
.Orientation = 0
.WrapText = True
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = True
End With
Selection.Merge
With Selection
.HorizontalAlignment = xlLeft
.VerticalAlignment = xlBottom
.WrapText = True
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = True
End With
Selection.Font.Italic = True
End If
i = i + 1
Loop
Call AutoFitMergedCellRowHeight
Columns("L:L").Select
Selection.Delete Shift:=xlToLeft
End Sub
Sub AutoFitMergedCellRowHeight()
Dim CurrentRowHeight As Single, MergedCellRgWidth As Single
Dim CurrCell As Range
Dim ActiveCellWidth As Single, PossNewRowHeight As Single
Dim StartCell As Range, c As Range, MergeRng As Range, Cell As Range
Dim a() As String, isect As Range, i
'Take a note of current active cell
Set StartCell = ActiveCell
'Create an array of merged cell addresses that have wrapped text
For Each c In ActiveSheet.UsedRange
If c.MergeCells Then
With c.MergeArea
If .Rows.Count = 1 And .WrapText = True Then
If MergeRng Is Nothing Then
Set MergeRng = c.MergeArea
ReDim a(0)
a(0) = c.MergeArea.Address
Else
Set isect = Intersect(c, MergeRng)
If isect Is Nothing Then
Set MergeRng = Union(MergeRng, c.MergeArea)
ReDim Preserve a(UBound(a) + 1)
a(UBound(a)) = c.MergeArea.Address
End If
End If
End If
End With
End If
Next c
Application.ScreenUpdating = False
'Loop thru merged cells
For i = 0 To UBound(a)
Range(a(i)).Select
With ActiveCell.MergeArea
If .Rows.Count = 1 And .WrapText = True Then
'Application.ScreenUpdating = False
CurrentRowHeight = .RowHeight
ActiveCellWidth = ActiveCell.ColumnWidth
For Each CurrCell In Selection
MergedCellRgWidth = CurrCell.ColumnWidth + MergedCellRgWidth
Next
.MergeCells = False
.Cells(1).ColumnWidth = MergedCellRgWidth
.EntireRow.AutoFit
PossNewRowHeight = .RowHeight
.Cells(1).ColumnWidth = ActiveCellWidth
.MergeCells = True
.RowHeight = IIf(CurrentRowHeight > PossNewRowHeight, _
CurrentRowHeight, PossNewRowHeight)
End If
End With
MergedCellRgWidth = 0
Next i
StartCell.Select
Application.ScreenUpdating = True
'Clean up
Set CurrCell = Nothing
Set StartCell = Nothing
Set c = Nothing
Set MergeRng = Nothing
Set Cell = Nothing
End Sub
What could i do to get rows after 12 to look like it intended to? With 1x height.
Making the rows equal size is quite a standard VBA task.
Just try to put this logic away from your code. The only 3 things you should know is the starting row, the ending row and the size. Thus, you may be able to do it quite well. In the code below change the parameters of Call AllRowsAreEqual(4, 10, 35) in order to make it work for you.
Option Explicit
Sub AllRowsAreEqual(lngStartRow As Long, lngEndRow As Long, lngSize)
Dim lngCounter As Long
For lngCounter = lngStartRow To lngEndRow
Cells(lngCounter, 1).RowHeight = lngSize
'Debug.Print lngCounter
Next lngCounter
End Sub
Public Sub Main()
Call AllRowsAreEqual(4, 10, 35)
End Sub
When I try to run this loop I get an Error: Object Required in the Cell.Value.Copy line. What do I need to do to fix this error?
Sub Findings()
Application.ScreenUpdating = False
Dim Cell As Object
Dim Rng As Range
Set Rng = Sheets("Sheet1").Range("C5:C74")
For Each Cell In Rng
If (Cell.Value <> "") Then
Cell.Value.Copy
End If
Next Cell
If IsEmpty(Range("C85").Value) = True Then
Range("C85").PasteSpecial xlPasteValues
ElseIf IsEmpty(Range("C86").Value) = True Then
Range("C86").PasteSpecial xlPasteValues
ElseIf IsEmpty(Range("C87").Value) = True Then
Range("C87").PasteSpecial xlPasteValues
End If
Application.ScreenUpdating = True
End Sub
If you want to copy only cells with values (without formulas that are returning empty values), you can use the SpecialCells(xlCellTypeConstants) to set the range.
See my code below:
Sub Findings()
Application.ScreenUpdating = False
Dim Rng As Range
With Sheets("Sheet1")
' set "Rng" only to cells inside the range with values inside them
Set Rng = .Range("C5:C74").SpecialCells(xlCellTypeConstants)
Rng.Copy
If IsEmpty(.Range("C85").Value) Then
.Range("C85").PasteSpecial xlPasteValues
ElseIf IsEmpty(.Range("C86").Value) Then
.Range("C86").PasteSpecial xlPasteValues
ElseIf IsEmpty(.Range("C87").Value) Then
.Range("C87").PasteSpecial xlPasteValues
End If
End With
Application.ScreenUpdating = True
End Sub
I have a worksheet with merged cells (e.g. B2:C3 with value "myValue"). If I try to search for a value which is in a merged cell with
r = ThisWorkbook.ActiveWorksheets.Range("$A:$D").Find("myValue")
Debug.Print r.Address
I only get the address of other single cells with similar values but not of the merged cell.
How can I do this with VBA? If I use the manual search function of Excel it finds the value in no time.
Best regards,
Harry
EDIT: When I use the code from Gary I get a runtime error 91. The variable r is Nothing.
Cleaning up a few things:
Sub MAIN()
Dim r As Range
Call Setup
Set r = ThisWorkbook.ActiveSheet.Range("$A:$D").Find("myValue")
Debug.Print r.Address
End Sub
Sub Setup()
Dim rng As Range
Set rng = Range("B2:C3")
With rng
.HorizontalAlignment = xlGeneral
.VerticalAlignment = xlBottom
.WrapText = False
.Orientation = 0
.AddIndent = False
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = True
End With
rng.Value = "MyValue"
End Sub
Will get you the upper left-hand corner of the merged area:
you should use MergeArea for such cases:
Sub test()
Dim r As Range
Set r = ThisWorkbook.ActiveSheet.[A:D].Find("myValue")
Debug.Print r.MergeArea.Address
End Sub
So everything works but the vlookup part. The lookup value of the vlookup does not move with the cell rows. I am not sure how to go about making the "F&cell.number" move along with the rows.
Sub fontredd()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Dim rngL As range
Dim cell As range
Set rngL = range("L1", range("L65536").End(xlUp))
For Each cell In rngL
If cell.Value = "0" Then
cell.EntireRow.Font.Color = vbRed
cell.Formula = "=VLOOKUP(F&cell.number,[PickupCompaniesCommissions.xls]Sheet1!$U:$V,2,FALSE)"
End If
Next cell
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
End Sub
cell.Formula = "=VLOOKUP(F" & cell.Row & ", [PickupCompaniesCommissions.xls]Sheet1!$U:$V,2,FALSE)"