I am trying to create a reference to a separate sheet using INDIRECT. I also want to check this for errors, so I preface the thing by using ISERROR.
H1 is a date value, formatted as "nn m.d". In this case, 42574 returns Sat 7.23
'Sat 7.23'.D2 equals 100
Let's say there's a tab named "Sat 7.23", and I would like to access cell D2. Using INDIRECT and converting the formatted date to text, I create this formula:
=INDIRECT("'" & TEXT(H1, "nn m.d") & "'.D2")
In other words, INDIRECT tells me to make the following reference:
='Sat 7.23'.D2
When the tab exists, this functions perfectly (it returns 100). But... what if the tab doesn't exist? INDIRECT returns #REF!, which is to be expected. So, I throw an ISERROR in front of it:
=ISERROR(INDIRECT("'" & TEXT(H1, "nn m.d") & "'.D2")
This returns nothing (or I guess FALSE), even though INDIRECT is generating a #REF! error and therefore should be TRUE. Should it not?
To go further:
=IF(ISERROR(INDIRECT("'" & TEXT(H1, "nn m.d") & "'.D2")),0,INDIRECT("'" & TEXT(H1, "nn m.d") & "'.D2"))
In this case, ISERROR is always true, so this IF always goes to it's "else" statement. Since the reference is invalid, the whole IF statement returns #REF!
I'm not sure what regional language uses nn to represent Sun - Sat in a format mask but ddd is used in an EN-US system and there is an exclamation mark between the worksheet and the cell address.
=IFERROR(INDIRECT("'"&TEXT(H1,"ddd m.d")&"'!D2"), 0)
This will return zero when copied to one cell above (#REF! on H0 as a cell address).
Some amends as proposed below should help you see through the issues:
Change the custom format of cell H1 which has the date value to "ddd m.dd" without the quotes. I see you have used "nn m.d" and it did not work for me.
Now, in cell I1 (adjacent to H1), let's try and pull the value of D2 from the sheet named 'Sat 7.23' by using the formula below:
=IF(ISERROR(INDIRECT("'" & TEXT(H1, "ddd m.d") & "'!D2")),"sheet doesn't exist, put your appropriate text message here",INDIRECT("'" & TEXT(H1, "ddd m.d") & "'!D2"))
To do a negative check, I recommend putting another date 'Sun 7.24" in H2 and use the same formula in I2 with a reference to the date in H2:
=IF(ISERROR(INDIRECT("'" & TEXT(H2, "ddd m.d") & "'!D2")),"sheet doesn't exist, put your appropriate text message here",INDIRECT("'" & TEXT(H2, "ddd m.d") & "'!D2"))
This is what it will look like in a completed worksheet:
I fixed similar problem by generating error
=IFERROR(QUERY(INDIRECT("'"&I2&"'!B3:E", TRUE), "select E where B = '"&I5&"'),"-")
Gives #REF!
=IFERROR(QUERY(INDIRECT("'"&I2&"'!B3:E", TRUE), "select E where B = '"&I5&"')*1,"-")
Works because multiplication of REF! with 1 gives an error
If you expect a number go with *1
If you expect string go with &''
Related
I'm trying to do Vlookup for target data in different rows.
But unfortunately, I can't find the way to do it.
Vlookup, Hlookup can't get the target data correctly.
Can you advise?
Resource Data Sheet
Result Output (expectation)
Matching ID number consist of these target data.
Dim A As String
Dim B As String
Dim C As String
Dim D As String
Dim E As String
Dim F As String
A = Application.WorksheetFunction.Index(iSheet.Range("G1"), Application.WorksheetFunction.Match(iSheet.Range("A11"), iSheet.Range("A3:A5"), 0))
B = Application.WorksheetFunction.Index(iSheet.Range("I1"), Application.WorksheetFunction.Match(iSheet.Range("A11"), iSheet.Range("A3:A5"), 0))
C = Application.WorksheetFunction.Index(iSheet.Range("K1"), Application.WorksheetFunction.Match(iSheet.Range("A11"), iSheet.Range("A3:A5"), 0))
'*** Error Thrown On Next Line (unable to get the index property of the worksheetfunction class)
D = Application.WorksheetFunction.Index(iSheet.Range("G1"), Application.WorksheetFunction.Match(iSheet.Range("A12"), iSheet.Range("A3:A5"), 0))
E = Application.WorksheetFunction.Index(iSheet.Range("I1"), Application.WorksheetFunction.Match(iSheet.Range("A12"), iSheet.Range("A3:A5"), 0))
F = Application.WorksheetFunction.Index(iSheet.Range("K1"), Application.WorksheetFunction.Match(iSheet.Range("A12"), iSheet.Range("A3:A5"), 0))
iSheet.Range("C7").Value = A & ", " & B & ", " & C
iSheet.Range("C8").Value = D & ", " & E & ", " & F
You're on the wrong track with VLookup() and HLookup().
Try using this: (on multiple lines for readability purposes)
=TEXTJOIN(",",
TRUE,
IF(NOT(ISBLANK(I3)),"POWER", ""),
IF(NOT(ISBLANK(K3)),"MB", ""),
IF(NOT(ISBLANK(M3)),"ANT", "")
)
Let me explain:
TextJoin() concatenates information, based on:
"," : the delimiter to be used
TRUE: how to handle empty cells
the arguments to be concatenated
IF(NOT(ISBLANK(I3)),"POWER", ""): if I3 is filled in, you need to put the word "POWER". If not, put an empty string.
Are you looking for something like this?
Right... so, this will technically do what you have asked for. But I suspect that it may not be exactly what you actually want. I am afraid your original question was quite unclear and I have had to make some guesses/assumptions.
=CONCAT(
IF(INDEX($H$3:$H$5,MATCH($A11,$A$3:$A$5,0))<>"",$G$1 & ", ",""),
IF(INDEX($J$3:$J$5,MATCH($A11,$A$3:$A$5,0))<>"",$I$1 & ", ",""),
IF(INDEX($L$3:$L$5,MATCH($A11,$A$3:$A$5,0))<>"",$K$1 & ", ","")
)
The CONCAT function just adds strings together, one after the other.
Within it, we have one formula for each of your merged column headers.
Please note: If you have lots of column headers, this probably won't be a viable solution. However, making a formula to handle a dynamic number of headers would be far more complex and I would advise re-organising your data to allow use of a simpler formula instead.
So, the inner formula:
IF(INDEX($H$3:$H$5,MATCH($A11,$A$3:$A$5,0))<>"",$G$1 & ", ",""),
Similar to how VLOOKUP would, the INDEX/MATCH is returning the POWER reference number for the specific ID Num. If there is no Ref No., it returns an empty string. If there is a Ref No., this is returned along with a trailing comma and space.
This is repeated for each of your Ref columns, and then CONCAT sticks all the results together. This does leave a trailing comma, however, that is relatively simple to remove if required, and I will leave that for you to work out.
As for returning the Ref No.'s themselves this can be done in the same way, but instead of returning the header, you repeat the INDEX/MATCH formula:
=CONCAT(
IF(INDEX($H$3:$H$5,MATCH($A11,$A$3:$A$5,0))<>"",INDEX($H$3:$H$5,MATCH($A11,$A$3:$A$5,0)) & ", ",""),
IF(INDEX($J$3:$J$5,MATCH($A11,$A$3:$A$5,0))<>"",INDEX($J$3:$J$5,MATCH($A11,$A$3:$A$5,0)) & ", ",""),
IF(INDEX($L$3:$L$5,MATCH($A11,$A$3:$A$5,0))<>"",INDEX($L$3:$L$5,MATCH($A11,$A$3:$A$5,0)) & ", ","")
)
Why Not VLOOKUP?
You may wonder why I used an INDEX/MATCH formula, rather than a VLOOKUP formula.
VLOOKUP would work, however, INDEX/MATCH is better in literally every way. To my knowledge, there is NEVER a situation where VLOOKUP would be a better option.
INDEX/MATCH is faster. When you have hundreds or thousands of formulas, you can often speed up a workbook drastically simply by swapping out all of the VLOOKUPs.
INDEX/MATCH is more versatile. It can work on rows or columns and your lookup range can be anywhere. You can even lookup a value in a 2D table using INDEX/MATCH/MATCH.
INDEX/MATCH is more stable. Moving or re-ordering columns doesn't break your formulas.
INDEX/MATCH is easier to use. It may look confusing if you are used to VLOOKUP, but once you understand it, it is actually easier to use because you can directly reference the ranges, rather than counting the number of columns accross.
I've got an Excel spreadsheet, with a Macro, that inserts a conditional formatting, like this:
Selection.FormatConditions.Add Type:=xlExpression, Formula1:="=UND($A3=""" & lastName & """; $B3=""" & firstName & """)"
As you can see, I've used the German formula for "AND" (i.e. "UND"), and obviously, this code doesn't work as soon as I use it on a French or English version of Excel.
Usually formulas are localized automatically, but how can I insert a formula during run-time that will work on ALL versions?
Ok, thanks for helping me with this, you've helped me crack this one.
It is indeed not possible to just use English. One can use English when operating on a formula, eg. by setting coding Range("A1").formula="AND(TRUE)", but this does not work with FormatConditions.
My solution is a function that writes a formula temporarily to a cell, reads it through the FormulaLocal property, and returns the localized formula, like so:
Function GetLocalizedFormula(formula As String)
' returns the English formula from the parameter in the local format
Dim temporary As String
temporary = Range("A1").formula
Range("A1").formula = formula
Dim result As String
result = Range("A1").FormulaLocal
Range("A1").formula = temporary
GetLocalizedFormula = result
End Function
The returned formula can be used on FormatConditions, which will be re-localized or un-localized when the document is later opened on a different-language version of Excel.
I just found a very elegant solution to the problem in a German Excel forum. This doesn't write to a dummy cell but rather uses a temporary named range. I used the original idea (credit to bst) to write a translating function for both directions.
Convert localized formula to English formula:
Public Function TranslateFormula_LocalToGeneric(ByVal iFormula As String) As String
Names.Add "temporaryFormula", RefersToLocal:=iFormula
TranslateFormula_LocalToGeneric = Names("temporaryFormula").RefersTo
Names("temporaryFormula").Delete
End Function
Convert English formula to localized formula:
Public Function TranslateFormula_GenericToLocal(ByVal iFormula As String) As String
Names.Add "temporaryFormula", RefersTo:=iFormula
TranslateFormula_GenericToLocal = Names("temporaryFormula").RefersToLocal
Names("temporaryFormula").Delete
End Function
This is very handy if you need to deal with formulas in conditional formatting, since these formulas are always stored as localized formulas (but you could need their generic version, e.g. to use Application.Evaluate(genericFormula)).
Store (a trivial version of) the formula in a (hidden) cell in your workbook.
Then when you open the workbook that formula will be translated automatically by excel for the user.
Now you just have to dissect this formula in your script (find the opening bracket "(" and take the past left of that:
Use something like:
strLocalizedFormula = Mid(strYourFormula, 2, InStr(1, strYourFormula, "(") - 2)
where strYourFormula will be a copy from the formula from your worksheet.
I hope this works as I only use an English environment.
Also from reading this:
http://vantedbits.blogspot.nl/2010/10/excel-vba-tip-translate-formulas.html
I am thinking you should (only) be able to use the english version of a cell formula from VBA.
Maybe try this (untested as I only have English version insatlled)
Write your international version of the formula to an out of the way cell using Range.Formula . Then read it back from Range.FormulaLocal, and write that string to the FormatConditions
I know this thread is ages old, and someone may have found an elegant solution, but I just had the same problem where I needed to apply conditional formatting without modifying the sheet, creating temporary cell contents or named ranges. All users use English language versions of Excel, so the functions used in the formulas are the same, but the regional settings vary by location, and therefore also the parameter separater; In Norwegian, it's ";" instead of ",", much like the rest of Europe, I guess.
For example, I needed to automatically create conditional formatting, using Excel formula for the following criterion:
.FormatConditions.Add xlExpression, Formula1:="=AND(ISNUMBER(B" & I & "),B" & I & ">=" & Ul1 & ")"
Where "Ul1" is a value defined in a previous step, and it's not important for the solution.
However, I needed to be able to run this on computers with both Norwegian and English settings
I and found a very short and simple solution from Andrew Pulsom here: https://www.mrexcel.com/board/threads/french-vba-vs-english-vba.729570/. He just made the parameter separator into a variable:
If Application.International(xlDecimalSeparator) = "," Then
Sep = ";"
Else
Sep = ","
End If
Cl1 = "=AND(ISNUMBER(B" & I & ")" & Sep & "B" & I & "<" & Ul1 & ")"
Worked like a charm for me :)
I know that this only solves part of the problem, but I assume that this could apply to many international companies which use English Office installations with local regional settings.
Thanks everyone! I found the post very useful.
My solution is a combination of others, I add it in case somebody finds it useful.
Dim tempform As String
Dim strlocalform1 As String
Dim strlocalform2 As String
' Get formula stored in WorksheetA Cell O1 =IFERROR(a,b)
tempform = Worksheets("Sheet").Range("O1").Formula
' Extract from the formula IFERROR statement in local language.
strlocalform1 = Mid(tempform, 2, InStr(1, tempform, "(") - 1)
' Extract from the formula separator , (comma) in local settings.
strlocalform2 = Mid(tempform, InStr(1, tempform, "a") + 1, 1)
' Add formula in local language to desired field.
pvt.CalculatedFields.Add Name:="NewField", Formula:="=" & strlocalform1 & "FORMULA" & strlocalform2 & ")"
Hope this helps!
Please refer to the link for more explanation: https://bettersolutions.com/csharp/excel-interop/locale-culture.htm
CultureInfo baseCulture = System.Threading.Thread.CurrentThread.CurrentCulture;
Thread.CurrentThread.CurrentCulture = new CultureInfo(xlapp.LanguageSettings.LanguageID(Office.MsoAppLanguageID.msoLanguageIDUI));
// do something
System.Threading.Thread.CurrentThread.CurrentCulture = baseCulture;
Not sure if my terminology is correct but the problem is that I have a vba module that I am using to analyze data(count unique values). The formula is fine and works when after I correct excels change.
VBA line to insert formula is
ws_MachineNumber.Range("D2").FormulaLocal = _
"=SUM(IF('Roh Daten_IA'!$B$2:$B$" & lastR_RDi & "= A2, 1/(COUNTIFS('Roh Daten_IA'!$B$2:$B$" & lastR_RDi & ",MachineNumber!A2,'Roh Daten_IA'!$G$2:$G$" & lastR_RDi & ",'Roh Daten_IA'!$G$2:$G$" & lastR_RDi & ")),0))"
Which I am expecting to show up in the cell as
=SUM(IF('Roh Daten_IA'!$B$2:$B$296= A2, 1/(COUNTIFS('Roh Daten_IA'!$B$2:$B$296,MachineNumber!A2,'Roh Daten_IA'!$G$2:$G$296,'Roh Daten_IA'!$G$2:$G$296)),0))
However for a reason unbeknownst to me excel keeps making it
=SUM(IF(#'Roh Daten_IA'!$B$2:$B$296= A2, 1/(COUNTIFS('Roh Daten_IA'!$B$2:$B$296,MachineNumber!A2,'Roh Daten_IA'!$G$2:$G$296,#'Roh Daten_IA'!$G$2:$G$296)),0))
not sure why it keeps referencing it that way. Prior to this I didn't have the abs ranges and figured that was the problem but the # symbol is somehow causing the formula to operate incorrectly and it gives a result of 0 for every occurrence regardless of what the correct evaluation should give.
Thank you
I'm trying to use Application.Evaluate method for evaluating a Sumif formula in which the criteria is ">="
Following is the line of code I'm trying to get an evaluation of
So I have Order Numbers 1 to 15 in Cell E1 to E15, and their Respective Amounts in Cell F1 to F15.
In J1 the user inputs his Order Number. Amount over and above that order number will be totaled and displayed using Sumif Function.
Now I want to find this answer using Application.Evaluate
MsgBox( Application.Evaluate("=SUMIF(E1:E15, ">=" & J1, F1:F15)"))
I get greeted with True or False Message Box.
Now I am guessing the inverted commas in Sumif Function ie. ">=" is causing this problem. Hence to fix this, I amended the function to
MsgBox( Application.Evaluate("=SUMIF(E1:E15, """">="""" & J1, F1:F15)"))
However now it returns 0, although there are values in it.
I would really appreciate if someone could help me understand a way around it
*Note: Please do not suggest to use any other function. I want to know it purely from Application.Evaluate perspective, as my further line of code depends on it. *
Thanks.
All quotes inside the string must be doubled:
">="
Should be
"">=""
Also:
Application.Evaluate
will work on the active sheet, thus if the wrong sheet is active the sumifs will be done on the wrong sheet since no sheet names are provided in the formula itself.
Use
Worksheets("Sheet1").Evaluate
Changing "Sheet1" to your sheet.
So in total:
MsgBox Worksheets("Sheet1").Evaluate("=SUMIF(E1:E15, "">="" & J1, F1:F15)")
I am trying to adapt the following formula (counting instances of values between 0 and 24):
=COUNTIFS(cancellations!AG2:AG408,">0",cancellations!AG2:AG408,"<24")
(formula evaluates to 75), to something like:
=COUNTIFS(cancellations!AG2:AG408,">0",cancellations!AG2:AG408,INDIRECT("" & "<" & B1*24 & ""))
but this evaluates to zero. (B1 = 1 in the above example.)
When I view the INDIRECT function inside the fx box it evaluates correctly. Not sure of what I am doing wrong.
When applied in a cell like so:
=INDIRECT("" & "<" & B1*24 & "")
It shows #REF!.
The INDIRECT function returns a reference to a range. You can use this function to create a reference that won't change if row or columns are inserted in the worksheet. Or, use it to create a reference from letters and numbers in other cells.
=COUNTIFS(cancellations!AG2:AG408,">0",cancellations!AG2:AG408,B1)
should work where B1 contains <24.
So, I read up the COUNTIFS() function in more detail and I found that the following works
=COUNTIFS(cancellations!AG2:AG408,">0",cancellations!AG2:AG408,"<"&B1*24)
Where:
B1=1