I have a Macro that loops through one column that hold dates that are not random (they go vertically from old to more recent ),then finds every date that is greater than Now () then goes to its adjacent cells and clears them
it works fine , except that the looping takes a small bit of time, which i believe could me much faster if the Macro wouldn't loop against all values in the column(500 rows) but instead just stops at the first cell match , then goes to its adjacent cells and clear all contents from that row till the bottom of the table ( ie if the match is at row 15 , then it clear contents from row 15 all the way down to 500 ) without having to check every single row
The code below as described is designed to loop through every value , i need it to stop at the first match and clear contents of adjacent cells underneath in the range the macro covers
can somone please help me acheive this
Dim R As Long
For R = 1 To 500
If Cells(R, "A").Value >= Now Then Cells(R, "B").Value = ""
If Cells(R, "A").Value >= Now Then Cells(R, "C").Value = ""
Next
End Sub
Using your methodology, if you want to know how to drop out of a loop once the criteria are matched - you would use an Exit For. You also can clear column B and C at the same time, like so:
Dim R As Long
With ActiveWorkbook.Sheets("Sheet1")
For R = 1 To 500
If .Cells(R, "A").Value >= Now Then
.Range("B" & R & ":C500").ClearContents
Exit For
End If
Next
End With
In the above, I've also added reference to the sheet. This is always good practice to prevent possible errors once more than one sheet is available.
Here's an example with a binary search.
Option Explicit
Public Sub ClearByDates(Optional targetDate As Variant = Null)
Dim thisSheet As Worksheet
Dim activeRange As Range
Dim lowerRow As Long, higherRow As Long, thisRow As Long
Dim thisDate As Date
' If no date is provided, assume today is the cutoff
If IsNull(targetDate) Then targetDate = Date
' Assuming that we're putting this code in the worksheet that you want to _
clear. If you decide to put it in a separate module you can either: _
(1) Pass in the worksheet you want to modify as an argument, or _
(2) Explicitly set the worksheet you want to modify using ActiveWorkbook.Worksheets(Name)
Set thisSheet = Me
Set activeRange = thisSheet.UsedRange
With activeRange
' Not only is it cleaner if you use With, you get better performance in VBA _
because it's a hint that the object should be kept loaded and ready.
' Getting the range of rows with values
lowerRow = .Rows(1).Row
higherRow = lowerRow + activeRange.Rows.Count - 1
' Don't start processing until you're in the date range; _
this should handle most common worksheet header situations.
Do Until IsDate(activeRange.Cells(lowerRow, 1))
lowerRow = lowerRow + 1
If lowerRow > higherRow Then Exit Sub
Loop
' Use a binary search to find the first row where the date is _
greater than or equal to the target date.
Do Until lowerRow >= higherRow - 1
thisRow = (higherRow + lowerRow) / 2
thisDate = .Cells(thisRow, 1)
Debug.Print "Row " & Right(" " & thisRow, 7) & ": " & Format(thisDate, "YYYY-MM-DD") & " ";
If thisDate >= targetDate Then
Debug.Print ">= " & Format(targetDate, "YYYY-MM-DD");
higherRow = thisRow
Else
Debug.Print "< " & Format(targetDate, "YYYY-MM-DD");
lowerRow = thisRow
End If
Debug.Print " (lowerRow = " & lowerRow & ", higherRow = " & higherRow & ")"
Loop
' Assuming we just want to clear columns B & C. This can easily be adjusted _
to clear all columns to the right by using .Columns(.Columns.Count) in the _
ending range.
thisSheet.Range("B" & thisRow & ":C" & .Rows(.Rows.Count).Row).ClearContents
End With
End Sub
Related
I'm making a VBA macro to concatenate a number given by the user with a previous column value. Once the loop gets to the value given by the user (the top value), the loop would start again since number one. By now my loop gets to the top value and starts from one, but every time this happened the code skip to the next cell, could you tell me why is this happening guys? (down value by default).
Sorry i'm a little bit new on VBA, here is my try:
Sub Balance()
Dim myValue As Integer
myValue = InputBox("Please, give me a number")
Range("A2").Select
Range("A:A,C:C,F:F,H:J,L:L,T:T,W:X").Delete
Range("A2").Select
firstrow = ActiveCell.Row
Selection.End(xlDown).Select
lastrow = ActiveCell.Row
For i = 1 To lastrow
If Range("M" & i) = "AB" Then
For j = 1 To myValue
watcher = j
Range("N" & i) = "TV" & " " & Range("M" & i) & " " & watcher
i = i + 1
Next j
End If
Next i
End Sub
This the output with the number 10 as input (Column N):
I would like to reach this goal:
You already have your answer by Vandear explaining why the row is getting skipped. However here is an alternative way using only one loop to achieve what you want. But before that couple of suggestions
Suggestions:
Use Option Explicit and declare your variables. You may want to see Optimizing the VBA Code and improve the performance
Avoid the use of Select/Activate You may want to see How to avoid using Select in Excel VBA
Avoid the use of xlDown to get the last row. You may want to see Finding Last Row
When accepting number from users, use Application.InputBox with a Type:=1 instead of just InputBox. This way you will only restrict numbers.
Is this what you are trying?
Code:
Option Explicit
Sub Balance()
Dim ws As Worksheet
Dim lRow As Long
Dim i As Long, counter As Long
Dim myValue As Long
myValue = Application.InputBox(Prompt:="Please, give me a number", Type:=1)
If myValue < 1 Then Exit Sub
'~~> Change this to the relevant sheet
Set ws = Sheet1
With ws
'~~> For demonstration below. I did not use this line below. But
'~~> If you need to delete those columns then use it this way
.Range("A:A,C:C,F:F,H:J,L:L,T:T,W:X").Delete
lRow = .Range("A" & .Rows.Count).End(xlUp).Row
'~~> Set your counter
counter = 1
For i = 1 To lRow
If .Range("M" & i) = "AB" Then
Range("N" & i) = "TV" & " " & .Range("M" & i).Value2 & " " & counter
counter = counter + 1
'~~> Reset your counter if it crosses user input
If counter > myValue Then counter = 1
End If
Next i
End With
End Sub
In action:
Couple of things before I answer your problem:
It's advisable to declare your variables for better structure:
Dim i As Integer, j As Integer, MyValue As Integer, firstrow As Integer, lastrow As Integer
You can skip the selection of a cell and directly reference it:
firstrow = Range("A2").Row
lastrow = Range("A2").End(xlDown).Row
The Answer to your Problem:
When the code exits the for-next loop for j, i is increased by 1 (i=i+1), and then it will be increased again by 1 when it proceeds to the next i line. This is the reason why it skips to the next row. So after the for-next loop for j, you need to decrease i by 1 before proceeding to the for-next loop for i.
For i = 1 To lastrow
If Range("M" & i) = "AB" Then
For j = 1 To myValue
watcher = j
Range("N" & i) = "TV" & " " & Range("M" & i) & " " & watcher
i = i + 1
Next j
i=i-1 <-------
End If
Next i
I Have Table like this, where i have to use macro because my table always change Every day (SSAS)
so i have use macro to filter automatically,
I am able to sum Amount based on same Vendorname, PONuber and Date on Column E (Subtotal).
and then filter to show Subtotal AMount >500
I want to show only row >500 (Column E), and pop up message to count PONumber (Column B) how many Unique PO Number (Only Visible Row to count)
i've been stuck how to count only Visible Unique PO Number and show it on Pop Up message
this is my Macro
Sub FilterCOunt_Click()
Dim Condition As Variant
Dim AVal As Variant
Dim LastRow As Long
Dim Hide, popup As Long
Dim message As String
Dim sht As Worksheet
'----------------------------
Dim dictionary As Object
Set dictionary = CreateObject("scripting.dictionary")
'---------------------------
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.AskToUpdateLinks = False
Application.DisplayAlerts = False
Application.Calculation = xlAutomatic
Application.ScreenUpdating = False
Application.StatusBar = False
'------------------
Columns.EntireColumn.Hidden = False
Rows.EntireRow.Hidden = False
Columns("E:Z").EntireColumn.Delete
Range("E:Z").EntireColumn.Insert
Range("E1").Value = "Sub Total >500 "
Set sht = ActiveSheet
LastRow = sht.Range("B" & Rows.Count).End(xlUp).Row
'-------------------
For i = 2 To LastRow ' with last row count =SUMIFS(I:I,A:A,A8,B:B,B8,C:C,C8)
AVal = "A" & i
BVal = "B" & i
CVal = "C" & i
Worksheets("Sheet3").Range("E" & i).Formula = "=SUMIFS(D:D,A:A," & AVal & ",B:B," & BVal & ",C:C," & CVal & ")"
Next i
With sht.Range("E1:E" & LastRow)
.AutoFilter
.AutoFilter field:=1, Criteria1:=">=500"
End With
'----------Count Pop UP
Dim CountPO As Long
Range("G1").FormulaArray = "=SUM(IF(FREQUENCY(IF(SUBTOTAL(3,OFFSET(B2,ROW(B2:B22)-ROW(B2),1)),IF(B2:B22<>"",MATCH(""&B2:B22,B2:B22&"",0))),ROW(B2:B22)- ROW(B2)+1),1))"
MsgBox "We Found " & CountPO & " PO Open(s)", _
vbInformation, "PO Found"
End Sub
and this is the formula to count it
{=SUM(IF(FREQUENCY(IF(SUBTOTAL(3,OFFSET(B2,ROW(B2:B22)-ROW(B2),1)),IF(B2:B22<>"",MATCH("~"&B2:B22,B2:B22&"",0))),ROW(B2:B22)-ROW(B2)+1),1))}
If you are pulling from a Database via SSAS you can use Power Query to link to your SSAS DataModel to Excel and you can insert a Calculated Measure in Dax from there with DistinctCount.
Count:=Calculate(DistinctCount(TableName[PONumber]),TableName[Amount]>500)
Alternatively if you want total insights on your specified issue you can add a measured column and then you can use Power Pivot to filter for your criteria live on refresh to the data model, completely negating the need for VBA entirely.
Incidentally it is pertinent to remember VBA is the sledge hammer of solutions please use the DataModel Tools before you ever think of a macro solution remember, VBA is an Application Programming Language and many IT Security Systems will disable it because it opens the system up for malware, you can literally change any file or program in VBA including calling delete system files
Meanwhile having a set DataModel in a locked file that requires user access behind LAN security is easily more secure than allowing your computer to have open programatic access.
This is an alternative formula (which doesn't require any filtering)
=SUM(--(FREQUENCY(IF(B2:B20>500,MATCH(A2:A20,A2:A20,0)),ROW(A2:A20)-ROW(A2)+1)>0))
It's an array formula so using VBA
Range("E1").FormulaArray = "=SUM(--(FREQUENCY(IF(B2:B20>500,MATCH(A2:A20,A2:A20,0)),ROW(A2:A20)-ROW(A2)+1)>0))"
A formula for your cell E2, which is not an array formula, is
=SUMPRODUCT((B2=B$2:B$23)*(A2=A$2:A$23)*(D$2:D$23))
Copy it down, as usual.
See here for why not using an array formula (if you have an alternative).
I am not certain this solves your question, as I did not fully understand it.
You can use the following code. I have implemented Collection to get the unique count.
This will count the unique rows in B column where value in E column > 500.
Private Sub GetUniqueCount() AS Variant
Dim Test As New Collection
Dim rng As Range
For i = 2 To 6 'Replace 6 with last row(without filtration)
Value = Cells(i, "B").Value
check = Contains(Test, Value)
If Cells(i, "E").Value > 500 And Not check And Len(Value) > 0 Then
Test.Add Value, CStr(Value)
End If
Next i
GetUniqueCount = Test.count
End Sub
'Function to check if the value exists in Collection or not
Public Function Contains(col As Collection, key As Variant) As Boolean
Dim obj As Variant
On Error GoTo err
Contains = True
obj = col(key)
Exit Function
err:
Contains = False
End Function
Step 1: Post my code to a new module.
Step 2: Bind you button to the macro named "filterAndCount"
Step 3: Click the buton and rejoice :-)
Code description:
1) The code loops all the rows in the table.
2) First it checks if the Sub Total is above the limit (500).
3) If equal or below it hides the row and moves on to the next row.
4) If above it checks if the value already exists in the array values above.
5) If it does not exists then the value is added to the array.
6) When all rows have been looped only rows with a Sub Total above the limit is visible.
7) Only the unique and visible PO Numbers have been added to the array.
8) The number of values in the array is dispayed in a message box.
Dim wb As Workbook
Dim ws As Worksheet
Dim i As Double
Dim n As Double
Dim subTotalLimit As Double
Dim arr() As String
Sub filterAndCount()
Set wb = ThisWorkbook
Set ws = wb.ActiveSheet
i = 2
subTotalLimit = 500
n = 0
ReDim arr(0 To 0) As String
arr(0) = 0
ws.Columns("E:Z").EntireColumn.Delete
ws.Range("E:Z").EntireColumn.Insert
ws.Range("E1").Value = "Sub Total >500 "
Do While ws.Range("B" & i) <> ""
ws.Range("E" & i).Formula = "=SUMIFS(D:D,A:A,A" & i & ",B:B,B" & i & ",C:C,C" & i & ")"
If ws.Range("E" & i) < subTotalLimit Then
ws.Range("B" & i).EntireRow.Hidden = True
Else
If Not IsNumeric(Application.Match(Range("B" & i).Text, arr(), 0)) Then
arr(n) = Range("B" & i).Value
n = UBound(arr) + 1
ReDim Preserve arr(0 To n) As String
arr(n) = 0
End If
End If
i = i + 1
Loop
MsgBox UBound(arr)
End Sub
Use 2 Dictionary Objects, one for totals and one for unique PO's
Sub filterCOunt()
Const LIMIT = 500
Dim wb As Workbook, ws As Worksheet
Dim iRow As Long, iLastRow As Long, amount As Single
Dim sVendor As String, sPO As String, msg As String, sKey As String
Dim dictPO As Object, dictTotal As Object
Set dictPO = CreateObject("Scripting.Dictionary")
Set dictTotal = CreateObject("Scripting.Dictionary")
Set wb = ThisWorkbook
Set ws = ActiveSheet
iLastRow = ws.Range("B" & Rows.Count).End(xlUp).Row
' first pass to total by po and vendor
For iRow = 2 To iLastRow
sVendor = Trim(ws.Cells(iRow, 1))
sPO = Trim(ws.Cells(iRow, 2))
amount = CSng(ws.Cells(iRow, 4))
sKey = sVendor & "_" & sPO
' sub total
If dictTotal.exists(sKey) Then
dictTotal(sKey) = dictTotal(sKey) + amount
Else
dictTotal.Add sKey, amount
End If
Next
' second pass for PO numbers
For iRow = 2 To iLastRow
sVendor = Trim(ws.Cells(iRow, 1))
sPO = Trim(ws.Cells(iRow, 2))
sKey = sVendor & "_" & sPO
' sub total
ws.Cells(iRow, 5) = dictTotal(sKey)
If dictTotal(sKey) > LIMIT Then
If Not dictPO.exists(sPO) Then
dictPO.Add sPO, iRow
End If
End If
Next
' filter
With ws.Range("E1:E" & iLastRow)
.AutoFilter
.AutoFilter field:=1, Criteria1:=">=" & LIMIT
End With
msg = "No of open PO's = " & dictPO.Count
MsgBox msg, vbInformation
End Sub
First, for your code Count Pop UP to work, let's change all from "" to """"
Second, to be able to notify a Unique PO Number and show it on Pop Up message, you must call the value received from cell G1, or, safer, use evaluate to get the result of this expression.
Your code will probably work now
'Dim CountPO As Long
Range("G1").FormulaArray = "=SUM(IF(FREQUENCY(IF(SUBTOTAL(3,OFFSET(B2,ROW(B2:B22)-ROW(B2),1)),IF(B2:B22<>"""",MATCH(""""&B2:B22,B2:B22&"""",0))),ROW(B2:B22)- ROW(B2)+1),1))"
MsgBox "We Found " & [g1].Value2 & " PO Open(s)", vbInformation, "PO Found"
however, your formula only counts all unique values including less than 500, in addition it is quite long. You can replace it using the shorter formula like the following code:
Dim formula_string As String
formula_string = "=SUMPRODUCT((B2:B22>3)*(C2:C22<>"""")/COUNTIF(B2:B22,B2:B22&""""))"
MsgBox "We Found " & Application.Evaluate(formula_string) & " PO Open(s)", vbInformation, "PO Found"
Hope it helps!
I have a lot of automatically generated reports, each consisting 24 named ranges.
Each named range can't be broken by a horizontal page break.
My idea was to loop through all named ranges and count the page breaks within.
But I can't find a way to count page breaks within a named range.
Does anybody know if it is possible at all?
EDIT: Thanks for the suggestions. Hopefully i can find the time to test it before Christmas, otherwise i will come back and answer in January.
Welcome to SO. May simply scan named ranges and then rows of the range for already existing page breaks. But I am afraid it is slow process and may take long time in file with many long named ranges. may please modify it according to your requirement.
Sub test()
Dim Rw As Range
Dim RngStr As String, Nm As Name
For Each Nm In ThisWorkbook.Names
RngStr = Nm.Name
For Each Rw In Range(RngStr).Rows
If Rw.PageBreak <> xlNone Then
Debug.Print RngStr & " on " & Range(RngStr).Address(, , , True) & " has a Pagebreak at Row " & Rw.Row
End If
Next Rw
Next Nm
End Sub
Carrying on from my comment on #VBasic2008 answer, and blatantly pinching his Intersect idea I found this works:
Sub CountBreaks()
Dim nr As Name
Dim Hpb As HPageBreak
Dim Vpb As VPageBreak
Dim h As Long, v As Long
'May need some method to look at a select number of named ranges.
For Each nr In ThisWorkbook.Names
For Each Hpb In nr.RefersToRange.Parent.HPageBreaks
If Not Intersect(Range(Hpb.Location.Address).EntireRow, _
Range(nr.RefersToRange.Address)) Is Nothing Then
h = h + 1
End If
Next Hpb
For Each Vpb In nr.RefersToRange.Parent.VPageBreaks
If Not Intersect(Range(Vpb.Location.Address).EntireColumn, _
Range(nr.RefersToRange.Address)) Is Nothing Then
v = v + 1
End If
Next Vpb
MsgBox nr.Name & " has: " & vbCr & _
h & " horizontal page breaks." & vbCr & _
v & " vertical page breaks.", vbOKOnly + vbInformation
h = 0
v = 0
Next nr
End Sub
I hope I've got the sheet qualifications correct - i.e. I think Range(Hpb.Location.Address) refers to the correct sheet as well.
The .PageSetup.PrintArea = nmAddress in the comment wasn't needed - was just having problems because my sheet didn't have any data on it.
PB Hell
I suggest you study first this code for one named range, then you will easily create a loop for all of them.
Sub PageBr()
Const cStrName As String = "HPBr"
Const cStrRange As String = "B50:B250"
Dim nmAddress As String
Dim i As Integer
Dim j As Integer
With Sheet1
' Define a name (Refers to ThisWorkbook (.Parent)).
.Parent.Names.Add cStrName, .Range("B50:B250")
nmAddress = .Parent.Names(cStrName).RefersToRange.Address
' Add horizontal pagebreaks.
With .HPageBreaks
.Add Before:=.Parent.Range("A59")
.Add Before:=.Parent.Range("B159")
.Add Before:=.Parent.Range("A248")
.Add Before:=.Parent.Range("D269")
End With
' Range version
For i = 1 To .HPageBreaks.Count
If Not Intersect(.Range(.HPageBreaks(i).Location.Address) _
.Resize(, .Columns.Count), .Range(nmAddress)) Is Nothing Then
j = j + 1
End If
Next
Debug.Print "The named range '" & cStrName & "' contains " & j _
& " horizontal pagebreaks."
' Row version
Dim pbRow As Long
Dim nmRow1 As Long
Dim nmRow2 As Long
nmRow1 = .Range(nmAddress).Row
nmRow2 = .Range(nmAddress).Rows.Count + .Range(nmAddress).Row - 1
j = 0
For i = 1 To .HPageBreaks.Count
pbRow = .Range(.HPageBreaks(i).Location.Address).Row
If pbRow >= nmRow1 And pbRow <= nmRow2 - 1 Then
j = j + 1
End If
Next
Debug.Print "The named range '" & cStrName & "' contains " & j _
& " horizontal pagebreaks."
End With
End Sub
I have this macro that I use to sum total entries by date. The macro can be run two or three times per day which causes a problem as it wants to sum by date. When I run it and it places the total in the last cell in column E, I want that total number to remain the next time I run the macro, but right now it erases the last entry and sums the new total plus the previous total. How can this be changed? I hope this makes sense the way I am explaining it.
Sub Sum_TodaysDate()
Dim sh As Worksheet
Set sh = ActiveSheet
Dim LastRow As Long, iCount As Long
Dim icell As Range
Dim dSplit As Variant
Dim dIndex As Date
LastRow = sh.Range("D" & Rows.Count).End(xlUp).Row
iCount = 0
For Each icell In sh.Range("D2:D" & LastRow)
dSplit = Split(icell.Value, " ")
dIndex = Format(dSplit(0), "mm/dd/yyyy")
If dIndex = Date Then
iCount = iCount + 1
icell.Offset(0, 1).Value = "|"
End If
Next icell
sh.Range("E" & LastRow).Value = iCount
sh.Range("E" & LastRow).Font.Color = vbRed
Application.ScreenUpdating = True
ThisWorkbook.Save
End Sub
If you wish to leave anything that is currently in column E untouched by the macro, so that previous counts remain in place, change the line that says:
icell.Offset(0, 1).Value = "|"
to
If IsEmpty(icell.Offset(0, 1)) Then
icell.Offset(0, 1).Value = "|"
Endif
If you want the new count to only be the count of records added since the previous time the macro was run (and the data is in date order), this could be modified to be:
If IsEmpty(icell.Offset(0, 1)) Then
icell.Offset(0, 1).Value = "|"
Else
iCount = 0
Endif
the code below works 100%. It scans for a match in Column B and copies and renames a group of cells when a match is found. However the is a line For lRow = Sheets("HR-Calc").Cells(Cells.Rows.count, "b").End(xlUp).Row To 7 Step -1
Where the step -1 will scan row by row from the bottom of the sheet until a match is found. It would be much easier if the step was set to End.(xlUp) instead of -1. searching every row is overkill because of how the data is set up End.(xlUp) would massive cut down the run time.
Is something like this possible?
Sub Fill_CB_Calc()
M_Start:
Application.ScreenUpdating = True
Sheets("summary").Activate
d_input = Application.InputBox("select first cell in data column", "Column Data Check", Default:="", Type:=8).Address(ReferenceStyle:=xlA1, RowAbsolute:=True, ColumnAbsolute:=False)
data_col = Left(d_input, InStr(2, d_input, "$") - 1)
data_row = Right(d_input, Len(d_input) - InStr(2, d_input, "$"))
Application.ScreenUpdating = False
Sheets("summary").Activate
Range(d_input).End(xlDown).Select
data_last = ActiveCell.Row
If IsEmpty(Range(data_col & data_row + 1)) = True Then
data_last = data_row
Else
End If
For j = data_row To data_last
CBtype = Sheets("summary").Range(data_col & j)
Sheets("HR-Calc").Activate
For lRow = Sheets("HR-Calc").Cells(Cells.Rows.count, "b").End(xlUp).Row To 7 Step -1
If Sheets("HR-Calc").Cells(lRow, "b") = CBtype Then
CBend = Sheets("HR-Calc").Range("C" & lRow).End(xlDown).Row + 1
Sheets("HR-Calc").Rows(lRow & ":" & CBend).Copy
CBstart = Sheets("HR-Calc").Range("c50000").End(xlUp).Row + 2
ActiveWindow.ScrollRow = CBstart - 8
Sheets("HR-Calc").Range("A" & CBstart).Insert Shift:=xlDown
CBold = Right(Range("c" & CBstart), Len(Range("C" & CBstart)) - 2)
box_name = Sheets("summary").Range(data_col & j).Offset(0, -10)
CBnew = Right(box_name, Len(box_name) - 2) & "-" ' <--this is custom and can be changed based on CB naming structure
If CBnew = "" Or vbCancel Then
End If
CBend2 = Range("c50000").End(xlUp).Row - 2
Range("C" & CBstart + 1 & ":" & "C" & CBend2).Select
Selection.Replace What:=CBold & "-", Replacement:=CBnew, LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
ReplaceFormat:=False
Range("C" & CBstart).FormulaR1C1 = "CB" & Left(CBnew, Len(CBnew) - 1)
GoTo M_Start2
Else
End If
Next lRow
M_Start2:
Next j
YN_result = MsgBox("Fill info for another block/inverter?", vbYesNo + vbExclamation)
If YN_result = vbYes Then GoTo M_Start
If YN_result = vbNo Then GoTo jumpout
jumpout:
' Sheets("summary").Range(d_input).Select
Application.ScreenUpdating = True
End Sub
I'm not sure if this will help but I've had a great performance increase with pulling the entire range you need to loop through into a variant array and then looping through the array. If I need to loop through large data sets, this method has worked out well.
Dim varArray as Variant
varArray = Range(....) 'set varArray to the range you're looping through
For y = 1 to uBound(varArray,1) 'loops through rows of the array
'code for each row here
'to loop through individual columns in that row, throw in another loop
For x = 1 to uBound(varArray, 2) 'loop through columns of array
'code here
Next x
Next y
You can also define the column indexes prior to executing the loop. Then you only need to execute the you need to pull those directly in the loop.
'prior to executing the loop, define the column index of what you need to look at
Dim colRevenue as Integer
colRevenue = 5 'or a find function that searches for a header named "Revenue"
Dim varArray as Variant
varArray = Range(....) 'set varArray to the range you're looping through
For y = 1 to uBound(varArray,1) 'loops through rows of the array
tmpRevenue = CDbl(varArray(y, colRevenue))
Next y
Hope this helps.
Look at doing a .find from the bottom up.
Perform a FIND, within vba, from the bottom of a range up
That will eliminate the need to do the for loop from the last row to the first occurrence of the value you want to locate.