How to use Range.ClearContents() within a Application.Evaluate() context in Excel2010 - excel

The ClearContents() method appears to be broken inside an Evaluate() context
minimal testing example
Dim ForceRunOnceTogg As Boolean
Public Sub cc_test()
Dim s As Range: Set s = Selection.Cells(1)
ForceRunOnceTogg = False
Evaluate Replace("cc(%1)", "%1", s.Address)
End Sub
Private Function cc(c As Range)
If ForceRunOnceTogg Then Exit Function
ForceRunOnceTogg = True 'also not sure why eval double fires
Debug.Print "marco" 'show double vs single eval fire
c.Value = "bananas" 'show it has correct cell
c.Interior.ColorIndex = 6 'Yellow
c.AddComment "a comment" 'show can run methods on cell
c.ClearContents ' this specific method doesn't fire?
End Function
I have tried various options to get ClearContents to fire inside the Evaluate, including just passing the address as a string and using set c = Application.Range(addr); however I have yet to find an option where ClearContents is working. Is there maybe a way to workaround ClearContents and still leave the cell in the same state as if it were cleared?
Otherwise, I guess I'm looking at a replacement for Evaluate in my usage case
minimal usage example
Dim ForceRunOnceTogg As Boolean
Private Sub MapSelection(Lambda As String)
Dim r As Range, ar As Range, col As Range
Set r = Selection
Dim i As Long, rowCount As Long, FirstRow As Long, func As String
Dim scrn As Boolean: scrn = Application.ScreenUpdating: Application.ScreenUpdating = False
Dim calc As XlCalculation: calc = Application.Calculation: Application.Calculation = xlCalculationManual
On Error GoTo RestApp
For Each ar In r.Areas
rowCount = ar.Columns(1).Cells.count
FirstRow = ar.Cells(1).Row - 1
For Each col In ar.Columns
For i = 1 To rowCount
If IsEmpty(col.Cells(i)) Then i = col.Cells(i).End(xlDown).Row - FirstRow
If i > rowCount Then Exit For
ForceRunOnceTogg = False
func = Replace(Lambda, "%1", col.Cells(i).Address(External:=False))
' Debug.Print func
Application.Evaluate func
Next i
Next col
Next ar
Application.Calculation = calc: Application.Calculate
Application.ScreenUpdating = scrn
On Error GoTo 0
Exit Sub
RestApp:
Application.Calculation = calc: Application.Calculate
Application.ScreenUpdating = scrn
On Error GoTo 0
Resume
End Sub
Private Function clearJunk_cell(c As Range)
If ForceRunOnceTogg Then Exit Function
ForceRunOnceTogg = True
If IsError(c.Value) Then
c.ClearContents ' ClearContents won't fire in this context
ElseIf c.Value = "" Then
c.ClearContents
ElseIf Strings.Trim(c.Value) = "" Then
c.ClearContents
End If
End Function
Private Function markJunk_cell(c As Range)
If ForceRunOnceTogg Then Exit Function
ForceRunOnceTogg = True
If IsError(c.Value) Then
c.Interior.Color = 16776960 'Bright Blue
ElseIf c.Value = "" Then
c.Interior.Color = 16776960
ElseIf Strings.Trim(c.Value) = "" Then
c.Interior.Color = 16776960
End If
End Function
Public Function ScrubText(text As String) As String
Dim i As Long, T As String, a As Long
For i = 1 To Len(text)
T = Mid(text, i, 1)
a = AscW(T)
If 31 < a And a < 128 Then ScrubText = ScrubText & T
Next i
End Function
Private Function Scrub_cell(c As Range)
If ForceRunOnceTogg Then Exit Function
ForceRunOnceTogg = True
c.Value2 = ScrubText(c.Value2)
End Function
Private Function markScrub_cell(c As Range)
If ForceRunOnceTogg Then Exit Function
ForceRunOnceTogg = True
If c.Value2 <> ScrubText(c.Value2) Then
c.Interior.Color = 16776960 'Bright Blue
End If
End Function
Public Sub clearJunk(): MapSelection "clearJunk_cell(%1)": End Sub
Public Sub markJunk(): MapSelection "markJunk_cell(%1)": End Sub
Public Sub scrubSelection(): MapSelection "Scrub_cell(%1)": End Sub
Public Sub markScrubSelection(): MapSelection "markScrub_cell(%1)": End Sub
Where clearJunk(), markJunk(), scrubSelection(), and markScrubSelection() along with other similar subs are called from ribbon buttons.

Thanks to the comments, it turns out that Application.Run() made for a much cleaner solution.
Enum SpeedSetting: Fastest: Fast: Medium: Slow: End Enum
Public Sub SetSpeedUp(Optional Speed As SpeedSetting = Slow)
Select Case Speed
Case Fastest
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.DisplayStatusBar = False
Application.Calculation = xlCalculationManual
ActiveSheet.DisplayPageBreaks = False
Case Fast
Application.ScreenUpdating = False
Application.EnableEvents = True
Application.DisplayStatusBar = True
Application.Calculation = xlCalculationManual
ActiveSheet.DisplayPageBreaks = False
Case Medium
Application.ScreenUpdating = False
Application.EnableEvents = True
Application.DisplayStatusBar = True
Application.Calculation = xlCalculationAutomatic
ActiveSheet.DisplayPageBreaks = False
Case Else 'Slow
Application.ScreenUpdating = True
Application.EnableEvents = True
Application.DisplayStatusBar = True
Application.Calculation = xlCalculationAutomatic
ActiveSheet.DisplayPageBreaks = False
End Select
End Sub
Private Sub Map(CellMacro As String, ApplyToRange As Range, Optional Speed As SpeedSetting = Fastest)
Dim ar As Range, col As Range
Dim i As Long, rowCount As Long, FirstRow As Long, MaxRow As Long
SetSpeedUp Speed
On Error GoTo RestApp
For Each ar In ApplyToRange.Areas
rowCount = ar.Columns(1).Cells.Count
FirstRow = ar.Cells(1).Row - 1
MaxRow = ar.Cells(1).EntireColumn.Cells.count
For Each col In ar.Columns
For i = 1 To rowCount
If IsEmpty(col.Cells(i)) Then i = col.Cells(i).End(xlDown).Row - FirstRow
If i > rowCount Then
Exit For
ElseIf i = MaxRow Then
If IsEmpty(col.Cells(i)) Then Exit For
End If
Application.Run CellMacro, col.Cells(i)
Next i
Next col
Next ar
SetSpeedUp Slow
On Error GoTo 0
Exit Sub
RestApp:
SetSpeedUp Slow
On Error GoTo 0
Resume
End Sub
Public Sub clearJunk(): Map "clearJunk_cell", Selection: End Sub
Private Sub clearJunk_cell(c As Range)
If IsError(c.Value) Then
c.ClearContents
ElseIf c.Value = "" Then
c.ClearContents
ElseIf Strings.Trim(c.Value) = "" Then
c.ClearContents
End If
End Sub
Public Sub markJunk(): Map "markJunk_cell", Selection: End Sub
Private Sub markJunk_cell(c As Range)
If IsError(c.Value) Then
c.Interior.Color = 16776960 'Bright Blue
ElseIf c.Value = "" Then
c.Interior.Color = 16776960
ElseIf Strings.Trim(c.Value) = "" Then
c.Interior.Color = 16776960
End If
End Sub
Public Sub Touch(): Map "touch_cell", Selection: End Sub
Private Sub touch_cell(c As Range)
If Asc(c.Formula) <> 61 Then c.Value = c.Value
End Sub
Public Function ScrubText(text As String) As String
Dim i As Long, T As String, a As Long
For i = 1 To Len(text)
T = Mid(text, i, 1)
a = AscW(T)
If 31 < a And a < 128 Then ScrubText = ScrubText & T
Next i
End Function
Public Sub ScrubSelection(): Map "ScrubText_cell", Selection: End Sub
Private Sub ScrubText_cell(c As Range): c.Value2 = ScrubText(c.Value2): End Sub
Public Sub markScrubSelection(): Map "ScrubText_cell", Selection: End Sub
Private Function markScrub_cell(c As Range)
If c.Value2 <> ScrubText(c.Value2) Then
c.Interior.Color = 16776960 'Bright Blue
End If
End Function

Related

Invalid use of property in VBA

I've been following a tutorial on Youtube for an employee manager, It uses a lot of features that i don't need so I've been trying to pick out parts that it need.
I have no experience with VBA or coding so I'm struggling to work out why certain things wont work.
The Screenshots have annotations of the intended results.
Than you in advance
Example and annotations of intended result
Error message
Debug view
Here are my Macros for the buttons and the refresh
Option Explicit
Public EventRow As Long
Public EventCol As Long
Public MapRng As String
Sub Event_SaveNew()
With Sheet6
'check req fields
If Sheet3.Range("g3").Value = Empty Or Sheet3.Range("g5").Value = Empty Then
MsgBox ("Event Name and Event Type are required fields for ANY Event")
Exit Sub
End If
EventRow = .Range("E2000").End(xlUp).Row + 1 'first av row
.Cells(EventRow, 5).Value = Sheet3.Range("b7").Value 'new event id
For EventCol = 6 To 12
.Cells(EventRow, EventCol).Value = Sheet3.Range(.Cells(1, EventCol).Value).Value 'event feild
Next EventCol
End With
With Sheet3
.Range("B2").Value = False 'set new event to false
.Range("B4").Value = Sheet6.Cells(EventRow, 1).Value 'New event ID
Event_Refresh
'reload events
End With
End Sub
Sub Event_Refresh()
Dim LastEventRow As Long
Dim LastFiltRow As Long
With Sheet3
'load Events list into events sheet using adv filter and sort
.Range("f22:m2000").ClearContents 'clear existing events list
LastEventRow = Sheet6.Range("e2000").End(xlUp).Row + 6
Sheet6.Range ("e4:L" & LastEventRow)
End With
End Sub
Sub Event_AddNew()
With Sheet3
.Range("B1").Value = True 'set event load to true
.Range("b2").Value = True 'set new event to true
.Range("J7,j5,g5,g3,f11:j17,g7,g8,j3").ClearContents
.Range("b1").Value = False 'set event load to false
.Range("G3").Select
End With
End Sub
Sub Event_Load()
Dim SelRow As Long
With Sheet3
SelRow = .Range("b9").Value
If .Range("B3").Value = Empty Then
MsgBox "Please select on an Event to display Event details"
Exit Sub
End If
.Range("b1").Value = True 'set empload to true
EventRow = .Range("b3").Value
End With
With Sheet6
For EventCol = 6 To 12
MapRng = Sheet6.Cells(1, EventCol).Value
.Range(MapRng).Value = Sheet6.Cells(EventRow, EventCol).Value 'add maped values
Next EventCol
End With
With Sheet3
.Range("B2").Value = False 'set new event to false
.Range("B1").Value = False 'set event load to false
End With
End Sub
Sub Event_Delete()
If MsgBox("Are you sure you want to DELETE this event?", vbYesNo, "Delete Event") = vbNo Then Exit Sub
With Sheet3
If .Range("B3").Value = Empty Then Exit Sub
EventRow = .Range("B3").Value 'event row
Sheet6.Range(EventRow & ":" & EventRow).EntireRow.Delete
Event_Refresh 'refresh events
End With
End Sub
Sub Event_CancelNew()
With Sheet3
.Range("b2").Value = False
Sheet3.Range("F22").Select
End With
End Sub
And here is the code for the Event log page
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Dim MapRng As Range
Dim FoundMapRng As Range
Dim CellAdd As String
Dim SellRow As Long
'exsisting event change update event tab
If Not Intersect(Target, Range("F3:L17")) Is Nothing And Range("B2").Value = False And Range("B1").Value = False And IsNumeric(Cells(Target.Row, Target.Column + 25).Value) = True And Cells(Target.Row, Target.Column + 25).Value <> Empty Then
Sheet6.Cells(Range("b3").Value, Cells(Target.Row, Target.Column + 25).Value).Value = Target.Value
End If
'update below
CellAdd = Target.Address
SellRow = Range("b9").Value
Set MapRng = Sheet3.Range("EventDataMap")
Set FoundMapRng = MapRng.Find(CellAdd, , xlValues, xlWhole)
If Not FoundMapRng Is Nothing Then Cells(SellRow, FoundMapRng.Column).Value = Sheet6.Cells(Range("b3").Value, Cells(Target.Row, Target.Column + 25).Value).Value
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Count > 1 Then Exit Sub
'on table selection
If Not Intersect(Target, Range("F22:M2000")) Is Nothing And Range("f" & Target.Row).Value <> Empty Then
Range("b9").Value = Target.Row 'add in selection row
Range("b4").Value = Range("f" & Target.Row).Value 'add event ID
Event_Load
End If
End Sub

VBA Worksheet_Change Only Working For One Cell

I'd like to preface by saying I am a novice to VBA, so hopefully this is an easy fix.
I am trying to get the following VBA code to work for multiple cells with formulas. The effect is that there is a ghost value in the cell a user can overwrite then see again if they delete their value. I can get one cell to work how I want it to, but the second (and third and fourth etc.) do not work. How can I repeat this same line of code so that the effect repeats itself in multiple cells with different formulas?
Working:
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
With Target
If .Address(False, False) = "F7" Then
If IsEmpty(.Value) Then
Application.EnableEvents = False
.Formula = "=IFERROR(INDEX(DATABASE!$D$2:$AG$3222,MATCH('Pricing Grid'!$B$11,DATABASE!$E$2:$E$3222,0),10),0)"
Application.EnableEvents = True
End If
End If
End With
End Sub
My attempt (Top working, bottom not):
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
With Target
If .Address(False, False) = "F7" Then
If IsEmpty(.Value) Then
Application.EnableEvents = False
.Formula = "=IFERROR(INDEX(DATABASE!$D$2:$AG$3222,MATCH('Pricing Grid'!$B$11,DATABASE!$E$2:$E$3222,0),10),0)"
Application.EnableEvents = True
End If
End If
End With
End Sub
Private Sub Worksheet_Change1(ByVal Target As Excel.Range)
With Target
If .Address(False, False) = "F8" Then
If IsEmpty(.Value) Then
Application.EnableEvents = False
.Formula = "=IFERROR(INDEX(DATABASE!$D$2:$AG$3222,MATCH('Pricing Grid'!$B$11,DATABASE!$E$2:$E$3222,0),9),0)"
Application.EnableEvents = True
End If
End If
End With
End Sub
Try this...
Private Sub Worksheet_Change(ByVal Target As Range)
Dim i&, j&, v, t
v = Target.Value2
If Not IsArray(v) Then t = v: ReDim v(1 To 1, 1 To 1): v(1, 1) = t
Application.EnableEvents = False
For i = 1 To UBound(v)
For j = 1 To UBound(v, 2)
If Len(v(i, j)) = 0 Then
With Target(i, j)
Select Case .Address(0, 0)
Case "A1": .Formula = "=""Excel"""
Case "A2": .Formula = "=""Hero"""
End Select
End With
End If
Next
Next
Application.EnableEvents = True
End Sub
Use your formulas and ranges instead of mine, of course.
Update
The above works well, but this is faster/better...
Private Sub Worksheet_Change(ByVal Target As Range)
Dim i&, v
DoEvents
ReDim v(1 To 3, 1 To 2)
v(1, 1) = "A1": v(1, 2) = "=""This"""
v(2, 1) = "A2": v(2, 2) = "=""Works"""
v(3, 1) = "A2": v(3, 2) = "=""Great!"""
Application.EnableEvents = False
For i = 1 To UBound(v)
With Range(v(i, 1))
If Not Intersect(Target, .Cells) Is Nothing Then
If Len(.Value2) = 0 Then
.Formula = v(i, 2)
End If
End If
End With
Next
Application.EnableEvents = True
End Sub
Both of the above methods work for single-cell deletes AND also for clearing and deleting large ranges, including whole columns and whole rows and the second method is particularly quick in all these scenarios.
You can do something like this:
Private Sub Worksheet_Change(ByVal Target As Excel.Range)
'only handle single cells
If Target.Cells.CountLarge > 1 Then Exit Sub
If IsError(Target.Value) Then Exit Sub '<< edit: added
'only handle empty cells
If Len(Target.Value) > 0 Or Len(Target.Formula) > 0 Then Exit Sub
On Error Goto haveError
Application.EnableEvents = False
Select Case Target.Address(False, False)
Case "F7": Target.Formula = "=IFERROR(INDEX(DATABASE!$D$2:$AG$3222,MATCH('Pricing Grid'!$B$11,DATABASE!$E$2:$E$3222,0),10),0)"
Case "F8": Target.Formula = "=IFERROR(INDEX(DATABASE!$D$2:$AG$3222,MATCH('Pricing Grid'!$B$11,DATABASE!$E$2:$E$3222,0),9),0)"
End Select
haveError:
'ensure events are re-enabled
Application.EnableEvents = True
End Sub

Update excel cell with date if a cell in a range is update

I need to update a cell with the date and time stamp (NOW()) if any cell is updated within any cell before it within that same row.
So update cell "CU" with date and time when any cell from "A-CR" is updated.
I have done some searching but I can only seem to find bits that work if only updating a single cell, I'm looking for if anything changes within that range.
I currently have some Vba which does something similar which will update the adjacent cell with time and date which is required but I also need an overall one for the whole process.
Private Sub Worksheet_Change(ByVal Target As Range)
If Not Intersect(Target, Range("F:F, I:I, L:L, O:O, R:R, U:U, X:X, AA:AA, AB:AB, AE:AE, AH:AH, AK:AK, AN:AN, AQ:AQ, AT:AT, AW:AW, AZ:AZ, BC:BC, BF:BF, BI:BI, BL:BL, BO:BO, BR:BR, BU:BU, BX:BX, CA:CA, CD:CD, CG:CG, CJ:CJ, CM:CM, CP:CP")) Is Nothing Then
On Error GoTo safe_exit
With Application
.EnableEvents = False
.ScreenUpdating = False
Dim trgt As Range, ws1 As Worksheet
'Set ws1 = ThisWorkbook.Worksheets("Info")
For Each trgt In Intersect(Target, Range("F:F, I:I, L:L, O:O, R:R, U:U, X:X, AA:AA, AB:AB, AE:AE, AH:AH, AK:AK, AN:AN, AQ:AQ, AT:AT, AW:AW, AZ:AZ, BC:BC, BF:BF, BI:BI, BL:BL, BO:BO, BR:BR, BU:BU, BX:BX, CA:CA, CD:CD, CG:CG, CJ:CJ, CM:CM, CP:CP"))
If trgt <> vbNullString Then
If UCase(trgt.Value) = "Y" Or UCase(trgt.Value) = "N" Then
Cells(trgt.Row, trgt.Column + 1) = Now()
Cells(trgt.Row, trgt.Column + 2) = Environ("username")
'Select Case trgt.Column
' Case 2 'column B
' Cells(trgt.Row, trgt.Column + 1) = Environ("username")
' Case 4 'column D
' 'do something else
' End Select
Else
trgt = ""
Cells(trgt.Row, trgt.Column + 1) = ""
Cells(trgt.Row, trgt.Column + 2) = ""
End If
End If
Next trgt
'Set ws1 = Nothing
End With
End If
safe_exit:
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
This works for me:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
If Intersect(Target, Me.Range("A" & Target.Row & ":CR" & Target.Row)) Is Nothing Then GoTo SafeExit
Me.Cells(Target.Row, "CU") = Now()
SafeExit:
Application.EnableEvents = True
End Sub
The below code takes care of:
Clearing the time if the row is blank.
Updating the time only if the values really change from the previous value.
Dim oldValue As String
'Change the range below where your data will be
Const RangeString = "A:CR"
'Below variable decides the column in which date will be displayed
'Change the below value to 1 for column A, 2 for B, ... 99 for CU
Const ColumnIndex = 99
Private Sub Worksheet_Change(ByVal Target As Range)
Dim WorkRng As Range
Dim HorizontalRng As Range
Dim Rng As Range
Dim HorRng As Range
Dim RowHasVal As Boolean
Set WorkRng = Intersect(ActiveSheet.Range(RangeString), Target)
If Not WorkRng Is Nothing Then
If WorkRng.Cells.Count = 1 And WorkRng.Cells(1, 1).Value = oldValue Then
Exit Sub
End If
Application.EnableEvents = False
For Each Rng In WorkRng
Set HorizontalRng = Intersect(ActiveSheet.Range(RangeString), Rows(Rng.Row))
RowHasVal = False
For Each HorRng In HorizontalRng
If Not VBA.IsEmpty(HorRng.Value) Then
RowHasVal = True
Exit For
End If
Next
If Not RowHasVal Then
ActiveSheet.Cells(Rng.Row, ColumnIndex).ClearContents
ElseIf Not VBA.IsEmpty(Rng.Value) Then
ActiveSheet.Cells(Rng.Row, ColumnIndex).Value = Now
ActiveSheet.Cells(Rng.Row, ColumnIndex).NumberFormat = "dd-mm-yyyy, hh:mm:ss"
End If
Next
Application.EnableEvents = True
End If
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Not Intersect(Target, ActiveSheet.Range(RangeString)) Is Nothing Then
If Target.Cells.Count = 1 Then
oldValue = Target.Value
Else
oldValue = ""
End If
End If
End Sub

VBA - Speed of Hiding/Unhiding Row as a Worksheet Event

I'm struggling with the speed at which the following VBA code executes.
The goal of this code is to activate whenever "C4" changes, and then scan column "R" for the value 'Y'. If there's a 'Y', then it hides the row, and if not, it unhides the row. The code works, it's just not speedy - for 500 rows, it can take 30 or more seconds every time I change the value of "C4".
Does anyone have any suggestions to improve the speed at which this code executes? Or another method of accomplishing this?
Thanks for taking a look.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim L As Long
Dim r As Range
L = Cells(Rows.Count, "R").End(xlUp).Row
If Not Intersect(Target, Range("C4")) Is Nothing Then
For Each r In Range("R2:R" & L)
If r.Value = "Y" Then
Rows(r.Row).Hidden = True
Else
Rows(r.Row).Hidden = False
End If
Next
End If
End Sub
In attempting to apply the suggestion below - use Union() - I have come up with the below, not working, code. Any help would be greatly appreciated.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim L As Long
Dim r As Range
Dim RowsToHide As Range
Dim RowsToUnhide As Range
L = Cells(Rows.Count, "R").End(xlUp).Row
If Not Intersect(Target, Range("C4")) Is Nothing Then
For Each r In Range("R2:R" & L)
If r.Value = "Y" Then
RowsToHide = Union(RowsToHide, r.Row)
Else
RowsToUnhide = Union(RowsToUnhide, r.Row)
End If
Next
End If
RowsToHide.Hidden = True
RowsToUnhide.Hidden = False
End Sub
Adding Application.EnableEvents = False at the beginning of the code then turning back to true will help, Also using Applciation.ScreenUpdating = False should help as well.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim L As Long
Dim r As Range
Application.EnableEvents = False
Application.ScreenUpdating = False
L = Cells(Rows.Count, "R").End(xlUp).Row
If Not Intersect(Target, Range("C4")) Is Nothing Then
For Each r In Range("R2:R" & L)
If r.Value = "Y" Then
Rows(r.Row).Hidden = True
Else
Rows(r.Row).Hidden = False
End If
Next
End If
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
There are several techniques that will help speed this up
Writing to .Hidden is much slower than reading it. So check if the row is already hidden or showing before setting Hidden
Collect the rows to Hide or Show into a range (Union) and Hide/Show tehm in one go.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim r As Range
Dim rngCheck As Range
Dim rngHide As Range, rngShow As Range
Application.ScreenUpdating = False
If Not Intersect(Target, Me.Range("C1")) Is Nothing Then
Set rngCheck = Me.Range(Me.Cells(1, "R"), Me.Cells(Me.Rows.Count, "R").End(xlUp))
For Each r In rngCheck.Cells
If r.Value2 = "Y" Then
If Not r.EntireRow.Hidden Then
If rngHide Is Nothing Then
Set rngHide = r.EntireRow
Else
Set rngHide = Union(rngHide, r.EntireRow)
End If
End If
Else
If r.EntireRow.Hidden Then
If rngShow Is Nothing Then
Set rngShow = r.EntireRow
Else
Set rngShow = Union(rngShow, r.EntireRow)
End If
End If
End If
Next
End If
If Not rngHide Is Nothing Then
rngHide.EntireRow.Hidden = True
End If
If Not rngShow Is Nothing Then
rngShow.EntireRow.Hidden = False
End If
Application.ScreenUpdating = True
End Sub

Combining IF else with LEFT to hide columns

I'm trying to write some code to Hide columns if the first 3 characters of cells in a range equal the contents of another. I have the code for hiding columns if cells in a range are blank as this;-
Private Sub Worksheet_Change(ByVal Target As Range)
Dim r As Range, cell As Range
On Error GoTo ErrHandler
Set r = Me.Range("C8:R8")
Application.ScreenUpdating = False
Application.EnableEvents = False
For Each cell In r
If cell.Value = "" Then
cell.EntireColumn.Hidden = True
Else
cell.EntireColumn.Hidden = False
End If
Next
ErrHandler:
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
And the code for identifiying the first 3 charcters of a cell;-
Dim LResult As String
LResult = Left ("Alphabet",3)
But how do I combine the two, referencing a specific cell rather than "Alphabet"?
Cant get this to work - any suggestions?
Private Sub Worksheet_Change(ByVal Target As Range)
Dim r As Range, cell As Range
On Error GoTo ErrHandler
Set r = Me.Range("B7:CG7")
Application.ScreenUpdating = False
Application.EnableEvents = False
Row = 1
col = 1
For Each cell In r
If cell.Value = "" And Left(cell.Value, 3) = cell(Row, col).Value Then
cell.EntireColumn.Hidden = True
Else
cell.EntireColumn.Hidden = False
End If
Next
ErrHandler:
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
Cheers
You have almost the working code. You are comparing cell.Value to an empty string - now just apply Left to it
LResult = Left (cell.Value,3)
Edit:
row = 20
col = 30
For Each cell In r
If cell.Value = "" and Left (cell.Value,3) = Cell(row, col).Value Then
cell.EntireColumn.Hidden = True
Else
cell.EntireColumn.Hidden = False
End If
where you want data from cell at row and col (I used 20, 30 as the example)

Resources