Excel for loop to get value from another row - excel

I have an spreadsheet that contains various data. It looks like this:
A A A B B C C C C
a 1 2 3 2 1 4 2 3 2
b 0 2 3 3 0 1 2 3 0
c 6 6 3 0 2 1 0 4 0
etc.
What I want is to add all the Aa's and come up with a Aa total, all the Bb's and come up with a Bb total, all the Ab's etc.
What I want to do is, for every column, check if it is A, B or C. I want to do that because the data may change I might end up with four columns for A, two for B, etc. I know however that a, b and c will stay where they are.
I also don't know the order of A, B and C. There could be two A's followed by two C's and then one B.
My final result will be a table containing all the totals:
Aa Ab Ac
Ba Bb Bc
Ca Cb Cc
Where in the previous example would mean that Aa = 1 + 2 + 3 = 6, Ab = 5, etc.
Something like that.
I think the way to go is for 1-1 (the total of Aa's) is to go through every column in the first row. Check if it is an A. If it is, then get the value of the same column but second row. Add it to the total. When gone through all the columns, show up the total in 1-1.
What I have so far (for A):
Sub getA()
Dim x As Integer
Dim total As Integer
'cols = Find number of columns with data in them
For x = 1 To cols
'cell = cell in Ax
If InStr(1, cellvalue, "a") = 1 Then
'val = value from row 5 in same column
total = total + Val
End If
Next
End Sub
But I don't really know how to proceed with the commented lines.
Finally, another thing I would like to know is how will these values be presented in their respective cells without any extra event being carried (button for example). They should just appear in their cells from the moment someone opens the spreadsheet.
Any help is greatly appreciated.
Thanks.

Just an FYI, this can be done using the SUMPRODUCT formula:
=SUMPRODUCT(($B$1:$J$1=D$9)*($A$2:$A$4=$C10)*$B$2:$J$4)
EDIT
To compare the first letter then use this formula:
=SUMPRODUCT((LEFT($B$1:$J$1,1)=D$9)*($A$2:$A$4=$C10)*$B$2:$J$4)

Are you looking for something like:
Function countletter(strLetter As String) As Double
Dim x As Double, y As Double, xMax As Double, yMax As Double
xMax = Range("A1").CurrentRegion.Columns.Count
yMax = Range("A1").CurrentRegion.Rows.Count
For x = 1 To xMax
For y = 1 To yMax
If Cells(y, x).Value = strLetter Then
countletter = countletter + 1
End If
Next
Next
End Function

Related

Auto-increment based on other column repeats

I need a macro or formula that can do this:
Column A Values:
1
1
1
2
2
2
3
3
4
4
4
5
5
6
6
I need Column B to do:
1
2
3
1
2
3
1
2
1
2
3
1
2
1
2
Because column B has to have an increment number while column A has the same repeated value (for example 1 1 1 2), when it changes (to 2 or 3 etc.) the counter on column B has to reset and increment itself while A repeats the next value (1 2 3 1)
Thanks
Edit
Have a look at bzimor's answer as he solves is in a more general way without a hard value in column B1!
Original Answer
You can solve it the following way without VBA:
Put a hard value of 1 in column B1. This is your start value and should be always correct because you start counting with 1.
Then enter the following formula in B2
=IF($A2=$A1;$B1+1;1)
Just drag the formula down to the other rows of B and you're done
So B3 should look like this
=IF($A3=$A2;$B2+1;1)
and so on ...
You can use single formula:
=COUNTIF($A$1:A1,A1)
Put it into cell B1 and fill down
Here is your desired macros
Sub jkjainGenerateSerialNumber20161124()
readcol = Val(InputBox("type ref col#"))
writecol = Val(InputBox("type dest col#"))
ts = 0
Range("A1000000").Select
Selection.End(xlUp).Select
lastrow = ActiveCell.Row
For n = 2 To lastrow
prev = Cells(n - 1, readcol)
curr = Cells(n, readcol)
If prev <> curr Then
ts = 1
End If
If prev = curr Then
ts = ts + 1
End If
Cells(n, writecol) = ts
Next
End Sub

How to find which value creates maximum combination - Excel VBA

I need to find which value creates the maximum combination shown below in Excel Vba
suppose,
I have combinations like this
a a+b a+b+c 1 1+2 1+2+1 3 4
b a+c a+b+d 2 1+1 1+2+3 2 6
c a+d a+b+e 1 1+3 1+2+2 4 5
d a+e a+c+d 3 1+2 1+1+3 3 5
e b+c a+c+e 2 2+1 1+1+2 3 4
b+d a+d+e 2+3 1+3+2 5 6
b+e b+c+d 2+2 2+1+3 4 6
c+d b+c+e 1+3 2+1+2 4 5
c+e b+d+e 1+2 2+3+2 3 7
d+e c+d+e 3+2 1+3+2 5 6
I need to find which combinations creates maximum value, In this case the value "7" is maximum which is created by 2,3,2. Hence I want these value as a output in unique cells.
I may have thousands of combinations, hence i want these to be found automatically and to be output in unique cells automatically and run the program further.
Please help.
Thanks
Balaji
Concept :
The greatest sum of m values within a set of n is the sum of the m bigger values.
Once the values are ordered in descending order, the solution is trivial.
Here is a pure Excel solution, without VBA.
Design & Implementation :
The user input (variable names and values) are in C4:D8.
The idea is the following:
Determine the order of data. For this, I use RANK in the column B.
Then use VLOOKUP in columns G and H to sort the data according to rank.
Then the maximum sums are trivial to compute in : sum of the n bigger numbers.
Here is the code:
A B C D E F G H I J K
1
2 User input Sorted by rank Maximum sums
3 Rank name value Rank name value name value
4 =RANK.EQ(C4;$C$4:$C$8) a 45 1 =VLOOKUP(E4;$A$4:$C$8;2;FALSE) =VLOOKUP(E4;$A$4:$C$8;3;FALSE) 2 numbers =CONCATENATE($F$4;"+";$F$5) =$G$4+$G$5
5 =RANK.EQ(C5;$C$4:$C$8) b 1 2 =VLOOKUP(E5;$A$4:$C$8;2;FALSE) =VLOOKUP(E5;$A$4:$C$8;3;FALSE) 3 numbers =CONCATENATE($F$4;"+";$F$5;"+";$F$6) =$G$4+$G$5+$G$6
6 =RANK.EQ(C6;$C$4:$C$8) c 2 3 =VLOOKUP(E6;$A$4:$C$8;2;FALSE) =VLOOKUP(E6;$A$4:$C$8;3;FALSE) 4 numbers =CONCATENATE($F$4;"+";$F$5;"+";$F$6;"+";$F$7) =$G$4+$G$5+$G$6+$G$7
7 =RANK.EQ(C7;$C$4:$C$8) d 12 4 =VLOOKUP(E7;$A$4:$C$8;2;FALSE) =VLOOKUP(E7;$A$4:$C$8;3;FALSE) 5 numbers =CONCATENATE($F$4;"+";$F$5;"+";$F$6;"+";$F$7;"+";$F$8) =$G$4+$G$5+$G$6+$G$7+$G$8
8 =RANK.EQ(C8;$C$4:$C$8) e 33 5 =VLOOKUP(E8;$A$4:$C$8;2;FALSE) =VLOOKUP(E8;$A$4:$C$8;3;FALSE)
Here is how the result looks:
A B C D E F G H I J K
1
2 User input Sorted by rank Maximum sums
3 Rank name value Rank name value name value
4 1 a 45 1 a 45 2 numbers a+e 78
5 5 b 1 2 e 33 3 numbers a+e+d 90
6 4 c 2 3 d 12 4 numbers a+e+d+c 92
7 3 d 12 4 c 2 5 numbers a+e+d+c+b 93
8 2 e 33 5 b 1
Note that it can be easily extended to more variables.
Expanding on d-stroyer's answer, and converting it to VBA:
create UDF:
Option Explicit
Function GetMax(RNames As Range, RVals As Range, MaxNums As Long) As String
Dim i As Long
Dim j As Long
Dim tmpName As String
Dim tmpVals As Long
Dim Names()
Dim Vals()
Names = RNames
Vals = RVals
For i = 1 To UBound(Names) - 1 'bubble sort
For j = i + 1 To UBound(Names)
If Vals(i, 1) < Vals(j, 1) Then 'largest first
tmpName = Names(i, 1)
Names(i, 1) = Names(j, 1)
Names(j, 1) = tmpName
tmpVals = Vals(i, 1)
Vals(i, 1) = Vals(j, 1)
Vals(j, 1) = tmpVals
End If
Next j
Next i
For i = 1 To MaxNums
If Vals(i, 1) <= 0 Then Exit For
'adding zero, or negative numbers will lower the total
Next i
For j = 1 To i - 1
GetMax = GetMax & Names(j, 1) & ","
'now we know how many values to use (from previous loop)
'make the string up
Next j
If Len(GetMax) > 0 Then
GetMax = Left(GetMax, Len(GetMax) - 1)
'remove the final comma
Else
GetMax = "No result found"
End If
End Function
Call using =getmax(A1:A5,D1:D5,3)
result would be d,b,e
I'll leave the rest up to you ov checking for error conditions, such as more than 1 column passed in the range, or ranges of unequal size, or a max # of items returned being larger than the range size

Excel VBA Macro to add a row when value changes and populate that row

I'm trying to build a macro in excel that will take a bunch of data like this:
D 1 2 3 4 5
D 1 2 3 9 5
D 1 2 3 4 5
And process it to insert a row when a value in column 4 differs. I also want to populate this row at the same time with either static values or a formula.
So ideally, taking the above table I would get:
D 1 2 3 4 5
H A B C D E <- This row got added as there was a change in column D
D 1 2 3 9 5
H A B C D E <- This row got added as there was a change in column D
D 1 2 3 4 5
I would want this to iterate through a quite long list.
Can anyone give me any pointers?
Thank you for your help.
Something like this should work. I didn't test it but if you run it and use F8 to iterate through it should be easy to debug if it doesn't work exactly as intended.
Dim i as integer
for i = 2 to cells(1,1).end(xldown).row 'itereate thru all rows
if cells(i,4).value <> cells(i-1,4).value then 'compare the cells in col 4 with previous row
rows(i).entirerow.insert 'insert a row if the values don't match
cells(i,1) = "A"
cells(i,2) = "B"
cells(i,3) = "C"
cells(i,4) = "D"
cells(i,5) = "E"
i = i + 1 'since we inserted a row we have to make i bigger to go down
end if
next i

Auto calculate average over varying number values row by row

I have an Excel file with several columns in it and many rows. One column, say A has ID numbers. Another column, say G has prices. Column A has repeating ID numbers, however not all numbers repeat the same amount of times. Sometimes just once, other times 2, 3 or several times. Each column G for that row has a unique price.
Basically, I need to average those prices for a given ID in column A. If each ID was repeated the same number of times, this would be quite simple, but because they are not I have to manually do my average calculation for each grouping. Since my spreadsheet has many many rows, this is taking forever.
Here is an example (column H is the average that I am currently calculating manually):
A ... G H
1 1234 3.00 3.50
2 1234 4.00
3 3456 2.25 3.98
4 3456 4.54
5 3456 5.15
11 8890 0.70 0.95
13 8890 1.20
...
So in the above example, the average price for ID# 1234 would be 3.50. Likewise, the average price for ID# 3456 would be 3.98 and for #8890 would be 0.95.
NOTICE how rows are missing between row 5 and 11, and row 12 is missing too? That is because they are filtered out for some other reason. I need to exclude those hidden rows from my calculations and only calculate the average for the rows visible.
Im trying to write a VBA script that will automatically calculate this, then print that average value for each ID in column H.
Here is some code I have considered:
Sub calcAvg()
Dim rng As Range
Set rng = Range("sheet1!A1:A200003")
For Each Val In rng
Count = 0
V = Val.Value '''V is set equal to the value within the range
If Val.Value = V Then
Sum = Sum + G.Value
V = rng.Offset(1, 0) '''go to next row
Count = Count + 1
Else
'''V = Val.Value '''set value in this cell equal to the value in the next cell down.
avg = Sum / Count
H = avg '''Column G gets the avg value.
End If
Next Val
End Sub
I know there are some problems with the above code. Im not too familiar with VBA. Also this would print the avg on the same line everytime. Im not sure how to iterate the entire row.
This seems overly complicated. Its a simple problem in theory, but the missing rows and differing number of ID# repetitions makes it more complex.
If this can be done in an Excel function, that would be even better.
Any thoughts or suggestions would be greatly appreciated. thanks.
If you can add another row to the top of your data (put column Headers in it) its quite simple with a formula.
Formula for C2 is
=IF(A2<>A1,AVERAGEIFS(B:B,A:A,A2),"")
copy this down for all data rows.
This applies for Excel 2007 or later. If using Excel 2003 or earlier, use AVERAGEIF instead, adjusting ranges accordingly
If you can't add a header row, change the first formula (cell C1) to
=AVERAGEIFS(B:B,A:A,A1)
In my way ..
Sub calcAvg()
Dim x, y, i, y2, t, Count, Mount As Integer
Dim Seek0 As String
x = 1 '--> means Col A
y = 1 '--> means start - Row 1
y2 = 7 '--> means end - Row 19
For i = y To y2
If i = y Then
Seek0 = Cells(i, x)
t = i
Count = Cells(i, x + 6)
Mount = 1
Else
If Cells(i, x) <> Seek0 Then
Cells(t, x + 7) = Count / Mount
Count = Cells(i, x + 6)
Mount = 1
t = i
Seek0 = Cells(i, x)
Else
Count = Count + Cells(i, x + 6)
Mount = Mount + 1
End If
End If
Next
End Sub
Hope this helps ..

Is it possible to add/subtract in one cell, and have it subtract/add in another cell that already has a value?

Is it possible to add/subtract in one cell, and have it subtract/add in another cell that already has a value?
I am thinking it may be a if function but I can not wrap my head around how I would write out the formula.
Let's say you have 2 columns B and C that already contain data.
And if you Add a number to B you want that number to be subtracted from C.
My recommendation is to write a macro that will work as follows:
First the user selects the two columns and then runs the macro
For each row
Cell c = getCell("C" + row);
double cval = c.Value;
c.type = FORMULA;
c.Formula = "=" + (cval + getCell("B" + row).Value) + "-B"+row;
c.Recalculate()
Example:
Original:
A B C
1 Gas 5 10
2 Air 8 12
Replace with:
A B C
1 Gas 5 =15-B1
2 Air 8 =20-B2
so you only change B, and the value of C is automatically calculated.

Resources