I want to use a variable that's in the scope of all my project, what's a good way to accomplish this?
public User as (some type)
(
var (sometype)
var2 (sometype)
)
Example:
If User.name = "ADMIN" Then
otherForm.Caption = User.name
otherForm.Show
End If
You could create a class that encapsulates all of this data inside of it:
Example:
Public Class User
Public Property Name As String
Public Property Age As Integer
Sub New(_Name As String, _age As Integer)
Name = _Name
Age = _age
End Sub
End Class
Then, you'd just declare it, and set the properties:
Dim U as new User("Thomas", 18)
Messagebox.Show(U.Name) ' Will print "Thomas"
I suggest you define a class for such 'global' properties.
For example, you could name it 'ProjectSettings'.
Public Class ProjectSettings
Public Shared CurrentUser as String
Public Shared DateTimeFormat as String
...etc...
Public Shared Sub Initialize()
'Initialize your members here
End Sub
End Class
From outside, you could access it like this:
ProjectSettings.CurrentUser
ProjectSettings.DateTimeFormat
But remember, there are heaps of different approaches of how to do this.
In the above case, you could also define the Members as Readonly Properties, making sure nobody accidentally overwrites the values. Or you could define an object 'User' for CurrentUser, if you need to store more data.
It really depends on what you want to achieve with your global properties. It's only important to keep them central so that everybody in your team (including yourself) knows where to find them. Else it can easily lead to unstructured, bad code.
If you are trying to have a "settings" class like some have suggested, you probably want to look at the My.Settings or My.Resources namespaces for VB .Net
You would end up with something like:
If User.name = My.Settings.Admin Then
otherForm.Caption = User.name
otherForm.Show
End If
Is this what you are trying to do?
Your other option is to use a module or a "Public NotInheritable" class with a private constructor, with public properties or constants. Like this:
Public NotInheritableClass ProjectSettings
Public Const Admin as String = "ADMIN"
Public Const Whatever as Decimal = 3.14D
Private Sub New()
End Sub
End Class
Then you could have:
If User.name = ProjectSettings.Admin Then
otherForm.Caption = User.name
otherForm.Show
End If
I like these solutions a little better because there is no way that you can instantiate the settings class.
If you just want your User class to be globally accessible (which implies there is only one given User at a time), then you could do something similar with the User class.
EDIT: Your User class would look like:
Public NotInheritableClass User
Public Const Name as String = "Some Name"
Public Property YouCanChangeThisProperty as String = "Change Me"
Private Sub New()
End Sub
End Class
To use it:
User.YouCanChangeThisProperty = "Changed"
MessageBox.Show("User name: " & User.Name & "; the other property is now: " & User.YouCanChangeThisProperty")
This will give you a message box with:
"User name: Some Name; the other property is now: Changed"
You can create New Class named User
Public Class User
Private mstrName As String
Private mdBirth As Date
Public Property Name() As String
Get
Return mstrName
End Get
Set(ByVal vName As String)
mstrName = vName
End Set
End Property
Public Property BirthDate() As Date
Get
Return mdBirth
End Get
Set(ByVal vBirth As Date)
mdBirth = vBirth
End Set
End Property
ReadOnly Property Age() As Integer
Get
Return Now.Year - mdBirth.Year
End Get
End Property
End Class
You can use this class like this :
Dim Name1 as New User
Name1.Name = "ADMIN"
Name1.BirthDate = CDate("February 12, 1969")
Then Check it (by Msgbox or whatever) :
Msgbox(Name1.Name)
Msgbox(Name1.BirthDate.ToString & " and Now is " & format(Name1.Age) & " years old")
Related
I have a class ClsAnimal containing the string property species, and also method plural which just returns a string with added "s" at the end of a string. I wonder if it's possible to apply .Plural to Animal.Species directly, as shown in the example below:
Sub Test()
Dim Animal As New ClsAnimal
Animal.Species = "cat"
debug.print Animal.Species
'expected result "cat"
debug.print Animal.Species.Plural
'expected result "cats"
End Sub
ClsAnimal Code:
Option Explicit
Private PSpecies As String
Property Let Species(val As String)
PSpecies = val
End Property
Property Get Species() As String
Species = PSpecies
End Property
'returns the name of an animal + "s"
Private Function Plural(val) As String
Plural = val & "s"
End Function
You can kind of hack your way to the behavior you are describing. They way I could implement this is to create a new class that "extends" strings. I've called mine StringExt and it looks like this:
Option Explicit
Private pValue As String
'#DefaultMember
Public Property Get Value() As String
Value = pValue
End Property
Public Property Let Value(val As String)
pValue = val
End Property
Public Function Pluralize() As String
Dim suffix As String
'Examine last letter of the string value...
Select Case LCase(Right(pValue, 1))
Case "" 'empty string
suffix = ""
Case "s" 'words that end in s are pluralized by "es"
suffix = "es"
'Test for any other special cases you want...
Case Else ' default case
suffix = "s"
End Select
Pluralize = pValue & suffix
End Function
This is a wrapper class that wraps around an inner string value. It has a single method which will try to return the plural of the inner string value. One thing to note here is the use of a DefaultMember. I used a really handy vba editor COM addin called RubberDuck to do all the behind-the-scenes work for me with the Default Member. You can do it manually though. You would need to export the class module and modify it in a text editor, adding the Attribute Value.VB_UserMemId = 0 tag inside the property getter:
...
Public Property Get Value() As String
Attribute Value.VB_UserMemId = 0
Value = pValue
End Property
Public Property Let Value(val As String)
pValue = val
End Property
...
Then, import the module back into your vba project. This attribute is not visible in the vba editor. More on default members here but it basically means this property will be returned if no property is specified.
Next, we change up your animal class a bit, using our new StringExt type for the Species property:
Option Explicit
Private pSpecies As StringExt
Public Property Set Species(val As StringExt)
pSpecies = val
End Property
Public Property Get Species() As StringExt
Set Species = pSpecies
End Property
Private Sub Class_Initialize()
Set pSpecies = New StringExt
End Sub
Note here that you'll now need to make sure the pSpecies field gets instantiated since it is an object type now. I do this in the class Initializer to enure it always happens.
Now, your client code should work as expected.
Sub ClientCode()
Dim myAnimal As Animal
Set myAnimal = New Animal
myAnimal.Species = ""
Debug.Print myAnimal.Species.Pluralize
End Sub
Disclamer:
Substituting a basic string type for an object type might cause unexpected behavior in certain fringe situations. You are probably better off just using some global string helper method that takes a string parameter and returns the plural version. But, my implementation will get the behavior you asked for in this question. :-)
I have several properties, for example
Public Property FIRSTNAME As New SQLString("FirstName", 50)
Public Property FULLNAME As New SQLString("Name", 50)
The SQLString object is defined as:
Public Class SQLString
Property SQL_Column As String
Property Limit As Integer
Property Value As String
Public Sub New(SQLcolumn As String, limit_ As Integer)
SQL_Column = SQLcolumn
Limit = limit_
End Sub
Public ReadOnly Property SQL_value() As String
Get
Return "'" & clean(Value, Limit) & "'"
End Get
End Property
End Class
Notice that through this method, each of my properties (e.g. FIRSTNAME) is able to have several sub properties, which is necessary.
To access them, it's simply for example FIRSTNAME.SQL_Column.
This works, however what I would like is to also be able to store a value (e.g. string data type) on the FIRSTNAME property itself, which would make accessing it like:
Dim MyFirstName As String = FIRSTNAME
Rather than:
Dim MyFirstName As String = FIRSTNAME.Value
Which is what I currently have to do.
The only way I can see to do this is to have the SQLString object be set to string (or another data type) by default, like:
Public Class SQLString As String
Obviously the above code does not work, but I'm wondering if there is an equivalent that does?
The default access modifier to a property (ie: Public, Private, etc) is the most restrictive when no access modifier is provided. In SQLString class, since there is not a Public access modifier in front of the properties in the class, they are essentially Private and not accessible from outside of the class.
Adding the access modifier to the properties should fix the issue you see:
Public Property SQL_Column As String
Public Property Limit As Integer
Public Property Value As String
Please tell me the problem for the vote downs - here is a working .NET fiddle of the proposed code changes above (https://dotnetfiddle.net/96o8qm).
Imports System
Dim p as Person = new Person()
p.FIRSTNAME = new SQLString("Test", 1)
p.FIRSTNAME.Value = "Test Value"
Console.WriteLine("Person Value: {0}", p.FIRSTNAME.Value)
Public Class Person
Public Property FIRSTNAME AS SQLString
End Class
Public Class SQLString
Public Property SQL_Column As String
Public Property Limit As Integer
Public Property Value As String
Public Sub New(SQLcolumn As String, limit_ As Integer)
SQL_Column = SQLcolumn
Limit = limit_
End Sub
Public ReadOnly Property SQL_value() As String
Get
Return ""
End Get
End Property
End Class
This yields the output:
Person Value: Test Value
The answer to your question is quite simple; add a CType widening operator.
Example:
Public Class SQLString
Public Shared Widening Operator CType(ByVal s As SQLString) As String
Return If((s Is Nothing), Nothing, s.Value)
End Operator
Public Property Value As String
End Class
Test:
Dim firstName As New SQLString() With {.Value = "Bjørn"}
Dim myName As String = firstName
Debug.WriteLine(myName)
Output (immediate window):
Bjørn
I'm having a heck of a time trying to add fields like department and title.
I'm using this to create a user account:
Dim ctx As New PrincipalContext(ContextType.Domain, "domain.name.pvt", "OU=Users,DC=global,DC=pvt")
Dim usr As UserPrincipal = New UserPrincipal(ctx)
I have no problem creating the account but can't add simple things like Department and Title. I read about using extensions but its in C++ and have no clue on how to do it.
Any help would be great!!! Thanks!
If you're on .NET 3.5 and up, you should check out the System.DirectoryServices.AccountManagement (S.DS.AM) namespace. Read all about it here:
Managing Directory Security Principals in the .NET Framework 3.5
MSDN docs on System.DirectoryServices.AccountManagement
To extend the UserPrincipal class, you don't need much - something like this will suffice (I wrote this in C# originally and just converted it to VB.NET on the 'net - I hope there's no issues with the VB.NET code!)
Imports System.DirectoryServices.AccountManagement
Namespace ADExtended
<DirectoryRdnPrefix("CN")> _
<DirectoryObjectClass("Person")> _
Public Class UserPrincipalEx
Inherits UserPrincipal
' Inplement the constructor using the base class constructor.
Public Sub New(context As PrincipalContext)
MyBase.New(context)
End Sub
' Implement the constructor with initialization parameters.
Public Sub New(context As PrincipalContext, samAccountName As String, password As String, enabled As Boolean)
MyBase.New(context, samAccountName, password, enabled)
End Sub
' Create the "Department" property.
<DirectoryProperty("department")> _
Public Property Department() As String
Get
If ExtensionGet("department").Length <> 1 Then
Return String.Empty
End If
Return DirectCast(ExtensionGet("department")(0), String)
End Get
Set
ExtensionSet("department", value)
End Set
End Property
' Create the "Title" property.
<DirectoryProperty("title")> _
Public Property Title() As String
Get
If ExtensionGet("title").Length <> 1 Then
Return String.Empty
End If
Return DirectCast(ExtensionGet("title")(0), String)
End Get
Set
ExtensionSet("title", value)
End Set
End Property
' Implement the overloaded search method FindByIdentity.
Public Shared Shadows Function FindByIdentity(context As PrincipalContext, identityValue As String) As UserPrincipalEx
Return DirectCast(FindByIdentityWithType(context, GetType(UserPrincipalEx), identityValue), UserPrincipalEx)
End Function
' Implement the overloaded search method FindByIdentity.
Public Shared Shadows Function FindByIdentity(context As PrincipalContext, identityType As IdentityType, identityValue As String) As UserPrincipalEx
Return DirectCast(FindByIdentityWithType(context, GetType(UserPrincipalEx), identityType, identityValue), UserPrincipalEx)
End Function
End Class
End Namespace
Now, you just use the UserPrincipalEx class:
Dim ctx As New PrincipalContext(ContextType.Domain, "domain.name.pvt", "OU=Users,DC=global,DC=pvt")
Dim usr As UserPrincipalEx = New UserPrincipalEx(ctx)
usr.Title = "......."
usr.Department = "......."
The new S.DS.AM makes it really easy to play around with users and groups in AD!
How can I see what properties an element has in a VB script? Example:
Dim list : Set list = CreateObject( "Scripting.Dictionary" )
' ... Fill List ...
WriteListElements list
...
Sub WriteListElements ( list )
Dim e, le
For Each e In list
Set le = list(e) ' what properties does le have?
le.name_of_user_defined_attribut ' I want to access a property but dont know the exact name
Next
End Sub
I use a Tool with a VBScript API. In that API I can read (user defined) attributes from that Tool. But while running the script I get an error telling me that it does not know the name of that user defined attribut. But I use it in the tool. Now I would like to know which attributes are availble in the array above to see if the user defined attributes are named specificly.
Not really possible. Only very basic type information is available in the VBScript runtime. Ideally you could create an adapter that translates your tool's objects into standard Dictionary objects and iterate the Keys. If that's not possible, the best you can do is check the type name for each object before invoking its members. Example:
<html>
<body>
<script type="text/vbscript">
Class Human
Private m_name
Public Property Get Name
Name = m_name
End Property
Public Property Let Name(newName)
m_name = newName
End Property
End Class
Dim joe
Set joe = new Human
joe.Name = "Joe Coder"
Dim list
Set list = CreateObject( "Scripting.Dictionary" )
list.Add "a", 5
list.Add "b", joe
list.Add "c", "apples"
WriteListElements list
Sub WriteListElements ( list )
Dim e
For Each e In list
If (TypeName(list.Item(e)) = "Human") Then
document.write("We have found a Human: " &_
"<b>" & list.Item(e).Name & "</b>")
End If
Next
End Sub
</script>
</body>
</html>
Will you be able to get the list of properties from a script like this?
http://www.vbsedit.com/scripts/misc/wmi/scr_1332.asp
And, you can then use eval() or execute to get the values of these properties.
Dim list : Set list = CreateObject( "Scripting.Dictionary" )
' ... Fill List ...
WriteListElements list
...
Sub WriteListElements ( list )
Dim e, le
For Each e In list
Set le = e.Items
Response.Write le(name_of_user_defined_attribut)
Next
End Sub
It is easy - use a pseudo reflection:
class Developer
Public reflection
'=============================
'Private properties
private mId
private mFirstName
private mLastName
private sub Class_Initialize()
reflection = Array("Id","FirstName","LastName")
end sub
private sub Class_Terminate()
end sub
'=============================
'public properties
public property get Id()
Id = mId
end property
public property let Id(val)
mId = val
end property
public property get FirstName()
FirstName = mFirstName
end property
public property let FirstName(val)
mFirstName = val
end property
public property get LastName()
LastName = mLastName
end property
public property let LastName(val)
mLastName = val
end property
end class
For each property in obj.reflection
document.write(property)
document.write( Eval ("obj." & property) )
Next
I am using Window Application for my project. There is situation where i need to define string enum and using it in my project.
i.e.
Dim PersonalInfo As String = "Personal Info"
Dim Contanct As String = "Personal Contanct"
Public Enum Test
PersonalInfo
Contanct
End Enum
Now i want value of that variable PersonalInfo and Contract as "Personal Info" and "Personal Contanct".
How can i get this value using ENUM? or anyother way to do it.
Thanks in advance...
For non-integer values, Const in a Structure (or Class) can be used instead:
Structure Test
Const PersonalInfo = "Personal Info"
Const Contanct = "Personal Contanct"
End Structure
or in a Module for direct access without the Test. part:
Module Test
Public Const PersonalInfo = "Personal Info"
Public Const Contanct = "Personal Contanct"
End Module
In some cases, the variable name can be used as a value:
Enum Test
Personal_Info
Personal_Contanct
End Enum
Dim PersonalInfo As String = Test.Personal_Info.ToString.Replace("_"c, " "c)
' or in Visual Studio 2015 and newer:
Dim Contanct As String = NameOf(Test.Personal_Contanct).Replace("_"c, " "c)
You could just create a new type
''' <completionlist cref="Test"/>
Class Test
Private Key As String
Public Shared ReadOnly Contact As Test = New Test("Personal Contanct")
Public Shared ReadOnly PersonalInfo As Test = New Test("Personal Info")
Private Sub New(key as String)
Me.Key = key
End Sub
Public Overrides Function ToString() As String
Return Me.Key
End Function
End Class
and when you use it, it kinda looks like an enum:
Sub Main
DoSomething(Test.Contact)
DoSomething(Test.PersonalInfo)
End Sub
Sub DoSomething(test As Test)
Console.WriteLine(test.ToString())
End Sub
output:
Personal Contanct
Personal Info
How about using Tagging. Something like:
Public Enum MyEnum
<StringValue("Personal Contact")>Contact
<StringValue("My PersonalInfo")>PersonalInfo
End Enum
You would have to write the StringValue attribute as:
Public Class StringValueAttribute
Inherits Attribute
Public Property Value As String
Public Sub New(ByVal val As String)
Value = val
End Sub
End Class
To get it out:
Public Function GetEnumByStringValueAttribute(value As String, enumType As Type) As Object
For Each val As [Enum] In [Enum].GetValues(enumType)
Dim fi As FieldInfo = enumType.GetField(val.ToString())
Dim attributes As StringValueAttribute() = DirectCast(fi.GetCustomAttributes(GetType(StringValueAttribute), False), StringValueAttribute())
Dim attr As StringValueAttribute = attributes(0)
If attr.Value = value Then
Return val
End If
Next
Throw New ArgumentException("The value '" & value & "' is not supported.")
End Function
Public Function GetEnumByStringValueAttribute(Of YourEnumType)(value As String) As YourEnumType
Return CType(GetEnumByStringValueAttribute(value, GetType(YourEnumType)), YourEnumType)
End Function
And then a call to get the Enum (using string attribute):
Dim mEnum as MyEnum = GetEnumByStringValueAttribute(Of MyEnum)("Personal Contact")
To get the "Attribute" value out (removed handling 'Nothing' for clarity):
Public Function GetEnumValue(Of YourEnumType)(p As YourEnumType) As String
Return DirectCast(Attribute.GetCustomAttribute(ForValue(p), GetType(StringValueAttribute)), StringValueAttribute).Value
End Function
Private Function ForValue(Of YourEnumType)(p As YourEnumType) As MemberInfo
Return GetType(YourEnumType).GetField([Enum].GetName(GetType(YourEnumType), p))
End Function
And the call to get the string attribute (using Enum):
Dim strValue as String = GetEnumValue(Of MyEnum)(MyEnum.Contact)
How can i get this value using ENUM? or anyother way to do it.
There are three common ways of mapping enum values to strings:
Use a Dictionary(Of YourEnumType, String)
Decorate the enum values with attributes (e.g. DescriptionAttribute) and fetch them with reflection
Use a Switch statement
The first of these options is probably the simplest, in my view.
I know this is an old post put I found a nice solution that worth sharing:
''' <summary>
''' Gives acces to strings paths that are used often in the application
''' </summary>
Public NotInheritable Class Link
Public Const lrAutoSpeed As String = "scVirtualMaster<.lrAutoSpeed>"
Public Const eSimpleStatus As String = "scMachineControl<.eSimpleStatus>"
Public Const xLivebitHMI As String = "scMachineControl<.xLivebitHMI>"
Public Const xChangeCycleActive As String = "scMachineControl<.xChangeCycleActive>"
End Class
Usage:
'Can be anywhere in you applicaiton:
Link.xChangeCycleActive
This prevents unwanted extra coding, it's easy to maintain and I think this minimizes extra processor overhead.
Also visual studio shows the string attributes right after you type "Link"
just like if it is a regular Enum
If all you want to do is display the enums in a list or combo, you can use tagging such as
Private Enum MyEnum
Select_an_option___
__ACCOUNTS__
Invoices0
Review_Invoice
__MEETINGS__
Scheduled_Meetings0
Open_Meeting
Cancelled_Meetings0
Current_Meetings0
End Enum
Then pull the MyEnum into a string and use Replace (or Regex) to replace the tags: "___" with "...", "__" with "**", "_" with " ", and remove trailing numbers. Then repack it up into an array and dump it into a combobox which will look like:
Select an option...
**ACCOUNTS**
Invoices
Review Invoice
**MEETINGS**
Scheduled Meetings
Open Meeting
Cancelled Meetings
Current Meetings
(You can use the numbers to, say, disable a text field for inputting an invoice number or meeting room. In the example, Review Invoice and Open Meeting might be expecting additional input so a text box might be enabled for those selections.)
When you parse the selected combo item, the enumeration will work as expected but you only really need to add a single line of code - the text replacement - to get the combo to look as you wish.
(The explanation is about 10 times as involved as the actual solution!)
This technique from Microsoft - "How to: Determine the String Associated with an Enumeration Value (Visual Basic)" - will be useful in some situations (it didn't help with mine unfortunately though :( ). Microsoft's example:
VB:
Public Enum flavorEnum
salty
sweet
sour
bitter
End Enum
Private Sub TestMethod()
MsgBox("The strings in the flavorEnum are:")
Dim i As String
For Each i In [Enum].GetNames(GetType(flavorEnum))
MsgBox(i)
Next
End Sub