Performance issue and error in Excel vba - vba

I have created a code for getting unique value from a column which is filled with date and from that unique column i have compare whether it is Sunday or Monday or Tuesday or etc and if it falls in between two time stamp [2:00:00 am to 2:59:59 am] i increment but if on same date for example 1/5/2014 it falls in two time stamp again[2:00:00 am - 2:59:59 am] i should not increment and if in the same date it falls in another time stamp it should increment that too only once.
It is working for 50 -100 rows but for 200k of rows it is hanging.
Private Sub CommandButton1_Click()
Range("I2:O25") = ""
Set Range1 = Range("B:B")
Dim dates As Variant
Dim Array1() As Variant
Dim MyArray1(24, 7) As Integer
Array1 = UniqueItems(Range1, False)
For Each dates In Array1
If Not (dates = "" Or dates = "Date") Then
For y = 2 To Range("B2").End(xlDown).Row
If (dates = (Cells(y, 2))) Then
For f = 2 To Range("f2").End(xlDown).Row
If ((TimeValue(Cells(y, 4).Text) >= TimeValue(Cells(f, 6).Text)) And (TimeValue(Cells(y, 4).Text) <= TimeValue(Cells(f, 7).Text))) Then
If (Cells(y, 3) = "Sunday") Then
' Cells(f, 12) = 1
Dim g As Integer
g = f - 2
MyArray1(g, 0) = 1
End If
If (Cells(y, 3) = "Monday") Then
' Cells(f, 12) = 1
g = f - 2
MyArray1(g, 1) = 1
End If
If (Cells(y, 3) = "Tuesday") Then
' Cells(f, 12) = 1
g = f - 2
MyArray1(g, 2) = 1
End If
If (Cells(y, 3) = "Wednesday") Then
' Cells(f, 12) = 1
g = f - 2
MyArray1(g, 3) = 1
End If
If (Cells(y, 3) = "Thursday") Then
' Cells(f, 12) = 1
g = f - 2
MyArray1(g, 4) = 1
End If
If (Cells(y, 3) = "Friday") Then
' Cells(f, 12) = 1
g = f - 2
MyArray1(g, 5) = 1
End If
If (Cells(y, 3) = "Saturday") Then
' Cells(f, 12) = 1
g = f - 2
MyArray1(g, 6) = 1
End If
End If
Next f
End If
Next y
For k = 0 To 7
For x = 0 To 23
Dim cellsval As Integer
Dim dayvals As Integer
cellsval = x + 2
dayvals = k + 9
Cells(cellsval, dayvals) = Cells(cellsval, dayvals) + MyArray1(x, k)
MyArray1(x, k) = 0
Next x
Next k
End If
Next
'For x = 2 To Range("H2").End(xlDown).Row
' For y = 2 To Range("A2").End(xlDown).Row
' If (Cells(y, 2) = Cells(x, 8)) Then
' If ((TimeValue(Cells(y, 4).Text) >= TimeValue(Cells(16, 6).Text)) And (TimeValue(Cells(y, 4).Text) <= TimeValue(Cells(16, 7).Text))) Then
' If (Cells(y, 3) = "Wednesday") Then
' Cells(x, 22) = 1
' End If
' End If
' End If
' Next y
'Next x
End Sub
Function RetTime(IntTime As Long) As Date
RetTime = TimeSerial(Int(IntTime / 10000), Int((IntTime Mod 10000) / 100), (IntTime Mod 100))
End Function
Function UniqueItems(ArrayIn, Optional Count As Variant) As Variant
' Accepts an array or range as input
' If Count = True or is missing, the function returns the number of unique elements
' If Count = False, the function returns a variant array of unique elements
Dim Unique() As Variant ' array that holds the unique items
Dim Element As Variant
Dim i As Integer
Dim FoundMatch As Boolean
' If 2nd argument is missing, assign default value
If IsMissing(Count) Then Count = True
' Counter for number of unique elements
NumUnique = 0
' Loop thru the input array
For Each Element In ArrayIn
FoundMatch = False
' Has item been added yet?
For i = 1 To NumUnique
If Element = Unique(i) Then
FoundMatch = True
Exit For '(exit loop)
End If
Next i
AddItem:
' If not in list, add the item to unique list
If Not FoundMatch And Not IsEmpty(Element) Then
NumUnique = NumUnique + 1
ReDim Preserve Unique(NumUnique)
Unique(NumUnique) = Element
End If
Next Element
' Assign a value to the function
If Count Then UniqueItems = NumUnique Else UniqueItems = Unique
End Function

I have taken the liberty of cleaning up your code a bit, I dropped a couple of comments in there to show you the changes and I have indented it properly.
Option Explicit
Private Sub CommandButton1_Click()
Dim dates As Variant, Array1() As Variant, MyArray1(24, 7) As Long, g As Long, MyWeekday As Variant, X As Long, K As Long, F As Long, Y As Long, Range1 As Range
MyWeekday = Array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")
Range("I2:O25").ClearContents
Set Range1 = Range("B:B")
Array1 = UniqueItems(Range1, False)
For Each dates In Array1
If Not (dates = "" Or dates = "Date") Then
For Y = 2 To Range("B" & Rows.Count).End(xlUp).Row
If (dates = (Cells(Y, 2))) Then
For F = 2 To Range("f" & Rows.Count).End(xlUp).Row
If ((TimeValue(Cells(Y, 4).Text) >= TimeValue(Cells(F, 6).Text)) And (TimeValue(Cells(Y, 4).Text) <= TimeValue(Cells(F, 7).Text))) Then
For X = LBound(MyWeekday) To UBound(MyWeekday)
If (Cells(Y, 3) = MyWeekday(X)) Then
g = F - 2
MyArray1(g, X) = 1
End If
Next
End If
Next
End If
Next
For K = 0 To 7
For X = 0 To 23
Cells(X + 2, K + 9) = Cells(X + 2, K + 9) + MyArray1(X, K)
MyArray1(X, K) = 0
Next
Next
End If
Next
End Sub
Function RetTime(IntTime As Long) As Date
RetTime = TimeSerial(Int(IntTime / 10000), Int((IntTime Mod 10000) / 100), (IntTime Mod 100))
End Function
Function UniqueItems(ArrayIn, Optional Count As Variant) As Variant
' Accepts an array or range as input
' If Count = True or is missing, the function returns the number of unique elements
' If Count = False, the function returns a variant array of unique elements
Dim Unique() As Variant, Element As Variant, i As Long, FoundMatch As Boolean, NumUnique As Long
' If 2nd argument is missing, assign default value
If IsMissing(Count) Then Count = True
' Counter for number of unique elements
NumUnique = 0
' Loop thru the input array
For Each Element In ArrayIn
FoundMatch = False
' Has item been added yet?
For i = 1 To NumUnique
If Element = Unique(i) Then
FoundMatch = True
Exit For '(exit loop)
End If
Next i
'AddItem - You don't need this as a GoTo heading you can jump to, keep it commented out
' If not in list, add the item to unique list
If Not FoundMatch And Not IsEmpty(Element) Then
NumUnique = NumUnique + 1
ReDim Preserve Unique(NumUnique)
Unique(NumUnique) = Element
End If
Next Element
' Assign a value to the function
If Count Then UniqueItems = NumUnique Else UniqueItems = Unique
End Function
Please post try the code I posted and see if it does the same as your code did, if so then we can begin making the changes you need.

Related

VBA sort Two-digit array

I want to sort below Two-digit array by VBA code
A 1
B 2
A 1
C 3
or below:
1 A
2 B
1 A
3 C
I have tried to sort them by Dictionary, but, Dictionary is not allowed to insert duplate key.
Is there any want to sort above array by number 1,2,3
I made this some time ago, it might help.
Function ArraySorter(ByVal RecArray As Variant, Optional ByVal RefCol As Integer = 0) As Variant
Dim Menor As String
Dim NewArray() As Variant
Dim i As Double, j As Double
Dim menorIndex As Double
Dim NewArrayIndex() As Double
Dim UsedIndex() As Double
ReDim NewArrayIndex(UBound(RecArray, 2))
ReDim NewArray(UBound(RecArray), UBound(RecArray, 2))
For i = 0 To UBound(NewArrayIndex)
NewArrayIndex(i) = -1
Next i
UsedIndex = NewArrayIndex
For i = 0 To UBound(RecArray, 2)
Menor = ""
menorIndex = -1
For j = 0 To UBound(RecArray, 2)
If UsedIndex(j) = -1 Then
If Menor = "" Then
Menor = RecArray(RefCol, j)
menorIndex = j
Else
If RecArray(RefCol, j) < Menor Then
Menor = RecArray(RefCol, j)
menorIndex = j
End If
End If
End If
Next j
UsedIndex(menorIndex) = 1
NewArrayIndex(i) = menorIndex
Next i
For i = 0 To UBound(NewArrayIndex)
For j = 0 To UBound(NewArray)
NewArray(j, i) = RecArray(j, NewArrayIndex(i))
Next j
Next i
ArraySorter = NewArray
End Function
If you have something like:
Function testArraySorter()
Dim myArr() As Variant
ReDim myArr(1, 3)
myArr(0, 0) = "A"
myArr(0, 1) = "B"
myArr(0, 2) = "A"
myArr(0, 3) = "C"
myArr(1, 0) = 1
myArr(1, 1) = 2
myArr(1, 2) = 1
myArr(1, 3) = 3
myArr = ArraySorter(myArr)
For i = 0 To UBound(myArr, 2)
Debug.Print myArr(0, i), myArr(1, i)
Next i
End Function
you'll get this in your immediate verification :
A 1
A 1
B 2
C 3
If you need to sort based in two or more columns, you could add a dummy column into your array, concatenate the criteria columns into it and then set this dummy column as RefCol: myArr = ArraySorter(myArr, addedColNumberHere).
Hope this helps.

search combination of words in worksheet using VBA

I need to find the row which as combination of words (Keyword - Column 1 , keyword 2 - column 2 , keyword 3 - column 3) of sheet1 with sheet 2 which as more than 800 rows and 275 columns.
I have done a coding but it gives a result as "not responding". Please help me to sort out this issue.
below is the coding:-
Private Sub CommandButton1_Click()
Dim keyword As String
Dim keyword1 As String
Dim keyword2 As String
Dim keyword3 As String
Dim k As Long
Dim k1 As Long
Application.ScreenUpdating = False
Set XML = ThisWorkbook.Worksheets("XML")
Set rn = XML.UsedRange
k = rn.Rows.Count + rn.Row - 1
Debug.Print (k)
For i = 1 To k
k1 = rn.Columns.Count + rn.Column - 1
Debug.Print (k1)
For j = 1 To k1
cellAYvalue = XML.Cells(i, j)
For a = 2 To 261
MatchAttempt = 0
keyword_Flag = False
keyword1_Flag = False
keyword2_Flag = False
keyword3_Flag = False
keyword4_Flag = False
keyword5_Flag = False
keyword = Trim(UCase(ThisWorkbook.Worksheets("Keyword").Cells(a, 2)))
keyword1 = Trim(UCase(ThisWorkbook.Worksheets("Keyword").Cells(a, 3)))
keyword2 = Trim(UCase(ThisWorkbook.Worksheets("Keyword").Cells(a, 4)))
keyword3 = Trim(UCase(ThisWorkbook.Worksheets("Keyword").Cells(a, 5)))
keyword4 = Trim(UCase(ThisWorkbook.Worksheets("Keyword").Cells(a, 6)))
keyword5 = Trim(UCase(ThisWorkbook.Worksheets("Keyword").Cells(a, 7)))
If keyword <> "" Then
keyword_Flag = True: MatchAttempt = MatchAttempt + 1
End If
If keyword1 <> "" Then
keyword1_Flag = True: MatchAttempt = MatchAttempt + 1
End If
If keyword2 <> "" Then
keyword2_Flag = True: MatchAttempt = MatchAttempt + 1
End If
If keyword3 <> "" Then
keyword3_Flag = True: MatchAttempt = MatchAttempt + 1
End If
If keyword4 <> "" Then
keyword4_Flag = True: MatchAttempt = MatchAttempt + 1
End If
If keyword5 <> "" Then
keyword5_Flag = True: MatchAttempt = MatchAttempt + 1
End If
MatchedCount = 0
Description = Trim(UCase(cellAYvalue = XML.Cells(i, j)))
Description1 = Trim(UCase(cellAYvalue = XML.Cells(i, j)))
Description2 = Trim(UCase(cellAYvalue = XML.Cells(i, j)))
Description3 = Trim(UCase(cellAYvalue = XML.Cells(i, j)))
Description4 = Trim(UCase(cellAYvalue = XML.Cells(i, j)))
Description5 = Trim(UCase(cellAYvalue = XML.Cells(i, j)))
EXITloop = Trim(UCase(ThisWorkbook.Worksheets("Keyword").Cells(a, 1)))
If EXITloop = "" Then
Exit For
End If
MatchComplete = False
If keyword_Flag = True Then
If keyword = Description Then
MatchedCount = MatchedCount + 1
If MatchAttempt = MatchedCount Then MatchComplete = True
End If
End If
If keyword_Flag1 = True Then
If keyword1 = Description1 Then
MatchedCount = MatchedCount + 1
If MatchAttempt = MatchedCount Then MatchComplete = True
End If
End If
If keyword_Flag2 = True Then
If keyword2 = Description2 Then
MatchedCount = MatchedCount + 1
If MatchAttempt = MatchedCount Then MatchComplete = True
End If
End If
If keyword_Flag3 = True Then
If keyword3 = Description3 Then
MatchedCount = MatchedCount + 1
If MatchAttempt = MatchedCount Then MatchComplete = True
End If
End If
If keyword_Flag4 = True Then
If keyword4 = Description4 Then
MatchedCount = MatchedCount + 1
If MatchAttempt = MatchedCount Then MatchComplete = True
End If
End If
If keyword_Flag5 = True Then
If keyword5 = Description5 Then
MatchedCount = MatchedCount + 1
If MatchAttempt = MatchedCount Then MatchComplete = True
End If
End If
inin = Trim(UCase(ThisWorkbook.Worksheets("XML").Cells(i, 112)))
ouou = Trim(UCase(ThisWorkbook.Worksheets("Keyword").Cells(a, 8)))
If MatchComplete = True Then
ouou = inin
End If
a = a + 0
Next
j = j + 0
Next
i = i + 0
Next
Application.ScreenUpdating = True
MsgBox "Completed"
End Sub
Edit: More details
I have a workbook with two worksheets
Sheet 1 is having “N” number of data with 807 rows and 277 column
Sheet 2 is having the standard keyword combination (201 combinations) set.
Note: - each combination from sheet 2 can be available in any of the row or columns of sheet 1, But combination match should be in row wise alone.
Requirements: - Need to find the keyword combination from sheet 2 in sheet 1 once the combination found in sheet 1 we need to fetch the output.
Sheet 1 (Data Sheet)
Sheet 2 (Keyword Sheet)
Searching keywords from sheet 2 in sheet 1
keywords can find in many cells of sheet 1 (Yellow highlighted) but the combination will be find in only one row and we need to find that row (Green highlighted)
once we have found the row in sheet 1 which has the combination we need to fetch the fourth value from the last combination word and paste it in the 10th column of sheet 2.
E.g
in sheet 1
we have found the combination 100th row
in that row keyword 1 in (100,20)
keyword 2 in (100,40)
keyword 3 in (100,60)
then output should be need to copy the value from cell (100,64) in sheet 1 then need to paste in 10th column of sheet 2 to respective combination row of sheet 2.
This identifies Sheet2 rows in Sheet1, based on the first 3 columns as keywords
Once a record is found, it copies value from the 3rd col in Sheet1 in the 10th column of Sheet2
Option Explicit
Private Sub CommandButton1_Click()
Const FR = 2 'Start row
Const KC = 3 'Last Keyword column
Const TC = 10 'Target column
Dim ws1 As Worksheet: Set ws1 = Sheet1 'Or: ThisWorkbook.Worksheets("Sheet1")
Dim ws2 As Worksheet: Set ws2 = Sheet2
Dim lr1 As Long: lr1 = ws1.Cells(ws1.Rows.Count, "A").End(xlUp).Row
Dim lr2 As Long: lr2 = ws2.Cells(ws2.Rows.Count, "A").End(xlUp).Row
Dim arr1 As Variant: arr1 = ws1.Range(ws1.Cells(FR, 1), ws1.Cells(lr1, KC))
Dim arr2 As Variant: arr2 = ws2.Range(ws2.Cells(FR, 1), ws2.Cells(lr2, KC))
Dim d1 As Object: Set d1 = CreateObject("Scripting.Dictionary")
Dim d2 As Object: Set d2 = CreateObject("Scripting.Dictionary")
Dim dr As Object: Set dr = CreateObject("Scripting.Dictionary") 'Result
LoadDictionary d1, arr1
LoadDictionary d2, arr2
GetKeywords d2, d1, dr
Dim r As Long
arr2 = ws2.Range(ws2.Cells(FR, 1), ws2.Cells(lr2, TC))
If dr.Count > 0 Then
For r = 1 To lr2
If dr.Exists(r) Then arr2(r, TC) = arr2(r, KC) 'Or arr2(r, TC) = dr(r)
Next
End If
ws2.Range(ws2.Cells(FR, 1), ws2.Cells(lr2, TC)) = arr2
End Sub
Private Sub LoadDictionary(ByRef d As Object, arr As Variant) 'Expects 2-d array
Dim r As Long, c As Long, k As String
For r = 1 To UBound(arr, 1)
k = "|"
For c = 1 To UBound(arr, 2)
k = k & arr(r, c) & "|" 'Concatenate all columns
Next
d(k) = r
Next
End Sub
Private Sub GetKeywords(ByRef d1 As Object, ByRef d2 As Object, ByRef dr As Object)
Dim r As Long, k As String, arr As Variant
For r = 0 To d1.Count - 1
k = d1.Keys()(r)
If d2.Exists(k) Then
arr = Split(k, "|")
dr(d1(k)) = arr(UBound(arr) - 1)
End If
Next
End Sub
.
Test Sheet 1
Test Sheet 2
Sheet1 Rows: 1,001, Cols: 501; Sheet2 Rows: 1,001, Cols: 501 - Time: 0.023 sec
New info:
Row 1 - Keyword 1 , keyword 2 , keyword 3 (once we find the row with
this order then we need to fetch the 4th value from keyword 3 in the
same row) and paste in 10 column of sheet 2

IF cells begin with AND Create random number

I want to make a sub, which determines if the cells in the 12th column starts with 262015. If it does start with this, it should create a new random 8-digit number starting with "18" and then 6 randomly created unique digits.
My code does not seem to figure out if the cell starts with 262015, and I have not been able to find help on creating the 8-digit number with these requirements.
Hope you can help me!
Sub Opgave8()
For i = 2 To 18288
If Left(Worksheets("arab").Cells(i, 12), 6) = "262015" Then
Worksheets("arab").Cells(i, 3) = "18" & studyid(6)
End If
Next i
Function UniqueRandDigits(x As Long) As String
Dim i As Long
Dim n As Integer
Dim s As String
Do
n = Int(Rnd() * 10)
If InStr(s, n) = 0 Then
s = s & n
i = i + 1
End If
Loop Until i = x + 1
UniqueRandDigits = s
End Function
End Sub
For i = 2 To 18288
If Left(Worksheets("Base").Cells(i, 12), 6) = "262015" Then
Worksheets("Base").Cells(i, 3) = "18" & Randdigits(6)
End If
Next i
Function RandDigits(x As Long) As String
Dim i As Long
Dim s As String
For i = 1 To x
s = s & Int(Rnd() * 10)
Next i
RandDigits = s
End Function
EDIT: here's one where all digits are different
Function UniqueRandDigits(x As Long) As String
Dim i As Long
Dim n As Integer
Dim s As String
Do
n = Int(Rnd() * 10)
If InStr(s, n) = 0 Then
s = s & n
i = i + 1
End If
Loop Until i = x + 1
UniqueRandDigits = s
End Function
EDIT2: And here is one that forces all numbers to be different
dim n as string
dim ok as boolean
For i = 2 To 18288
If Left(Worksheets("Base").Cells(i, 12), 6) = "262015" Then
ok = false
do
n = UniqueRandDigits(6)
If Application.WorksheetFunction.CountIf(Worksheets("Base").Range("L2:L18288"), n) = 0 Then
Worksheets("Base").Cells(i, 3) = "18" & n
ok = true
end if
loop until ok
End If
Next i
Using Left function, you need to specify the String, then the number of characters from the left, and then you check if it's equal to "262015".
Try the code below:
For i = 2 To 18288
If Left(Worksheets("Base").Cells(i, 12), 6) = "262015" Then
Worksheets("Base").Cells(i, 3) = "XXX"
End If
Next i

Find Method Object Variable Not Set

This is an error I've been trying to figure out for awhile now, my find method is not producing any results and I cannot figure out why.
The code is suppose to search InputSheet for a string, report the row number and start moving information over to Background based on that row number. Then the next .find will find the string in SummaryResults and start moving information from Background, reformat it a bit, and paste to SummaryResults.
My find method is not producing any results and leaves FindRow = Nothing even though the strings are present in the sheets and in the correct Ranges.
This error started occurring after running the macro with another Excel sheet open so maybe the ActiveWorkbook was incorrect, but I have not been able to get it to run since.
Some of the variables shown are from other sections of the code but when I hover over them in the debug mode they are showing what they're suppose to.
Option Explicit
Sub CAESARCONVERSION()
Dim InputSheet As Worksheet, SummaryResults As Worksheet, Background As Worksheet
Dim i As Integer
Dim j As Integer
Dim x As Integer
Dim y As Integer
Dim h As Integer
Dim v As Integer
Dim c As Integer
Dim z As Integer
Dim myBook As Workbook
Set myBook = Excel.ThisWorkbook
Set InputSheet = myBook.Sheets("Input Sheet")
Set SummaryResults = myBook.Sheets("Summary Results")
Set Background = myBook.Sheets("Background")
Dim NodeList As Integer
Dim TotalCases As Integer
Dim sMyString As String
Dim Nodes As Variant
Dim FindRow As Range
Dim intValueToFind As String
Dim FindRowNumber As Long
Dim SecondRowNumber As Long
'Clear the last run of macro
Background.Range("A2:A1000").Cells.Clear
Background.Range("C2:I10000").Cells.Clear
SummaryResults.Cells.Clear
'Code that will count the total number of load cases
TotalCases = 0
h = 2
Dim text As String
For v = 12 To 100
If InputSheet.Cells(v, 2).Value <> "" Then
text = LTrim(InputSheet.Cells(v, 2).Value)
Background.Cells(h, 3).Value = text
h = h + 1
TotalCases = TotalCases + 1
Else
GoTo NodeCounter
End If
Next v
NodeCounter:
y = TotalCases - 1
x = 0
Dim LoadCaseList() As Variant
ReDim LoadCaseList(y)
LoadCaseList:
For x = 0 To y
LoadCaseList(x) = Background.Cells(2 + x, 3).text
Next x
j = 2
For i = 17 + TotalCases To 20000 'Need to define how far for the program to search, we may exceed 20000 at some point
If InputSheet.Cells(i, 2).Value <> "" Then
Background.Cells(j, 1).Value = InputSheet.Cells(i, 2).Value
j = j + 1
End If
Next i
With Background
NodeList = Background.Cells(2, 2).Value
Background.Range("AA1:XX" & NodeList + 1).Cells.Clear
End With
ReDim Nodes(NodeList - 1)
v = 0
j = 2
For i = 0 To NodeList - 1
Nodes(i) = Background.Cells(j, 1).Value
j = j + 1
Next i
Headers:
Dim LoadCaseHeader() As String
Dim TypHeader()
TypHeader = Array("Node", "L", "Direction", "Magnitude")
Dim LoadDirections()
LoadDirections = Array("X", "Y", "Z", "MX", "MY", "MZ")
x = 0
z = 0
For x = 0 To NodeList - 1
For z = 0 To TotalCases - 1
SummaryResults.Range(("B" & 2 + (NodeList * 6 + 2) * z) & ":" & "E" & 2 + (NodeList * 6 + 2) * z) = TypHeader()
SummaryResults.Range("A" & 2 + (NodeList * 6 + 2) * z) = Background.Range("C" & 2 + z)
Next z
Next x
'Search rows for the first instance of this value.
LoadCases:
'Code that copies information from the InputSheet to the SummaryResults
Dim LoadCases() As Long
ReDim LoadCases(NodeList, 6)
FindRowNumber = 0
SecondRowNumber = 0
For c = 0 To y
intValueToFind = LoadCaseList(c)
For i = 7 To 31 + TotalCases
With InputSheet
If Trim(Cells(i, 3).Value) = intValueToFind Then
MsgBox ("Found")
Set FindRow = InputSheet.Range("C:C").Find(What:=intValueToFind, LookIn:=xlValues)
FindRowNumber = FindRow.Row
End If
End With
Next i
'MsgBox FindRowNumber
With InputSheet
For i = 0 To NodeList - 1
x = 4
For j = 0 To 5
LoadCases(i, j) = InputSheet.Cells(FindRowNumber + (TotalCases + 3) * i, x)
x = x + 1
Next j
Next i
End With
Background.Range("AC2:AH" & NodeList + 1).Offset(0, c * 7) = LoadCases
For i = 1 To NodeList * 6 * TotalCases
With SummaryResults
If Trim(Cells(i, 5).Value) = intValueToFind Then
Set FindRow = SummaryResults.Range("A:A").Find(What:=intValueToFind, LookIn:=xlValues)
SecondRowNumber = FindRow.Row
GoTo Step2
End If
End With
Next i
Step2:
With SummaryResults
For x = 0 To NodeList - 1
For j = 0 To 5
SummaryResults.Cells(SecondRowNumber + 1 + j + 6 * x, 5) = Background.Cells(x + 2, 29 + j)
SummaryResults.Cells(SecondRowNumber + 1 + j + 6 * x, 3) = TypHeader(1)
SummaryResults.Cells(SecondRowNumber + 1 + j + 6 * x, 4) = LoadDirections(j)
SummaryResults.Cells(SecondRowNumber + 1 + j + 6 * x, 2) = Nodes(x)
Next j
Next x
End With
Next c
End Sub
Any help would be appreciated. EDIT: Uploaded the entire code. Additional information, the code works when not tabbed into excel but will fail when tabbed in a ran again.
The issue seems to be that the LoadCaseList() array is never getting populated. This is your Find statement:
Set FindRow = InputSheet.Range("C:C").Find(What:=intValueToFind, LookIn:=xlValues)
intValueToFind is set by this statement:
intValueToFind = LoadCaseList(c)
But the LoadCaseList() array is populated by the following code which is a label that is never called by a GoTo statement (as far as I can tell):
LoadCaseList:
For x = 0 To y
LoadCaseList(x) = Background.Cells(2 + x, 3).text
Next x
So because the LoadCaseList label statement is never being called by a GoTo statement, the LoadCaseList() array is never being populated so intValueToFind has no value and therefore the Find method has no value to search for (except for maybe the empty string).

How to get average by cell content on VBA

In excel, I have column 1 with tickers, and column 2 with numbers, like this:
A B
1 AAA 10
2 AAA 12
3 AAA 14
4 BBB 9
5 BBB 10
6 BBB 11
I need a piece of code to calculate average BY TICKER, which means that in this case I would have AAA average : 12 and BBB average = 10, etc etc etc. Up to now all i got is this code which tries to calculate the sums, I will do the divisions later, but something's wrong:
For row = 2 to 6
Ticker = Cells(row - 1, 1)
If Cells(row, 1) = Cells(row - 1, 1) Then
sum = sum + Cells(row, 2)
Else
Cells(row, 6) = sum
sum = 0
row = row + 1
Next
I get an error saying "For is missing"
Maybe something like this in C1.
=IF(A1<>A2,AVERAGEIF(A:A,A1,B:B),"")
        
In your code:
sum ignored the first AAA
missed the End If
incremented row twice, once by row = row+1 and then by next
and some other not used variables
Try this:
Prev = "***"
For row = 1 to 6
If Cells(row, 1) = prev Then
sum = sum + Cells(row, 2)
Else
Cells(row, 6) = sum
sum = 0
End If
prev = Cells(row,1)
Next
To extend the answer from Jeeped and do it with a list which is not ordered, you also could do it like this:
C1: =A1
C2: =IF(LEN(C1),IFERROR(INDEX(A:A,MATCH(1,(COUNTIF(C$1:C1,A$1:A$1000)=0)*(A$1:A$1000<>""),0)),""),"")}
C3....Cn: copy down from C2
D1: =IF(LEN(C1),AVERAGEIF(A:A,C1,B:B),"")
D2...Dn: copy down from D1
C2 is an array formula and needs to be confirmed with Ctrl+Shift+Enter
to do it via VBA (should be faster than my formula for really big tables) you can use something like that: (put this in a "Module" in the VBA-Window, the same like your recorded macros ar written)
Option Explicit
Public Function getAllAvg(rng As Range) As Variant
Set rng = Intersect(rng.Parent.UsedRange, rng)
Dim varInput As Variant
varInput = rng.Value
Dim varOutput() As Variant
ReDim varOutput(1 To UBound(varInput), 1 To 2)
varOutput(1, 1) = ""
Dim i As Long, j As Long
For i = 1 To UBound(varInput)
If Len(varInput(i, 1)) Then
j = 1
While Len(varOutput(j, 1)) And (varOutput(j, 1) <> varInput(i, 1)) And (j < UBound(varOutput))
j = j + 1
Wend
If Len(varOutput(j, 1)) = 0 Then
varOutput(j, 1) = varInput(i, 1)
varOutput(j, 2) = Application.AverageIf(rng.Columns(1), varOutput(j, 1), rng.Columns(2))
varOutput(j + 1, 1) = ""
End If
End If
Next
While Len(varOutput(j, 1)) And (j < UBound(varOutput))
j = j + 1
Wend
If Len(varOutput(j, 1)) = 0 Then
For i = j To UBound(varOutput)
varOutput(i, 1) = ""
varOutput(i, 2) = ""
Next
End If
getAllAvg = varOutput
End Function
then select a range like C2:D12 and enter:
=getAllAvg(A:B)
and confirm with Ctrl+Shift+Enter. it will directly output the whole list (and recalculate if needed)
EDIT:
If your list is always in a sorted order, you also could use this code:
Option Explicit
Public Function getAllAvgSorted(rng As Range) As Variant
Set rng = Intersect(rng.Parent.UsedRange, rng)
Dim varInput As Variant
varInput = rng.Value
Dim varOutput() As Variant
ReDim varOutput(1 To UBound(varInput), 1 To 2)
varOutput(1, 1) = ""
Dim i As Long, j As Long
j = 1
For i = 1 To UBound(varInput)
If Len(varInput(i, 1)) Then
If varOutput(j, 1) <> varInput(i, 1) Then
If Len(varOutput(j, 1)) Then j = j + 1
varOutput(j, 1) = varInput(i, 1)
varOutput(j, 2) = Application.AverageIf(rng.Columns(1), varOutput(j, 1), rng.Columns(2))
End If
End If
Next
While j < UBound(varOutput)
j = j + 1
varOutput(j, 1) = ""
varOutput(j, 2) = ""
Wend
getAllAvgSorted = varOutput
End Function