VBA Applying formula to range and finding sum of outputs - vba

Im tring to apply the formula GammaSingle to each cell in my range root (its range is just 1 column wide), then find the sum of the ouput of all of those cells. Not sure how to go about doing this
Public Function PsiFinal(ByVal Variables As Range, ByVal root As Range, ByVal t As Double) As Double
For Each cell In Range
'something that will apply GammaSingle(Variables, cell.value, t) to each cell in the range
PsiFinal = Application.WorksheetFunction.Sum(root)
'PsiFinal would be the sum of all their values after theyve gone through the formula GammaSingle
End Function

Like this:
Public Function PsiFinal(ByVal Variables As Range, _
ByVal root As Range, _
ByVal t As Double) As Double
Dim c As Range, rv
For Each c In root.Cells
rv = rv + GammaSingle(Variables, c.Value, t)
Next c
PsiFinal = rv
End Function

Related

VBA using cell values instead of cell names

I know that I can select a range when I have cell names. For example Range(A1:B30).select in VBA.
Is there a way to select a range with values written in the cells? I know the following code does NOT work but only that you know what I mean. Range(217:216,9).select.
I want to search for a value and specify the range but how can I do this?
I have already searched the web but I can not find a solution. I also tried to record the macro but it only recorded the code with cell names. I am new to VBA and I can't find a solution for my problem somewhere else. I hope you can understand what I mean.
Say we have:
and we want the range with values between (and including) 10 and 20. This code:
Sub RangeFromValues()
Dim v1 As Long, v2 As Long
Dim r1 As Range, r2 As Range, rng As Range
v1 = 10
v2 = 20
Set r1 = Range("A:A").Find(what:=v1, after:=Range("A1"))
Set r2 = Range("A:A").Find(what:=v2, after:=r1)
Set rng = Range(r1, r2)
rng.Select
End Sub
will produce:
Public Sub TestMe()
Range("1:10").Cells.SpecialCells(xlCellTypeConstants).Select
End Sub
would select only the values, which are not formulas in the first 10 rows:
To select the formulas: type xlCellTypeFormulas instead of xlCellTypeConstants. Just note, that if you do not have anything to Select, it would throw an error.
Another approach, you only need to specify x (low boundary), y (upper boundary) and rngTest (range where you wish to select cells):
Sub Test()
Dim x As Long, y As Long
Dim rngTest As Range
Set rngTest = Range("A1:J20"): x = 5: y = 10
Call RangebyValue(x, y, rngTest)
End Sub
Private Sub RangebyValue(ByVal x As Long, _
ByVal y As Long, _
ByVal rngTest As Range)
Dim vArr(), i As Long, j As Long, rngSelect As Range
vArr = rngTest.Value
For i = LBound(vArr, 1) To UBound(vArr, 1)
For j = LBound(vArr, 2) To UBound(vArr, 2)
If vArr(i, j) >= x And vArr(i, j) <= y Then
If Not rngSelect Is Nothing Then
Set rngSelect = Union(rngSelect, rngTest.Cells(i, j))
Else
Set rngSelect = rngTest.Cells(i, j)
End If
End If
Next j
Next i
rngSelect.Select
End Sub
I think that #Vityata's solution would work well to select all cells that have any value. If you are trying to find a specific value,
Following #Foxfire And Burns And Burns,
I would recommend using a loop through those cells.
For example:
Sub findTheNine()
Dim rng As Range
For Each rng In Range("I7:L11")
If rng.Value = 9 Then
rng.Select
End If
Next rng
End Sub
However, this would only select one of the '9's you wanted to find

VBA sum each column in another workbook

Hello,
I want to sum each column in another workbook (see example) ,
i did the code below :
Function sumrange(rng As Range)
Summ = 1
For Each cell In rng
Do While cell <> ""
Summ = Summ + cell.Value
Loop
Next
sumrange = Summ
End Function
sub test()
x = sumrange(Workbooks("Clients").Worksheets("Numbers").Range("A:A"))
thisworkbook.worksheets("Result").cells(1,1)=x
MsgBox x
end sub
but i didn't know how to loop throught each column (There will be more that 2 columns) and it blocks because the first cell contain a string : error , how can i define that it should begun from the second cell to end ?
Use SpecialCells method of Range object to sum over numbers only
Should numbers be "constants" (e.g.: not deriving from formulas) only, then use:
Function sumrange(rng As Range) As Double
sumrange = WorksheetFunction.Sum(rng.SpecialCells(xlCellTypeConstants, xlNumbers))
End Function
Should numbers come from formulas only, then use:
Function sumrange(rng As Range) As Double
sumrange = WorksheetFunction.Sum(rng.SpecialCells(xlCellTypeFormulas, xlNumbers))
End Function
Finally, could numbers be both constants or coming from formulas then use:
Function sumrange(rng As Range) As Double
On Error Resume Next
sumrange = WorksheetFunction.Sum(rng.SpecialCells(xlCellTypeFormulas, xlNumbers))
sumrange = sumrange + WorksheetFunction.Sum(rng.SpecialCells(xlCellTypeConstants, xlNumbers))
End Function
You can use the IsNumeric function to decide whether to add the cell's value to the sum:
Function SumRange(rng As Range)
Dim dblSum As Double
Dim rngCell As Range
For Each rngCell In rng
If VBA.IsNumeric(rngCell.Value) Then
dblSum = dblSum + CDbl(rngCell.Value)
End If
Next rngCell
SumRange = dblSum
End Function
That might be quite slow if you are iterating over all the cells in column A and there are only a handful of entries. The following enhancement also checks if the cell IsEmpty and quits the loop if that's the case - otherwise, empty cells may evaluate to zero:
Function SumRange(rng As Range)
Dim dblSum As Double
Dim rngCell As Range
For Each rngCell In rng
If VBA.IsEmpty(rngCell.Value) Then
Exit For
ElseIf VBA.IsNumeric(rngCell.Value) Then
dblSum = dblSum + CDbl(rngCell.Value)
End If
Next rngCell
SumRange = dblSum
End Function
Start at the second cell and specify the column in the function and call like this.
Function sumrange(rng As Range, c as integer)
dim summ as integer
dim I as integer
dim cell as integer
Summ = 1
'Wouldn't you want to start at 0 for your sum?
for i = 2 to 50,000
cell = rng.cells(i,c)
Summ = Summ + cell
Next
sumrange = Summ
End Function
sub test()
x = sumrange(Workbooks("Clients").Worksheets("Numbers").Range("A:A"),'column#')
thisworkbook.worksheets("Result").cells(1,1)=x
MsgBox x
end sub
You can sum range without looping , using the built-in sum function
example:
Sub test()
Dim LastRow As Long
'open the other workbook , clients
Set book = Workbooks.Open("clients.xlsx")
'get last raw starting from B2 down to the last filled cell
LastRow = book.Worksheets("Numbers").Range("B2").End(xlDown).Row
Debug.Print LastRow
Set range2 = book.Worksheets("sheet1").Range("B1:B" & LastRow)
sum1 = Application.WorksheetFunction.Sum(range2)
Debug.Print sum1
'write result to active sheet
ThisWorkbook.Worksheets("result").Cells(1, 1) = sum1
End Sub

Excel Formula with VBA

Need formula to match text from one column to text in different worksheet and count the highlighted cells. This is similar to doing a sumif, but instead of returning a numerical value in a static column, I will return the count of highlighted cells.
I have successfully written the VBA to count the highlighted cells in a given column, but now must do a match of names. Meaning, if name in column A1:A50 matches name in Sheet2 Column J1:J52, then return a count of highlighted cells in sheet 2 column X.
Formula to count highlighted cells: countbycolor('sheet2'!J4:J1847,A52)
VBA:
Function CountByColor(InputRange As Range, ColorRange As Range) As Long
Dim cl As Range, TmpCount As Long, ColorIndex As Integer
Application.Volatile
ColorIndex = ColorRange.Interior.ColorIndex
TmpCount = 0
On Error Resume Next
For Each cl In InputRange.Cells
If cl.Interior.ColorIndex = ColorIndex _
Then TmpCount = TmpCount + 1
Next cl
CountByColor = TmpCount
End Function
Adding a parameter for the criteria range and implementing Application.Countif should be sufficient.
Function CountByColorAndName(InputRange As Range, NameRange As Range, ColorRange As Range) As Long
Dim cl As Range, TmpCount As Long, ColorIndex As Integer
Application.Volatile
ColorIndex = ColorRange.Interior.ColorIndex
TmpCount = 0
On Error Resume Next
For Each cl In InputRange.Cells
If cl.Interior.ColorIndex = ColorIndex and _
cbool(application.countif(NameRange , cl.value)) then _
TmpCount = TmpCount + 1
Next cl
CountByColor = TmpCount
End Function
Sample syntax:
=CountByColorAndName('sheet2'!J4:J1847, A1:A50, A52)
There is a little confusion as your description of the situation refers to both Sheet2 Column J1:J52 and 'sheet2'!J4:J1847. If this isn't appropriate, please clarify.
The MATCH function is actually more efficient than the COUNTIF function, both on the worksheet and within VBA. This should reduce calculation load some.
For Each cl In InputRange.Cells
If cl.Interior.ColorIndex = ColorIndex then _
if not iserror(application.match(cl.value, NameRange , 0)) then _
TmpCount = TmpCount + 1
Next cl

Passing a Variable to an Add-in Function in Excel VBA

I want to write a for loop that takes the value of each cell, passes it into a function called FixID(), then outputs the result of the function into the value of the cell. The below code passes in values to the function fine, but it does not write the new value to the cell.
Sub test()
Total_Rows = Cells(Rows.Count, 3).End(xlUp).Row
For Each C In Range("A3", "C" & Total_Rows )
C = FixID(C.Value)
Next
End Sub
UPDATE: Here is a quick little example I put together to test the technique, and it worked as expected...
Option Explicit
Sub Test()
Dim MyRange As Range, Cell As Range
Dim Temp As String
Dim Total_Rows As Long
Total_Rows = Cells(Rows.Count, 3).End(xlUp).Row
Set MyRange = Range("A1:C" & Total_Rows)
For Each Cell In MyRange
Cell.Value = AddShrimp(Cell.Value)
Next Cell
End Sub
'Bubba Gump Function
Public Function AddShrimp(InputValue As String) As String
AddShrimp = InputValue & " Shrimp"
End Function
Before:
After:
ORIGINAL RESPONSE: Make sure you define the Range you're going to iterate through like this:
For Each C In Range("A3:C" & Total_Rows)
C.Value = FixID(C.Value)
Next C
I would probably add Option Explicit to the top of your routine as well, and declare all your variables up-front too (to prevent confusion, typo-related errors etc.):
Option Explicit
Sub Test()
Dim Total_Rows As Long
Dim C As Range, TotalRange As Range
Total_Rows = Cells(Rows.Count, 3).End(xlUp).Row
Set TotalRange = Range("A3:C" & Total_Rows)
For Each C In TotalRange
C.Value = FixID(C.Value)
Next C
End Sub

Count number of different cells in VBA

I want to count no of different cells which are selected using VBA.
Consider if we select five distinct cells - D5, C2, E7, A4, B1.
Is there a way I can count these number of cells.
Secondly how can I retrieve data in these cells. Lets say I want to store it in an array.
Thank you for the help.
Dim rngCell as Range, arrArray() as Variant, i as integer
Redim arrArray(1 to Selection.Cells.Count)
i = 1
For each rngCell in Selection
arrArray(i) = rngCell.Value
i = i + 1
Next
Looks like you got it mostly figured out, but here is something to load it into an array if you want it:
Public Sub Example()
Dim test() As Variant
test = RangeToArray(Excel.Selection, True)
MsgBox Join(test, vbNewLine)
End Sub
Public Function RangeToArray(ByVal rng As Excel.Range, Optional ByVal skipBlank As Boolean = False) As Variant()
Dim rtnVal() As Variant
Dim i As Long, cll As Excel.Range
ReDim rtnVal(rng.Cells.Count - 1)
If skipBlank Then
For Each cll In rng.Cells
If LenB(cll.Value) Then
rtnVal(i) = cll.Value
i = i + 1
End If
Next
ReDim Preserve rtnVal(i - 1)
Else
For Each cll In rng.Cells
rtnVal(i) = cll.Value
i = i + 1
Next
End If
RangeToArray = rtnVal
End Function
Thankfully I got a way around it by doing - Selection.Cells.Count
It returns me the cell count for selected cells.
But I am still stuck with dynamically assigning this value to an array as in ---
I = Selection.Cells.Count Dim ValArr(I)