Finding the sum of the first two rows VBA - excel

I am trying out a simple summation vba code. I want to find the sum of the first 2 rows in a defined range. However, I get a #VALUE error return upon running the following code:
Function test(prices As Range)
test = prices.Rows.Value + prices.Rows.Offset(1, 0).Value
End Function
Please advise, thanks v much!

Value will only look at a single cell while Rows is looking at all rows in your range so your code is trying to add a single cell that thinks it's the entire row and coming back with the computer equivalent of a shoulder shrug.
Try using:
Function test(prices As Range) As Double
test = Application.WorksheetFunction.Sum(prices.Rows(1).Resize(2))
End Function
It will look at the first two rows of whichever range you give it.
This would also work - now looking up as not sure of difference of leaving out the Worksheetfunction bit:
Function test(prices As Range) As Double
test = Application.Sum(prices.Rows(1).Resize(2))
End Function

Related

Print array called from Excel cell (VBA)

I'm not sure if I need a sub or a function here, but I need something that can:
Be called from a cell in Excel
Can print values into other cells in the same worksheet
For eg.
Function PrintDemo(CellRef As Range)
Set CellRef = ActiveCell.CurrentRegion
Dim i as Integer
CellRef.Offset( , 5).Value = i
PrintDemo = 3
End Function
If I try to call this using =PrintDemo(D1) in an excel cell, hoping to print '123' 5 cells to the right, it just shows VALUE error. The function doesn't actually need to return anything, I made it hoping it would solve the error (it didn't). Nothing gets printed.
I haven't used VBA much (definitely not for printing) and I'm sure I'm missing something very fundamental in terms of how things are called. Please help me out.
EDIT: Makes sense that I can't change other cells, can I store my result as an array somewhere and have a range of cells access its values one at a time?
eg. outputArr=[1,2,3,4,5]
A2 -> =outputArr(0)
B2 -> =outputArr(1) and so on
It'll actually be 2D array but I don't think that should make much of a difference. The reason I need formulae everywhere is because this has to run in many places in the sheet, hence can't have any manual steps.

Excel VBA Worksheetfunction.Match doesn't work with Dates

I need to apply MATCH function to a range of dates (in VBA. The standard MATCH function written as cell formula does work as intended.) looking for the largest possible index whose corresponding date is <= the looked-up date. Here's my code and a minimum working example:
Function test_debug_func(x As Date, arr As Range) As Integer
Debug.Print "entered function"
test_debug_func = WorksheetFunction.Match(x, arr, 1)
End Function
And I checked that the function is indeed entered by printing the debug statement. However, it cannot proceed with the WorksheetFunction.Match function. I also checked that all dates are indeed Date and not other formats.
It simply doesn't make any sense to me why this wouldn't work. Could anyone kindly help? Thanks!
Since dates are just numbers, you can use CLng:
test_debug_func = WorksheetFunction.Match(CLng(x), arr, 1)

how to write results of a formula directly into an excel range by VBA code

I have a series of functions for each of listobject columns. The file is heavy and crashing, so I want just to keep the results of each formula as static values. I can allocate formula to the range and ask excel to convert the range to value. But I am wondering if there is a way to ask VBA to write only the static values in the range instead of the formula itself.
Here is what I have so far:
Sub calculate2()
Dim i As Long, t As Long
t = Timer
With Sheet3.ListObjects(1)
For i = 3 To 9
.ListColumns(i).DataBodyRange.ClearContents
.Range.Cells(2, i).Formula = sheets3.range("formula").cells(i,1).formula
.ListColumns(i).DataBodyRange = .ListColumns(i).DataBodyRange.Value
Next i
End With
Debug.Print Timer - t
End Sub
As an answer to my own question,
What I was looking for is: " application.Evaluate " I am posting that so if anyone came here by search can find the idea and the sollution I eventually found. Here is an example:
Sheet3.ListObjects(1).ListColumns(3).DataBodyRange = [IFERROR(IF(COUNTIFS(ZZ84!$B:$B,[WO],ZZ84!$E:$E,"=*V99"‌​,ZZ84!$L:$L,"<>")=1,1,0),"")]
in this case there is no need to loop and for each range has to write needful line of code (Embed the function in VBA, what I excatly was looking for). The only different in above function with directly putting that in a excel cell is using [WO] instead of [#WO]. So evaluat caculate an array of data and directly write that in specified range. (here body range of list columns 3 ).
For me it helped to avoid crashes beacause of voilate calculation by my functions.
Another simple example would be:
range("b1:b10")=[if(row(1:10),if(a1:a10>3,"big","Small"))]
or
range("b1:b10") = evaluate("if(row(1:10),if(" & range("a1:a10").address&">3,""big"",""small""))")
Kind regards,
M

SumIf with Strings?

This may be a stupid question, and if it is, I apologise. I have a table in excel:
Column a...........Column b
1 property1.......problem x
2 property2.......problemy
3 property3.......problemz
4 property1......problem a
I was wondering if I could use sumif (or any similar formula) to add the problems, referring to a certain property, in one cell. for ex:
I would have
Column a...........Column b
1 property1.......problem x problem a
The problem is I can't figure out where to start. I tried using sumif but I get an error. Probably because I'm trying to add strings. I tried to mix a vlookup with sumif but that didn't produce anything too. Im stuck here. Thanks for any help!
I am not 100 % sure, but I think you might need to use VBA for this. You could try to create the following custom function:
Create named ranges properties and problems in your sheet.
Click ALT+F11 to open VBA editor.
Press Insert --> Module
Write code
'
Function ConcatIF(Property As String, PropertyRange As Range, ProblemRange As Range) As String
Dim counter As Integer
Dim result As String
result = ""
Dim row As Range
counter = 1
For Each row In PropertyRange.Rows
If (Property = row.Cells(1,1).Value) Then
result = result + ProblemRange.Cells(counter,1).Value + " "
End If
counter = counter +1
Next row
ConcatIF = result
End Function
As I do not have excel on the machine I am writing this on, I could only test it on another machine, and therefore there could be spelling mistakes in this code.
Ensure that you write the code in the module you created, it cannot be written in a Sheet's code, must be module.
This function can then be called as a regular function, like sum, average and if. Create a unique list of all your properties on another sheet. Properties in column A, and then in column B you can call the cuntion. Assume row 1 is used for headings, write the following and copy down.
=ConcatIF(A2,properties,problems)
NOTE!!!! This code gets out of hand very quickly. It needs to do (number of properties) x (number of property/problem pairs) comparisons, so if this number is huge, it could slow down your sheet.
There could be faster methods, but this was from the top of my head.

Sum function not giving right answer

I am using the following code to sum all the numbers in different columns. The formula always gives me wrong answer. Please help! Thanks
Sub TOTALVALNEW(colNumber As Integer)
Dim StartOfTheRANGE As Range
Dim EndOfTheRange As Range
Set StartOfTheRANGE = Evaluation.Cells(3, colNumber)
Set EndOfTheRange = StartOfTheRANGE.End(xlDown)
'Evaluation is the name of the sheet.
Evaluation.Cells(3, colNumber).End(xlDown).Offset(1, 0) = Application.Sum(StartOfTheRANGE, EndOfTheRange)
End Sub
VBA's Application.Sum works exactly the same as the worksheet function SUM() in a cell formula. It takes an object, or a list of objects. If you specify two objects namely the first and last cells, it will just take the sum of the values of the contents first and last cells only (a 2-term sum), not anything in between. If you want to include all cells between the first cell and last cell inclusive, you need to make make a range object by using the Range() function. So changing to this:
Evaluation.Cells(3, colNumber).End(xlDown).Offset(1, 0) = Application.Sum(Range(StartOfTheRANGE, EndOfTheRange))
should work.

Resources