comparing the content of two cells in VBA - excel

I need to compare the content of two cells in macro
RC1=2.0
RC2=2
I am using if(RC1=RC2,"''","x") for this which prints x for the above input but 2.0 and 2 are same, I need it to be '' in this case, please suggest

Your failing 'code' suggests you're merely using a formula:
if(RC1=RC2,"''","x")
If you are happy using a formula to test them, you could use:
IF(VALUE(RC1)=VALUE(RC2),"''","x")
Be aware though, a blank cell has a VALUE of 0 (zero) so an empty cell would match a cell containing 0.00

First and foremost
You are trying to compare two different data types, let's say consider that one is an integer, which does not have decimal values, and the other one a double, with a decimal.
I would suggest you to have a better look at data types in VBA.
Hence we will need to convert the types to one that is the same for both cells with CDbl() to convert them to double. To put it simply, since integers are a simpler form of doubles we will use the more complete type of both.
Code to compare the types
Sub COMPARING_TYPES()
Dim a As Double, b As Double
' Let's assume the both values are numeric
a = CDbl(Cells(1, 1))
b = CDbl(Cells(2, 1))
If a = b Then
' Other code to execute when the values are matching
End If
End Sub
This is all considering you want to compare the numbers in a VBA code.

Related

Excel custom formatting numbers (0 especially)

Based on this comment fom SoftTimur I did some testing on formatting and came across the following problem:
If I put =SEQUENCE(4,,-2) in A1 and custom format the range with 0;-0; it'll show the values as I intended.
If I sum the spill range in A6 using =SUM(A1#) it shows the correct value (-2).
If I put the following in B1: =TEXT(SEQUENCE(4,,-2),"0;-0;") I expected the same result as above. However Excel sees it as text (by default aligned to the left).
If I sum the spill range in B6 using =SUM(B1#) it shows the result 0 while if I sum B1+B2 I get a correct result.
Question 1: What's the explanation of the incorrect sum result in B6 versus the correct one in B7?
Question 2: Is there a different way to display a zero as blank, but keep the ability to calculate the range containing that value?
Question 1:
The TEXT function returns text and computers can't add text strings together. They can only add numbers together.
Excel will sometimes automatically perform type conversions to allow formulas to deliver what Excel guesses as being the expected result. In this case, it is sometimes turning text into numbers before adding them together. This can make like easier for users but the inconsistency can easily lead to errors.
Say A1 and A2 are formatted as text and contain the text character "1". Excel will do an implicit type conversion for operators (+-*/):
=A1 + A2
It won't do conversion for ranges in functions:
=SUM(A1:A2)
=SUM(A1,A2)
When taking in a range, the SUM function will ignore all text, so that it can still sum the numbers in the range without throwing an error. If all cells in the range contain text it will return 0.
However if you tried to use the addition operator on two cells containing text that can't be converted to numbers, it will throw an error.
Note that when you put "A1 + A2" inside the SUM function, excel first evaluates the addition operation (as this is a single input within the function which must be evaluated first), so it converts A1 and A2 to numbers at this point to create a single numeric result, and then the SUM function takes just the single numeric value as input and returns it again as the total.
If you use SUM with two separate inputs, as =SUM(A1,A2), it doesn't convert either input to a number first.
Question 2:
To get the correct result using the SUM function over the range, you can modify the original sequence formula so that it is delivering numeric values. This can be done in various ways:
1 - Convert the text back to a number by multiplying by 1 (forcing another implicit type conversion), handling the error generated for the nullstring which can't be converted to a number:
=IFERROR(TEXT(SEQUENCE(4,,-2),"0;-0;")*1,"")
2 - Test for 0 using an IF statement and return the null string:
=IF(SEQUENCE(4,,-2)<>0,SEQUENCE(4,,-2),"")
3 - Invert the sequence twice, which throws an error only when it is equal to 0:
=IFERROR(1/(1/SEQUENCE(4,,-2)),"")
OR you can modify the SUM formula to convert the range to numbers on input:
=SUM(IFERROR(B1#*1,0))
However this approach requires you to modify all formulas that look at the original sequence. If the original sequence is intended to be used as numbers (as it is in this case), it is better to have it be generated as numbers in the first place.

Separate specific values from a cell value in excel?

I have a excel sheet with values shown as below:
I'm trying to separate the numeric values given in the first column to columns a,b and c so that the final output should look like
Now, I can get the value in the a column using the formula
=LEFT(A1,FIND("x",A1)-1)
But I'm struggling to get the other values (column b and c)
Any help will be appreciated :)
Another formula option
Assume data housed in A2:A5
To find "a", in B2 formula copied down :
=LEFT(A2,FIND("x",A2)-1)
To find "b", in C2 formula copied down :
=LOOKUP(9^9,0+MID($A2,FIND("(",$A2)+1,ROW($1:$9)))
To find "c", in D2 formula copied down :
=LOOKUP(9^9,0+MID($A2,FIND("x",$A2,FIND("(",A2))+1,ROW($1:$9)))
You could probably cook up something to do this using Excel's built-in functionalities, but it'd be long, difficult to grasp and prone to errors if the input format ever changes. Instead, I would probably use VBA to create a simple custom formula that can extract the numbers using a regular expression.
Press Alt + F11 to open the Developer Tools
Go to Tools > References and check Microsoft VBScript Regular Expression 5.5
Choose Insert > Module
Enter the following code:
Function FINDNUMBERS(sInput As String, Optional iIndex As Integer = 0) As String
Dim regEx As New RegExp
Dim strPattern As String
strPattern = "[0-9]+"
With regEx
.Global = True
.Pattern = strPattern
End With
Set Matches = regEx.Execute(sInput)
FINDNUMBERS = Matches(iIndex)
End Function
You can then call the function in your worksheet like this:
=FINDNUMBERS(A1;0)
Where the first parameter is the cell you'd like to get the numbers from, and the second parameter is the position of the number you would like. Enter 0 for the first number found, 1 for the second number, etc.
To find b, try
=--MID(A2,FIND("(",A2)+1,FIND("x",SUBSTITUTE(A2,"x(","[["))-FIND("(",A2)-1)
The logic is to use FIND function to find the position of the second x by replacing/substituting the first x with another symbol which is [ in my example, then you will know the ending point of value b.
Use the FIND function again to find the position of ( then you will know the starting point of value b, the difference between the two will be the length of value b,
then you can use MID function to return value b from the string. The starting point of the MID function is determined by the position of (.
Double minus signs -- in front of the formula is used to turn the value into a numeric value. It is working in the same way as NUMBERVALUE function. This is optional if you do not need to show the result as number.
To find c, try
=--MID(A2,FIND("x",SUBSTITUTE(A2,"x(","[["))+1,FIND(" ",A2)-FIND("x",SUBSTITUTE(A2,"x(","[[")))
The logic is similar to the previous one. Use FIND function to find the position of the space " " and find the position of the second x, the difference of the two positions is the length of value c,
then use MID function to return value c from the string. The starting point of the MID function is determined by the position of the second x.
Replace A2 to suit your case.

Excel Average - Counting the number of variables

I'm using the average function excel to get the average of a series of hotel prices in various European cities.
=average(21,42,63,84,105)
I'd like to be able to count the number of variables in each average function (for example, in the above example there's 5). The data is scrubbed from websites which is why it's in the format above rather than placed into separate cells.
Is there a way to do this without taking out the variables, putting them into a cell and then separating out the cells using Text to Columns?
Thanks!
You can turn your equation into a string using FORMULATEXT() and then deduce the number of values being averaged by counting the instances of commas in your string (which relates to your final answer by Total Commas + 1 = Total Values
The first portion of the equation counts the character length with commas. The second portion counts the character length without commas. The difference is simply the number of commas present. We then add one since your last value is not followed by a comma
=LEN(FORMULATEXT(A1))-LEN(SUBSTITUTE(FORMULATEXT(A1),",",""))+1
Assumes your average formula is in cell A1
I am a fan of using UDFs, so here's an alternate method.
You can create a custom User Defined Function (UDF) for this. Just split the function by the deliminator and get your number from the UBOUND().
Public function getNumArgs(inputRng as range) as long
'First check that you are actually looking at a formula
If Left(inputRng.Formula, 1) <> "=" Then
getNumArgs = False
exit function
End If
getnumargs = ubound(split(inputrng.formula, ",")) + 1
end function
You will add 1 because VBA uses Base 0.
You will then use your custom UDF the same way you do any other worksheet formula:
=getNumArgs(A1)
The largest benefit of using a UDF is that you do not have to remember a complex formula.

Return list of integers between two cells

I am hoping for a formula or vba function to add a list of values to a cell, given an upper and lower bound. For example, refer to columns A and B in the image below:
I would like to generate a formula or function that returns a list of both the upper and lower bounds, as well as, all the values in between. See column C in the example above for the desired output.
The issue is the the range between the two cells vary (the output in column C will not always contain 4 integers - it could be more or less).
Does anyone know what the best way to accomplish this task would be? I really appreciate any and all help.
If you are on Office365 or Excel 2016 and higher, you can use the TextJoin function like so (entered as an array formula with Ctrl+Shift+Enter):
=TEXTJOIN(",",TRUE,ROW(INDEX(A:A,A2):INDEX(A:A,B2)))
Otherwise you'll need to use VBA to create a UDF as shown in Gary's Student's answer.
With VBA:
Public Function Seq(n1 As Long, n2 As Long) As String
For i = n1 To n2
Seq = Seq & "," & i
Next i
Seq = Mid(Seq, 2)
End Function
EDIT#1:
In the most recent version of Excel, this array formula:
=TEXTJOIN(",",TRUE,ROW(1:5))
will return a sequence of values:
Perhaps a really clever person can tell us how to replace the 1:5 with cell references.

How do I return the intersecting value from 2 partial match lookups? Index/Match

I have two tables in an excel worksheet. I'm trying to gather product info from data on another table in the same workbook. The first table is the product data feed I'm building with the product part numbers. Those part numbers include the variables of the product (in this case the length and the width). On the other sheet, I have partial part numbers in the header column and the rough dimensions in the header row. The intersection gives the final dimensions which is the data I'm trying to gather on sheet 1. I've been trying to use and Index/Match formula to solve the problem, but since there are only partial part numbers on the 2nd sheet the lookup is inconclusive. I know the lookup value supports wildcards, but it seems I would need some sort of wildcard search within the lookup array instead.
Example product names on sheet 1 column A "EXP81285-150-11 x 14-Flat"
Example of product names on sheet 2 column A "EXP81285-150"
Example of rough dimensions on sheet 2 row 1 "11 x 14"
Here is what I have so far:
=INDEX('sheet 2'!$A$1:$L$87,MATCH($A3,'sheet 2'!$A:$A,0),MATCH($A3,'sheet 2'!$1:$1,0))
Sheet 1
Sheet 2
Any help is greatly appreciated!
Asuming its always like string1-string2-unused and string2 and unused doesn't contain "-" you can get the first string with:
*updated due to misunderstanding*
=MID(A3,4,FIND("|",SUBSTITUTE(A3,"-","|",LEN(A3)-LEN(SUBSTITUTE(A3,"-",""))-1))-4)
While the string2 one is a hell of a formula:
=MID(A3,FIND("|",SUBSTITUTE(A3,"-","|",LEN(A3)-LEN(SUBSTITUTE(A3,"-",""))-1))+1,FIND("|",SUBSTITUTE(A3,"-","|",LEN(A3)-LEN(SUBSTITUTE(A3,"-",""))))-FIND("|",SUBSTITUTE(A3,"-","|",LEN(A3)-LEN(SUBSTITUTE(A3,"-",""))-1))-1)
Asuming the last part is allways in Q3 then:
=MID(SUBSTITUTE($A3,"-"&$Q3,""),FIND("|",SUBSTITUTE($A3,"-","|",LEN($A3)-LEN(SUBSTITUTE($A3,"-",""))-1))+1,99)
You may also use an arrayformula for the second part like:
=MID(SUBSTITUTE($A3,"-"&$Q3,""),LARGE((MID($A3,ROW($1:$99),1)="-")*ROW($1:$99),2)+1,99)
This is an array formula and must be confirmed with Ctrl+Shift+Enter.
(the second formula may work faster)
You could use array formulas in a reverse Match however... having lots of entrys even one formula will slow down the calculation by ~2-5 seconds.
You better use VBA like:
(in Module)
Public Function MATCH2(str As String, rng As Range) As Long
Dim i As Long, var1 As Variant
i = 0
For Each var1 In rng
i = i + 1
If InStr(str, var1.Value) Then MATCH2 = i: Exit Function
Next
End Function
And then use your formula as followed:
=INDEX('sheet 2'!$A$1:$L$87,MATCH2($A3,'sheet 2'!$A:$A,0),MATCH2($A3,'sheet 2'!$1:$1,0))
EDIT 2015-11-19
OK... some small problems:
some sizes doesnt exist (like 6 x 9)
size 7 x 12 was bugged (a space at the end > fixed it)
the function needs to be in a module (also fixed that)
also some items doesn't exist like 600823-002
a misunderstanding regarding the formulas (doesn't matter at the VBA-version) > all asumed the A:A-searchstring starts at the 1st character (but it is the 4th, no EXP)
Also there will be an error at each "header" (the ones without the * x * but that should be ok)
You can download the updated workbook here
If you still have questions, just ask :)
Here is one using vlookup:
=VLOOKUP(LEFT(A2,FIND("-",A2,10)-1),Sheet2!A:L,MATCH(MID(A2,FIND("-",A2,10)+1,(FIND("-",A2,15))-(FIND("-",A2,10)+1)),Sheet2!A1:L1,0),FALSE)
But I agree with Dirk, This could be done faster and probably more accurate with vba.
Edit, I realized that my dictating of 10 and 15 in the formula would not work, I have fixed it, but it is based on the part number has 1 and only 1 "-" in the part name. Warning it is quite long.
=VLOOKUP(LEFT(A2,FIND("-",A2,FIND("-",A2,1)+1)-1),Sheet2!A:L,MATCH(MID(A2,FIND("-",A2,FIND("-",A2,1)+1)+1,(FIND("-",A2,FIND("-",A2,FIND("-",A2,FIND("-",A2,1)+1))+1))-(FIND("-",A2,FIND("-",A2,1)+1)+1)),Sheet2!A1:L1,0),FALSE)

Resources