Conditional loop with running sum is skipping values - vba

I have created this code with the purpose of:
First Loop:
Loop through cells in column O to find anything that starts with DAAP.
If Cell 5 columns left of DAAP is empty then add the cell 1 column to the right (which is a number) to Total. Then rename the cell to GAAF
If Cell 5 columns left is not empty then just rename the cell to GAAF
Second Loop:
Find all GAAF cells in column O and then change the cell 1 column to the right to Total
Here is the code I have, it runs with no errors but just does nothing. I'm assuming something is syntax'ed wrong so it's looking in the wrong place but I can't find it! Any help is greatly appreciated :)
Dim rng As Range
Dim lstRow As Long
Dim AUMCell As Range
Dim Total As Long
lstRow = Cells(Rows.Count, "O").End(xlUp).Row
Set rng = Range("O2", Cells(lstRow, "O"))
Total = 0
For Each AUMCell In rng
If AUMCell.value = "DAAP" & "*" And AUMCell.Offset(0, -5).value = "" Then
Total = Total + AUMCell.Offset(0, 1).Value
AUMCell.value = "GAAF"
ElseIf AUMCell.value = "DAAP" & "*" And AUMCell.Offset(0, -5).value <> "" Then
AUMCell.value = "GAAF"
End If
Next AUMCell
For Each AUMCell In rng
If AUMCell.Value = "GAAF" Then
AUMCell.Offset(0, 1).Value = Total
End If
Next AUMCell

While the code is longer the execution of Find will be much quicker than a loop through each cell.
Sub Recut()
Dim rng1 As Range
Dim rng2 As Range
Dim rng3 As Range
Dim aCell As Range
Dim bCell As Range
Dim ws As Worksheet
Dim SearchString As String
Set ws = ActiveSheet
Set rng1 = ws.Range("O:O")
SearchString = "DAAP"
Set aCell = rng1.Find(SearchString, , xlFormulas, xlPart, xlByRows, xlNext)
If Not aCell Is Nothing Then
Set bCell = aCell
If Left$(aCell.Value, 4) = SearchString Then Set rng2 = aCell
Do
Set aCell = rng1.FindNext(After:=aCell)
If Not aCell Is Nothing Then
If aCell.Address = bCell.Address Then Exit Do
If Left$(aCell.Value, 4) = SearchString Then
If Not rng2 Is Nothing Then
Set rng2 = Union(rng2, aCell)
Else
Set rng2 = aCell
End If
End If
Else
Exit Do
End If
Loop
Else
MsgBox SearchString & " not Found"
Exit Sub
End If
If rng2 Is Nothing Then Exit Sub
For Each rng3 In rng2
If Len(rng3.Offset(0, -5)) = 0 Then Total = Total + rng3.Offset(0, 1).Value
rng3.Value = "GAFF"
Next
MsgBox Total
End Sub

Try to replace this code
For Each AUMCell In rng
If AUMCell.value = "DAAP" & "*" And AUMCell.Offset(0, -5).value = "" Then
Total = Total + AUMCell.Offset(0, 1).Value
AUMCell.value = "GAAF"
ElseIf AUMCell.value = "DAAP" & "*" And AUMCell.Offset(0, -5).value <> "" Then
AUMCell.value = "GAAF"
End If
Next AUMCell
by this code
For Each AUMCell In rng
If AUMCell.value like "DAAP*" Then
If AUMCell.Offset(0, -5).value = "" Then
Total = Total + AUMCell.Offset(0, 1).Value
End If
AUMCell.value = "GAAF"
End If
Next AUMCell
P.S.: Sorry my english

Related

Adding additional destination cell in vba code

I have the below code that copies a range from one sheet and pastes it in a differ sheet and does a calculation (ignores the colored values).
What I want to do is, I want to add additional cells into this code to perform the same function but for a slightly different formula...
The formula I ant to use is given below and the destiantion cells are AH 101 and AH102.
"=PERCENTILE.INC(" & Rng.Address(, , , True) & ",90%)*24"
"=PERCENTILE.INC(" & Rng.Address(, , , True) & ",50%)*24"
This is my entire code:
Sub TPNoRed()
Dim cel As Range
Dim Rng As Range
Dim arr As Variant
Dim i As Long
Application.ScreenUpdating = False
For Each cel In Sheets("TP").Range("A3:D30")
If cel.Font.Color = 0 Then
If Rng Is Nothing Then
Set Rng = cel
Else
Set Rng = Union(cel, Rng)
End If
End If
Next cel
ReDim arr(Rng.count - 1)
If Not Rng Is Nothing Then
For Each cel In Rng
arr(i) = cel
i = i + 1
Next cel
Sheets("TP").Range("AH1").Resize(UBound(arr) + 1).Value = Application.Transpose(arr)
Set Rng = Sheets("TP").Range("AH1:AH" & Sheets("TP").Cells(Rows.count, "AH").End(xlUp).Row)
Sheets("WBR45").Range("AH103").Formula = "=PERCENTILE.INC(" & Rng.Address(, , , True) & ",99%)*24"
Sheets("WBR45").Range("AH103").Value = Sheets("WBR45").Range("AH103").Value
Sheets("TP").Columns("AH:AH").ClearContents
Application.ScreenUpdating = True
End Sub

VBA: Cells Starting with "=" Causing Problems in my Move Macro

I currently have some code that finds cells not in the first column and moves them over. I'm facing a problem with cells that start with "=". Can you guys think of any work-arounds to solve this problem. Thanks in Advance.
Sub Move()
Dim cel As Range, rng As Range
Dim wk As Worksheet
Set wk = ActiveWorkbook.ActiveSheet
Set rng = wk.UsedRange
For Each cel In rng
If cel.Value <> "" And cel.Column <> 1 Then
wk.Cells(cel.Row, 1) = cel.Value
cel.Value = ""
End If
Next cel
End Sub
Either every time in your For each loop
If Cstr(cel.Value) <> "" And ... 'you need to do that for every cel.Value occurencies
Or declare a variable at the beginning
Dim StringInCell as String
For Each cel In rng
StringInCell=Cstr(cel.Value)
If StringInCell...
You may try .Text property as well (though I haven't had luck using that ever, I rather to use CStr).
This may work as well if the parsed data is throwing an error exception or something:
...
wk.Cells(cel.Row, 1).NumberFormat = "#"
wk.Cells(cel.Row, 1) = Cstr(cel.Value) 'related to the option chosen from above
Try this
Sub Move()
Dim cel As Range, rng As Range
Dim wk As Worksheet
Set wk = ActiveWorkbook.ActiveSheet
Set rng = wk.UsedRange
For Each cel In rng
If cel.HasFormula Then
wk.Cells(cel.Row, 1).Formula = cel.Formula
cel.ClearContents
Else
If cel.Value <> "" And cel.Column <> 1 Then
With wk.Cells(cel.Row, 1)
.NumberFormat = "#" '<<edit: added formatting
.Value = cel.Value
End with
cel.Value = ""
End If
End If
Next cel
End Sub
If you have cells that begin with =, but are not to be treated as formulas, but rather as Text, then using Sgdva's alternative suggestion:
Sub Move()
Dim cel As Range, rng As Range
Dim wk As Worksheet
Set wk = ActiveWorkbook.ActiveSheet
Set rng = wk.UsedRange
For Each cel In rng
If cel.Text <> "" And cel.Column <> 1 Then
wk.Cells(cel.Row, 1) = cel.Text
cel.Value = ""
End If
Next cel
End Sub
EDIT#1:
This version should "de-formularise" a cell before moving it to column 1:
Sub Move2()
Dim cel As Range, rng As Range
Dim wk As Worksheet, s As String
Set wk = ActiveWorkbook.ActiveSheet
Set rng = wk.UsedRange
For Each cel In rng
s = cel.Text
If s <> "" And cel.Column <> 1 Then
wk.Cells(cel.Row, 1).Value = s
cel.Value = ""
End If
Next cel
End Sub

populate listbox with specific rows from an excel sheet

I have an excel sheet named ("PPSBoarded") with 15 columns. I want to select rows based on similar values in column B and then display it in listbox on a VBA form. I tried this but it's not working:
Dim FoundCell As Range
Dim LastCell As Range
Dim FirstAddr As String
With Range("B1:B2")
Set LastCell = .Cells(.Cells.Count)
End With
Set FoundCell = Range("B1:B").Find(what:="EK261/GRU", after:=LastCell)
If Not FoundCell Is Nothing Then
FirstAddr = FoundCell.Address
End If
Do Until FoundCell Is Nothing
Debug.Print FoundCell.Address
Set FoundCell = Range("B1:B").FindNext(after:=FoundCell)
If FoundCell.Address = FirstAddr Then
Exit Do
End If
Loop
Me.ListBox1.List = FirstAddr
Your code should look like this:
Dim arrLstBox()
Dim rng, FoundCell, tmpCell As Range
Dim i, j, numRows, lastColumn, lastRow As Long
Dim FirstAddress, searchFor, colWidth As String
Set rng = ActiveSheet.UsedRange
numRow = 0
With rng
lastRow = .Rows.Count
lastColumn = .Columns.Count
End With
Me.ListBox1.ColumnCount = lastColumn
For x = 1 To lastColumn
If x = lastColumn Then
colWidth = colWidth & "1,5cm"
Exit For
End If
colWidth = colWidth & "1,5cm;"
Next x
Me.ListBox1.ColumnWidths = colWidth
searchFor = InputBox("Your word:")
Set FoundCell = rng.Find(what:=searchFor)
If Not FoundCell Is Nothing Then _
FirstAddress = FoundCell.Address
Do Until FoundCell Is Nothing
Set FoundCell = rng.FindNext(after:=FoundCell)
If FoundCell.Address = FirstAddress Then
numRow = numRow + 1
Exit Do
ElseIf FoundCell.Row <> rng.FindNext(after:=FoundCell).Row Then
numRow = numRow + 1
End If
Loop
ReDim arrLstBox(1 To numRow, 1 To lastColumn)
Do Until FoundCell Is Nothing
For i = 1 To numRow
For j = 1 To lastColumn
If Not IsEmpty(Cells(FoundCell.Row, j).Value) Then
arrLstBox(i, j) = Cells(FoundCell.Row, j).Value
End If
Set FoundCell = rng.FindNext(after:=FoundCell)
Next j
If FoundCell.Address = FirstAddress Then _
Exit For
Next i
If FoundCell.Address = FirstAddress Then _
Exit Do
Loop
Me.ListBox1.List = arrLstBox()

VBA search in two ranges

I'm more than new at this, and I'm having trouble sorting out For...Next loops.
I want to track to two text variables in two columns, so that when both variables are found in a row text is added to that row in a different column.
This is what I have so far:
Sub AB()
Dim Rng1 As Range
Dim Rng2 As Range
Set Rng1 = Range("B1:B100")
Set Rng2 = Range("A1:A100")
For Each cel In Rng1
If InStr(1, cel.Value, "A") > 0 Then
For Each cel In Rng2
If InStr(1, cel.Value, "B") > 0 Then
cel.Offset(0, 5).Value = "AB"
End If
Next
End If
Next cel
End Sub
You might even be able to just do this?
Sub AB()
With ActiveSheet
For I = 1 To 100
If InStr(1, .Cells(I, 2), "A") > 0 And InStr(1, .Cells(I, 1), "B") > 0 Then
.Cells(I, 6).Value = "AB" 'i think offset 5 is column F?
End If
Next
End With
End Sub
Appreciate you have an answer now, but here's a different method using Find. Always good to know several ways to do something.
Sub AB()
Dim rng As Range
Dim itemaddress As String
With Columns(1)
Set rng = .Find("A", searchorder:=xlByRows, lookat:=xlWhole)
If Not rng Is Nothing Then
itemaddress = rng.Address
Do
If rng.Offset(0, 1) = "B" Then
rng.Offset(0, 2).Value = "AB"
End If
Set rng = .FindNext(rng)
Loop While Not rng Is Nothing And itemaddress <> rng.Address
End If
End With
End Sub
You're using `cel' to step through each loop - the inner loop will get confused.
Along the vein of #findwindow answer (appeared as I was typing this). Loop just once and when a match is found check the cell next to it.
Sub AB()
Dim Rng1 As Range
Dim Rng2 As Range
Dim cel1 As Range
'Be specific about which sheet your ranges are on.
With ThisWorkbook.Worksheets("Sheet1")
Set Rng1 = .Range("B1:B100")
Set Rng2 = .Range("A1:A100")
End With
For Each cel1 In Rng1
'Check each value in column B.
If InStr(1, cel1.Value, "A") > 0 Then
'If a match is found, check the value next to it.
If InStr(1, cel1.Offset(, -1), "B") > 0 Then
cel1.Offset(, 4).Value = "AB"
End If
End If
Next cel1
End Sub

Filter in Excel VBA

I have a loop in VBA that loops through about 3000+ records and hides the ones that don't fit the criteria. It works just fine but it runs SUPER slow. Is there a faster or more efficient way to filter based on the following criteria? Any help would be greatly appreciated.
Dim i As Long, rng1 As Range, rng2 As Range, rng3 As Range, rng4 As Range, rng5 As Range, j As Long, sheetName As String, rng6 As Range, rng7 As Range, rng8 As Range, rng9 As Range
Set rng1 = FindHeader("Client Exclusion List", Sheet8.Name)
Set rng2 = FindHeader("CLIENT NAME", Sheet5.Name)
Set rng3 = FindHeader("MARKET SEGMENT", Sheet5.Name)
Set rng4 = FindHeader("ARCHIVED", Sheet5.Name)
Set rng5 = FindHeader("FORMULARY NAME", Sheet5.Name)
Set rng6 = FindHeader("WEBSITE", Sheet5.Name)
Set rng7 = FindHeader("PDF", Sheet5.Name)
Set rng8 = FindHeader("HPMS EXPORTED", Sheet5.Name)
Set rng9 = FindHeader("SERFF EXPORTED", Sheet5.Name)
For i = 1 To rng2.Rows.Count
'Checks to see if the Client Name is in the Excluded list
For j = 1 To rng1.Rows.Count
If rng2.Cells(i, 1).Value = rng1.Cells(j, 1).Value Then
rng2.Cells(i, 1).EntireRow.Hidden = True
End If
Next j
'Checks For all CMS records and hides the ones that are not from current year
If Left(rng3.Cells(i, 1).Value, 8) = "CMS Part" Then
If rng3.Cells(i, 1).Value <> "CMS Part D (CY " & Year(Date) & ")" Then
rng3.Cells(i, 1).EntireRow.Hidden = True
End If
End If
'Checks if record is archived
If rng4.Cells(i, 1).Value = "Yes" Then
rng4.Cells(i, 1).EntireRow.Hidden = True
End If
'Checks if record contains "Test" or "Demo" in the Name
If InStr(1, CStr(rng5.Cells(i, 1).Value), "test") > 0 Or InStr(1, CStr(rng5.Cells(i, 1).Value), "Test") > 0 Or InStr(1, CStr(rng5.Cells(i, 1).Value), "demo") > 0 Or InStr(1, CStr(rng5.Cells(i, 1).Value), "Demo") > 0 Or InStr(1, CStr(rng5.Cells(i, 1).Value), "TEST") > 0 Or InStr(1, CStr(rng5.Cells(i, 1).Value), "DO NOT USE") > 0 Then
rng5.Cells(i, 1).EntireRow.Hidden = True
End If
Next i
Here's an example that should be faster. It uses array, autofilter and doesn't process all the other ranges for each row of rng2:
Dim rng1 As Range
Dim rng2 As Range
Dim rng3 As Range
Dim rng4 As Range
Dim rng5 As Range
Dim rng6 As Range
Dim rng7 As Range
Dim rng8 As Range
Dim rng9 As Range
Dim i As Long
Dim j As Long
Dim sheetName As String
Dim vData1
Set rng1 = FindHeader("Client Exclusion List", Sheet8.Name)
Set rng2 = FindHeader("CLIENT NAME", Sheet5.Name)
Set rng3 = FindHeader("MARKET SEGMENT", Sheet5.Name)
Set rng4 = FindHeader("ARCHIVED", Sheet5.Name)
Set rng5 = FindHeader("FORMULARY NAME", Sheet5.Name)
Set rng6 = FindHeader("WEBSITE", Sheet5.Name)
Set rng7 = FindHeader("PDF", Sheet5.Name)
Set rng8 = FindHeader("HPMS EXPORTED", Sheet5.Name)
Set rng9 = FindHeader("SERFF EXPORTED", Sheet5.Name)
Application.ScreenUpdating = False
vData1 = rng1.Value
For i = 1 To rng2.Rows.Count
'Checks to see if the Client Name is in the Excluded list
For j = LBound(vdata1, 1) To UBound(vdata1, 1)
If rng2.Cells(i, 1).Value = vdata1(j, 1) Then
rng2.Cells(i, 1).EntireRow.Hidden = True
Exit For
End If
Next j
Next i
'Checks For all CMS records and hides the ones that are not from current year
rng3.AutoFilter 1, "<>CMS Part*", xlOr, "CMS Part D (CY " & Year(Date) & ")"
'Checks if record is archived
rng4.AutoFilter 1, "<>Yes"
'Checks if record contains "Test" or "Demo" in the Name
rng5.AutoFilter 1, "<>*test*", xlAnd, "<>*demo*"
Application.ScreenUpdating = True
One small change that should help is adding
Application.ScreenUpdating = False
at the beginning and
Application.ScreenUpdating = True
at the end
The screen updating time can be much more substantial than the logic.
Edit as an alternative to the array loop. Creates a dictionary filled with the excluded items as keys before the big loop. A set would be better here since you have a useless item to go with each key but I don't think VBA has those.
Instead of the loop through the range or an array you just check for the existence of the key in the dictionary.
'before loop
Dim excludedList As Object
Set excludedList = CreateObject("Scripting.Dictionary")
For i = 1 To rng1.Rows.Count
excludedList.Add rng1.Cells(i, 1).value, 1
Next i
'****************************************
'in loop
If excludedList.exists(rng2.Cells(i, 1).Value) Then
rng2.Cells(i, 1).EntireRow.Hidden = True
End If