Reputation: 45
I am new at writing VBA and have been looking through stack overflow to accomplish what I've needed so far. The code I have written works just fine for me, but other people seem to get compiling issues. I have shrunk the code down (there are 1204 procedures in the actual string which, needless to say, is a lot).
I am looking for help with consolidating what I have written. Will you please take a look and recommend a good way to shrink this code in order to alleviate the redundancy?
Thank you for the help!
Private Sub Worksheet_Change(ByVal Target As Range)
Dim c&, i&, k, v, col
DoEvents
ReDim v(1 To 1224, 1 To 2)
For i = 1 To 102
v(i, 1) = "O" & 6 + i
Select Case i
Case Is <= 70
v(i, 2) = "=A"
Case Is <= 100
v(i, 2) = "=B"
Case Else
v(i, 2) = "=D"
End Select
Next i
For i = 103 To 204
v(i, 1) = "T" & 6 + i
Select Case i
Case Is <= 172
v(i, 2) = "=A"
Case Is <= 202
v(i, 2) = "=B"
Case Else
v(i, 2) = "=D"
End Select
Next i
For i = 205 To 306
v(i, 1) = "Y" & 6 + i
Select Case i
Case Is <= 274
v(i, 2) = "=A"
Case Is <= 304
v(i, 2) = "=B"
Case Else
v(i, 2) = "=D"
End Select
Next i
With Application
.Calculation = xlCalculationManual
.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
.EnableEvents = True
.Calculation = xlCalculationAutomatic
End With
End Sub
Upvotes: 0
Views: 77
Reputation: 4457
You can do it easily with a For loop.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim c&, i&, k, v, col$, fml$
DoEvents
ReDim v(1 To 306, 1 To 2)
For i = 1 To 306
'Decide on the Formula
Select Case i
Case Is <= 70, 103 To 172, 205 To 274
fml = "=A"
Case 71 To 100, 173 To 202, 275 To 304
fml = "=B"
Case 101 To 102, 203 To 204, Is >= 305
fml = "=D"
End Select
'Decide on the Column
Select Case i
Case Is <= 102
col = "O"
Case Is <= 204
col = "T"
Case Is <= 306
col = "Y"
End Select
v(i, 1) = col & 6 + i 'This may need correction
v(i, 2) = fml
Next i
With Application
.Calculation = xlCalculationManual
.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
.EnableEvents = True
.Calculation = xlCalculationAutomatic
End With
End Sub
The line v(i, 1) = col & 6 + i
will result in the range looking like "O7:O108,T109:T210,Y211:Y312"
. But if you wanted "O7:O108,T7:T108,Y7:Y108"
then you will need to edit that line into
v(i, 1) = col & 6 + ((i - 1) Mod 102) + 1
I didn't look at the other half of the code at first, but I now notice the With Range()
inside the For loop. That's already inside the With Application
block! It's not a good idea to double up seperate With
blocks like that.
Suggested Edit for the second half:
Application.Calculation = xlCalculationManual
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
Application.Calculation = xlCalculationAutomatic
Upvotes: 1
Reputation: 166156
Something like this should work
Private Sub Worksheet_Change(ByVal Target As Range)
Dim i As Long, c As Range, f
On Error GoTo haveError
Application.EnableEvents = False
For Each c In Target.Cells 'loop over Target cells
For i = 15 To 70 Step 5 'check each column from O to BR
If Not Application.Intersect(c, Me.Range(Me.Cells(7, i), Me.Cells(109, i))) Is Nothing Then
'Target cell is in the column range...
If Len(c.Value) = 0 and c.Row <> 35 Then
Select Case c.Row
Case 7 To 77: f = "=A"
Case 78 To 107: f = "=B"
Case Else: f = "=D"
End Select
c.Formula2 = f 'this formula seems incomplete though?
End If
End If
Exit For 'stop checking for this cell
Next i
Next c
'ensure events not left off in the event of an error
haveError:
Application.EnableEvents = True
End Sub
Upvotes: 2