find average of all non-zero values in an array - excel

I have populated an array with five values. The values were pulled from cells elsewhere in the spreadsheet. How do I find the average of all nonzero values?
I tried a for-next loop, but couldn't skip the zero values without another conditional statement. I assume there is a dedicated command for it. Thanks in advance!
Dim varIncome as variant
varIncome = Application.Transpose(Range("B3:B7").Value)

Try this (note: I didn't use the varIncome variable as it didn't seem necessary in order to get a result):
Sub avgNonZeroNumbers()
'Declare:
Dim rng As Range
'Initialize:
Set rng = Sheet3.Range("B3:B7") 'Change Sheet3 to your actual sheet's code name
' Print result to the Immediate window
Debug.Print WorksheetFunction.AverageIf(rng, "<>0")
End Sub

Related

Referencing a range that is input into the function is causing the code to stop

this is both my first post on stack overflow and my first vba project so please forgive and correct any mistakes.
I am trying to create a function that looks at two ranges and pastes only non-null duplicate values into a third range.
My function takes in the two ranges that are to be compared as input (rangeOne and rangeTwo). It also takes in a third range, which is the first cell in the paste range (strtCell). I am trying to make it so that the duplicate values are pasted along a column for now, but so that they start at the cell that the user inputs.
The problem is that whenever I reference strtCell, the code just stops running. I have tested various breakpoints and using strtCell in many different contexts. However, whenever it is used at all in the code, the code stops executing at that line without any error message. If I comment out or delete the lines referencing it, the cell I enter the function in is set to "Success" as expected.
Also as an aside, whenever I type Option Explicit on the top line, it disappears from the workspace but still seems to be in effect. I am confused as to why it is disappearing.
Here is the relevant code [I put the bracketed text for comments I added in the post]:
(Option Explicit)
Public Function CopyDuplicates(rangeOne As Range, strtCell As Range, rangeTwo As Range)
'Declare necessary things
Dim arrayOne(), arrayTwo(), element, element2, element3, element4
Dim cell As Range
Dim pairs As New Collection
pairs.Add ""
Dim flag As Boolean
Dim numberOfDuplicateValues As Integer, i As Integer
numberOfDuplicateValues = 0
i = 0
'Import the Ranges
'Set array lengths to sizes of ranges
ReDim arrayOne(rangeOne.Count - 1)
ReDim arrayTwo(rangeTwo.Count - 1)
'Set array values to values of ranges
'Range 1
For Each cell In rangeOne
arrayOne(i) = cell.Value
i = i + 1
Next cell
'Range 2
[Exact same process as Range 1]
'Check for Duplicates
[This is just some code that adds all the duplicate values into pairs.
I have used a breakpoint to verify that pairs is being updated as intended.]
'Print duplicates
For Each element4 In pairs
strtCell.Value = CStr(element4)
strtCell = strtCell.Offset(1, 0)
Next element4
CopyDuplicates = "Success"
End Function
I'll also just add that strtCell is meant to be a single-cell range, but I have tested it as both a single and multi cell range, with the same weird stopping result in both cases.
Thanks for any help, this problem has had me stumped for hours!

Is there a way to not have a blank cell considered 0 in VBA?

New to vba and trying to do something very basic. I have a column full of numbers that also contains blank cells. When I try to do this If statement, Excel considers the blank cells as the value 0. I only want the cells with numbers to have the "Alerted Transaction" value, not the blank cells. Any help is appreciated. Thanks.
If Columns("J").Value > 0 Then Columns("J").Value = "Alerted Transaction"
Define the range you want to check, loop each cell in the range and check for empty cells.
dim myWS As Worksheet
set myWS = ThisWorkbook.Worksheets("myWorksheet")
With myWS
Dim loopRange As Range
set loopRange = .Range(.Cells(2,10),.Cells(.UsedRange.Rows.Count,10))
End with
dim currCell As Range
for each currCell in loopRange
if currCell.Text<>vbNullString Then
currCell.Offset(0,3).Value = "Alerted Transaction"
end if
next
There are better ways to get the last populated cell in a column, but that is for another day :)
For Each c In Worksheets("Sheet1").Range("J1:J10").Cells
If Not IsEmpty(c.Value) Then c.Value = "Alert"
Next
As #BigBen pointed out, you probably don't want to IsEmpty the whole column, this code checks Row 1 to Row 10 in Column J. You may adopt the code to your scenario accordingly.
See doc on IsEmpty and doc on For loop
You can check to see if a cell is empty by using the
IsEmpty function. I don't really mess around with Excel so I don't know how you would check a range of cells.

Looking to delete named range2 when all values in named range1 are equal to “N/A” VBA Application.WorksheetFunction

We are looking to delete an entire section of rows (named range “Remove_Allowances_Credits”) when all values in the section (named range "Allowances_Credits_Range") are equal to “N/A”.
For example, we are looking to delete rows 156:171 when each value in C161:C170 equal “N/A”. How do I use application.worksheetFunction count and countif to accomplish this?
If Application.WorksheetFunction.Count(Range("Allowances_Credits_Range")) = Application.WorksheetFunction.Count(Range("Allowances_Credits_Range", "n/a")) Then
Workbooks(PharmacyPricingGuarantees2).Sheets("Pharmacy Pricing Guarantees").Range("Remove_Allowances_Credits").Delete
End If
I am getting an Error 1004
If Application.WorksheetFunction.Count(Range("Allowances_Credits_Range")) = Application.WorksheetFunction.Count(Range("Allowances_Credits_Range", "n/a")) Then
Workbooks(PharmacyPricingGuarantees2).Sheets("Pharmacy Pricing Guarantees").Range("Remove_Allowances_Credits").Delete
End If
To delete the named range "Remove_Allowances_Credits"
I am getting an error 1004
Not entirely sure what you are trying to achieve, so I added a few different methods.
Sub Examples()
'Might need to change Workbook reference to PharmacyPricingGuarantees2?
Dim ws As Worksheet: Set ws = Thisworkbook.Sheets("Pharmacy Pricing Guarantees")
If ws.Range("Allowances_Credits_Range").Cells.Count = WorksheetFunction.CountIf(ws.Range("Allowances_Credits_Range"), "n/a") Then
ws.Range("Remove_Allowances_Credits").ClearContents '<-- Clear the values?
ws.Range("Remove_Allowances_Credits").EntireRow.Delete '<-- Delete the rows?
ThisWorkbook.Names("Remove_Allowances_Credits").Delete '<-- Delete the named range?
End If
End Sub
Try the following:
If Application.WorksheetFunction.COUNTA(Range("Allowances_Credits_Range")) =
Application.WorksheetFunction.COUNTIF(Range("Allowances_Credits_Range"), "#N/A")) Then
Workbooks(PharmacyPricingGuarantees2).Sheets("Pharmacy Pricing Guarantees").Range("Remove_Allowances_Credits").Delete
End If
Firstly, you want to use COUNTA instead of COUNT for the first part. COUNT only counts numerical values. COUNTA counts all non-empty values (including #N/A).
Secondly, you want to use the COUNTIF function to count values = #N/A.

Selecting an area with exception of merged cells in dynamic range

IMPORTANT EDIT: The main issue here is caused by hidden merged cells that are causing the entirity of their active range to be selected. Unless you know a way how to dynamically skip merged cells (in a dynamic range), the it most likely won't help. Have changed the entirity of question accordingly
any idea what am I doing wrong?
Got the following code, fyi the function find_last_row returns the value of last active row as integer. In this case, the returned variable would be 40
Private Sub initalize_button_Click()
Dim lastRow As Integer
Dim ws As Worksheet: Set ws = Sheets("Training_Planner")
lastRow = find_last_row
With ws
.Activate
.Range("E5:H" & lastRow).Select
End With
End Sub
Pretty basic code, should open the worksheet Training_Planner and select from E5 to HlastRow (in this case lastRow is 40) so the selected range should be E5:H40
Here is the expected result:
What I get instead:
Curiously enough, it selects only active range, but it's as if it didn't pay attention to columns, instead of the expected E5:H40 i get B5:I40
Any idea what's causing this?
Ok, first of all, if your range is gonna start always as E5, your range is 50% dinamic, because it starts always in same column and same row. Your Range is (Cells(a,b),Cells(c,d)), this means a = 5 and b = 5 (Column E).
Also, you say and Inputbox asks users for end cell of range (in your example is H40, but this is dynamic).
So, my code checks EVERY SINGLE cell in the range formed, and then, using Application.UnionI set a final big range. We cannot just use an array to select all of them, because your range is dynamic, and selecting ranges with arrays is limited to 30 args, so we need to update our FinalRange for each cell.
Dim MyCell As Range
Dim RangeWanted As Range
Dim MyFinalRange As Range
Set RangeWanted = Range("E5:" & InputBox("Cell Address")) 'User inputs Final Cell of Range. Start is always E5
'let's get all invididual addresses of each cell inthat dynamic RangeWanted
For Each MyCell In RangeWanted
If MyCell.MergeCells = False Then 'If not merged, we add it to FinalRange
If MyFinalRange Is Nothing Then
Set MyFinalRange = MyCell
Else
Set MyFinalRange = Application.Union(MyFinalRange, MyCell)
End If
End If
Next MyCell
Set RangeWanted = Nothing
MyFinalRange.Select
With this code, from Range("E5:H40") in image,yellow cells are merged. I want to select only the not merged ones. And using this code, I get this:
My example is with Range("E5:H40") but it works also with other ranges.
Try it and adapt the code to your needs.
Whenever something small like this is happening, simply try to simplify as much as you can. In your case, it would be this:
Sub TestMe()
Worksheets("Training_Planner").Range("E5:H40").Select
End Sub
If it selects E5:H40 then everything is ok. If not, try to select it manually. Probably you have a hidden row, which is merged from B to I, thus it is happenning this way.
Instead of this:
.Range("E5:H" & lastRow).Select
Try going with this:
.Range("E5", (Cells(Rows.Count, "H").End(xlUp))).Select
It count all the rows "H" has and then goes up until it finds the first item. And it will then select from "E1" to last item in "H"

Excel VBA union deletes data from column

What I am doing is very simple - selecting a union of columns which contain numbers stored as text and converting them. Every time this runs, all even union numbered columns of data are getting cleared.
Union(Columns(19), Columns(22), Columns(25), Columns(28), Columns(31), Columns(34), Columns(37), Columns(40), Columns(43), Columns(46)).Select
With Selection
.Value = .Value
End With
I've looked though my entire code multiple times are cant figure why this is behaving so weird. any help is greatly appreciated.
The Value property of a discontiguous range only returns the first area of that range. When you then try and assign that value (array, in this case) back to a discontiguous range, you get strange results. For this particular case, every second column will get the value of the first cell in the first area.
You should loop through the areas in your range.
For each rArea in Selection.Areas
rarea.value2 = rarea.value2
Next rarea
Try to avoid using Select, and fully qualify your ranges. This makes things easier to diagnose and more robust...
Dim myRange As Range
With ThisWorkbook.Sheets("Sheet1")
Set myRange = Union(.Columns(19), .Columns(22), .Columns(25)) ' etc.
End With
Now if you're trying to convert text to numbers, you might be better off using the NumberFormat property as discussed here: What are .NumberFormat Options In Excel VBA?
Looping through range areas and number-formatting:
Dim area As Range
For Each area In myRange.Areas
area.NumberFormat = 0 ' for numbers, could still use area.Value = area.Value
Next area

Resources