I want to set a result with 2 digits after the comma.
Is there any fast way to do this please ?
Because I need first to look for the result.
(If positif : add "+", negatif let the "-" and null "make it on 0.00)
Dim VariationX as Single
VariationX = 0,5
If VariationX >= 0.01 Then
VariationXString = "+" & VariationX
ElseIf VariationX = 0 Then
VariationXString = "0,00"
End If
VariationXString = Replace(VariationXString, ",", ".")
In this exemple
The result will be "+0.5"
But I want "+0.50" because in some case, the VariationX could be "10,50", "1,20", "-2.8" or simply "1". And I always need to have 2 digit after the comma.
Was going to use InStr, Len and Mid, but this would make a lot of line just for this.
Sorry to be boring, but this looks like a job for a custom number format...
Number formats are structured like so: [positive];[negative];[zero];[text]. So you want something like this:
"+"#,##0.00;"-"#,##0.00;#,##0.00
I get 0.00 for any zero value, +0.50 for 0.5, and -0.25 for -0.2463.
The representation of a value is different from that value. If you want to be able to use 0.5 in calculations, having it stored as "+0.50" is going to cause headaches - but having it stored as 0.5 and represented as +0.50 won't break anything.
If the presentation concern needs to be addressed in code (e.g. if you want that formatted string value to show up in some form's TextBox), then you can use the Strings.Format function to get the same result:
Public Function PrettifyVarianceFigure(ByVal value As Double) As String
PrettifyVarianceFigure = Strings.Format$(value, _
IIf(value > 0, "+", vbNullString) & _
"0" & Application.International(xlDecimalSeparator) & "00")
End Function
You can convert back to /round-trip to a Double by using the standard conversion functions*:
Debug.Print CDbl(PrettifyVarianceFigure(0.42)) ' outputs 0.42
*I doubt CDbl will handle a non-dot decimal separator though, so you might need to make a Strings.Replace call first.
Related
Good Evening
I have a problem on VBA I have a variable as countif
Dim Y As Integer
Y = Application.WorksheetFunction.CountIf(Worksheets("Calc_Giac").Range("I11:EZ11"), ">0")
So If I use the variable in a formula
Range("B21").Formula = "=SumIF((I11:EZ11), "">0"") / (" & Y & ")"
The value is correct
But if use in a condition the result is the variable*-1
If ("(" & Y & ")" > 0) Then
Range("L19") = "(" & Y & ")"
Else
Range("L19") = "HELLO"
End If
Any Idea about it?
First: You have a strange if-condition. Let's assume that Y has the value 3 as a result of your CountIf: "(" & Y & ")" resolves in a String "(3)". After that, you check if the string "(3)" is greater that 0. That makes no sense. Try
If Y > 0 then
Second: You write the String "(3)" into a cell. Now depending on how the cell is formatted, either you have "(3)" (as String) in the cell (when the cell is formatted as Text), or Excel tries to convert the string "(3)" into a number. However, numbers in Excel that are entered with brackets are interpreted as negative numbers (try it by entering "(3") into a cell manually. Use:
Range("L19").Value = 3
However, within the formula, =SumIF((I11:EZ11), "">0"") / (3), the (3) is just part of the calculation and the brackets tells Excel to evaluate anything within the brackets first before continuing the calculation. As 3 is already evaluated, there is nothing to do so the brackets are ignored.
I am using:
For t = 1 To ActiveProject.Tasks.Count
With Tasks(t)
' DurSen is a Custom Field Name. It returns an application field Number (such as 188743770 for Number4)
Projectfield = FieldNameToFieldConstant("DurSen")
' the SpearmanRankCorrelation function occasionally produces a result like -6.06060606060606E-03.
.SetField (Projectfield), SpearmanRankCorrelation(ProjectDuration, TmpVec, NN)
End With
Next t
This is a number expressed as an exponent. Due to the presence of the "E" in the number, it fails the Setfield function. The .Setfield places the calculated value into the field referenced by ProjectField for a specific task, (t) but fails when the calculated value contains an "E".
Any ideas on avoiding this problem?
The SetField method expects the Value parameter to be a string. So the solution is to format the number as a string. (e.g. Format(-6.06060606060606E-03, "0.0#####") => -0.006061)
However, Microsoft Project will round the value to the nearest hundredth, so you will lose the precision.
Better to store numbers that require more than two decimal places in a text field and convert them back to numbers as needed in code.
I had a simpler answer hat I figured out yesterday. Instead of trying to deal with it as a number, I simply converted to a string, used the InStr method to see if an "E" was present and if it is, assign a value of 0.001 as the result, as any E value will be smaller than .01.
If InStr(SpearmanRankCorrelation(ProjectDuration, TmpVec, NN), "E") > 0 Then
.SetField (Dursen), 0.001
PD = 0.001
outputstr = ("575 - ID= " & tasks(t).ID & " SpearmanRankCorrelation= " & SpearmanRankCorrelation(ProjectDuration, TmpVec, NN) & " Replaced by 0.001")
Call Txt_Append(myfile, outputstr)
Else
.SetField (Dursen), SpearmanRankCorrelation(ProjectDuration, TmpVec, NN)
End If
Thank you, Rachel, for your answer. I am trying not to use Project Custom fields. The .Setfield above assigns the Result to the field which is identified by the value of Dursen ( which is an internal field reference).
Rachel, I tried your approach but whenever I encountered a result that was expressed with an "E" in the Result, the conversion failed. using >Setfield will only round to the nearest hundreth if the entire string is a numeric value (when converted). The >Setfield method does not work when there is an "E" in the expression.
I would like to have a quick single line VBA code to pad a number in string form to always have a length of a multiples of 3's.
For example:
"12" becomes "012"
"1234" becomes "001234"
"1234567" becomes "001234567"
"12345678912345678" becomes "012345678912345678"
and so on.
The number string will not have any fraction or decimal points, so not to worry about that.
The length of the resulting string should be a multiple of 3 by adding 0's to the Left.
The number string should remain a string throughout the coding and should not be converted into a number using a numeric function such as Val, as the original string could be very long over 150 digits and using a numeric function could truncate or round the number and give undesirable results.
I had come up with the following as a possible solution by checking the string length but feel there is a better more efficient way of doing it in one (1) coding statement.
Result = String((3 - (Len(MyString) Mod 3)) Mod 3, "0") & MyString
After several attempts and your ideas, I have come up with the following using a single Mod Function:
MyString = String((Len(MyString) * 2) Mod 3, "0") & MyString
In general, a general formula would be:
MyString = String((Len(MyString) * (Multiples-1) ) Mod Multiples, "0") & MyString
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.
I'm looking for a simple macro to specify cells as being of type "time" and typing only numbers (for example "955") will format that (and recognise as) "hh:mm" time. In other words, by typing "955", the cell would interpret to "09:55", whereas all I can have it do right now is interpret to "1902-08-12 00:00:00" (most likely 955 is the day number for 1902-08-12).
EDIT:
Part of the need for this is to allow calculation of times post typing (for example, substract two time values to get a timespan, or add several timespans to get a total).
VBA code:
Dim val As String
val = myCell.Value
Dim newval As String
If Len(val) = 2 Then
newval = "00:" & val
ElseIf Len(val) = 3 Then
newval = "0" & Left(val, 1) & ":" & Right(val, 2)
ElseIf Len(val) = 4 Then
newval = Left(val, 2) & ":" & Right(val, 2)
Else
newval = "Not a valid time"
End If
myCell.Value = newval
This code does not detect if the last two digits are a valid time (greater than 59 minutes), but otherwise it should handle most cases.
You'll also need to add a case if someone types in 1 digit, ie. 1 thru 9 minutes after midnight.
If you want it to be formatted as an actual time (date-time type), then change the formatting of the cell to hh:mm.
The value typed in, for example 955, must be manipulated to produce a fraction of a day.
pseudocode:
(left(myCell,len(myCell)-2) + (right(myCell,2)/60)) / 24
This produces the proper decimal value for how much of the day has elapsed and thus will display as a proper 'Time' in the cell with hh:mm formatting.
This isn't the VBA, but a formula that will change the formatting. You could incorporate this into VBA if you wanted to, but should help as a jumping point.
=TIMEVALUE(IF(LEN(A5)=3,"0"&LEFT(A5,1)&":",LEFT(A5,2)&":")&RIGHT(A5,2))
(If A5 is the cell where you enter 955)
(Also, make sure to format the formula cell as your desired time formatting.)
I can help with the code if needed. Just post back.
For some reason Excel does not allow to use ":" in your custom format.
But if you OK with another delimiter, say dash "-", then you can simply create a custom format like this: ##-##
Of course your time has to be in 24 hours format.
Alternatively, you may first enter all your times just like numbers (or better as text if you don't want to lose trailing zeros). And then run your script to insert semicolons between hours and minutes.