I am looking a way of creating excel vba for calculating average, depends upon another cell
In above picture, I want calculate average of those cell in column C, where A column has the name on it.In this case, average of cells C6,C7,C8 (and skip C9 and C10)because Name column (Column A) has data in only A6,A7,A8. While calculating I need to count 0 as well.
not getting a way to create formula, tried with averageif, but that only check for a specific data
can somebody give a hint to form the this vba function
Try this:
=(SUMPRODUCT(--(ISBLANK(A6:A10)=FALSE),--(C6:C10)))/COUNTA(A6:A10)
Maybe:
=AVERAGEIF(A6:A10,"<>",C6:C10)
In VBA you can try something like this:
Dim lastRowOfColA As Long
lastRowOfColA = ActiveSheet.Cells(Rows.Count, "A").End(xlUp).Row 'Get last row of column A containing data
Dim rowCount As Long 'Number of rows containing data in column C
Dim sum As Long 'The sum of the values in column C
Dim i As Long
For i = 6 To lastRowOfColA
Dim valOfColA As String
valOfColA = Cells(i, 1).Value
Dim valOfColC As String
If valOfColA <> "" Then
valOfColC = Cells(i, 3).Value
If valOfColC <> "" Then
rowCount = rowCount + 1
sum = sum + valOfColC
End If
End If
Next
If rowCount > 0 Then
MsgBox ("Average: " & (sum / rowCount))
Else
MsgBox ("No rows with data found!")
End If
Of course you have to put that in a function and use parameters instead of the hard coded values above.
Related
I apologize, this is my first crack at Excel VBA so excuse my lack of knowledge!
So I have a list of (currently) 3 names to assign to the days in column A in a repeating order in Excel.
Currently my VBA code allows it to populate the selected cells with the names in a repeating pattern (this part is good), however there are two pieces I need help with.
1- with current code, once it reaches the bottom of the names it checks for the blank box that would end that list and starts over at the tops as directed but it puts a blank cell first (see screenshot). How can I have it put next name without adding blank cell first?
2- I want to be able to (once this gets going)select the entire D column through what dates need to be filled and:
-check the lowest non blank box
-match to list and set the
counter to name below that so
it continues the name order
from the last person who was
assigned
This is code I have now:
Sub EXAMPLE()
Dim count As Integer
count = 0
For Each c In Selection
c.Value = Range("X1").Offset(count, 0).Value
If c.Value = "" Then count = -1 And c.Value = Range("x1").Offset(count, 0).Value
count = count + 1
Next c
End Sub
Sorry I know that was long, I hope this makes sense.
I think it's worth reading about arrays, as this task is ideally suited to their use. Your best bet would be to read the names into an array and then build a recurring array whose dimension is equal to the number of rows in your dates column (or selection, or however you want to define the size of the output range).
Code would look a little like this:
Dim v As Variant
Dim people() As Variant, output() As Variant
Dim rowCount As Long, i As Long, j As Long
Dim endRange As Range
'Read the list of names into an array.
'This just takes all data in column "X" -> amend as desired
With Sheet1
Set endRange = .Cells(.Rows.Count, "X").End(xlUp)
v = .Range(.Cells(1, "X"), endRange).Value
End With
'Sense check on the names data.
If IsEmpty(v) Then
MsgBox "No names in Column ""X"""
Exit Sub
End If
If Not IsArray(v) Then
ReDim people(1 To 1, 1 To 1)
people(1, 1) = v
Else
people = v
End If
'Acquire the number of rows for repeating list of names.
'This just takes all data in column "A" -> amend as desired
With Sheet1
Set endRange = .Cells(.Rows.Count, "A").End(xlUp)
rowCount = .Range(.Cells(3, "A"), endRange).Rows.Count
End With
'Sense check date data.
If endRange.Row < 3 Then
MsgBox "No dates in Column ""A"""
Exit Sub
End If
'Make a recurring array.
ReDim output(1 To rowCount, 1 To 1)
i = 1
Do While i <= rowCount
For j = 1 To UBound(people, 1)
output(i, 1) = people(j, 1)
i = i + 1
If i > rowCount Then Exit Do
Next
Loop
'Write the output to column "D"
Sheet1.Range("D3").Resize(UBound(output, 1)).Value = output
So first my disclaimer. While I have some programming background, im not proficient in VB scripting so I may need some hand holding on this but I am mighty grateful for any help you wonderful people can render.
Im creating a print button that will print a worksheet based on criteria that the user will type in. Well basically I need the script to check certain cells in a row and if there is data in those cells, move to the next line. Rinse and repeat until you get to a row with no data in those certain cells and then automatically print the correct number of pages based on the data. I hope that makes sense. I hope that makes sense.
I tried writing a piece of code to check certain columns and return the value when all of those columns are blank. Hope that helps you
Sub Printing()
Dim CheckCol1 As Integer, CheckCol2 As Integer
Dim rowCount As Integer, rowCount1 As Integer, rowCount2 As Integer, currentRow As Integer
Dim currentRowValue1 As String, currentRowValue2 As String
Dim found As String
found = "No"
CheckCol1 = 1 'column A has a value of 1
CheckCol2 = 2 'column B has a value of 2
rowCount1 = Cells(Rows.Count, CheckCol1).End(xlUp).Row
rowCount2 = Cells(Rows.Count, CheckCol2).End(xlUp).Row
rowCount = Application.Max(rowCount1, rowCount2)
' find the first blank cell on both the columns
For currentRow = 1 To rowCount
currentRowValue1 = Cells(currentRow, CheckCol1).Value
currentRowValue2 = Cells(currentRow, CheckCol2).Value
If (IsEmpty(currentRowValue1) Or currentRowValue1 = "") And (IsEmpty(currentRowValue2) Or currentRowValue2 = "") Then
MsgBox ("No data on Column A and B in row" & currentRow)
found = "Yes"
End If
Next
If found = "No" Then ' This will return rowcount+1 when the columns have values throughout the range
MsgBox ("No data on Column A and B in row" & rowCount + 1)
End If
End Sub
Note:- You can increase the number of columns to be checked by adding few variables. You can try Adding third column by adding Checkcol3, rowcount3, currentrowvalue3 and adding one more condition to the if clause
I would like to ask your help for this task.
The excel sheet contains duplicated items in ColumnA. I want to combine these duplicates into one row. Please see the picture.
As the actual picture shows, there are three As in ColumnA. For every A there are some cells from ColumnB. Lets say those are the values to A. The values from every rows are marked with different colors seperately.
I want to combine A's values into one row, as the target picture shows.
The excel sheet was pre-sorted, so that all duplicates from ColumnA always appear together.
Please be noticed there are also items without duplicates: There is only one E in ColumnA. No transpose is required for this row.
Please also be noticed that there could be more duplicted items in ColumnA. E.g. 10x Ts, or 30x Ks.
To make the task easier, it is no need to delete the blank rows after the transformation.
The colors are used only to show the problem, there is no color in the excel sheet.
So far for this task.
Actually I asked a similar question before: Excel VBA: How to transform this kind of cells?
In the link there are some very good codes, but sadly I am not capable to rewrite the code for this task.
So please help me~
But please dont forget to have a happy weekend~
Thanks!
Try the code below ("bonus" feature, also removes the empty rows).
As you wrote in your post, the data is sorted according to Column A, and there are no empty rows in your data.
Sub TransposeDup()
Dim LastCol, LastColCpy As Long
Dim lrow As Long
lrow = 1
While Cells(lrow, 1) <> ""
If Cells(lrow, 1) = Cells(lrow + 1, 1) Then
LastCol = Cells(lrow, Columns.Count).End(xlToLeft).Column
LastColCpy = Cells(lrow + 1, Columns.Count).End(xlToLeft).Column
Range(Cells(lrow + 1, 2), Cells(lrow + 1, LastColCpy)).Copy Destination:=Cells(lrow, LastCol + 1)
Rows(lrow + 1).EntireRow.Delete
Else
lrow = lrow + 1
End If
Wend
End Sub
Something like the following should get you in the right direction. This doesn't copy formats, but it gets the values. You could tweak it to get where you need to go though:
Sub dedup_and_concat()
Dim intWriteCol As Integer
Dim intReadCol As Integer
Dim intWriteRow As Integer
Dim intReadRow As Integer
Dim intStartRow As Integer
Dim intEndRow As Integer
Dim strPrevRowValue As String
'Start and end rows:
intStartRow = 1
intEndRow = 8
'initial values:
intWriteRow = 1
'Loop from your start row to your end row
For intReadRow = intStartRow To intEndRow 'beginning and ending rows
intReadCol = 2
'If we are at the first row, then just capture values
'Also if this is a new value, then reset all of the write variables
If intReadRow = intStartRow Or Sheet1.Cells(intReadRow, 1).Value <> Sheet1.Cells(intWriteRow, 1).Value Then
'set the row and initial column we are writing to
intWriteRow = intReadRow
intWriteCol = Sheet1.Cells(intReadRow, 1).End(xlToRight).Column() + 1
Else
'We are on a row that needs to be concatenated and deleted
'So loop through all of the columns to get their values
'And write their values to the read row and read col
Do Until Sheet1.Cells(intReadRow, intReadCol).Value = ""
Sheet1.Cells(intWriteRow, intWriteCol).Value = Sheet1.Cells(intReadRow, intReadCol).Value
'increment read and write columns
intWriteCol = intWriteCol + 1
intReadCol = intReadCol + 1
Loop
'remove this rows values
Sheet1.Rows(intReadRow).ClearContents
End If
Next intReadRow
End Sub
I have a number of columns (in Excel file) that represent months of the year; each column has a number of records and I'd like to be able to run a macro that would insert a cell in the last row of each column with an Average. The first cell of each column is a header, so I need to be including cells from row 2 down to the last record in the column. The number of columns and rows will be different each time i use the macro . I would very much appreciate your help. Thanks!
Here's a solution that will work out of the box for you. It takes the average of each column, starting at row 2.
Sub AverageColumn()
Dim count As Integer
Dim sum As Integer
Dim lastCol As Integer
lastCol = ActiveSheet.UsedRange.Columns(ActiveSheet.UsedRange.Columns.count).Column
For c = 1 To lastCol
sum = 0
count = 0
ActiveSheet.Cells(2, c).Select
Do While ActiveCell.Value <> ""
sum = sum + ActiveCell.Value
count = count + 1
ActiveCell.Offset(1, 0).Activate
Loop
ActiveCell.Value = sum / count
Next c
End Sub
I am finding this surprisingly hard to find an answer for, given its simple description. I hope this is not a duplicate, though it probably is because of its simplicity, and I simply cannot find the answer.
In VBA, I have hundreds of columns, and I'd like to know all their lengths. I know there are exactly "COLS" columns. I want something like this:
For i in COLS
length = 'Some one line formula to find the length of column i
'Some code that works with the value of length
Next i
By length I mean the number of non-empty cells... For my specific purposes there will be no blank cells in the columns, and all the cells in the column I wish to count will contain text (all the rest will be empty).
Help would be much appreciated on this seemingly simple matter!
Edit: I also want to make this dependent on the column index (which will be 'i' in the loop above). I won't always know the column letter...
This will count text non-empty cells in VBA:
For i = 1 To Columns.Count
n = WorksheetFunction.CountA(Columns(i))
Next
It is best to use a routine that works automatically from the last row in all Excel versions.
Dim lngRow As Long
lngRow = Cells(Rows.Count, "A").End(xlUp).Row
I think you could use
LastRowColA = Range("A" & Rows.Count).End(xlUp).Row
to find last used row in column A.
Navigating through every column you can have what you want...
You can find the last non-empty row using Range(large row number, column).End(xlUP).row where large row number should be large enough to always be beyond your last used cell.
You can use an alternative approach using the worksheet function CountA as follows
Test Data:
Col1 Col2 Col3
A A A
B B
C C C
D D D
E E
VBA function:
Sub Test()
Dim sht As Excel.Worksheet
Set sht = Worksheets("Sheet1")
Dim i As Integer
Dim max As Integer
Dim length As Integer
max = 0
For i = 1 To 3
'CountA returns the number of non-blank cells in a range
length = WorksheetFunction.CountA(sht.Columns(i))
If length > max Then max = length
Next i
MsgBox max - 1 ('remove 1 if you have column headers)
End Sub
len = sheet1.Range("B" & Rows.Count).End(xlUp).Row ' gives the count of B column
len = sheet1.Range("A" & Rows.Count).End(xlUp).Row ' gives the count of A column
dim i as integer
For i = 1 To Columns.Count
debug.print i, cells(i, rows.count).end(xlup).row
Next