Reputation: 23
I have a list of points with the following "fields" (every field in a column, B to G):
Point Name (B), Easting (C), Northing (D), Survey Crew (E), Date of Survey (F), Survey Method (G)
The user have to input
Survey Crew (H2)
Survey Date (I2)
Survey Method (J2)
Line (H4) Point's Name first part
Start (I4)
End (J4)
And I want :
- Check if the point exists
- If the point exists and the "fields" are empty populate them with the info the user has to iput in some specific cells
- If the cells are already populated to retrieve the info to show it in some other cells
I've come to these code lines and they work but the check process take too long.
Could anyone help me to figure out how to do it faster? because every time the check is performed it takes too long.
I'm not so good on this and I think there could be one faster way to do it; any comment or suggestion is welcome
Sub CheckProd()
Dim FR1, Bin, Track, Min, MinBin, Max, MaxBin, Tre As Integer
Bin = 10 ^ Range("O2").Value
Track = Range("H4").Value 'Input value (first part of the point name)
MinBin = Range("I4").Value ' Input Value (second part of the point name - Start)
MaxBin = Range("J4").Value ' Input Value (second part of the point name - End)
If MaxBin > MinBin Then ' calculates first and last point to update
Min = Bin * Track + MinBin
Max = Bin * Track + MaxBin
Else
Min = Bin * Track + MaxBin
Max = Bin * Track + MinBin
End If
Tre = Max - Min + 1 'Counts number of points to update
FR1 = Range("B65536").End(xlUp).Row 'Counts total design points points
Range("K2:M65536").ClearContents
Check = Min - 1
For i = 1 To Tre
Check = Check + 1
Find = False
For J = 2 To FR1
Station = Cells(J, "B").Value
datte = Cells(J, "F").Value
If (Check = Station) Then
Find = True
If IsEmpty(Cells(J, "F")) Then
Cells(J, "E").Value = Cells(2, "H").Value 'Updates Crew number
Cells(J, "F").Value = Cells(2, "I").Value 'Updates Survey Date
Cells(J, "G").Value = Cells(2, "J").Value 'Updates Survey Method
Else
FRL = Range("K65536").End(xlUp).Row
Cells(FRL + 1, "K").Value = Station 'Shows the point already reported
Cells(FRL + 1, "L").Value = "Reportado" 'Shows the status "Reported"
Cells(FRL + 1, "M").Value = datte ' Shows the date when the point was reported
End If
End If
If ((J = FR1) And (Not Find)) Then
FRM = Range("K65536").End(xlUp).Row
Cells(FRM + 1, "K").Value = Check 'Shows the point without design coordinates
Cells(FRM + 1, "L").Value = "No Preplot" 'Shows the status "No Preplot"
End If
If (Find) Then J = FR1
Next J
Next i
End Sub
Upvotes: 0
Views: 320
Reputation: 3061
Everything up to the For loop will all things being equal will be ultra fast. Clearly the speed hit is in your double For loop.
For i = 1 To Tre
Check = Check + 1
Find = False
For J = 2 To FR1
'performance problem happens here...
Next J
Next i
The code isn't insanely bad.
But it's clear that you are moving through a large body of data doing a lookup. Doing this lots of times through a long loop isn't a great because your basically moving through a large number of iterations constantly examining individual cell values for little benefit (i.e. to lookup 3 values).
Instead consider replacing this "search algo" with a VLookup() or Index(Match()) function that uses the value in Cells(J, "B").Value to find the 3 values at Cells(2, "H").Value, Cells(2, "I").Value and Cells(2, "J").Value.
An even better method involving code is to read all values into an array at the start. To do this first load the data into the array. Ok your now no longer wasting time talking to Excel.
Dim arr()
arr = Range("H2:J666").Value2
Now re-write your "search algo" to process this Array. To do that you will reconstruct the For loop to iterate through the elements and dimensions of the variable arr. i.e.
For rowCount = 0 to 664
For columnCount = 0 to 2
If arr(rowCount, columnCount) = CheckValue(GetStationValue(station)) Then
' we have found the correct set of values
Range("E" & J).Value = arr(rowCount,columnCount)
Range("F" & J).Value = arr(rowCount,columnCount)
Range("G" & J).Value = arr(rowCount,columnCount)
Else
' do other update of data
End If
Next
Next
' where GetStation value is just a seperate function to get the dynamic "station" value based on the original station variable value (use global variable if you need to update this value), and CheckValue then compares this to the Check sum that you are using.
hope this helps.
Upvotes: 2