I'm trying to match any combination of float numbers with a regular expression in VBA inside of Microsoft Word.
Example:
<text="">
<text="1">
<text="2">
<text="3">
<text="3.5">
<text="4">
<text="44">
I've tried the following patterns:
regex.Pattern = "<text=" & Chr(34) & "\d*\.*\d*" & Chr(34) & ">"
regex.Pattern = "<text=" & Chr(34) & "[\d\.]*" & Chr(34) & ">"
What's interesting is neither of these patterns will match the 44 either.
from the regex tester site,
Positive Integers --- ^\d+$
Negative Integers --- ^-\d+$
Integer --- ^-{0,1}\d+$
Positive Number --- ^\d*\.{0,1}\d+$
Negative Number --- ^-\d*\.{0,1}\d+$
Positive Number or Negative Number - ^-{0,1}\d*\.{0,1}\d+$
to test for the empty result being valid, and assuming all positive numbers, you would end up with
regex.Pattern = "<text=" & Chr(34) & "\d*\.{0,1}\d*" & Chr(34) & ">"
Let's break it down. A floating point number has two parts, integral and decimal. There are some choices on the format:
Here is pattern for a pretty common notation:
regex.Pattern = "<text=" & Chr(34) & "(-?\d+(\.\d+)?)?" & Chr(34) & ">"
Some choices:
Do you want to support omitting the integral part? (e.g. '.001')
Use * instead of + in the first number match: (-?\d*(\.\d+)?)?
Do you want to support leading zeros? (e.g. 000.)
This is gonna be more tricky :)
Do you want to support decimal point without decimal part? (e.g. '12.')
Then add ? after the decimal point match: (-?\d*(\.?\d+)?)?
Is the decimal part mandatory?
Remove the very last ?: (-?\d*(\.?\d+))?
Related
I have a loop like this to save sheets as CSV files but my first 9 sheets are name liked sinani-01 ... sinani-09 (not like sinani-1 ... sinani-9). How I can concatenate a 0 only before numbers less than 10?
Sub Adder()
Dim animal As String
Dim i As Integer
For i = 1 To 120
animal = "sinani-" & i
Sheets(animal).SaveAs "E:\Data\CSV\" & animal & ".csv", xlCSV
Next i
End Sub
VBA has a Format() function that you can use to pad numbers.
animal = "sinani-" & Format$(i, "00")
This will pad single-digit numbers with a 0. Your two- and three-digit numbers will continue to work as expected.
In the fifth line use the Format function like this:
animal = "sinani-" & Format(i, "#00")
The # means optionally a digit (i.e. present only if there are that many digits in i), 0 means definitely a digit, whereby leading zeros are used if i hasn't got enough digits.
Concatenate with a leading series of zeroes and peel off as many digits from the right-hand side as you need.
animal = "sinani-" & Right("00" & i, 2)
'alternate for many leading zeroes (e.g. DUNS number)
animal = "sinani-" & Right(String(9, "0") & i, 9)
Replace & i by & IIF(i < 10,"0","") & i
On edit: Even though in this case Format provides a cleaner solution than IIF, the IIF trick has some other uses in tweaking output. For example, if you wanted to inform the user how many cells were found which satisfy some condition you could use something like
MsgBox n & "cell" & IIF(n <> 1,"s","") & " found"
to gracefully handle plural vs. singular endings
I have a bunch of different sets of engineering measurements in the format:
77.170 (+/- 0.025)
And I need to split it into the first number, which is the nominal value, and the number in the parenthesis, the tolerance. Not sure exactly how to do this in excel VBA. I was thinking I would use the Split function with a space delimiter, giving me the first number, then the unnecessary characters, then the tolerance, but the tolerance will include a parenthesis. How could I get rid of just that parenthesis, and will what I just suggested even work? Thanks!
Consider:
Sub dural()
s = "77.170 (+/- 0.025)"
s2 = Replace(Replace(Replace(s, " ", ""), "+/-", ""), ")", "")
ary = Split(s2, "(")
MsgBox ary(0) & vbCrLf & ary(1)
End Sub
Use Text to Columns and a formula.
Go to Data--->Text to Columns. Choose delimited and choose Space as your delimiter. This should split the text string into something like:
ColA |ColB|ColC
77.170|(+/-|0.025)
Column C is a bit funky, so let's just grab everything but the last character.
In column D put this:
=LEFT(C1,LEN(C1)-1)
Finally, you should get:
ColA |ColB |ColC |ColD |
77.170|(+/- |0.025)|0.025|
I would use a combination of instr() and mid to get what you need. For example
measurments="77.170 (+/- 0.025)"
mid(measurements,1,instr(measurements," "))
trim(mid(measurements,instr(measurements,"-")+1,instr(measurements,")")-instr(measurements,"-")-1))
or, to combine,
measurments="77.170 (+/- 0.025)"
mid(measurements,1,instr(measurements," ")) & " " & trim(mid(measurements,instr(measurements,"-")+1,instr(measurements,")")-instr(measurements,"-")-1))
Try using a combination of InStr(), Left(), Right().
Get the index/position of the '(' using InStr and then extract the characters using Left and Right. If you want to get the final data as a double or a Long use CDbl() or CLng() respectively.
For getting text out of other text consider using Regular Expresions.
To use them in VBA you will need in Reference 'VBScript_RegExp_55' library.
The reason why you might want to do that is because following code returns whatever first two numbers show up in your text( it can be modified to be much smarter than that), regardless of other text around it.
Dim Regex As RegExp
Dim Matches As MatchCollection
Set Regex = New RegExp
Regex.Pattern = "\d*\.\d*"
Regex.Global = True
Set Matches = Regex.Execute("77.170 (+/- 0.025)")
MsgBox (Matches(0).Value & " " & Matches(1).Value)
Assuming s is your measurement string, here is the most direct way:
v = Split(Left(s, Len(s) - 1), " (+/- ")
That's it. Now v(0) holds the nominal value and v(1) holds the tolerance.
The user, through a userform, can insert a numeric value (say 1,000,000) and an ISO code (say USD). When he will validate, the value will be printed in range A1 and will be formatted as currency through the use of the following macro-recorded line of code:
.Range("A1").NumberFormat = _
"_-[$" & Me.ISOTextBox.Value & "] * #,##0.00_-;-[$" & Me.ISOTextBox.Value & "] * #,##0.00_-;_-[$" & Me.ISOTextBox & "] * ""-""??_-;_-#_-"
Basically, the above is the string to assign the .NumberFormat property; in the case of "USD", for example, the string will look like:
"_-[$USD] * #,##0.00_-;-[$USD] * #,##0.00_-;_-[$USD] * ""-""??_-;_-#_-"
My question is: if with the above string I set the number format, how could I get it?
I could clearly make string parsing, and this is the currently "horrible" solution I'm adopting for extracting the 3-letters ISO code:
ISOcode = Left(Replace(Split(Range("A1").NumberFormat, "[")(1), "$", ""), 3)
Note: the above code is splitting the all NumberFormat by [, hence taking the second element (starting with $USD), replacing the $ with "" and taking the first three letters, standing to the standard of ISO codes that are always 3-letters long).
Documentations are very poor on this: does anyone know if there's a way of properly get the ISO code from the currency format (without turning into an unelegant string parsing)?
I'm pretty sure you will need to parse the string, but the ISO code can be extracted slightly more cleanly using:
If InStr(Range("A1").NumberFormat, "[$") <> 0 Then _
ISOcode = Mid(Range("A1").NumberFormat, InStr(Range("A1").NumberFormat, "[$") + 2, 3)
In the code below, I'm using the current date and time, with the help of which I am generating a file name. My problem is that it's giving me an output without leading zeros:
Dim strDateTime As String = DateTime.Now.Day.ToString() & "" & _
DateTime.Now.Month.ToString() & "" & DateTime.Now.Year.ToString() & "" & _
DateTime.Now.Hour.ToString() & "" & DateTime.Now.Minute.ToString() & "" & _
DateTime.Now.Second.ToString() & DateTime.Now.Millisecond.ToString()
For example, my query is giving output as below currently:
Assume time is 1:5:30 :: hh:mm:ss
Required output is: 01:05:30
How can I achieve this?
Try this,
DateTime.Now.Hour.ToString("00") & ":" & DateTime.Now.Minute.ToString("00") & ":" & DateTime.Now.Second.ToString("00")
EDIT :
As suggested by 'mdb' in the answers, using Custom Date and Time Format Strings would be more efficient and cleaner
DateTime.Now.ToString("hh:mm:ss tt") '12 Hour format with AM/PM designator, Eg :- 09:01:01 PM
DateTime.Now.ToString("HH:mm:ss") '24 Hour format Eg :- 21:01:01
Instead of concatenating strings, which is highly inefficient, you'll want to use String.Format. This also supports Custom Date and Time Format Strings, which make it trivial to achieve what you want.
I need my macro to input the following formula:
Worksheets("U_NEDC_COLD_online_0").Cells(3, A).formula = "=IF(" & Worksheets (U_NEDC_COLD_online_0).Cells(3, AA).Value & "=" & Worksheets(U_NEDC_COLD_online).Cells(3, AA).Value & ";" & Worksheets(U_NEDC_COLD_online).Cells(3, A).Value & ";" & Worksheets(U_NEDC_COLD_online_0).Cells(3, A).Value & ")"
I've also tried the same formula with the ".Address" property and it doesn't work. What am I doing wrong?
The final formula should look like this:
=IF($AA3 = U_NEDC_COLD_online!$AA3; U_NEDC_COLD_online!A3; U_NEDC_COLD_online_0!A3)
PS: Worksheets("U_NEDC_COLD_online_0") is not the same as Worksheets(U_NEDC_COLD_online_0). (its not a typo)
Thanks.
Use commas instead of semicolons to separate the arguments of the IF statement.
Your formula appears to have a circular relationship; the formula is going into cell A3 and references cell A3... I'll leave that to you to work out.
Always use Option Explicit. Once you put that line at the top of your module, you'll get the error: Variable not defined for the variables: A, AA, and possibly U_NEDC_COLD_online and U_NEDC_COLD_online_0 that you probably intended to use as string literals. (see next bullet for a workaround)
If U_NEDC_COLD_online_0 is truly a variable/constant name and is not equal to the string literal that you use elsewhere (e.g. U_NEDC_COLD_online_0), you should really change the variable name to something else!
If the only reason you are dynamically building the formula is to accommodate variable row indexes, use this where the 3 can be replaced by a variable:
Worksheets("U_NEDC_COLD_online_0").Cells(3, 1).Formula = "=IF($AA" & 3 & "=" & "U_NEDC_COLD_online!AA" & 3 & ", U_NEDC_COLD_online!A" & 3 & ", A" & 3 & ")"
If you don't even need variable row indexes, just use this:
Worksheets("U_NEDC_COLD_online_0").Range(A3).Formula = "=IF($AA3=U_NEDC_COLD_online!AA3, U_NEDC_COLD_online!A3, A3)"