Error while using count - vba

I have an sheet "Result" and I am trying to count the number of "Green", "red" and "" values in the column "K" of my sheet. I am then printing this value In my sheet "status". in sheet status I have a table with column A as week number. So if the weeks in the column A of sheet "status" is the same as the weeknumber in sheet "result" of column O, then I start counting for the values in column K
I have the code working, But I am lost, due to somereason, the count value I receive is not the correct one. For eg "green" I have 73 rows with green in column K of result. but I could see it printed in my sheet "status" as 71.
Could anyone help to figure what is going wrong ?
Sub result()
Dim i As Integer
Dim j As Integer
Dim cnt As Integer
Dim cntu As Integer
Dim sht As Worksheet
Dim totalrows As Long
Set sht = Sheets("Status")
Sheets("Result").Select
totalrows = Range("E5").End(xlDown).Row
n = Worksheets("Result").Range("E5:E" & totalrows).Cells.SpecialCells(xlCellTypeConstants).Count
For i = 2 To WorksheetFunction.Count(sht.Columns(1))
cntT = 0
cntu = 0
cntS = 0
If sht.Range("A" & i) = Val(Format(Now, "WW")) Then Exit For
Next i
For j = 5 To WorksheetFunction.CountA(Columns(17))
If sht.Range("A" & i) = Range("Q" & j) And Range("K" & j) = "Green" Then cntT = cntT + 1
If sht.Range("A" & i) = Range("Q" & j) And Range("K" & j) = "Red" Then cntu = cntu + 1
If sht.Range("A" & i) = Range("Q" & j) And Range("F" & j) = "" Then cntS = cntS + 1
If cntT <> 0 Then sht.Range("C" & i) = cntT
If cntu <> 0 Then sht.Range("D" & i) = cntu
If cntS <> 0 Then sht.Range("B" & i) = cntS
If n <> 0 Then sht.Range("G" & i) = n
Next j
If cntR + cntu <> 0 Then
'sht.Range("D" & i) = cntR / cntu * 100
End If
End Sub

I worked my way through your code and found a irregularities in your loops. Your variables I and j seem to be counting both rows and valid rows. Therefore I renamed these variables to make clear that they are rows. Also, your code tests each row for Red, Green and "". I think it can only be one of these. Therefore, if one is a match the other two can't be. This can lead to double counting. Finally, I found that you seem to be writing the final result to the Status sheet, in the same cells, many, many times.
I'm sorry, the following code isn't tested because I have no data. But I have tried to address the above problems.
Option Explicit
Sub MyResult() ' "Result" is a word reserved for the use of VBA
Dim cntT As Integer, cntU As Integer, cntS As Integer
Dim WsStatus As Worksheet, WsResult As Worksheet
Dim TotalRows As Long
Dim Rs As Integer, Rr As Long ' RowCounters: Status & Result
Dim n As Integer
Set WsStatus = Sheets("Status")
Set WsResult = Sheets("Result")
TotalRows = Range("E5").End(xlDown).Row
n = WsResult.Range("E5:E" & TotalRows).Cells.SpecialCells(xlCellTypeConstants).Count
' Improper counting: Rs is not necessarily aligned with the row number:
' For Rs = 2 To WorksheetFunction.Count(WsStatus.Columns(1))
For Rs = 2 To TotalRows
If WsStatus.Cells(Rs, "A").Value = Val(Format(Now, "WW")) Then Exit For
' If WsStatus.Range("A" & Rs) = Val(Format(Now, "WW")) Then Exit For
Next Rs
' Improper counting: Rr is not necessarily aligned with the row number:
' For Rr = 5 To WorksheetFunction.CountA(Columns(17))
With WsStatus
For Rr = 5 To TotalRows
If (.Cells(Rs, "A").Value = .Cells(Rs, "Q").Value) Then
If (.Cells(Rs, "K").Value = "Green") Then
cntT = cntT + 1
ElseIf (.Cells(Rs, "K").Value = "Red") Then
cntU = cntU + 1
Else
If (.Cells(Rs, "A").Value = "") Then cntS = cntS + 1
End If
End If
Next Rr
End With
With WsResult.Rows(Rs)
' it would be better to write even 0 to these cells
' if you don't want to show 0, format the cell to hide zeroes
.Cells(2).Value = IIf(cntS, cntS, "") ' 2 = B
.Cells(3).Value = IIf(cntT, cntT, "") ' 3 = C
.Cells(4).Value = IIf(cntU, cntU, "") ' 4 = D
.Cells(7).Value = IIf(n, n, "") ' 7 = G
End With
' If cntR + cntU <> 0 Then ' cntR isn't defined
'WsStatus.Range("D" & Rs) = cntR / cntu * 100
End If
End Sub
I urge you to use Option Explicit at the top of your sheet and declare every variable you use.

Related

Find out the cases having discrepancies

I am having a sheet having seven cloumns. First six columns having either true or false and in last column I have to mention the heading of false cases in one statement. Below is the excel.
Excel sheet
I have tried if else statement but there are too many possibilities. Since I am new to VBA i don't know any shortcut to that.Any suggestions?.... Thanks
Try this simple vba code,
Sub TEXTJOIN()
Dim i As Long, str As String, k As Long, j As Long
str = ""
j = 0
For i = 2 To Cells(Rows.Count, 1).End(xlUp).Row
If Application.WorksheetFunction.CountIf(Range("A" & i & ":F" & i), True) = 6 Then
Cells(i, 7) = "No Discrepancy Found"
Else
For k = 1 To 6
If Cells(i, k) = False Then
str = str & Cells(1, k) & ","
j = j + 1
End If
Next k
str = Left(str, Len(str) - 1) & " mismatch found"
Cells(i, 7) = Application.WorksheetFunction.Substitute(str, ",", " and ", j - 1)
str = ""
j = 0
End If
Next i
End Sub
Here's simple code which you should try:
Sub FindDiscrepancies()
Dim lastRow, i, j As Long
Dim discrepancies As String: discrepancies = ""
'find number of last row
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
For i = 2 To lastRow
For j = 1 To 6
If LCase(Cells(i, j).Value) = "false" Then
discrepancies = discrepancies & Cells(1, j).Value & ", "
End If
Next j
If discrepancies = "" Then
Cells(i, 7).Value = "No discrepancies found"
Else
Cells(i, 7).Value = "Mismatch found in " & discrepancies
End If
discrepancies = ""
Next i
End Sub

Look for an value in a sheet count it and paste the result in another sheet

I am having two Sheets sheet1 and sheet2
In sheet1 , in column AX I have my present week printed using an formula. I am looking for the sheet1, column T and U and Count the number of 1'S in both the columns.
the counted number of 1's of both the columns should be pasted in sheet2 looking into the week of sheet1 in column AX. if the column AX has week number 24, then it should run along the sheet2, column A for 24 and paste the Count value of T in column B and Count value of U in column C, and calculate the percentage for both and Paste in C and D.
I tried through a code, I am often getting it as 0,I am struck where I am wrong. Ist neither checking the Count nor weeks.
Sub test()
Dim col As Range
Dim row As Range
Dim sh1 As Worksheet
Dim sh2 As Worksheet
Dim T As Integer
Dim U As Integer
Dim wk As String
Set sh1 = Sheets("BW")
Set sh2 = Sheets("Results")
For Each col In sh2.Columns 'This loops through all populated columns in row one
If sh2.Cells(1, col.Column).Value = "" Then
Exit For
End If
wk = sh2.Cells(1, col.Column).Value
For Each rw In sh1.Rows
If sh1.Cells(rw.row, 50).Value = "" Then
Exit For
End If
If sh1.Cells(rw.row, 50) = wk And sh1.Cells(rw.row, 20) = 1 Then
T = T + 1
End If
If sh1.Cells(rw.row, 50) = wk And sh1.Cells(rw.row, 21) = 0 Then
U = U + 1
End If
Next rw
sh2.Cells(2, col.Column) = T 'put counters into 2nd and 3rd row under each week, you can adjust this to put the number in a different cell.
sh2.Cells(3, col.Column) = U
T = 0 'reset counters to start looking at next week.
U = 0
Next col
End Sub
It appears from the question that sheet "Results" for a given week indicated in column A, shows in column B & C count of 1's in column T & U of the other sheet respectively.
One approach to solve this is that for each row in "Results" sheet, the counter looks into all rows of "BW" sheet for that week indicated in column "AX" to get the count from column T & U.
This'll give some idea:
Sub test()
Dim i As Integer, j As Integer, cntT As Integer, cntU As Integer, ws As Worksheet
Set ws = Sheets("Results")
Sheets("BW").Select
For i = 2 To WorksheetFunction.CountA(ws.Columns(1))
If ws.Range("A" & i) = Val(Format(Now, "ww")) Then Exit For
Next i
ws.Range("B" & i & ":" & "E" & i).ClearContents
cntT = 0
cntU = 0
For j = 5 To WorksheetFunction.CountA(Columns(50))
If ws.Range("A" & i) = Range("AX" & j) And Range("AA" & j) <> "" Then
If Range("T" & j) = 1 Then cntT = cntT + 1
If Range("U" & j) = 1 Then cntU = cntU + 1
End If
Next j
If cntT <> 0 Then ws.Range("B" & i) = cntT
If cntU <> 0 Then ws.Range("C" & i) = cntU
If cntT + cntU <> 0 Then
ws.Range("D" & i) = cntT / (cntT + cntU)
ws.Range("E" & i) = cntU / (cntT + cntU)
End If
ws.Range("D" & i & ":E" & i).NumberFormat = "0%"
End Sub
Update: as per subsequent discussion with #Mikz below criteria added to the above updated code:
it only overwrites current week, so for Jul 2, 2017 it'll only overwrite the current week of 27 if found in `column A` of `Results` sheet
if the is output is 0, it will leave the target cells as blank
if respective cell of the AA column of "BW" sheet is blank, that row won't be counted for 1s
sheet "BW" data starts from row 5

VBA access different ranges based on which (of 3) comboboxes has an item selected

I am looking to search for different values (Commodity Group in range "FY", Sub Group in range "FZ", Product in Range "GA") on the same Worksheet based on 3 comboboxes - one for each of the items - and copy it to another Worksheet.
Note: It is not necessary to select all 3 comboboxes because Combobox2 is populated based on combobox1 and Combobox3 based on Combobox2. Moreover, the user Needs to be able to create a Portfolio based on Inputs from only 1 or 2 comboboxes. Also, if that makes a difference, the items in all 3 ranges on the Database-Worksheet may contain ( ) / , -
I cannot seem to get it working beyond the point that it looks for the item in the first Combobox.
Two pictures for Illustration-purposes:
http://imgur.com/a/FxeNh
http://imgur.com/a/KtqdU
Here my take on it - thank you all in advance:
Dim wb As Workbook
Set wb = ActiveWorkbook
Dim ws1, ws2, ws3 As Worksheet
Set ws1 = wb.Worksheets("Meta DB")
'ws2 not here
Set ws3 = wb.Worksheets("Supplier Criteria TreeView")
'1. - - get all Suppliers for the selected Input
Dim strFind As String
Dim strRange As String
Dim i, j, k As Long
'1.1. - - Get value to search for and range to go through (depending on combobox selections)
If Me.comboProduct.ListIndex = -1 And Me.comboSubGroup.ListIndex = -1 And Me.comboCG.ListIndex <> -1 Then
strRange = "FY"
strFind = Me.comboCG.value
ElseIf Me.comboProduct.ListIndex = -1 And Me.comboSubGroup.ListIndex <> -1 And Me.comboCG.ListIndex <> -1 Then
strRange = "FZ"
strFind = Me.comboSubGroup.value
ElseIf Me.comboProduct.ListIndex <> -1 And Me.comboSubGroup.ListIndex <> -1 And Me.comboCG.ListIndex <> -1 Then
strRange = "GA"
strFind = Me.comboProduct.value
End If
'Paste starting at row 2 or 30 in ws3, respectively (Active / Inactive)
j = 2
k = 30
'Start searching from row 4 of Database, continue to end of worksheet
For i = 4 To ws1.UsedRange.Rows.Count
If ws1.Range(strRange & i) = strFind Then
'Check for active Supplier
If ws1.Range("E" & i) = "Yes" Then
'Copy row i of Database to row j of ws3 then increment j
ws1.Range("B" & i & ":" & "E" & i).Copy Destination:=ws3.Range("B" & j & ":" & "E" & j) 'Copy Name, Potential Supplier, ID, Active
j = j + 1
Else
'If inactive Supplier, post further down from 30 onwards. Second listbox populates from there
If ws1.Range("E" & i) = "No" Then
ws1.Range("B" & i & ":" & "E" & i).Copy Destination:=ws3.Range("B" & k & ":" & "E" & k) 'Copy Name, Potential Supplier, ID, Active
k = k + 1
Else
Exit Sub
End If
End If
End If
Next i
Private Sub cmdPortfolio_Click()
Dim product As String, col As Variant
Dim rw As Long, x As Long
Dim c As Range, Target As Range
'1.0. - - Clear previously used range
Worksheets("Supplier Criteria TreeView").Range("A2:L28,A30:L100").Clear
'1.1. - - Get value to search for and range to go through (depending on combobox selections)
If Me.comboProduct.ListIndex = -1 And Me.comboSubGroup.ListIndex = -1 And Me.comboCG.ListIndex <> -1 Then
col = "FY"
product = Me.comboCG.Value
ElseIf Me.comboProduct.ListIndex = -1 And Me.comboSubGroup.ListIndex <> -1 And Me.comboCG.ListIndex <> -1 Then
col = "FZ"
product = Me.comboSubGroup.Value
ElseIf Me.comboProduct.ListIndex <> -1 And Me.comboSubGroup.ListIndex <> -1 And Me.comboCG.ListIndex <> -1 Then
col = "GA"
product = Me.comboProduct.Value
End If
With Worksheets("Meta DB")
For x = 4 To .Cells(Rows.Count, col).End(xlUp).row
If .Cells(x, col) = product Then
rw = IIf(.Range("E" & x) = "Yes", 29, Rows.Count)
Set Target = Worksheets("Supplier Criteria TreeView").Cells(rw, "B").End(xlUp).Offset(1)
.Range("B" & x & ":" & "E" & x).Copy Destination:=Target
With Target.EntireRow
Set c = Worksheets("Criteria").Range("K3", Worksheets("Criteria").Range("K" & Rows.Count).End(xlUp)).Find(.Cells(1, "D"))
If Not c Is Nothing Then
.Cells(1, "A") = Round(c.EntireRow.Cells(1, "L"))
.Cells(1, "F") = Round(c.EntireRow.Cells(1, "Q"))
.Cells(1, "G") = Round(c.EntireRow.Cells(1, "AG"))
End If
End With
End If
Next
End With
End Sub

VBA loop with arrays duplicating output

I'm new to using arrays (and VBA in general) and I'm trying to incorporate a series of arrays into a module that formats SPSS syntax output in worksheets in a single workbook. Below is my code, which works, but is duplicating the results that are found. I think it has something to do with the order of my loops but I can't seem to figure out how to fix it. Any thoughts would be greatly appreciated.
Sub FindValues()
Call CreateSummary
'This code will build the initial summary file
Dim ws As Excel.Worksheet
'Application.ScreenUpdating = False
MsgBox ("It will take a moment for data to appear, please be patient if data does not immediately appear")
Dim LastRow As Long
Dim i As Integer
Dim i2 As Integer
Dim x As Integer
Dim y As Integer
Dim CopiedRows As Integer
Dim LocationA(4) As String
Dim LocationB(4) As String
Dim LocationC(4) As String
Dim LocationD(4) As String
Dim VariableA(4) As Integer
Dim VariableB(4) As Integer
Dim ColumnA(4) As String
Dim ColumnB(4) As String
Dim n As Long
'Find DateTime Info
LocationA(1) = "Date_Time"
LocationB(1) = "Quarter"
LocationC(1) = "N"
LocationD(1) = "Minimum"
VariableA(1) = 1
VariableB(1) = 1
ColumnA(1) = "B"
ColumnB(1) = "C"
LocationA(2) = "Dur*"
LocationB(2) = "Methodology_ID"
LocationC(2) = "Mean"
LocationD(2) = "N"
VariableA(2) = 1
VariableB(2) = 1
ColumnA(2) = "C"
ColumnB(2) = "D"
LocationA(3) = "WebTimeout"
LocationB(3) = "Methodology_ID"
LocationC(3) = "Mean"
LocationD(3) = "N"
VariableA(3) = 1
VariableB(3) = 1
ColumnA(3) = "C"
ColumnB(3) = "D"
'LocationA(4) = "Crosstabulation"
'LocationB(4) = "Quarter"
'LocationC(4) = "N"
'LocationD(4) = "Minimum"
'VariableA(4) = 1
'Find OSAT Data
'LocationA(2) = "*Report*"
'LocationB(2) = "*CallMonth*"
'LocationC(2) = "Mean*"
'LocationD(2) = "*Overall*"
'VariableA(2) = 2
For Each ws In Application.ThisWorkbook.Worksheets
'Starting row
i = 1
'Find LastRow
LastRow = ws.Cells(Rows.Count, 1).End(xlUp).Row
If ws.Name <> "Run Macros" Then
Do While i <= LastRow
For x = 1 To 3
If ws.Range("A" & i).Value Like LocationA(x) And ws.Range("A" & i + 1).Value Like LocationB(x) And ws.Range(ColumnA(x) & i + VariableA(x)).Value Like LocationC(x) And ws.Range(ColumnB(x) & i + VariableB(x)).Value Like LocationD(x) Then
CopiedRows = 0
i2 = i
Do While ws.Range("A" & i2 + 1).Borders(xlEdgeLeft).LineStyle = 1 And ws.Range("A" & i2 + 1).Borders(xlEdgeLeft).Weight = 4
i2 = i2 + 1
CopiedRows = CopiedRows + 1
Loop
n = Sheets("Summary").Cells(Rows.Count, "A").End(xlUp).Row + 4
ws.Rows(i & ":" & i + CopiedRows).Copy Sheets("Summary").Range("A" & n)
On Error Resume Next
End If
Next x
i = i + 1
Loop
End If
Next
'Application.ScreenUpdating = True
End Sub
This works if anyone want to reuse this code...
For x = 1 To 3 Step 1
For Each ws In Application.ThisWorkbook.Worksheets
'Starting row
i = 1
'Find LastRow
LastRow = ws.Cells(Rows.Count, 1).End(xlUp).Row
Do While i <= LastRow
If ws.Name <> "Run Macros" Or ws.Name <> "Summary" Then
If ws.Range("A" & i).Value Like LocationA(x) And ws.Range("A" & i + 1).Value Like LocationB(x) And ws.Range(ColumnA(x) & i + VariableA(x)).Value Like LocationC(x) And ws.Range(ColumnB(x) & i + VariableB(x)).Value Like LocationD(x) Then
CopiedRows = 0
i2 = i
Do While ws.Range("A" & i2 + 1).Borders(xlEdgeLeft).LineStyle = 1 And ws.Range("A" & i2 + 1).Borders(xlEdgeLeft).Weight = 4
i2 = i2 + 1
CopiedRows = CopiedRows + 1
Loop
n = Sheets("Summary").Cells(Rows.Count, "A").End(xlUp).Row + 4
ws.Rows(i & ":" & i + CopiedRows).Copy Sheets("Summary").Range("A" & n)
Exit For
On Error Resume Next
End If
End If
i = i + 1
Loop
Next
Next x

how to find largest positive or negative value pattern from a given standpoint

I'm currently writing a sub but I'm unclear of how to approach the problem programatically
Essentially I have a sheet with a column of data values starting at "A1"
How do I write a sub that will check through the column to find the largest pattern starting from the first cell and the direction of the pattern?
ie. if A1 is 2, A2 is 5, A3 is -2 ... the sub should return 2 (positive 2 days in a row)
if A1 is -2, A2 -1, A3 is -5, A4 is -2, A5 -1, A6 2 ... the sub should return -5 (negative 5 days in a row)
What I want is to somehow gather this number but in the process also save the last row in the pattern so I can compute averages, std variation etc. to store to a collection
Here is the code to check for patterns.... the j is a column counter... I need to figure out how to make the loop go back up to right before the for loop instead of iterating the j variable and then going back down....
but in any case here is the check pattern sub
<i> Sub pattern_recogADR()
'add back in as parameters
x As Long
pat_days As Long
sht_start As Long
x = 1
pat_days = 5
sht_start = 13
Dim st As Long
Dim st_num As Long
Dim st_end As Long
Dim count As Long
Dim patrn As Long
count = sht_start
Dim i As Long
Set pat = New pattern
For j = 8 To 12
st_num = 0
If IsNumeric(Cells(count, j).value) Then
st_num = count 'sets default pattern to beginning cell value
If Cells(st_num, j).value < 0 Then
For i = count + 1 To count + 1 + pat_days
If IsNumeric(Cells(i, j).value) And Cells(i, j).value < 0 Then
st_end = i
Else
Exit For
End If
Next i
patrn = st_end - st_num
tix.arbPnl = patrn
'**CONFUSION HERE WANT TO SAVE PATTERN TO AN EXISTING COLLECTION STARTING `
'AT THE FIRST ITEM **
ElseIf Cells(st_num, j).value > 0 Then
For i = count + 1 To count + 1 + pat_days
If IsNumeric(Cells(i, j).value) And Cells(i, j).value < 0 Then
st_end = i
Else
Exit For
End If
Next i
patrn = st_end - st_num
TIX.arbPnl = patrn
'save to separate class for patterns
Else
count = count + 1
End If
Next j
End Sub
Here is where I previously define the object. Basically I want to get this pattern and then add it to the respective attribute (? I dont know coding vocab) in this collection which is already define so the pattern matches with the respective item in the collection.
Option Explicit
Public TixCollection As New Collection
Sub DefineTixCollection()
Application.ScreenUpdating = False
Sheets("Input").Activate
Set TixCollection = Nothing
Dim tix As clsTix
Dim i As Long
Dim last_row As Long
last_row = Range("A" & Rows.count).End(xlUp).Row
'Add tix properties
For i = 3 To last_row
Set tix = New clsTix
'only adds active tickers to collection
If Range("A" & i).value = "x" Then
'Random data
tix.ORD = Range("B" & i).value
tix.ADR = Range("C" & i).value
tix.ratio = Range("D" & i).value
tix.crrncy = Range("E" & i).value
tix.hedge_index = Range("F" & i).value
tix.hedge_ord = Range("G" & i).value
tix.hedge_ratio = Range("H" & i).value
' ADR is the id key
TixCollection.Add tix, tix.ADR
End If
Next i
' Error Check
' For i = 1 To 5
' 'retrieve by collection index
' Debug.Print TixCollection(i).ORD
' Debug.Print TixCollection(5).ADR
' Debug.Print TixCollection(5).ratio
' Debug.Print TixCollection(i).crrncy
' Debug.Print TixCollection(i).hedge_index
' Debug.Print TixCollection(i).hedge_ord
' Debug.Print TixCollection(i).hedge_ratio
' Next i
End Sub
Any help would be much appreciated getting frustrated now... ugh
Sub Button1_Click()
Dim patrn() As Long
ReDim patrn(0 To 4)
Dim count As Long
Dim posCount As Integer
Dim negCount As Integer
Dim sign As Boolean
posCount = 0
negCount = 0
count = 0
Dim i As Long
Dim j As Integer
Dim lastRow As Long
For j = 8 To 12
lastRow = ActiveSheet.Cells(ActiveSheet.Rows.count, j).End(xlUp).Row
For i = 1 To lastRow
If IsNumeric(Cells(i, j).Value) Then
If count = 0 Then
If Cells(i, j).Value > 0 Then
sign = True
posCount = posCount + 1
ElseIf Cells(i, j).Value < 0 Then
sign = False
negCount = negCount + 1
End If
ElseIf count > 0 And count <= 4 Then
If Cells(i, j).Value > 0 And sign = True Then
sign = True
posCount = posCount + 1
ElseIf Cells(i, j).Value > 0 And sign = False Then
sign = True
posCount = 1
ElseIf Cells(i, j).Value < 0 And sign = True Then
sign = False
negCount = 1
ElseIf Cells(i, j).Value < 0 And sign = False Then
sign = False
negCount = negCount + 1
End If
ElseIf count = 5 Then
Exit For
End If
count = count + 1
End If
Next i
If posCount > negCount Then
patrn(j - 8) = posCount
Else
patrn(j - 8) = negCount - (negCount * 2)
End If
negCount = 0
posCount = 0
count = 0
Next j
'Do your other calculations here.
For i = LBound(patrn) To UBound(patrn)
Debug.Print patrn(i)
Next
End Sub