Have a column in Datagridview (over 300 rows) and would like to get the sum of every 10 rows. There is no gap between the data in Column 1.
I just want to have the sum value for every 10th rows in the other column. What I have tried showing me the cumulative #s in each row!
Any help would be appreciated. Thanks so much!
C1 C2
2
3
4
6
5
3
5
7
6
5 46
8
9
4
7
5
2
1
2
5
4 47
1
2
6
.
.
.
Dim sum As integer = 0
For i = 0 To data1.Rows.Count - 1
sum += data1.Rows(i).Cells(0).Value
data1.Rows(i).Cells(1).Value = sum
If (i+1) = 10 Then
Sum = 0
Else
End If
Next
There are multiple ways, here is one example:
Loop over every row to sum, then on every 10th output sum and reset number.
For i = 0 To data1.Rows.Count - 1
sum += data1(0, i).Value
If i.ToString.EndsWith("9") Then 'since it starts at 0, 10th ends with 9 not 0
data1(1, i).Value = sum
sum = 0
End If
Next
Use LINQ to get the sum of each group of n rows
Private Function getSumsOfGroupsOfNRows(n As Integer) As IEnumerable(Of Double)
Return DataGridView1.Rows.OfType(Of DataGridViewRow).
GroupBy(Function(r) Math.Truncate(r.Index / n)).
Select(Function(g) g.Sum(Function(r) CDbl(r.Cells(0).Value)))
End Function
Test it with this
Dim n = 10
' adds numbers 1 through 100 in the datagridview, for testing
DataGridView1.Rows.AddRange(Enumerable.Range(1, 100).Select(
Function(r)
Dim row As DataGridViewRow = DataGridView1.Rows(0).Clone
row.Cells(0).Value = r
Return row
End Function).ToArray())
' get the sums in an IEnumerable(Of Double)
Dim sums = getSumsOfGroupsOfNRows(n)
' write into second column
For i = 1 To n
DataGridView1.Rows.Item(n * i - 1).Cells(1).Value = sums(i - 1)
Next
Related
I have 5 items that can be placed in any unique order, I want to store the values (numbers) of a single unique order to a variable, one by one. For example:
User input: 7
Then i_Int = 7
should give me
v_Var = 1
wait 1 sec
v_Var = 3
wait 1 sec
v_Var = 2
wait 1 sec
v_Var = 4
wait 1 sec
v_Var = 5
The data below list all possible permutations of 5 items, where the first row lists the permutation #, I will not have this data to make things easy.
1 1 2 3 4 5
2 1 2 3 5 4
3 1 2 4 3 5
4 1 2 4 5 3
5 1 2 5 3 4
6 1 2 5 4 3
7 1 3 2 4 5
8 1 3 2 5 4
9 1 3 4 2 5
10 1 3 4 5 2
...
111 5 3 2 1 4
112 5 3 2 4 1
113 5 3 4 1 2
114 5 3 4 2 1
115 5 4 1 2 3
116 5 4 1 3 2
117 5 4 2 1 3
118 5 4 2 3 1
119 5 4 3 1 2
120 5 4 3 2 1
Here is a function that returns the permutation of 1,...,n of rank i:
Function Unrank(ByVal n As Long, ByVal rank As Long, Optional lb As Long = 1) As Variant
Dim Permutation As Variant
Dim Items As Variant
ReDim Permutation(lb To lb + n - 1)
ReDim Items(0 To n - 1)
Dim i As Long, j As Long, k As Long, q As Long
Dim fact As Long
For i = 0 To n - 1
Items(i) = i + 1
Next i
rank = rank - 1
j = lb
For i = n - 1 To 1 Step -1
fact = Application.WorksheetFunction.fact(i)
q = Int(rank / fact)
Permutation(j) = Items(q)
'slide items above q 1 unit to left
For k = q + 1 To i
Items(k - 1) = Items(k)
Next k
j = j + 1
rank = rank Mod fact
Next i
'place last item:
Permutation(lb + n - 1) = Items(0)
Unrank = Permutation
End Function
As a default, it returns the result as a 1-based array. To make it 0-based, use a call like Unrank(5,7,0). As a test:
Sub test()
'fills A1:A120 with the permutations of 1,2,3,4,5
Dim i As Long
For i = 1 To 120
Cells(i, 1).Value = Join(Unrank(5, i), " ")
Next i
End Sub
13! is too large to hold in a Long variable, so the code throws an untrapped error when n=14. The algorithm that I use depends on the ability to do modular arithmetic with the relevant factorials, so there is no easy fix in VBA. Note that you could easily tweak the code so that you pass it an array of items to permute rather than always permuting 1-n. The algorithm destroys the array Items, so such a tweak would involve creating a 0-based (so that the modular arithmetic works out) copy of the passed array.
Let's say I have 2 columns (the following table includes the result)
Product ID Price Average
1 4 5
1 4 5
1 7 5
2 3 3
2 3 3
3 9 9
I want to be able to write a VBA code to loop through the rows of Product IDs and create the 3rd column which has average out the Prices.
I guess a For statement would work, but how do I define temp variables to store each ID?
Thanks!
As Vasily and L.Dutch told, AVERAGEIF() function is all you need. If you want to loop it through all cells, you can use Do While loop like this:
Sub avg()
Dim i As Integer
i = 2
Do While Range("A" & i).Value <> ""
Range("C" & i).FormulaR1C1 = "=AVERAGEIF(C1,RC1,C2)"
i = i + 1
Loop
End Sub
The first two consecutive numbers with two free denominators are:
14 = 2 × 7
15 = 3 × 5
The first three consecutive numbers with three free denominators are:
644 = 2 × 7 × 23
645 = 3 × 5 × 43
646 = 2 × 17 × 19
How can I find the first four consecutive numbers with exactly four free denominators?
It isn't the case that 644 = 2 x 7 x 23. Rather 644 = 2 x 2 x 7 x 23 -- you are looking for numbers which have distinct prime divisors which might be repeated. In fact, 1309, 1310, 1311 are the first 3 numbers which have 3 distinct non-repeated factors, and it is impossible to do that for 4 since any run of 4 successive numbers will have a repeated factor of 4.
To solve the problem of finding 4 successive numbers each of which has 4 distinct (albeit possibly repeated) prime factors, you can use a modified version of the Sieve of Eratosthenes, one which keeps track of the number of distinct divisors:
Function SieveK(n As Long, k As Long) As Long
'Implements a modified Sieve of Erasthones
'to return the first of k successive numbers
'less than or equal to n, each of which has
'k distinct prime factors.
'Returns -1 if no such number exists
Dim nums As Variant
Dim i As Long, p As Long
Dim run As Long
Dim limit As Long
Dim primes As Variant
primes = Array(2, 3, 5, 7, 11, 13) 'small primes
p = 1
For i = 0 To k - 2
p = p * primes(i)
Next i
limit = Int(1 + n / p)
ReDim nums(2 To n) As Long
p = 2 'first prime
Do While p < limit
'mark subsequent multiples of p by adding 1
For i = 2 * p To n Step p
nums(i) = nums(i) + 1
Next i
'find next p -- which will be next 0
p = p + 1
Do While nums(p) <> 0
p = p + 1
Loop
Loop
'At this stage, all numbers are marked.
'primes are marked by 0 and composites are marked
'by the number of distinct prime factors.
'Check for a run of k ks
run = 0
For i = 2 To n
If nums(i) = k Then
run = run + 1
If run = k Then 'we have a winner!
SieveK = i - k + 1
Exit Function
End If
Else
'reset run counter
run = 0
End If
Next i
SieveK = -1
End Function
SieveK(10^6,4) evaluates to 134043 in less than a second. The function doesn't yield the factorization of this or the next 3 numbers, but those are easy to find. SieveK(10^8,5) evaluates to -1, so there isn't a run less than 100 million of 5 consecutive numbers each of which has 5 different prime factors.
Remark: in an earlier version of this answer I had a logic flaw (which didn't prevent the output from being correct). Namely -- I had sieved only to the square root of n, though if e.g. a number m looks like 2x3x5xp with p prime then m could have 4 distinct prime factors even though p might exceed the square root of n. I revised the algorithm to take care of this possibility.
Here you go:
134043 = 3 x 7 x 13 x 491
134044 = 2 x 23 x 31 x 47
134045 = 5 x 17 x 19 x 83
134046 = 2 x 3 x 11 x 677
Assuming that I have the table below to work with:
project name total units
a 3
b 4
c 1
d 5
e 2
f 5
g 8
h 12
i 8
j 10
k 4
l 7
m 9
n 19
o 15
p 6
q 3
I would like to have the project names grouped with the total units not exceeding 20 for example.
So if I add up project a up to f, it will give me a total of 20. So this group of projects to be grouped and given a unique identifier by Excel.
I want to easily determine which file number the specific project goes into. So as soon as I enter the project name and the total units, it can return a number to me saying which file number the project should go into.
project name total units file number
a 3 1
b 4 1
c 1 1
d 5 1
e 2 1
f 5 1
g 8 2
h 12 2
i 8 3
j 10 3
k 4 4
l 7 4
m 9 4
n 19 5
o 15 6
p 6 7
q 3 7
The final outcome I would like to have whereby the total units are summed up and the project names with sum equal or less than 20 is grouped and given a file number.
Is it possible to have Excel do such thing?
Don't do with VBA, what you could easily do with Excel's inbuilt functions. The SUMIF() function will help a lot here
Place the following formula into cell C2 (assuming the setup above)
=IF(A2="a",ROUNDDOWN((B2-1)/20,0)+1,IF(SUMIF($C1:C$2,C1,$B1:B$2)+B2>20,C1+1,C1))
The formula is doing the following:
If the name is "a" then check how many files needed based on units in "a"
For all other names: sum the previous units in the current file (i.e. file number in cell above) and add the current project units. If the number exceeds 20 add 1 to the file number, otherwise use the same file number
I have tested this, but let me know if you have any problems.
OK with the provisos mentioned by barryleajo and assuming your individual total units are between 1 and 19 you need this algorithm I think:-
If it's the first line of data
Running total=total units
Else
If (Previous running total + total units) > 20
Running total=total units
Else
Running total=Previous running total + total units
So in the spreadsheet below I've set D2=B2 and E2=1,
then put the formula
=IF(D2+B3>20,B3,D2+B3)
into D3
and
=IF(B3=D3,E2+1,E2)
into E3 and pulled them down.
The following code works. I added comments to help you understand the answer.
Dim total_units As Range
Dim file_number As Integer
Dim cumulative_sum As Integer
Sub filenumber()
'Fill in column C header with string 'file_number'
Range("C1") = "file_number"
'Set total_units as the range variable
Set total_units = ThisWorkbook.Sheets(1).Range("B2")
'File_number starts equal to 1
file_number = 1
'Cumulative sum starts in the first row of total_units
cumulative_sum = total_units
'Loop until non empty rows of column project_name
Do While Not total_units = ""
'Fill in column C
total_units.Offset(, 1) = file_number
'Records the cumulative_sum in the row
cumulative_sum = cumulative_sum + total_units.Offset(1, 0)
'If cumulative sum exceeds 20, then, `file_number` changes and the start point in `cumulative_sum` also changes
If cumulative_sum > 20 Then
cumulative_sum = total_units.Offset(1, 0)
file_number = file_number + 1
End If
'Move the range
Set total_units = total_units.Offset(1, 0)
'Next row
Loop
End Sub
I have an array of numbers , i want to get some numbers only in loop.
I want to get from 1 to 20 and from 40 to 50
My Code:
For i As Integer = 1 To 50
Next
But this code gets all the numbers(from 1 to 50).
I wish you can help me.
Thanks
Well, either do this:
For i As Integer = 1 to 20
Next
For i As Integer = 40 to 50
Next
or this
For i As Integer = 1 to 20
If 20 < i OrElse i < 40 Then Continue
Next