Simple Replace function not working with degree symbol - vba

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.

Related

How to use VBA .Formula with row number incrementation? [duplicate]

I want to insert an if statement in a cell through vba which includes double quotes.
Here is my code:
Worksheets("Sheet1").Range("A1").Value = "=IF(Sheet1!B1=0,"",Sheet1!B1)"
Due to double quotes I am having issues with inserting the string. How do I handle double quotes?
I find the easiest way is to double up on the quotes to handle a quote.
Worksheets("Sheet1").Range("A1").Formula = "IF(Sheet1!A1=0,"""",Sheet1!A1)"
Some people like to use CHR(34)*:
Worksheets("Sheet1").Range("A1").Formula = "IF(Sheet1!A1=0," & CHR(34) & CHR(34) & ",Sheet1!A1)"
*Note: CHAR() is used as an Excel cell formula, e.g. writing "=CHAR(34)" in a cell, but for VBA code you use the CHR() function.
Another work-around is to construct a string with a temporary substitute character. Then you can use REPLACE to change each temp character to the double quote. I use tilde as the temporary substitute character.
Here is an example from a project I have been working on. This is a little utility routine to repair a very complicated formula if/when the cell gets stepped on accidentally. It is a difficult formula to enter into a cell, but this little utility fixes it instantly.
Sub RepairFormula()
Dim FormulaString As String
FormulaString = "=MID(CELL(~filename~,$A$1),FIND(~[~,CELL(~filename~,$A$1))+1,FIND(~]~, CELL(~filename~,$A$1))-FIND(~[~,CELL(~filename~,$A$1))-1)"
FormulaString = Replace(FormulaString, Chr(126), Chr(34)) 'this replaces every instance of the tilde with a double quote.
Range("WorkbookFileName").Formula = FormulaString
This is really just a simple programming trick, but it makes entering the formula in your VBA code pretty easy.
All double quotes inside double quotes which suround the string must be changed doubled. As example I had one of json file strings : "delivery": "Standard",
In Vba Editor I changed it into """delivery"": ""Standard""," and everythig works correctly. If you have to insert a lot of similar strings, my proposal first, insert them all between "" , then with VBA editor replace " inside into "". If you will do mistake, VBA editor shows this line in red and you will correct this error.
I have written a small routine which copies formula from a cell to clipboard which one can easily paste in Visual Basic Editor.
Public Sub CopyExcelFormulaInVBAFormat()
Dim strFormula As String
Dim objDataObj As Object
'\Check that single cell is selected!
If Selection.Cells.Count > 1 Then
MsgBox "Select single cell only!", vbCritical
Exit Sub
End If
'Check if we are not on a blank cell!
If Len(ActiveCell.Formula) = 0 Then
MsgBox "No Formula To Copy!", vbCritical
Exit Sub
End If
'Add quotes as required in VBE
strFormula = Chr(34) & Replace(ActiveCell.Formula, Chr(34), Chr(34) & Chr(34)) & Chr(34)
'This is ClsID of MSFORMS Data Object
Set objDataObj = CreateObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
objDataObj.SetText strFormula, 1
objDataObj.PutInClipboard
MsgBox "VBA Format formula copied to Clipboard!", vbInformation
Set objDataObj = Nothing
End Sub
It is originally posted on Chandoo.org forums' Vault Section.
In case the comment by gicalle ever dies:
I prefer creating a global variable:
Public Const vbDoubleQuote As String = """" 'represents 1 double quote (")
Public Const vbSingleQuote As String = "'" 'represents 1 single quote (')
and using it like so:
Shell "explorer.exe " & vbDoubleQuote & sPath & vbDoubleQuote, vbNormalFocus

.range.Formula of a Concatenate() to a server path

I'm trying to fill in a cell with the =CONCATENATE() formula which gave me errors,
strformula = "=CONCATENATE("\\SERVER\PATH\DIR\";$A5;".pdf")"
I tried to fix this with the incode concatenate & method
but I somehow have an error with the Sub
"Method or data member not found"
Any ideas?
Sub Fillcells()
Dim pthstr As String
Dim strformula As String
With sheetNAME
pthstr = "\\SERVER\PATH\DIR"
strformula = "=CONCATENATE(" & pthstr & ";$A5;\" \ .pdf \ ")"
.Range("N5:N5").Formula = strformula
'.Range("N5", "N" & GetLastRow(sheetNAME)).FillDown
End With
End Sub
You have a couple issues with how you're handling your string text. I think this will work as a formula for you or at least allow you to avoid errors.
strformula = "=CONCATENATE(""" & pthstr & """,$A5,""\ .pdf \ "")"
Note that for quotes within the formula, you have to use 2x double quotes. And if this is the end of your quote, you;ll have THREE sets, followed by an & sign.
However, I'm not sure concatenate is really what you want. You might just consider typing ="\\SERVER\PATH\DIR\"&A5&".PDF"
There's almost no reason one should ever use Concatenate when compared to alternative functions such as textjoin or Concat. This article explains. Good luck.

What does a hyperlink range.start and range.end refer to?

I'm trying to manipulate some text from a MS Word document that includes hyperlinks. However, I'm tripping up at understanding exactly what Range.Start and Range.End are returning.
I banged a few random words into an empty document, and added some hyperlinks. Then wrote the following macro...
Sub ExtractHyperlinks()
Dim rHyperlink As Range
Dim rEverything As Range
Dim wdHyperlink As Hyperlink
For Each wdHyperlink In ActiveDocument.Hyperlinks
Set rHyperlink = wdHyperlink.Range
Set rEverything = ActiveDocument.Range
rEverything.TextRetrievalMode.IncludeFieldCodes = True
Debug.Print "#" & Mid(rEverything.Text, rHyperlink.Start, rHyperlink.End - rHyperlink.Start) & "#" & vbCrLf
Next
End Sub
However, the output between the #s does not quite match up with the hyperlinks, and is more than a character or two out. So if the .Start and .End do not return char positions, what do they return?
This is a bit of a simplification but it's because rEverything counts everything before the hyperlink, then all the characters in the hyperlink field code (including 1 character for each of the opening and closing field code braces), then all the characters in the hyperlink field result, then all the characters after the field.
However, the character count in the range (e.g. rEverything.Characters.Count or len(rEverything)) only includes the field result if TextRetrievalMode.IncludeFieldCodes is set to False and only includes the field code if TextRetrievalMode.IncludeFieldCodes is set to True.
So the character count is always smaller than the range.End-range.Start.
In this case if you change your Debug expression to something like
Debug.Print "#" & Mid(rEverything.Text, rHyperlink.Start, rHyperlink.End - rHyperlink.Start - (rEverything.End - rEverything.Start - 1 - Len(rEverything))) & "#" & vbCrLf
you may see results more along the lines you expect.
Another way to visualise what is going on is as follows:
Create a very short document with a piece of text followed by a short hyperlink field with short result, followed by a piece of text. Put the following code in a module:
Sub Select1()
Dim i as long
With ActiveDocument
For i = .Range.Start to .Range.End
.Range(i,i).Select
Next
End With
End Sub
Insert a breakpoint on the "Next" line.
Then run the code once with the field codes displayed and once with the field results displayed. You should see the progress of the selection "pause" either at the beginning or the end of the field, as the Select keeps "selecting" something that you cannot actually see.
Range.Start returns the character position from the beginning of the document to the start of the range; Range.End to the end of the range.
BUT everything visible as characters are not the only things that get counted, and therein lies the problem.
Examples of "hidden" things that are counted, but not visible:
"control characters" associated with content controls
"control characters" associated with fields (which also means hyperlinks), which can be seen if field result is toggled to field code display using Alt+F9
table structures (ANSI 07 and ANSI 13)
text with the font formatting "hidden"
For this reason, using Range.Start and Range.End to get a "real" position in the document is neither reliable nor recommended. The properties are useful, for example, to set the position of one range relative to the position of another.
You can get a somewhat more accurate result using the Range.TextRetrievalMode boolean properties IncludeHiddenText and IncludeFieldCodes. But these don't affect the structural elements involved with content controls and tables.
Thank you both so much for pointing out this approach was doomed but that I could still use .Start/.End for relative positions. What I was ultimately trying to do was turn a passed paragraph into HTML, with the hyperlinks.
I'll post what worked here in case anyone else has a use for it.
Function ExtractHyperlinks(rParagraph As Range) As String
Dim rHyperlink As Range
Dim wdHyperlink As Hyperlink
Dim iCaretHold As Integer, iCaretMove As Integer, rCaret As Range
Dim s As String
iCaretHold = 1
iCaretMove = 1
For Each wdHyperlink In rParagraph.Hyperlinks
Set rHyperlink = wdHyperlink.Range
Do
Set rCaret = ActiveDocument.Range(rParagraph.Characters(iCaretMove).Start, rParagraph.Characters(iCaretMove).End)
If RangeContains(rHyperlink, rCaret) Then
s = s & Mid(rParagraph.Text, iCaretHold, iCaretMove - iCaretHold) & "" & IIf(wdHyperlink.TextToDisplay <> "", wdHyperlink.TextToDisplay, wdHyperlink.Address) & ""
iCaretHold = iCaretMove + Len(wdHyperlink.TextToDisplay)
iCaretMove = iCaretHold
Exit Do
Else
iCaretMove = iCaretMove + 1
End If
Loop Until iCaretMove > Len(rParagraph.Text)
Next
If iCaretMove < Len(rParagraph.Text) Then
s = s & Mid(rParagraph.Text, iCaretMove)
End If
ExtractHyperlinks = "<p>" & s & "</p>"
End Function
Function RangeContains(rParent As Range, rChild As Range) As Boolean
If rChild.Start >= rParent.Start And rChild.End <= rParent.End Then
RangeContains = True
Else
RangeContains = False
End If
End Function

Run-time error VBA upon changing ":" to ";"

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

vbmsgBox prompt is a mix of RTL(Persian) and LTR(English) but text is displayed in wrong order

I am designing a vba userform for excel 2013, in which I use English and Persian text, the problem is when I use a mix of both languages in a msgBox the bits of text come out in the wrong order, the number is supposed to be displayed at the end. here is the code:
Private Sub CommandButton1_Click()
MsgBox "نام" & " - " & "نام" & " - " & "VF" & " - " & 52 & " ." _
, 1 + 1048576 + 524288, "نام برگه"
End Sub
The parts in double quotes and the number are supposed to come from listBoxes.(I just replaced them here with examples, the code behaves the same)
I tried spacing the bits out(works in windows), rearranging the bits and changing msgBox's alignment and reading order, but the result was the same. How to fix this thing?
Could you put all the persian into a string. Have the message box output the string and then have the message box output the numbers?
So it would be something like
aString = ListBox1.value & "-" & listbox2.Value ....
msgbox aString & 52 etc...