I want to use following type of SUMPRODUCT formula in VBA:
=SUMPRODUCT(A1:A2,C1/B1:B2)
It works fine in excel, but when using it as a VBA function it gives an #VALUE! result:
Function Test(LineA As Range, LineB As Range, ValueC As Double)
Test = Application.WorksheetFunction.SumProduct(LineA, ValueC / LineB)
End Function
How can I write that formula with its values using vba?
Try using the Evaluate method...
Function Test(LineA As Range, LineB As Range, ValueC As Double)
Test = Evaluate("SUMPRODUCT(" & LineA.Address(external:=True) & "," & LineB.Address(external:=True) & "/" & ValueC)
End Function
Wrap it in evaluate
Converts a Microsoft Excel name to an object or a value.
Name... Variant .....A formula or the name of the object, using the naming
convention of Microsoft Excel. The length of the name must be less than or equal to 255 characters.
Application.Evaluate("=SUMPRODUCT(A1:A2,C1/B1:B2)")
Very similar to the above - but just in case it helps anyone, here is what I did with reference to sheet names and variable column lengths
Set a = Sheets("TheSheetName").Range([M10], [M10000].End(xlUp))
Set b = Sheets("TheSheetName").Range([L10], [L10000].End(xlUp))
c = Application.Evaluate("=SUMPRODUCT(" & a.Address & ",1/" & b.Address & ")")
Related
I have an excel file with four columns: name, surname, address, area.
There are a lot of rows.
Is there a way to concatenate all the values of every single row in a variable, using vba?
I need a variable that should contain something like this:
(name1, surname1, address1, area1); (name2, surname2, address2, area2); (name3, surname3, address3, area3)...
If you have the following data in your worksheet
Then the following code will read the data into an array …
Option Explicit
Public Sub Example()
Dim RangeData() As Variant ' declare an array
RangeData = Range("A1:D5").Value2 ' read data into array
End Sub
… with the following structure:
Alternatively you can do something like
Public Sub Example()
Dim DataRange As Range
Set DataRange = Range("A2:D5")
Dim RetVal As String
Dim Row As Range
For Each Row In DataRange.Rows
RetVal = RetVal & "(" & Join(Application.Transpose(Application.Transpose(Row.Value2)), ",") & "); "
Next Row
Debug.Print RetVal
End Sub
To get this output:
(name1, surname1, address1, area1); (name2, surname2, address2, area2); (name3, surname3, address3, area3); (name4, surname4, address4, area4);
.. is there a way to write the result like a sort of list that shows all the values of the cells of the range?
Yes, there is. In addition to PEH's valid answers and disposing of Excel version MS365 you might also use
Dim s as String
s = Evaluate("ArrayToText(A2:D5, 1)") ' arg. value 1 representing strict format
resulting in the following output string:
{"name1","surname1","address1","area1";"name2","surname2","address2","area2";"name3","surname3","address3","area3";"name4","surname4","address4","area4"}
Syntax
ARRAYTOTEXT(array, [format])
The ARRAYTOTEXT function returns an array of text values from any specified range. It passes text values unchanged, and converts non-text values to text.
The format argument has two values, 0 (concise default format) and 1 (strict format to be used here to distinguish different rows, too):
Strict format, i.e. value 1 includes escape characters and row delimiters. Generates a string that can be parsed when entered into the formula bar. Encapsulates returned strings in quotes except for Booleans, Numbers and Errors.
Thank you for your answers, suggestions, ideas and hints. I am sorry if my question was not so clear, all the solutions you added were perfect and extremely elegant.
In the end I found a way - a dumber way in comparison to all the things you wrote - and I solved with a for statement.
I did like this:
totRow = ActiveSheet.UsedRange.Rows.Count
For i = 1 To totRow
name = Cells(i, 1)
surname = Cells(i, 2)
address = Cells(i, 3)
area = Cells(i, 4)
Example = Example & "(" & name & ", " & surname & ", " & address & ", " & area & "); "
Next i
Range("E1").Value = Example
It works (it does what I wanted to do), but I noticed a little limit: if the rows are a lot I can't keep the whole text in the variable.
I'm trying to find the ID for each value in a cell. I tried using a VLOOKUP but it fails when a cell has more than one value.
In this scenario, B2 would be updated to 4,1
TEXTJOIN with an IF:
=TEXTJOIN(",",TRUE,IF(ISNUMBER(SEARCH(","&SUBSTITUTE('Item Details'!$A$2:$A$6," ","")&",",","&SUBSTITUTE(A2," ","")&",")),'Item Details'!$B$2:$B$6,""))
This will order the output on the lookup table order
Another option is using XLOOKUP:
=TEXTJOIN(",",TRUE,XLOOKUP(FILTERXML("<a><b>"&SUBSTITUTE(A2,",","</b><b>")&"</b></a>","//b"),'Item Details'!A:A,'Item Details'!B:B,"",0))
with Office 365 which will order by the input.
Give this small User Defined Function a try:
Public Function zlookup(v As Variant, rng As Range) As String
Dim a, arr, r As Range
arr = Split(v, ",")
For Each a In arr
Set r = rng.Columns(1).Find(What:=a)
zlookup = zlookup & "," & r.Offset(0, 1).Value
Next a
zlookup = Mid(zlookup, 2)
End Function
I am trying to count the number of unique values in a table column. I have set the range as the relevant column in the table. In defining the number of unique values to count I am getting the following error:
Required_Rows = WorksheetFunction.SumProduct(1 / WorksheetFunction.CountIf(Range(Rng), Range(Rng)))
You won't be able to use Sumproduct and SumIf in that manner. Try using the Evaluate method instead...
Dim Required_Rows As Variant 'declared as Variant in case Evaluate returns error
Required_Rows = Evaluate("SUMPRODUCT(1/COUNTIF(A1:A10,A1:A10))")
If Not IsError(Required_Rows) Then
'do something
Else
'do something else
End If
Note that Evaluate has a 255 character limit.
EDIT
With the Range object you've defined (ie. Rng), try...
Required_Rows = Evaluate("SUMPRODUCT(1/COUNTIF(" & Rng.Address(external:=True) & "," & Rng.Address(external:=True) & "))")
Hope this helps!
I have a sample data (1,2,3,4) on A2:D2 columns and on F1, I have (1,3), and on G1 (2,3,4).
I was suggested to use this formula
=INDEX($A2:$D2,AGGREGATE(15,6,ROW($A2:$D2)/ISNUMBER(SEARCH(TEXT($A2:$D2,"000,"),F$1&",")),1))
on F2, and G2 which is supposed to give the matching values on F2 and G2 respectively. Since both values (1,3) match, the result should be (1,3) on F2, and (2,3,4) on G2.
So basically this formula is supposed to work like index/match formula but instead of single values, it works on comma separated 2 or 3 values.
When I try to use the formula I keep getting #NUM! error. Can I get a little help to make this formula work, please?
Thanks.
Note: I am open to alternative solutions, but if it requires VBA, it has to be with a user defined formula. Without UDF, it is not useful for me.
A UDF should look like this
Option Explicit
Function MultFind(r As Range, s As String) As String
Dim c As Range
Dim result As String
For Each c In r
If InStr("," & s & ",", "," & c & ",") <> 0 Then result = result & c & ","
Next c
If Len(result) > 0 Then result = Left(result, Len(result) - 1)
MultFind = result
End Function
Called as
=MultFind($A2:$D2,F1)
Edit
Here it is with optional parameter for delimiter:
Option Explicit
Function MultFind(r As Range, s As String, Optional delimiter As String = ",") As String
Dim c As Range
Dim result As String
' Check each cell in range against search string
For Each c In r
If InStr(delimiter & s & delimiter, delimiter & c & delimiter) <> 0 Then result = result & c & delimiter
Next c
' Delimiter may be more than one character
If Len(result) > 0 Then result = Left(result, Len(result) - Len(delimiter))
MultFind = result
End Function
I'm trying to convert a list of names, each in a seperate cell, into a list with # before each name commas afterwards and combined into a single cell. What type of macro would I use for that. So:
Help
Me
Please
Thank
You
into (single cell):
#help, #me, #please, #thank, #you
Thanks
Try this code:
function convertNames(startRow as long,endRow as long,column as long) as string
dim result as string
for c=startRow to endRow
result=result & "#" & Cells(c,column) & ", "
next
result=left(result,len(result)-2)
convertNames=result
end function
You would call this function in the cell where you want to display the results as:
=convertNames(5,12,2)
substituting in the start row, end row, and column index that you need.
Try this function:
Function ConvertNames(List As Range) As String
Dim C As Range
For Each C In List
ConvertNames = ConvertNames & "#" & C.Value2 & ", "
Next C
ConvertNames = Left(ConvertNames, Len(ConvertNames) - 2)
End Function
It is inspired by sigil's answer, but this one works with a range, and allows Excel to manage the references to cells. Sigil's function should be volatile and would slow down large files.
You need to add a module to the project and put this function in the module. Then you can use it by typing =ConvertNames(A1:A5) on the cell that uses it.