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
Related
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
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 the following data in sheet1.
TransId CustID Account Stake
1 1 NP1 10
2 1 NP1 11
3 1 NP1 12
4 1 NP1 13
5 1 NP1 14
6 2 NP2 15
7 2 NP2 16
8 2 NP2 17
9 2 NP2 18
10 2 NP2 19
11 3 NP3 20
12 3 NP3 21
13 3 NP3 22
14 3 NP3 23
15 3 NP3 24
and the following details in sheet2.
Account Agent master SuperMaster
NP1 1 5 4
NP2 9 5 6
NP3 4 3 7
NP4 8 3 2
NP5 2 7 8
NP6 8 10 2
I would need to to calculate in sheet3 that, for each customerId in table, I need to consider all the TransId and the relevant stake & Account. Then i should compare account in sheet2 and retrieve the values of agent, master and Supermaster. Therefore my final calculation in sheet3 would be,
for each CustId, transId1(stake*agent*master*supermaster) + transId2(same as 1) and goes on until TransId5, since there are 5 transactions in CutomerId1.
Kindly guide me how do I do this in VBA ? (I am new to programming & VBA)
In my opinion, the easiest way to go about this is using vlookup and pivot tables. I tried for a bit to set something up purely in vba, I know it's possible, but for me this was much easier. This will produce a table on sheet1 that you can run a pivot table off of to produce the result you want.
Sub Main()
Dim rowCount1, rowCount2 As Integer
rowCount1 = Sheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row
rowCount2 = Sheets("Sheet2").Cells(Rows.Count, 1).End(xlUp).Row
Sheets("Sheet1").Range("E1").Value = "Agent"
Sheets("Sheet1").Range("F1").Value = "Master"
Sheets("Sheet1").Range("G1").Value = "SuperMaster"
Sheets("Sheet1").Range("H1").Value = "Sum"
Dim x As Integer
For x = 2 To rowCount1
Sheets("Sheet1").Range("E" & x).Formula = "=vlookup(C" & x & _
",Sheet2!A1:D" & rowCount2 & ",2,false)"
Sheets("Sheet1").Range("F" & x).Formula = "=vlookup(C" & x & _
",Sheet2!A1:D" & rowCount2 & ",3,false)"
Sheets("Sheet1").Range("G" & x).Formula = "=vlookup(C" & x & _
",Sheet2!A1:D" & rowCount2 & ",4,false)"
Sheets("Sheet1").Range("H" & x).Formula = "=product(D" & x & ":G" & x & ")"
Next x
End Sub
Then on sheet 3, using a pivot table on the data from sheet 1, you get
Row Labels Sum of Sum
1 1200
2 22950
3 9240
Grand Total 33390
I have two excel sheets. I have to merge the two such that the values in one match with the other. For eg.
The first excel, the 2nd excel
1 t 1 tes1
2 5 3 tes3
3 t 4 tes4
4 g
Notice that in the first column of the 2nd excel, 2 is missing, so I want the first excel to look like this,
1 tes1 t
2 5
3 tes3 t
4 tes4 g
I am new to excel. Any help on this will be highly appreciated.
Sub left_join()
Dim res As Variant
Dim i As Long, lastUsedRowSh1 As Long, lastUsedRowSh2 As Long
Dim cell As Range
Sheets(3).Cells.ClearContents
Sheets(1).Range("a:b").Copy Destination:=Sheets(3).Range("a1")
Sheets(3).Columns(2).Insert Shift:=xlToRight
lastUsedRowSh1 = Sheets(1).Cells(ActiveSheet.Rows.Count, "A").End(xlUp).Row
lastUsedRowSh2 = Sheets(2).Cells(ActiveSheet.Rows.Count, "A").End(xlUp).Row
i = 1
For Each cell In Sheets(1).Range("a1:a" & lastUsedRowSh1)
On Error Resume Next
res = Application.WorksheetFunction.VLookup(cell.Value, Sheets(2).Range("a1:b" & lastUsedRowSh2), 2, 0)
If Err.Number = 0 Then
Sheets(3).Range("b" & i).Value = res
i = i + 1
Else
i = i + 1
End If
Next cell
End Sub
You can even solve with a simple formula.
Foglio1
A B
1 t
2 5
3 t
4 g
Foglio2
A B
1 tes1
3 tes3
4 tes4
Foglio3
Copy the content of Foglio1 in Foglio3, then run this formula
=IF(ISERROR(VLOOKUP(Foglio1!A1,Foglio2!$A$1:$B$3,2,0))=TRUE,"",VLOOKUP(Foglio1!A1,Foglio2!$A$1:$B$3,2,0))
and drag it down. Regards.
I have been trying to write a macro to re-arrange the Cells in the rows and columns of Stock tables for the output I desire. Luckily the Stock Tables are generally the same each and every time (Different names and values), and the desired outcome is the same format..
Here is some example Data.
A
1 Name
2 description
3 description
4 description
5 description
6 ID#: 56284
7 Quantity in stock: 34
8 Zoom In and Configure
B
1 Name
2 description
3 description
4 description
5 description
6 ID#: 56284
7 Quantity in stock: 50
8 Zoom In and Configure
And I would like the Output to go into something like this(If possible to sheet2 starting on Cell B2):
B C E
B Being Row 1
C being Row 2 3 4 and 5 Combined
E being JUST Row 7 Stock Value I.E 50
On a single spreadsheet there would be 4 columns, and 8 rows I would have to re-arrange.. Making 32 total.
It would be great to automated this, so any help would be greatly appreciated.
Let me clarify my understanding. For each column you want the following data format:
A A
1 Name 1 Name
2 Desc1 2 Desc1; Desc2; Desc3; Desc4
3 Desc2 On sheet 2 3 50
4 Desc3 --------------->
5 Desc4
6 Id#: 56284
7 Quantity in Stock: 50
8 Zoom in and configure
If this is the case you can use the following code. It assumes your data is in A1 to D8 in Sheet 1.
Sub FormatData()
Dim col As Integer
For col = 1 To 4
With Worksheets(2)
.Cells(1, col) = Cells(1, col) //Get name
.Cells(2, col) = Cells(2, col) & "; " & Cells(3, col) & "; " & Cells(4, col) & "; " & Cells(5, col) //Concatenate descriptions into single string
.Cells(3, col) = Cells(7, col) //Get quantity in stock
End With
Next col
End Sub