I have a conditional formatting from VBA code for a column which applies when there is a change of value.
The column is actually a Price column, So when the price value is entered,based on some formulas i apply my condition. It is working when the decimal separator is "." (DOT) (For Example: 1.323)
But when the decimal separator is "," in the system setting. I'm getting error when adding formula for conditional formatting ..
**
Code below..
**
Dim MyRange As Range
Set MyRange =Target.Address
formula_1 = "=IF(OR($AV" & Target.Cells.row & "=""No"",AND($AV" & Target.Cells.row & "=""Yes"")),IF(Y" & Target.Cells.row & "=AJ" & Target.Cells.row & ",FALSE,TRUE),FALSE)"
formula_2 = "=0"
formula_3 = "=IF($N" & Target.Cells.row & "=""EUR"",TRUE,FALSE)"
MyRange.Interior.Color = RGB(250, 191, 143)
MyRange.FormatConditions.Delete
MyRange.FormatConditions.Add Type:=xlExpression, Formula1:=formula_1
MyRange.FormatConditions.Add Type:=xlCellValue, Operator:=xlEqual, Formula1:=formula_2
MyRange.FormatConditions.Add Type:=xlExpression, Formula1:=formula_3
MyRange.FormatConditions(1).Interior.Color = RGB(255, 192, 0)
MyRange.FormatConditions(1).SetFirstPriority
MyRange.FormatConditions(1).StopIfTrue = False
MyRange.FormatConditions(2).StopIfTrue = True
MyRange.FormatConditions(2).NumberFormat = "##0.00"
MyRange.FormatConditions(3).StopIfTrue = True
MyRange.FormatConditions(3).NumberFormat = "[$EUR] #,##0.0000"
Error triggered in line
"MyRange.FormatConditions.Add Type:=xlExpression, Formula1:=formula_1" Error code: 5
I assume it's not about the decimal separator but about the list separator. This separator is, among others, used as separator for function parameters.
Regular (cell-) formulas are always translated into the US versions. If you work on a system with list separator = ";" and enter a formula like =OR(A1=1;B1=2) in a cell, in VBA you will see =OR(A1=1,B1=2). So far so good, all well known.
For some strange reasons, however, for formulas that are used in conditional formatting, the translation is not done, so you need to write the formula with the actual list separator character. You can get the current setting (it's not an Excel setting, it's a system setting) with Application.International(xlListSeparator). However, once set, the formula will work when you open that workbook on a system with different settings (so some kind of translation happens).
If you want to be flexible, do something like this:
Const formula_1 = "=OR(A1=1<SEP>B1=2)"
Dim localFormula_1 As String
localFormula_1 = replace(formula_1, "<SEP>", Application.International(xlListSeparator))
MyRange.FormatConditions.Add Type:=xlExpression, Formula1:=localFormula_1
Btw: You shouldn't have the decimal separator and the list separator set to the same character.
Related
I currently work for a company which uses a set house-style for its documents. This includes multi-levelled numbered headings built in to our Word template. I.e.
Heading 1
1.1 Heading 2
1.1.1 Heading 3
etc...
A large part of our current task involves adding in cross references to other parts in the document. This can be quite time consuming when the doc runs to several hundred pages with around 10 references on each page.
What I was wondering was if a macro could be set up to add a x-ref based on whatever is highlighted by the cursor. I.e. if you had a sentence that read "please refer to clause 3.2" you could highlight the "3.2" part, run the macro and have the x-ref linked to heading 3.2 be inserted.
Not sure if this is even possible but would be grateful for any advice.
This code will - conditionally - do what you want.
Sub InsertCrossRef()
Dim RefList As Variant
Dim LookUp As String
Dim Ref As String
Dim s As Integer, t As Integer
Dim i As Integer
On Error GoTo ErrExit
With Selection.Range
' discard leading blank spaces
Do While (Asc(.Text) = 32) And (.End > .Start)
.MoveStart wdCharacter
Loop
' discard trailing blank spaces, full stops and CRs
Do While ((Asc(Right(.Text, 1)) = 46) Or _
(Asc(Right(.Text, 1)) = 32) Or _
(Asc(Right(.Text, 1)) = 11) Or _
(Asc(Right(.Text, 1)) = 13)) And _
(.End > .Start)
.MoveEnd wdCharacter, -1
Loop
ErrExit:
If Len(.Text) = 0 Then
MsgBox "Please select a reference.", _
vbExclamation, "Invalid selection"
Exit Sub
End If
LookUp = .Text
End With
On Error GoTo 0
With ActiveDocument
' Use WdRefTypeHeading to retrieve Headings
RefList = .GetCrossReferenceItems(wdRefTypeNumberedItem)
For i = UBound(RefList) To 1 Step -1
Ref = Trim(RefList(i))
If InStr(1, Ref, LookUp, vbTextCompare) = 1 Then
s = InStr(2, Ref, " ")
t = InStr(2, Ref, Chr(9))
If (s = 0) Or (t = 0) Then
s = IIf(s > 0, s, t)
Else
s = IIf(s < t, s, t)
End If
If LookUp = Left(Ref, s - 1) Then Exit For
End If
Next i
If i Then
Selection.InsertCrossReference ReferenceType:="Numbered item", _
ReferenceKind:=wdNumberFullContext, _
ReferenceItem:=CStr(i), _
InsertAsHyperlink:=True, _
IncludePosition:=False, _
SeparateNumbers:=False, _
SeparatorString:=" "
Else
MsgBox "A cross reference to """ & LookUp & """ couldn't be set" & vbCr & _
"because a paragraph with that number couldn't" & vbCr & _
"be found in the document.", _
vbInformation, "Invalid cross reference"
End If
End With
End Sub
Here are the conditions:-
There are "Numbered Items" and "Headings" in a document. You asked for Headings. I did Numbered Items because I don't have that style on my PC. However, on my PC "Headings" are numbered items. If the code doesn't work on your documents, exchange wdRefTypeNumberedItem for wdRefTypeHeading at the marked line in the code.
I presumed a numbering format like "1" "1.1", "1.1.1". If you have anything different, perhaps "1." "1.1.", "1.1.1.", the code will need to be tweaked. The key points are that the code will look for either a space or a tab following the number. If it is followed by a period or closing bracket or a dash it won't work. Also, if you happen to select "1.2." (with the final full stop) in the text the code will ignore the full stop and look for a reference "1.2". Note that the code is insensitive to casual mistakes in the selection. It will remove any leading or trailing spaces as well as accidentally included carriage returns or paragraph marks - and full stops.
The code will replace the selection you make with its own (identical) text. This may cause existing formatting to change. In fact the inserted Reference Field takes the text from the target. I didn't quite figure out which format it applies, the target's or the one being replaced. I didn't deal with this problem, if it is one.
Please take a look at the properties of the cross reference the code inserts. You will see that InsertAsHyperlink is True. You can set it to False, if you prefer. IncludePosition is False. If you set this property to True you would see "above" or "below" added to the number the code replaces.
Yes it is totally possible...
I'll give you (an example of) the key elements:
' Check if a reference exists
If instr(lcase(selection.Sentences(1).Text), "refer to clause") then
' Figure out the reference number...
(see here: https://stackoverflow.com/questions/15369485/how-to-extract-groups-of-numbers-from-a-string-in-vba)
' Get a list of available references
refList = ActiveDocument.GetCrossReferenceItems(wdRefTypeNumberedItem)
' Add the reference
selection.InsertCrossReference(wdRefTypeNumberedItem ,wdNumberFullContext, xxxxxx...
Im trying to dynamically add a formula in an Excel sheet using VBA. Something really odd happens. When dynamically creating a formula by using "&" to link together the various components of a string, its gives a Run-time error '1004': Application-defined or object defined error.
This is working (but produces the wrong formula):
Worksheets("Sheet1").Cells(row, 7).Value = "=BDP(f" & row & ":Security Name)"
This is not working (produces the above mentioned error):
Worksheets("Sheet1").Cells(row, 7).Value = "=BDP(f" & row & ";Security Name)"
Note that the ONLY difference is the ":" in front of Security Name became a ";".
Any idea why this is producing this error?
Also, "Security Name" should also be between quotation marks, but when I double up the quotation marks, or use & Chr(34) I get the same error again.
What I am looking for is a formula to be added to the cell which looks like this =BDP(F4:"Security Name")
Your help is appreciated!
If you want a ; in the actual formula you need to use a , in the String you are using.
Also If you write this "" inside the string it will result in this in your string "
So this in you VBA:
.Formula = "=BDP(f" & Row & ",""Security Name"")"
will result in this in you actual cell:
=BDP(F5;"Security Name") (For me the Row was 5)
(You also can set the .Value property instead, but since you´re setting a formula i´d suggest using the .Formula)
Edit:
The method I used, mentioned in the comments:
Sub test()
BBCode = "XS0357495513 Corp"
Sheets(1).Range("A1").Formula = "=BDP(""" & BBCode & """,""Security Name"")"
'Range("A1") is like Cells(1, 1)
End Sub
If I try this -
Replace("±1°", "°", vbNullString)
Result is as expected.
However, I'm extracting data from another workbook, so it's stored in a variable. So, when I run -
Replace(ToleranceLabel, "°", vbNullString)
it never works. Then I tried with the 'Chr' function.
Replace(ToleranceLabel, Chr(176), vbNullString)
still didn't work.
I wanted to verify that the text I was getting the unicode symbol for decimal number 176 and not the unicode using the decimal number 186 for degree. I checked the decimal number and I get 176.
I tried different compare methods, vbTextCompare vs vbBinaryCompare. I still cannot get it to replace the text.
Using InStr to see if it can even find the symbol and it cannot find the degree symbol.
It must be something simple. I'm hoping any of you geniuses might be able to help. Thanks in advance.
You need to understand exactly what is in the cell. Click on the cell and run:
Sub WhatIsInThere()
Dim i As Long, msg As String
msg = Len(ActiveCell.Value) & vbCrLf
For i = 1 To Len(ActiveCell.Value)
msg = msg & vbCrLf & i & vbTab & Mid(ActiveCell.Value, i, 1) & vbTab & AscW(Mid(ActiveCell.Value, i, 1))
Next i
MsgBox msg
End Sub
For example:
Then you can decide how to process the cell.
I am trying to write a VLOOKUP in a cell as a string, with VBA. This means that I do not want the result to appear in the cell as a value, but I want the whole VLOOKUP expression instead (For this example : "VLOOKUP(C6,'[path_to_file.xlsm]OTD Table!$B:$F,4,0)"). The challenge is that the range argument of the VLOOKUP is a concatenation of a path (path_to_file.xlsm) that the user selects with a GetOpenFilename, and a string that specifies the tab in which the lookup table is located ("OTD Table!$B:$F,4,0").
The issue I am getting is very interesting :
When I print my expression in a Msgbox, the expression appears correctly. However, when I write it in a cell, the path mysteriously appears incorrectly.
Sub macro()
dim data_file_new as String
data_file_new = CStr(Application.GetOpenFilename(FileFilter:="Excel Workbooks (*.xls*),*.xls*", Title:="Select new data file")) ' The user selects the file
str_ = "=VLOOKUP(C6," & "'[" & data_file_new & "]OTD Table!$B:$F,4,0)" ' This will display the expression correctly
cells(1,10)="=VLOOKUP(C6," & "'[" & data_file_new & "]OTD Table!$B:$F,4,0)"' This will not display the same thing as in the messagebox above
end Sub
I hope one of you guys can make sens of this !
Because you're dropping a formula into a cell that you want to display as straight text, you have to be explicit with Excel and tag the text string to prevent interpreting it as a formula. The simplest way to do this is pre-pend the string with a single-quote "'".
Sub macro()
Dim data_file_new, str_ As String
str_ = "'=VLOOKUP(C6,'["
data_file_new = CStr(Application.GetOpenFilename(FileFilter:="Excel Workbooks (*.xls*),*.xls*", Title:="Select new data file")) ' The user selects the file
str_ = str_ & data_file_new & "]OTD Table!$B:$F,4,0)" ' This will display the expression correctly
ActiveSheet.Cells(1, 10).Value = str_
End Sub
Yeah either you'll need to set the string to add a single quote, or you'll need to change the numberformat of the cell to text (Cells(1,10).NumberFormat = "#")
Either of those should work.
I'm using this function to retrieve a value from a closed workbook. In this 8th line of this code, I don't understand why "A1" is being used. What exactly is happening in that entire 8th line? I'm confused by the xlR1C1 argument as well.
Private Function GetValue(path, file, sheet, ref)
Dim arg As String
If Right(path, 1) <> "\" Then path = path & "\"
If Dir(path & file) = "" Then
GetValue = "File Not Found"
Exit Function
End If
arg = "'" & path & "[" & file & "]" & sheet & "'!" & _
Range(ref).Range("A1").Address(, , xlR1C1)
GetValue = ExecuteExcel4Macro(arg)
End Function
Range().Range() Documentation here:
When applied to a Range object, the property is relative to the Range object. For example, if the selection is cell C3, then Selection.Range("B1") returns cell D3 because it’s relative to the Range object returned by the Selection property. On the other hand, the code ActiveSheet.Range("B1") always returns cell B1.
The code is using that second Range("A1") to ensure that if you have a ref range larger than one cell, it only returns the top left cell of that range. Also it would appear your other Sub called ExecuteExcel4Macro() requires an R1C1 type cell reference so the address is being converted into that type for passing the arg string into the Sub.
xlR1C1 is a reference style which is used to specify how formulas work. When using this style, your formulas will work and look very differently than you expect. The R1C1 specification, basically means the cells are referred to differently using row & column ordinals instead of letter names. For example, when using xlR1C1, you would access cell B2 by using =R2C2 (row2, column 2). Another Example, cell C10 could be referred to as =R10C3
As to whats happening on line 8... you are constructing a cell reference that looks like this: (Note that your cell reference will be different because it has a file path in it)
='[Myfilename.xlsx]Sheet1'!R1C1
You can use the debugger to view the string contained in the arg variable.
Adding Range("A1") to the code doesn't appear to do anything at all. Typing this into the immediate window results in some... unexpected results.
?Range("B3").Range("A1").Address
$B$3
Now, I would have expected that to return $A$1, but it seems that this part of the function will return the address of Range(ref).
Now, calling Range.Address with the ReferenceStyle argument would produce these results.
?Range("B3").Range("A1").Address(,,xlR1C1)
R3C2