Add leading zero to numbers - string

I, need get values like 05:00, -05:00 ,when on input have number values 5, -5..If on input values like 10,-12 then don't need adding leading zeros..I can create some function which check how many digits have number and then add if needed "0" char, but maybe anyone have finest decision?

The closest thing I can find to help with this is the FormatNumber function in VBScript. W3 has a good example and test tool here: http://www.w3schools.com/vbscript/func_formatnumber.asp
You will most likely have to wrap this function to handle your specific case of appending a 0. This should be pretty simple though, simply do an IFTHEN statement sort of like:
IF x > 0 & x < 10 THEN "0" + x
ELSEIF x > -10 & x < 0 THEN "-0" + Abs(x)
Or something of that nature. Again this would have to be a string formatting thing as the integer will always reflect 5 or -5 not 05 or -05
Hope that helps

Try
Function FormatHour (input)
Dim sign
If (input < 0) Then
sign = "-"
End If
FormatHour = sign & FormatDateTime(TimeSerial(Abs(input), 0, 0), vbShortTime)
End Function

How about this lpad and rpad example from Microsoft?
http://support.microsoft.com/kb/96458

Alexey, next time please publish what you've got, now we have to guess what you really want, so here is my guess
a = array(0, 5, -5, 15, -55)
for each e in a
wscript.echo mid(" -",instr(e,"-")+1,1)&right("0"&abs(e),2)&":00"
next
00:00
05:00
-05:00
15:00
-55:00
OR
for i = 0 to uBound(a)
a(i) = mid(" -",instr(a(i),"-")+1,1)&right("0"&abs(a(i)),2)&":00"
next
wscript.echo join(a,",")
'00:00, 05:00,-05:00, 15:00,-55:00

Related

How to specify last character in 1 cell ( Inside IF )

i have a code that copies and rewrites anything thats between "(" and ")", but now i have different type of data which do not end with ")" so, i need it to stop when it reaches the last character in cell. Maybe it is dumb question but i cant seem to find how to fix my problem. I am a student and total newbie in vba (5 days ago i didn't know what vba is...) also sorry for my bad english.
I've tried to search (in here, google, youtube) but i couldnt find anything i need
'zaciatok=start koniec=end dlzka=length
Do While Mid(LookInHere, y, 1) <> ""
If Mid(LookInHere, Z, 1) = "(" Then
zaciatok = Z
End If
If Mid(LookInHere, y, 1) = ")" Then
koniec = y
dlzka = (koniec - 1) - zaciatok
dlzka = Abs(dlzka)
SplitCatcher = Mid(LookInHere, zaciatok + 1, CStr(dlzka))
MsgBox SplitCatcher
End If
y = y + 1
Z = Z + 1
Loop
In your specific implementation, one option is to modify your Do While ... loop to also test against the length of the string. That line would look something like:
Do While Mid(LookInHere, y, 1) <> "" And y < Len(LookInHere)
That modification tells the statement that it should terminate the loop when the iterating variable y goes past the length of the statement.
Another option is to change it from a Do While loop to a For loop. It would read something like:
For i = 1 to Len(LookInHere)
MsgBox Mid(LookInHere, i, 1)
'Input your logic here
Next i
The problem is that each of these versions is relatively inefficient, looping through each letter in a string a performing a calculation. Consider using built-in Excel functions. The Instr returns the position of a character, or a zero if it is not found. As an example, Instr("Abcdef", "b") would return the number 2, and Instr("Abcdef", "k") would return zero. You can replace the entire loop with these two function calls.
Z = Instr(LookInHere, "(")
y = Instr(LookInHere, ")")
If y = 0 Then y = Len(LookInHere)
Final note: if your patterns begin to get more and more complex, consider reviewing and implementing regular expressions.
You can use Right(LookInHere, 1) to get the last character of LookInHere

How to truncate less than 30 characters and delete in Excel VBA?

I have an excel sheet with some rows of descriptions in a single column, what I am aiming is to get a formula that would truncate it upto certain character limit for example 30 characters and if the truncation stops at 30 character in the middle of the word then I remove that last word.
Here is the Formula that i am trying to make it work.
=LEFT(A1,FIND(" ",A1,30)-1)
Use AGGREGATE to locate the last space within the first 31 characters.
=LEFT(A2, AGGREGATE(14, 7, ROW($1:$31)/(MID(A2&" ", ROW($1:$31), 1)=" "), 1) -1)
A none loop method
=IF(LEN(A2)<30,A2,LEFT(A2,FIND("}}}",SUBSTITUTE(A2," ","}}}",30-LEN(SUBSTITUTE(LEFT(A2,30)," ",""))))-1))
Try something like this:
Put in a module at VBA Editor (ALT+F11) -> Insert New Module.
When you past this code you can call it from any cell with "=NotTruncateWord(A1;30)"
There is some ajustments to do, because it is hard to know what is a Word (something after a space?), I ask because if someone write a 35 characteres string with no space, I will consider a word and remove all?
Public Function NotTruncateWord(Value, Limit)
LastSpaceBeforeLimit = 0
FirstSpaceAfterLimit = 9999
Phrase_Lenght = Len(Value)
If Phrase_Lenght > Limit Then
For i = 1 To Phrase_Lenght
check = Mid(Value, i, 1)
If Asc(check) = 32 Then
If i < Limit Then
LastSpaceBeforeLimit = i
ElseIf i < FirstSpaceAfterLimit Then
FirstSpaceAfterLimit = i
End If
End If
Next
If LastSpaceBeforeLimit > 0 Then
NotTruncateWord = Left(Value, LastSpaceBeforeLimit)
Else
NotTruncateWord = Left(Value, Limit)
End If
Else
'no need to truncate
NotTruncateWord = Value
End If
End Function

How to split a number into individual digits VB using substring

I tried to put seconds in 2 text-boxes, each digit in one. Example x= 56 x1= 5 and x2= 6
' s = TimeOfDay.Second
TextBox15.Text = s.Substring(0, 1)
TextBox16.Text = s.Substring(1, 1)'
When I try this I get the following error: System.ArgumentOutOfRangeException
Any ideas on how to fix this?
ArgumentOutOfRange exceptions occurs whenever you attempt to get a character that doesn't exist at the given position. So what is happening is that there is either not a String at position 0 with a length of 1 or there is not a String at position 1 with a length of 1.
To prevent this, add a simple If/Then statement to check if the length of the original String at least equal to the position of the character. Also for what it's worth, since you only want one letter, simply get the character at the desired index of the String.
Here is a quick example:
If s.Length >= 1 Then
TextBox15.Text = s(0).ToString()
End If
If s.Length >= 2 Then
TextBox16.Text = s(1).ToString()
End If
Fiddle: Live Demo
You don't need to convert it to a string before getting the digits, just doing the maths to get them will work well enough:
Dim rightNow = DateTime.Now
TextBox15.Text = (rightNow.Second \ 10).ToString()
TextBox16.Text = (rightNow.Second Mod 10).ToString()
And another approach.
Dim c() As Char = DateTime.Now.Second.ToString("00").ToArray
TextBox1.Text = c(0)
TextBox2.Text = c(1)

Comparing time in ASP classic/VBscript

I am working on a function for an asp page that compares if a time entered is greater than a time with added leeway. I noticed certain times when checked would fail the test when the times are equal. Included is a snip of my function to illustrate. Not sure why equal dates would fail, and would like to know if this is a good way to go about comparing time.
<%
function TimeTest(testTime, checkTime, buffer, try)
checkingTime = FormatDateTime(cdate(DateAdd("n", buffer, cdate(checkTime))),4)
if try = 1 then
testTime = FormatDateTime(testTime, 4)
checktime = FormatDateTime(checkTime, 4)
end if
if cdate(testTime) > DateAdd("n", buffer, cdate(checkTime)) then
TimeTest = "<p class = 'redS'>Fails! testTime: "&testTime&" < checkTime:"&checkingTime&"</p>"
else
TimeTest = "<p class = 'greenS'>Works! testTime: "&testTime&" > checkTime:"&checkingTime&"</p>"
end if
end function
response.write("<br><br><h1>Test2</h1><br>")
for i=0 to 23
for j=0 to 59
response.write(TimeTest(i&":"&j&":00", i&":00:00", j, 1))
response.write("<BR>")
next
next
%>
This problem has earned my attention! I can reproduce the results and it's very unclear what's going on behind the scenes in these comparisons. However, I have a workaround for you
Here is a modified version of the code that I've been using to analyse the issue...
<%
Option Explicit
Function TimeTest(a, b, buffer)
Dim c : c = DateAdd("n", buffer, b)
Dim s : s = Join(Array("a=" & a, "b=" & b, "c=" & c, "buffer=" & buffer), ", ")
Dim passed : passed = a <= c
'Dim passed : passed = DateDiff("s", a, c) <= 0
If passed Then Exit Function
Dim color : color = "red" : If passed Then color = "green"
TimeTest = "<div style='color:" & color & "'>" & s & "</div>"
End Function
Dim i, j, a, b
For i = 0 To 23
For j = 0 To 59
a = CDate(i & ":" & j & ":00")
b = CDate(i & ":00:00")
'a = CDate(Date() & " " & i & ":" & j & ":00")
'b = CDate(Date() & " " & i & ":00:00")
Response.Write(TimeTest(a, b, j))
Next
Response.Write("<hr>")
Next
%>
Note that commenting out line 13 will reveal lines that pass. By default, I'm showing only failures.
The first thing to note is that I have some commented variants on lines 24-25 where I add today's date to the value before casting it. Interestingly, doing this changes the pattern of which times fail the test. There are still roughly the same number of failures but they occur at different buffer values.
This leads me to believe that behind the scenes in VBScript, these datetimes might be cast to floating-point numbers when you use the native < <= > >= comparison operators on them and that's resulting in some precision errors. If they were converted to long integers, then they should surely be correct.
I did a version of the code where instead of using a direct comparison on the VBDateTimes, I compared the integer representation of them (unix time) using this function:
Function date2epoch(myDate)
date2epoch = DateDiff("s", "01/01/1970 00:00:00", myDate)
End Function
When doing that, all tests passed. However, it is an unusual way to do things. I thought there should be a more 'normal' way.
I then went back and replaced the straightforward <= operator with a call to DateDiff instead (comment out line 10, uncomment line 11). Whether I used seconds or minutes, the tests passed. So, I think the takeaway lesson here might be to always use DateDiff when comparing VBDateTimes. As someone who's used VBS for a while and never encountered issues with native comparisons before, this is a revelation and I may need to offer this advice to my colleagues too.

How can I divide a number string by 1000 without converting to number?

I am trying to make a certain string with Digits change form, so that it looks like below.
Modified to show with Digits instead of X.
So let´s set, i get a number, like this.
234.123123123
I need to change how it appears, for 3 digits before a Dot, it would need to become.
0.234123123123
And let´s say it´s 2.23123123123, that would become, 0.0023123123123
Now i will try to explain the Formula, bare with my English.
The formula needs to change the position of the Dot ".".
You can see that it changes place, But you can also see that i am adding 0s.
That is important, the 0s needs to be added IF the dot get´s to the far left (the beginning of the string).
So how much must the Dot move?
The Dot must Always move 3 steps to the left.
And if it hit´s the wall (the start of the string) you need to add 0s, and then one 0s before the dot.
So if the number is, 2.222222
I will first have to move the dot to the left, let´s show step by step.
Step 1:
.2222222
Step 2:
.02222222
Step 3:
0.02222222
It must Always be a 0 Before the Dot, it it ever hit the Start.
It sounds more complicated then it is, it´s just that i don't know how to explain it.
EDIT:
My attempt:
TextPos = InStr(1, TextBox4.Value, ".") - 2
If (TextPos = 4) Then
sLeft = Left(TextBox4.Value, Len(TextBox4.Value) - Len(TextBox4.Value) + 2)
sRight = Right(TextBox4.Value, Len(TextBox4.Value) - 2)
sFinal = (sLeft & "." & Replace(sRight, ".", ""))
TextBox4.Value = Replace(sFinal, "-", "")
End If
If (TextPos = 3) Then
TextBox4.Value = "0." + Replace(TextBox4.Value, ".", "")
End If
If (TextPos = 2) Then
TextBox4.Value = "0.0" + Replace(TextBox4.Value, ".", "")
End If
If (TextPos = 1) Then
TextBox4.Value = "0.00" + Replace(TextBox4.Value, ".", "")
End If
TextBox4.Value = Replace(TextBox4.Value, "-", "")
If i /1000 it, may work, but it seems like it will alter the number, leaving it to fail.
Original: 25.1521584671082
/1000 : 2.51521584671082E-02
As you can see, it doesn't work as expected.
It should become 0.0251521584671082E-02 (And of course i don't want " E- " to be there.
So if it's possible to do this, but ONLY moving and not actually, dividing (i think excel is limited to how many numbers it can calculate with) then it will work.
Worth Noting, the numbers shown are actually less (shorter) then the real number for some reason, if i write it down to a text file, it becomes this:
2.51521584671082E-02251521584671082E-02
So as you can see, i probably hit a Wall in the calculation, so it changes to Characters (I know math uses those, but no idea what they mean, and they are useless for me anyway).
And i think it's because of them that it fails, not sure though.
EDIT:
Okay, by limiting to 15 decimals it will return the correct place, but i would like not to do this round about, should Excel really be limited to only 15 Decimals, or is it "Double,Float etc" that does this?
EDIT 2:
Tony's example provides this:
Original: 177.582010543847177582010543847
Tony's: 0.1775820110177582011
Round(15decimals): 0.1775820105438470177582010543847
Not really sure, but isn't it Incorrect, or perhaps i did something wrong?
If possible, i want ALL decimals and number to stay in place, as everything is already correct, it's just that they are in the wrong place.
/1000 solves this, but not in the best way, as it will recalculate instead of just moving.
Normally i wouldn't care, the results are the same, but here it does matter as you can see.
I can however think of a solution, where i till look for the position of the Dot, then cut out the last decimals, divide the Result by 1000, then later add the last decimals, though that is more of a hack , not sure if it will actually work.
I conclude that this is Answered, it does what i want, and the limitations is in the Calculation itself, not the Solution.
All Solutions work pretty much in the same way, but i chose Tony's as he was first to comment the solution in my question.
Many Thanks everyone!
It appears to me through all your edits that you want to divide the number by one thousand. To do this, you can simply use
TextBox4.Value = TextBox4.Value / 1000
You code sometimes fails because it does not handle every situation. You calculate TextPos so:
TextPos = InStr(1, TextBox4.Value, ".") - 2
You then handle TextPos being 4, 3, 2 or 1. But if, for example, TextBox4.Value = "2.22222" then TextPos = 0 and you have no code for that situation.
At 11:45 GMT, I suggested in a comment that dividing by 1000 would give you the result you seek. At 14:08 GMT, tunderblaster posted this as an answer. It is now 15:23 but you have not responded to either of us.
Having tried your code, I now know these answer do not match the result it gives when it works because you remove the sign. The following would give you almost the same as a working version of your code:
TextBox4.Value = Format(Abs(Val(TextBox4.Value)) / 1000, "#,##0.#########")
The only deficiency with this statement is that it does not preserve all the trailing decimal digits. Is this really important?
While I was preparing and posting this answer, you edited your question to state that dividing by 1000 would sometimes give the result in scientific format. My solution avoids that problem.
If you want to avoid floating point error when dividing by 10, you may use the Decimal type
Private Sub CommandButton1_Click()
Dim d As Variant
d = CDec(TextBox1.Text)
TextBox1.Text = d / 1000
End Sub
Is this what you are trying?
Sub Sample()
Dim sNum As String, SFinal As String
Dim sPref As String, sSuff As String
Dim nlen As Long
sNum = "234.123123123123123123131231231231223123123"
SFinal = sNum
If InStr(1, sNum, ".") Then
sPref = Trim(Split(sNum, ".")(0))
sSuff = Trim(Split(sNum, ".")(1))
nlen = Len(sPref)
Select Case nlen
Case 1: SFinal = ".00" & Val(sPref) & sSuff
Case 2: SFinal = ".0" & Val(sPref) & sSuff
Case 3: SFinal = "." & Val(sPref) & sSuff
End Select
End If
Debug.Print SFinal
End Sub
Try this. It works by initialy padding the string with leading 0's, shifting the DP, then removing any unnecassary remaining leading 0's
Function ShiftDecimalInString(str As String, Places As Long) As String
Dim i As Long
If Places > 0 Then
' Move DP to left
' Pad with leading 0's
str = Replace$(Space$(Places), " ", "0") & str
' Position of .
i = InStr(str, ".")
str = Replace$(str, ".", "")
If i > 0 Then
' Shift . to left
str = Left$(str, i - Places - 1) & "." & Mid$(str, i - Places)
' strip unnecassary leading 0's
Do While Left$(str, 2) = "00"
str = Mid$(str, 2)
Loop
If str Like "0[!.]*" Then
str = Mid$(str, 2)
End If
ShiftDecimalInString = str
Else
' No . in str
ShiftDecimalInString = str
End If
ElseIf Places < 0 Then
' ToDo: Handle moving DP to right
Else
' shift DP 0 places
ShiftDecimalInString = str
End If
End Function
This "answer" responses to the issue that you want as much precision in the result as possible.
When I was at school this was called spurious accuracy. I have forgotten most of my mathematics in this area but I will try to give you an understanding of the issue.
I have a value, 2.46, which is accurate to 2 decimal places. That is the true value is somewhere in the range 2.455 to 2.465.
If I feed these values into a square root function I will get:
sqrt(2.455) = 1.566843961599240
sqrt(2.46) = 1.568438714135810
sqrt(2.465) = 1.570031846810760
From this I see the square root of the true value is somewhere between 1.567 and 1.570; any extra decimal digits are spurious.
If I understand correctly, you wish to use these numbers to make adjustments. Are you capable of making adjustments to 15 decimal digits?
If you remember your calculus you can look up "propogation of error" for a better explanation.

Resources