I have a function where the intention is to return either a string to signify that the function has completed and retrieved the required value or an error to indicate there has been an issue.
To see whether I could do this, I bashed together the following:
Private Function one()
Debug.Print TypeName(two(False))
End Function
Private Function two(b As Boolean) As Variant
Dim e As New ErrObject
If (b) Then
two = True
Else
two = e.number
End If
End Function
Now, this fails at two = e.number because you don't appear to be able to set an error number in this way - the syntax is incorrect.
I could use err.raise but then the intention is to pass the whole error object back as I can then have a custom number and fill in my own description etc...
How do you actually pass the err object back? Can you actually do it and is this the most effective way in achieving what I am setting out to do?
Thanks
You don't. Err is a globally-scoped Function from the standard library VBA.Information module, that returns an ErrObject instance.
the intention is to pass the whole error object back as I can then have a custom number and fill in my own description
You don't need to pass the whole error object back to throw custom errors.
Const ERR_SomethingBad = vbObjectError + 42
Err.Raise ERR_SomethingBad, "MyModule.MyProcedure", "Uh-oh"
Err is already in global scope - you don't need to pass error objects around... and in fact, you simply can't. Because the ErrObject class isn't creatable. This:
Dim e As ErrObject
Set e = New ErrObject
Throws run-time error 429 "ActiveX can't create object".
The very idea behind errors (and exceptions, if you're any familiar with languages that feature exceptions), is that they replace the old archaic "return status code" way, e.g.:
''' DON'T DO THIS, IT's 2017!!!
Public Function DoSomething(ByVal p1 As Double, ByRef outResult As Double) As Long
If p1 = 0 Then
DoSomething = 11 'return code for division by zero error
Exit Function
End If
outResult = 42 / p1
DoSomething = 0 'return code for OK - everything went well!
End Function
With this pattern every procedure is a Function that returns an error code; the actual return value is passed as a ByRef / out parameter, and the caller would have to do this before they can trust the result:
Dim result As Double
Dim e As Long
e = DoSomething(42, result)
If e = 0 Then
' happy path
Else
MsgBox Error$(e) ' error path
End If
The On Error statement streamlines the code by taking most error-handling concerns out of the "happy path".
I am following a tutorial and get a compile error at the hello world example function.
What's wrong here?
Here is the code I tried:
Function hi()
hi = "hello world"
End Function`
edit: suggested declarations didn't help
edit: getting closer. brackets seem to be a problem when calling "hi()"
You can use 2 ways to implement your "Hello World" example.
Option 1: Simple and good enough for your example, using a regular Sub :
Sub Hi_()
Dim HiStr As String
HiStr = "Hello World"
MsgBox HiStr
End Sub
Option 2: Using a Function with "Hello World" example:
Function Hi(TestHi As String) As String
' Input: this function receives a string as a parameter
' Output: returns a string
Hi = "Test Function with " & TestHi
End Function
Now we need a Sub to test the Function:
Sub Test_Hi_Function()
Dim TstHiFunc As String
' send "Hello World" to Function Hi as a parameter
' TstHiFunc gets the returned string result
TstHiFunc = Hi("Hello World")
' for debug only
MsgBox TstHiFunc
End Sub
I am trying to fix a VBA that uses Selenium1.0.23 to open a site and login. My client said everything is working on his end except that the VBA must be putting the wrong Username and Password because the site is giving the wrong username-password message.
Now I got the script and try to run it but I got stuck on the functions giving "Argument Not Optional". Below is the script:
Here is the part with error. It highlights the ".setVariation" part.
Private Function setVariationOnPage(browser As SeleniumWrapper.WebDriver, variations As Scripting.Dictionary) As Long
Dim name
For Each name In variations.keys
ProductVariations.setVariation browser, variations(name)
Next name
End Function
I believe the above function is calling another function on a separate module because there is a module name ProductVariations and a function called setvariation in it.
Public Function setVariation(browser As SeleniumWrapper.WebDriver, ByVal name As String, value As String)
On Error GoTo setVariationError
Dim li As WebElement
Dim lis As Collection
Set lis = getVariationListItems(browser, name)
If lis Is Nothing Then
GoTo setVariationError
Exit Function
End If
For Each li In lis
Dim link As WebElement
Set link = getLinkFromVariationListItem(li)
If LCase(Trim(getVariationValueNameFromListItem(li))) = LCase(Trim(value)) Then
If InStr(li.getAttribute("class"), "active") = 0 Then
link.Click
ScrapingUtil.waitForPageToLoad browser
If InStr(li.getAttribute("class"), "active") = 0 Then
GoTo setVariationError
End If
End If
Exit Function
End If
Next li
setVariationError:
Dim msg As String
msg = "Unable to set variation: ""{name}"" = ""{value}"""
msg = Replace(msg, "{name}", name)
msg = Replace(msg, "{value}", value)
Err.Description = msg
Err.raise 1
End Function
Then obviously this function calls another function and that function calls another. It's hell to troubleshoot it and I really need help.
making parameter as optional..
Public Function setVariation(browser As SeleniumWrapper.WebDriver, ByVal name As String, optional value As String).
I'm trying to grab user input from a console window, and break into array which works fine with split. I've recently read about split. I have created the following arrays to check for 'input' possibilities in each position of the split index.. but can't figure out how to actually check each position for valid input, let alone do something with the users 'command'.
Dim l1args as Array = {"help","exit","start"} 'first position possibilities
Dim l2args as Array = {"server","exit"} 'second position possibilities
Console.Write("console# ")
Dim input = Console.ReadLine()
Dim tokens As String() = input.Split(CChar(" "))
Can anyone give me some guidance? I want to be able to check for a combo of user input and do something with it. Then, if no possibilities exist or is off, I want to write an error message to console like "command not recognized"....
Thanks....
This should be a "recurrent algorithm".
you should think like this "start" is function that gets a variable (what to start?).
This variable is also a command and so you need to run it before starting the "start command".
for example the command: "start print 1"
lets say that print just prints 1, so basically what you are doing is getting the value of print 1 (the value of this is 1 because print 1 just prints 1) and then you will do start 1 (you will start 1, if there is no "1" make an error msg to the user.
The way I would do it is like this:
A command has a name and the amount of arguments it needs.
for example the start command will have the name "start" and it need 1 argument.
OR the command help will have a name "help" and will need 0 arguments.
OR the command print will have a name "print" and will need 1 arguments.
Now lets say the user entered the command "start print chrome"
you will look on the first word and see that start is a recognized command, so now you know you need to get its argument so you will go to the next word and run it as a command and give the result to the start command. So when going to the next word you see print this is also a recognized command so you will go to the next command to get the argument to the print command, now chrome is not a recognized command so you will assume that it is the value "chrome" (can be anythings else string, double ...) and you will run the command print with the argument "chrome" after that you will run the command start with the result of the command print.
Run Example:
Requested implementation:
This is a console application in vb.net .
Usually I am now putting all the classes in one file, but to post it here I had to do so.
try using the command "print sum 9 10", this will print 19
Option Strict On
Option Explicit On
Module Module1
Public AllCommand As Dictionary(Of String, ConsoleCommand)
Sub Main()
GenerateAllCommands()
Dim UserCommand() As String
While True
UserCommand = Console.ReadLine().Split({" "c}, System.StringSplitOptions.RemoveEmptyEntries)
RunCommand(UserCommand, True, 0)
End While
End Sub
Public Function RunCommand(FullCommand() As String, IsFirst As Boolean, CommandIndex As Integer) As CommandReturnedValue
If CommandIndex > FullCommand.Length - 1 Then
Return Nothing
End If
Dim CurrentCommand As String
If FullCommand.Length = 0 Then
If IsFirst Then
Console.WriteLine("Error - Empty String is not a valid command")
End If
Return New CommandReturnedValue("", CommandIndex)
End If
CurrentCommand = FullCommand(CommandIndex).Trim().ToLower()
If CurrentCommand.Length = 0 Then
If IsFirst Then
Console.WriteLine("Error - Empty String is not a valid command")
End If
Return New CommandReturnedValue("", CommandIndex)
End If
Dim TheCommnad As ConsoleCommand
If AllCommand.ContainsKey(CurrentCommand) Then
TheCommnad = AllCommand.Item(CurrentCommand)
Dim TempArgs(TheCommnad.Args - 1) As CommandReturnedValue
Dim TempIndex As Integer = CommandIndex + 1
For i As Integer = 0 To TheCommnad.Args - 1 Step 1
If TempIndex > FullCommand.Length - 1 Then
Console.WriteLine("Error - Need more arguments for """ & TheCommnad.CommandName & """ Command, You entered " & i & " Arguments, This command need " & TheCommnad.Args & " Arguents")
Return New CommandReturnedValue("", CommandIndex)
End If
TempArgs(i) = RunCommand(FullCommand, False, TempIndex)
If TempArgs(i) Is Nothing Then
Console.WriteLine("Error - Need more arguments for """ & TheCommnad.CommandName & """ Command, You entered " & i & " Arguments, This command need " & TheCommnad.Args & " Arguents")
Return New CommandReturnedValue("", CommandIndex)
End If
If TempArgs(i).CommandIndex <> -1 Then
TempIndex = TempArgs(i).CommandIndex + 1
Else
TempIndex += 1
End If
Next
If TempArgs.Length = 0 Then
Return TheCommnad.DoCommand(TempArgs, CommandIndex)
Else
Return TheCommnad.DoCommand(TempArgs, TempArgs(TempArgs.Length - 1).CommandIndex)
End If
Else
If IsFirst Then
Console.WriteLine("Error - Unknown Command """ & CurrentCommand & """")
End If
Return New CommandReturnedValue(FullCommand(CommandIndex), CommandIndex)
End If
End Function
Public Sub GenerateAllCommands()
'NOTE - ALL COMMAND MUST BE LOWER CASE
AllCommand = New Dictionary(Of String, ConsoleCommand)
AllCommand.Add("help", New HelpCommand())
AllCommand.Add("start", New StartCommand())
AllCommand.Add("print", New PrintCommand())
AllCommand.Add("sum", New SumCommand())
End Sub
End Module
Public Class CommandReturnedValue
Public Value As String
Public CommandIndex As Integer
Public Sub New(Value As String, Optional index As Integer = -1)
Me.Value = Value
Me.CommandIndex = index
End Sub
End Class
Public MustInherit Class ConsoleCommand
Public ReadOnly CommandName As String
Public ReadOnly Args As Integer
Public Sub New(Name As String, args As Integer)
Me.CommandName = Name
Me.Args = args
End Sub
Public MustOverride Function DoCommand(AllArgs() As CommandReturnedValue, CommandIndex As Integer) As CommandReturnedValue
End Class
Public Class StartCommand
Inherits ConsoleCommand
Public Sub New()
MyBase.New("start", 1)
End Sub
Public Overrides Function DoCommand(AllArgs() As CommandReturnedValue, CommandIndex As Integer) As CommandReturnedValue
If System.IO.File.Exists(AllArgs(0).Value) Then
Shell(AllArgs(0).Value, AppWinStyle.NormalFocus)
Else
Console.WriteLine("Error - Unknown file (Start Command)")
End If
Return Nothing
End Function
End Class
Public Class HelpCommand
Inherits ConsoleCommand
Public Sub New()
MyBase.New("help", 0)
End Sub
Public Overrides Function DoCommand(AllArgs() As CommandReturnedValue, CommandIndex As Integer) As CommandReturnedValue
Console.WriteLine("I see you tryed doing the help commnad ;)")
Console.WriteLine("Commands: ")
Console.WriteLine(" Start <FileName> - will try to start the <filename>")
Console.WriteLine(" help - will show a help list")
Console.WriteLine(" print <value> - will print (and return) <value>")
Return New CommandReturnedValue("Help Command", CommandIndex)
End Function
End Class
Public Class SumCommand
Inherits ConsoleCommand
Public Sub New()
MyBase.New("sum", 2)
End Sub
Public Overrides Function DoCommand(AllArgs() As CommandReturnedValue, CommandIndex As Integer) As CommandReturnedValue
Dim x As Integer
Dim y As Integer
Try
x = Convert.ToInt32(AllArgs(0).Value)
Catch ex As Exception
Console.WriteLine("Error - Arguments to sum must be an integer, """ & AllArgs(0).Value & """ is not an integer")
Return Nothing
End Try
Try
y = Convert.ToInt32(AllArgs(1).Value)
Catch ex As Exception
Console.WriteLine("Error - Arguments to sum must be an integer, """ & AllArgs(1).Value & """ is not an integer")
Return Nothing
End Try
Return New CommandReturnedValue((x + y).ToString, CommandIndex)
End Function
End Class
Public Class PrintCommand
Inherits ConsoleCommand
Public Sub New()
MyBase.New("print", 1)
End Sub
Public Overrides Function DoCommand(AllArgs() As CommandReturnedValue, CommandIndex As Integer) As CommandReturnedValue
Console.WriteLine("Print Command: """ & AllArgs(0).Value & """")
Return AllArgs(0)
End Function
End Class
English is not my mother tongue; please excuse any errors on my part.
I am trying to learn more about programming language.
I am using the following code using Recursion.
I cause it to run until a stack exception is thrown.
Without traping the error and/or defensively coding to prevent
such a deep recursion: - Are there adjustments I can make
to free any stack space when this routine runs?
Module Module1
Private var As Integer = 1
Sub Main()
Take1(var)
End Sub
Public Function Take1(p1 As Integer) As Integer
p1 = p1 + 1
Console.Write(p1 & vbCrLf)
Take1 = Nothing
Call Take2(p1)
End Function
Public Function Take2(p1 As Integer) As Integer
p1 = p1 + 1
Console.Write(p1 & vbCrLf)
Take2 = Nothing
Call Take1(p1)
End Function
End Module
Your code is resulting in unbounded recursion. See link here that describes this: http://msdn.microsoft.com/en-us/library/system.stackoverflowexception.aspx
The link is saying that starting from .NET 2.0 you can't catch this type of exception with try-catch block and gives good reasons why not.