i make function that convert time string ("hh\:mm\:ss\,fff" - example:"00:00:00,100") to parts
strTime = "00:00:00,100" =
h int = 0
m int = 0
sec int = 0
millisec int = 100
The function:
Public Function ShowInLabel(ByVal TEXT As String, ByVal time As String, ByVal startTime As Boolean) As Boolean
On Error Resume Next
Dim sss As String
sss = time
Dim start As String = StrReverse(sss)
start = StrReverse(start.Substring(0, 3))
Dim s As Integer
s = Integer.Parse(start)
Dim secstart As String = StrReverse(sss).Substring(0, 6)
secstart = StrReverse(secstart)
Dim secs As Integer = Integer.Parse(secstart.Substring(0, 2))
Dim hurs As Integer = Integer.Parse(sss.Substring(0, 2))
Dim mins As Integer = Integer.Parse(StrReverse(StrReverse(sss.Substring(0, 5)).Substring(0, 2)))
Dim stopWatch As New Stopwatch()
stopWatch.Start()
noh:
If stopWatch.Elapsed.Hours = hurs Then
GoTo yesh
Else
GoTo noh
End If
yesh:
If stopWatch.Elapsed.Minutes = mins Then
GoTo yesm
Else
GoTo yesh
End If
yesm:
If stopWatch.Elapsed.Seconds = secs Then
GoTo yess
Else
GoTo yesm
End If
yess:
If stopWatch.Elapsed.Milliseconds > s Or stopWatch.Elapsed.Milliseconds = s Then
GoTo done
Else
GoTo yess
End If
done:
If startTime = False Then
Label1.Text = ""
Else
Label1.Text = TEXT
End If
Return True
End Function
example:
ShowInLabel("SubTitle", "00:00:00,100", True)
The Function Works ,
but when the function runing the application is Stucked Till the function return true
Why it happening?
All you need to do is something like this:
Dim time As Date = DateTime.ParseExact("00:01:02,123", "hh:mm:ss,fff", CultureInfo.InvariantCulture)
Dim h As Integer = time.Hour
Dim m As Integer = time.Minute
Dim sec As Integer = time.Second
Dim millisec As Integer = time.Millisecond
However, being all to familiar with what you're trying to accomplish :), I suspect what you really need is this:
Dim time As Date = DateTime.ParseExact("00:01:02,123", "hh:mm:ss,fff", CultureInfo.InvariantCulture)
Dim startTime As Date = DateTime.ParseExact("00:00:00,000", "hh:mm:ss,fff", CultureInfo.InvariantCulture)
Dim elapsed As TimeSpan = time - startTime
Dim totalMilliseconds As Integer = CType(elapsed.TotalMilliseconds, Integer)
You could, in the same way, convert the start and end times for each subtitle to total milliseconds and then compare them that way.
As others have pointed out, On Error Resume Next is only really available in VB.NET for backwards compatibility with VB6 code. You should use a Try/Catch block, instead. However, just putting a resume next above your entire method was never considered good practice, even in VB6, just as putting a try/catch block around the entire method would also be considered a bad idea.
Similarly, GoTo is just about the most terrible thing you could ever do by just about any programmer's sensibilities. You should consider other options such as loops, if/else blocks, breaking the code up into separate methods, etc., and avoid GoTo's at all costs.
Related
This is a very simple code. I am just beginning to use vb. Im making a game where you try to solve a puzzle in the least amount of time and least amount of clicks. Every time I debug the program, it highlights the Clicks and FinalTime and says Null Reference Exception was Unhandled. I declared Clicks and FinalTime globally
Public Class Form1
Dim Clicks As Integer = 0 'The variable that counts the number of times you clicked
Dim Time As Integer 'The vairable that holds the time
Dim TimeMin As Integer 'The variable that holds the minutes
Dim TimeSec As Integer 'The variable that holds the seconds
Dim FinalTime As String 'The variable that holds the final time (minutes and seconds)
Dim NumArray() As Integer
Dim NumArray1() As String
Private Sub Times
Time = Time + 1
TimeSec = TimeSec + 1
TimeMin = Convert.ToInt32(TimeSec \ 60)
If Time >= 60 Then
Time = 0
End If
FinalTime = TimeMin & " min " & Time & " seconds"
lblTime.Text = FinalTime
End Sub
Private Sub Record(ByVal NumArray() As Integer, ByVal NumArray1() As String)
For i As Integer = 0 To 1000
NumArray(i) = Clicks 'Problem is here
i = +1
Array.Sort(NumArray)
Next i
lblRecordClicks.Text = NumArray(0) & " Clicks"
For k As Integer = 0 To 1000
NumArray1(k) = FinalTime 'Problem is here
k = +1
Array.Sort(NumArray1)
Next k
lblRecordTime.Text = NumArray1(0)
End Sub
Rule #1. Strings in VB.NET are not the same as Strings in VB6.
In VB6 you can say
Dim text as String
and you would have text = "" initialized
In VB.NET you need
Dim text as String = vbNullString
or
Dim text as New String
The same applies to arrays of string (or any other array)
Dim arr as String() ' This makes arr = Nothing
arr = New String(10) { } ' This allocates an array with 11 items (0..10)
or
Dim arr as String() = New String(10) {}
or
Dim arr() As String = New String(10) {}
or
Dim arr() = New String(10) {}
or
Dim arr = New String(10) {}
See related: Classes and arrays how to initialize?
I have an issue trying to program a simple combat simulation for a project that I and another person is working on.
Module Module1
Dim Player_Vitality As Integer
Dim PlayerReiatsu As Integer
Dim PlayerZanjustu As Integer
Dim PlayerHakuda As Integer
Dim PlayerHoho As Integer
Dim PlayerKido As Integer
Dim PlayerAbility As Integer
Dim Player_Physical_Damage As Integer
Dim Player_Spirit_Damage As Integer
Dim Player_Critical_Chance As Integer
Dim Player_Critical_Damage As Integer
Sub Main()
Call Shuhei()
End Sub
Sub Shuhei()
Dim Shuhei_reiatsu As Integer
Dim Shuhei_Vitality_TurnStart As Integer
Dim Shuhei_Vitality_TurnEnd As Integer
Dim Attack As String
Dim Kido As Integer
Dim Sword As Integer
Dim Shuhei_Temp As Integer
PlayerZanjustu = 40
PlayerHakuda = 50
PlayerKido = 50
PlayerAbility = 75
Shuhei_reiatsu = 80
Kido = Player_Spirit_Damage
Sword = Player_Physical_Damage
'Player_Vitality = 100
Shuhei_Vitality_TurnStart = 1000
Console.WriteLine("FIGHT 1")
Console.ReadLine()
Do While Shuhei_Vitality_TurnStart > 0
Player_Physical_Damage = ((PlayerZanjustu + PlayerHakuda) - Shuhei_reiatsu)
Player_Spirit_Damage = ((PlayerKido + PlayerAbility) - Shuhei_reiatsu)
'Player_Critical_Chance = ((PlayerZanjustu + PlayerHoho) - Shuhei_reiatsu) / 100
'Player_Critical_Damage = (PlayerZanjustu + PlayerHakuda) * 10
Shuhei_Temp = Shuhei_Vitality_TurnStart
Console.WriteLine("Shuhei has " & Shuhei_Temp & "Hp")
Console.WriteLine("Which attack do you want to use?")
Attack = Console.ReadLine
If Attack = "Kido" Or Kido Then
Shuhei_Vitality_TurnEnd = ((Shuhei_Temp) - Player_Spirit_Damage)
ElseIf Attack = "Sword" Or Sword Then
Shuhei_Vitality_TurnEnd = Shuhei_Temp - Player_Physical_Damage
Else
Console.WriteLine("Please choose an attack")
End If
Shuhei_Vitality_TurnEnd = Shuhei_Vitality_TurnStart
If Shuhei_Vitality_TurnStart <= 0 Then
Call FightEnd()
End If
Loop
Console.ReadKey()
End Sub
Sub FightEnd()
Console.WriteLine("Shuhei has been defeated")
Console.ReadKey()
End Sub
This is all copied down to the point in a new sub where there is deactivated junk with no purpose as of yet, so I doubt that is the issue, it is just the skeleton of the combat code but with ' in front to disable it. Then at the bottom the End Module command
In your IF Statement Attack could really never be "Kido" or Kido. You are comparing a string to a string or a string to an integer and that is likely your issue. Try converting Kido the variable to a string and that might supress the error.
Pseudo code:
If Attack = "Kido" Or Kido.ToString
Which are the combinations that the sum of each digit is equal to 8 or less, from 1 to 88,888,888?
For example,
70000001 = 7+0+0+0+0+0+0+1 = 8 Should be on the list
00000021 = 0+0+0+0+0+0+2+1 = 3 Should be on the list.
20005002 = 2+0+0+0+5+0+0+2 = 9 Should not be on the list.
Sub Comb()
Dim r As Integer 'Row (to store the number)
Dim i As Integer 'Range
r = 1
For i = 0 To 88888888
If i = 8
'How can I get the sum of the digits on vba?
ActiveSheet.Cells(r, 1) = i
r = r + 1
End If
Else
End Sub
... Is this what you're looking for?
Function AddDigits(sNum As String) As Integer
Dim i As Integer
AddDigits = 0
For i = 1 To Len(sNum)
AddDigits = AddDigits + CInt(Mid(sNum, i, 1))
Next i
End Function
(Just remember to use CStr() on the number you pass into the function.
If not, can you explain what it is you want in a bit more detail.
Hope this helps
The method you suggest is pretty much brute force. On my machine, it ran 6.5min to calculate all numbers. so far a challenge I tried to find a more efficient algorithm.
This one takes about 0.5s:
Private Const cIntNumberOfDigits As Integer = 9
Private mStrNum As String
Private mRng As Range
Private Sub GetNumbers()
Dim dblStart As Double
Set mRng = Range("a1")
dblStart = Timer
mStrNum = Replace(Space(cIntNumberOfDigits), " ", "0")
subGetNumbers 8
Debug.Print (Timer - dblStart) / 10000000, (Timer - dblStart)
End Sub
Private Sub subGetNumbers(intMaxSum As Integer, Optional intStartPos As Integer = 1)
Dim i As Integer
If intStartPos = cIntNumberOfDigits Then
Mid(mStrNum, intStartPos, 1) = intMaxSum
mRng.Value = Val(mStrNum)
Set mRng = mRng.Offset(1)
Mid(mStrNum, intStartPos, 1) = 0
Exit Sub
End If
For i = 0 To intMaxSum
Mid(mStrNum, intStartPos, 1) = CStr(i)
subGetNumbers intMaxSum - i, intStartPos + 1
Next i
Mid(mStrNum, intStartPos, 1) = 0
End Sub
It can be sped up further by about factor 10 by using arrays instead of writing directly to the range and offsetting it, but that should suffice for now! :-)
As an alternative, You can use a function like this:
Function isInnerLowr8(x As Long) As Boolean
Dim strX As String, inSum As Long
isInnerLowr8 = False
strX = Replace(CStr(x), "0", "")
For i = 1 To Len(strX)
Sum = Sum + Val(Mid(strX, i, 1))
If Sum > 8 Then Exit Function
Next i
isInnerLowr8 = True
End Function
Now change If i = 8 to If isInnerLowr8(i) Then.
Working through trace tables and wanted to check to see if my results where correct, I have designed the following code to check each stage of the loop, but the code keeps throwing up an error about casting when i try to run it. I can see when the error comes back that the writeline is holding info but what have i done wrong.
Module Module1
Sub Main()
Dim aWord As String
Dim bWord As String
Dim result As Boolean
Dim temp As Char
Dim pos As Integer
Dim index As Integer
index = 0
aWord = "Simple"
bWord = "abcdef"
result = True
If Not (aWord.Length = bWord.Length) Then
result = False
Else
While index < bWord.Length And result
temp = bWord.Chars(index)
pos = aWord.IndexOf(temp)
If pos >= 0 Then
aWord = aWord.Remove(pos, 1)
Else
result = False
End If
WriteLine(bWord, aWord, temp, pos.ToString, index.ToString)
End While
End If
End Sub
End Module
You are calling WriteLine() incorrectly. It should be:
WriteLine("{0}, {1}, {2}, {3}, {4}", bWord, aWord, temp, pos.ToString, index.ToString)
I have string "ololo123".
I need get position of first digit - 1.
How to set mask of search ?
Here is a lightweight and fast method that avoids regex/reference additions, thus helping with overhead and transportability should that be an advantage.
Public Function GetNumLoc(xValue As String) As Integer
For GetNumLoc = 1 To Len(xValue)
If Mid(xValue, GetNumLoc, 1) Like "#" Then Exit Function
Next
GetNumLoc = 0
End Function
Something like this should do the trick for you:
Public Function GetPositionOfFirstNumericCharacter(ByVal s As String) As Integer
For i = 1 To Len(s)
Dim currentCharacter As String
currentCharacter = Mid(s, i, 1)
If IsNumeric(currentCharacter) = True Then
GetPositionOfFirstNumericCharacter = i
Exit Function
End If
Next i
End Function
You can then call it like this:
Dim iPosition as Integer
iPosition = GetPositionOfFirstNumericCharacter("ololo123")
Not sure on your environment, but this worked in Excel 2010
'Added reference for Microsoft VBScript Regular Expressions 5.5
Const myString As String = "ololo123"
Dim regex As New RegExp
Dim regmatch As MatchCollection
regex.Pattern = "\d"
Set regmatch = regex.Execute(myString)
MsgBox (regmatch.Item(0).FirstIndex) ' Outputs 5
I actually have that function:
Public Function GetNumericPosition(ByVal s As String) As Integer
Dim result As Integer
Dim i As Integer
Dim ii As Integer
result = -1
ii = Len(s)
For i = 1 To ii
If IsNumeric(Mid$(s, i, 1)) Then
result = i
Exit For
End If
Next
GetNumericPosition = result
End Function
You could try regex, and then you'd have two problems. My VBAfu is not up to snuff, but I'll give it a go:
Function FirstDigit(strData As String) As Integer
Dim RE As Object REMatches As Object
Set RE = CreateObject("vbscript.regexp")
With RE
.Pattern = "[0-9]"
End With
Set REMatches = RE.Execute(strData)
FirstDigit = REMatches(0).FirstIndex
End Function
Then you just call it with FirstDigit("ololo123").
If speed is an issue, this will run a bit faster than Robs (noi Rob):
Public Sub Example()
Const myString As String = "ololo123"
Dim position As Long
position = GetFirstNumeric(myString)
If position > 0 Then
MsgBox "Found numeric at postion " & position & "."
Else
MsgBox "Numeric not found."
End If
End Sub
Public Function GetFirstNumeric(ByVal value As String) As Long
Dim i As Long
Dim bytValue() As Byte
Dim lngRtnVal As Long
bytValue = value
For i = 0 To UBound(bytValue) Step 2
Select Case bytValue(i)
Case vbKey0 To vbKey9
If bytValue(i + 1) = 0 Then
lngRtnVal = (i \ 2) + 1
Exit For
End If
End Select
Next
GetFirstNumeric = lngRtnVal
End Function
An improved version of spere's answer (can't edit his answer), which works for any pattern
Private Function GetNumLoc(textValue As String, pattern As String) As Integer
For GetNumLoc = 1 To (Len(textValue) - Len(pattern) + 1)
If Mid(textValue, GetNumLoc, Len(pattern)) Like pattern Then Exit Function
Next
GetNumLoc = 0
End Function
To get the pattern value you can use this:
Private Function GetTextByPattern(textValue As String, pattern As String) As String
Dim NumLoc As Integer
For NumLoc = 1 To (Len(textValue) - Len(pattern) + 1)
If Mid(textValue, NumLoc, Len(pattern)) Like pattern Then
GetTextByPattern = Mid(textValue, NumLoc, Len(pattern))
Exit Function
End If
Next
GetTextByPattern = ""
End Function
Example use:
dim bill as String
bill = "BILLNUMBER 2202/1132/1 PT2200136"
Debug.Print GetNumLoc(bill , "PT#######")
'Printed result:
'24
Debug.Print GetTextByPattern(bill , "PT#######")
'Printed result:
'PT2200136