Excel VBA Overflows when dividing two Doubles - vba

I'm getting an Overflow error when I try to divide two doubles, and I can't figure out why.
Here's my code as it is now
'x will be used to sum the elements
Dim x, ct As Double
x = 0
ct = 0
For Each cell In Range(rng)
If cell.Offset(, offset1).Value = Crit1 And cell.Offset(, offset2).Value = Crit2 Then
x = x + cell.Value
ct = ct + 1
End If
Next
'Divide by count
Avg = x / ct
At first, ct was declared as Long, but I changed it to Double to see if that might fix it, but it didn't.
I've also tried changing the last line to Avg = CDbl(x / ct), but I get the same error.
The values in cell.Value will always be real numbers, usually ranging between 0 and about 9,000,000, occasionally going up as high as 17,000,000. The numbers greater than about 20,000 are almost always integers.

It's divide by zero error. VBA just reported it as "overflow".

Related

Format number in datagridview- If integer then F0, if decimal then F

I need to format all numbers in a datagridview.
If the number is a whole number then do not show the decimal point and if the number has a fraction then do show the decimal point.
I have achieved this by looping through each column and checking if the content is a double/single/decimal and then looping through each row in those columns to check each value whether the number is whole or has a fraction.
But this takes a long time for the application to process since i might have 2000 rows or more with 5 or more columns being double/single/decimal.
I can't find a standard format which does this.
Can anybody help?
dgv.SuspendLayout()
For i = 0 To dgv.Columns.Count - 1
If dgv.Columns(i).ValueType = GetType(Double) Or dgv.Columns(i).ValueType = GetType(Single) Or dgv.Columns(i).ValueType = GetType(Decimal) Then
'check If the number has a fraction
For u = 0 To dgv.Rows.Count - 1
If Not IsDBNull(dgv.Rows(u).Cells(i).Value) Then
If dgv.Rows(u).Cells(i).Value Mod 1 <> 0 Then
'number has a fraction
dgv.Rows(u).Cells(i).Style.Format = "F"
Else
'number is an integer
dgv.Rows(u).Cells(i).Style.Format = "F0"
End If
End If
Next
End If
Next
dgv.ResumeLayout()
Using the Datagridview.CellFormatting event seemed to solve the issue - Thanks Jimi. I just can't understand the difference between using the event and setting the format in a loop after populating the datagridview

Converting input range to array in function

I have been learning VBA and thought I was getting the hang of it, but for some reason this basic task is eluding me. I am trying to create a function where I select an input region of numbers (really only one row or column), and then output the summation of the numbers in a cell. Here is my code:
Function CashFlow(CashArray As Excel.Range)
Dim cashflows() As Variant
cashflows = CashArray.Value
amount = CashArray.Rows.Count
dim y()
redim y(amount)
Sum = 0
For i = 1 To amount
y(i) = cashflows(i)
Sum = Sum + y(i)
Next i
CashFlow = Sum
End Function
Despite me knowing how to do essentially this in a subroutine, the fact that I'm getting my data from the function's input is throwing me off. How do I accomplish this task?
Just to summarize the above comments, please give the following code a try:
Option Explicit
Function CashFlow(CashArray As Excel.Range)
Dim sum As Double
Dim x As Long, y As Long
Dim cashflows() As Variant
cashflows = CashArray.Value
sum = 0
For y = LBound(cashflows, 1) To UBound(cashflows, 1)
For x = LBound(cashflows, 2) To UBound(cashflows, 2)
sum = sum + cashflows(y, x)
Next x
Next y
CashFlow = sum
End Function
Note, that this code summarizes all cells in the given range (even if there are multiple rows and columns in that range). Basically, the range is stored in the array cashflows. As mentioned in the comments, this will yield a two-dimensional array. The function LBound(cashflows) will give you the Lower Boundary of that array.
By specifying LBound(cashflows, 1) I am specifically asking for the lower boundary of the first dimension (in this case the rows). UBound returns the Upper Boundary of that array for the specified dimension. Similarily UBound(cashflows, 2) returns the last column (second dimension) of the given array.
Remark: I am always using LBound() and UBound() in my code instead of starting with 0 or 1 to avoid coding errors. Some people prefer Option Base 0 and some prefer Option Base 1. While neither will have an impact on the above (as ranges always yield an array starting with 1) it is just good coding practice to prevent bugs in the future.

Finding max value of a loop with VBA

I am trying to find max value of a loop. First, I have two random arrays and I want to find these two arrays correlation coefficient. Then, I want to calculate it multiple times as much as "I3" cell. After that, I want to write a code which finds max correlation coefficient from this calculation. I wrote the code below but it didn't work.
Sub Macro1()
Dim i As Long
For i = 1 To Range("I3")
Calculate
Next
DMax = Application.WorksheetFunction.Max("A2")
Range("I4").Value = DMax
End Sub
Any help is appreciated.
Your Max-Function needs a proper argument. Just typing "A2" doesn't work in VBA. Try:
DMax = Application.WorksheetFunction.Max(Range("A2"))
This will give you the max-Value of the Array A2. But keep in mind that the max-Value of a range consisting of a single cell is always the cell value.
If you want to calculate the maximum value of all iterations, you should use the max-function in each iteration (inside for-loop) and store it's value. In each following iteration you should then overwrite the max-Value if your new max value is larger than the old one. Just like this:
Sub Macro1()
Dim i As Long
DMax = 0
For i = 1 To Range("I3")
Calculate
DMax2 = Application.WorksheetFunction.Max(Range(...))
If DMax2 > DMax Then DMax = DMax2
Next i
Range("I4").Value = DMax
This will give you the max-Value of Range(...) of all iterations.
I barely understand your code, but the solution will be nasted loop. Suppose you have two sets of numbers: A2 (Cells(2, 1)) through I2 (Cells(2, 7)) and A3 (Cells(3, 1)) through I3 (Cells(3, 7)). You want to calculate partial correlation and find what was the maximum value of it.
For i = 1 To 7
For j = 1 To i
'Calculate the correlation
Next j
'here you have partial coefficient and you can compare it,
'if it is greater than previous one then save it and store
Next i
For i = 1 To Range("I3").value 'to calculate from 1 to the value in that cell
what i would recommend for your question.
For i = 1 To 10 ' loop 10 times
For j = 1 To i ' here it will allow you to check your stuff multiple times before moving on to the next value
arr1(i) = arr2(j) ' see if your array match
Next j
Next i

#ERROR: Unable to get match property of the worksheet class. I have already tried solutions available online

NOTE: My problem was not solved by other similar questions on this as well as other sites. Please have a fair view at my question before judging the same
I am trying to perform a task in which first I have to identify the smallest, 2nd smallest numbers and so on and according to this I have to copy data from one column to another. This will continue until the sum of the copied values becomes grater than or equal to certain value in the sheet (Here row no. for the comparison is given by variable "b"). This will be repeated for 172 different sets which are repeated after every 43 cells.
I have written the following code:
Dim m As Range, k As Double, j As Double, b As Double, lIndex As Double, a As Double
Set m = ActiveSheet.Range("E3:E40")
For i = 1 To 172
j = 1
b = 45 + 43 * (i - 1)
For k = 1 To 38
a = Application.Small(m, j)
lIndex = Application.WorksheetFunction.Match(a, m, 0)
If Cells(b, 7).Value < Cells(b, 1).Value Then
Cells(lIndex, 7).Value = Cells(lIndex, 2).Value
Else
End If
j = j + 1
Next k
Set m = m.Offset(43)
Next i
Now there is an error that pops up saying, Unable to get match property of the worksheet class.
NOTE: I have tried solutions online.
Can there be any other way to do it
OR
Is there something wrong I am doing logically or in the syntax as I am new to excel VBAs and coding itself.
a = Application.Small(m, j) will surely return an Error Code when j is actually bigger that the size of te range m. In your code, the range m = Range("E3:E40") has 38 cells, but j can go as high as 38 * 172.
Then you try to call Match with an error code as the first parameter a. This resuts in run-time error. Note here that Application.Match would result in an error code while WorksheetFunction.Match raises a run-time error.
In all cases, no error should occur in your Match if you had fetched correctly the "kth smallest" element. Without being able to check all of you code, I guess what you wanted here was
a = Application.Small(m, k) ' <--- k, not j
And then no error should occur in *.Match(a, m, 0).
After checking your code:
After getting the smallest value, the next value of j should be a + 1 not j + 1.
Why? because if your smallest value is 4 from (4, 6, 10)
on first loop, j = 1, small will return 4.
on second loop, j = 2, small will still return 4, instead of 6.

Find Lowest Sum of "x" Consecutive Numbers in A List

I am looking to find the lowest sum of x consecutive numbers in a column of 91 numbers (column A, for example). For example, if x is 30, I want to find the lowest sum of 30 consecutive numbers in the 91 number column. I will need to do this calculation for each value of x between 30 and 78.
The brute force, non-VBA approach would look something like this for the case where x = 30:
=MIN(SUM(A1:A30),SUM(A2:A31),SUM(A3:32),...,SUM(A62:A91))
For the case where x = 78, this non-VBA approach would look like this:
=MIN(SUM(A1:A78),SUM(A2:A79),SUM(A3:A80),...,SUM(A14:A91))
I have 20 columns (each with 91 numbers) that I need to apply this function to, so the column needs to be a variable as well. My guess is that we would define a function with a range length input (i.e. x) and a column input.
I don't have much experience with VBA syntax. Can you guys/gals help me formulate something?
I would normally try to solve this myself (I tried the Excel brute force way then tried making my own UDF but I didn't know where to start).
Consider the following UDF:
Public Function consec(rng As Range, x As Long) As Double
Dim r As Range, i As Long, mymin As Double, temp As Double
Dim wf As WorksheetFunction
Set wf = Application.WorksheetFunction
i = 1
Set r = rng(i).Resize(x, 1)
mymin = wf.Sum(r)
For i = 2 To rng.Count - x + 1
Set r = rng(i).Resize(x, 1)
temp = wf.Sum(r)
If temp < mymin Then
mymin = temp
End If
Next i
consec = mymin
End Function
For example:
Do you require VBA?
It's possible to do this with an "array formula", e.g. if your "x" value is in cell Z1 you can use this formula
=MIN(SUBTOTAL(9,OFFSET(A1:A91,ROW(INDIRECT("1:"&COUNT(A1:A91)-Z1+1)),0,Z1)))
confirmed with CTRL+SHIFT+ENTER