Related
my code was working fine until today when it isn't working (everthing running without errors)
and lblUp1lvl is set to 0
here is my code:
(I use the better comments extention so that's why some of the comments look funky)
Idle Time Waster.vb
Public Class formIdleTimeWaster
'*When User Loads the Program
Private Sub FormIdleTimeWaster_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'TODOSet cps value
Cps = 0
ClickValue = 0
timerCPS.Interval = 1000
timerCPS.Start()
'todo Update variables from save file
End Sub
'*When User Clicks the Button
Private Sub BtnUserClick_Click(sender As Object, e As EventArgs) Handles btnUserClick.Click
UserClicked()
lblTotalHW.Text = CStr(Total)
End Sub
'*Every Second this code runs
Private Sub TimerCPS_Tick(sender As Object, e As EventArgs) Handles timerCPS.Tick
AddCPS()
'Show CPS Value
lblCPS.Text = CStr(Cps)
End Sub
'?Adds 1 extra of what is meant to be added
'*User clicks Click Value upgrade button
Private Sub btnUp1_Click(sender As Object, e As EventArgs) Handles btnUp1.Click
Upgrade(Up1lvl, Up1Cost)
Up1Update()
lblUp1Cost.Text = CStr(Up1Cost)
lblUp1lvl.Text = CStr(Up1lvl)
lblClickValue.Text = CStr(Up1lvl)
End Sub
'*User clicks CPS upgrade value
Private Sub btnUp2_Click(sender As Object, e As EventArgs) Handles btnUp2.Click
Upgrade(Up2lvl, Up2Cost)
Up2Update()
lblUp2Cost.Text = CStr(Up2Cost)
lblUp2lvl.Text = CStr(Up2lvl)
lblCPS.Text = CStr(Up2lvl)
End Sub
End Class
Functions.vb
Public Module Functions
'*Define All Needed Values
Public Total As Integer
Public Cps As Integer
Public ClickValue As Integer
Public Up1lvl As Integer = 0
Public Up1Cost As Integer
Public Up2lvl As Integer = 0
Public Up2Cost As Integer
'*When User Clicks the Button
Function UserClicked()
Total = ClickValue + Total
Return Total
End Function
'*Calculate Cps
Function AddCPS()
'Add Cps to HWTotal
Total = Total + Cps
Return Total
End Function
'*Upgrade
Sub Upgrade(ByRef lvl, ByRef Cost)
If Total >= Cost Then
Total = CInt(Total) - Cost
lvl = lvl + 1
Else
MsgBox("Not Enough time wasted, go do nothing some more to get better at doing nothing", 0, "to early!")
End If
End Sub
'FIXME:the program seems to have difficulty when i try to bring ``Up1Cost`` and ``Up2Cost`` into the function
'*xUpdate Upgrade Values
'xFunction Update(ByRef Cost As Integer, ByRef lvl As Integer, ByRef Value As Integer)
'x Cost = lvl * 10
'x Value = lvl
'xReturn Cost & lvl & Value
'xEnd Function
'*Update Click Value Upgrade Values
Sub Up1Update()
Up1Cost = Up1lvl * 10
ClickValue = Up1lvl
End Sub
'*Update CPS Upgrade Values
Sub Up2Update()
Up2Cost = Up2lvl * 10
Cps = Up2lvl
End Sub
End Module
Idle Time Waster.Designer.vb
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class formIdleTimeWaster
Inherits System.Windows.Forms.Form
'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.components = New System.ComponentModel.Container()
Dim gbStats As System.Windows.Forms.GroupBox
Dim lblHWPerClickTitle As System.Windows.Forms.Label
Dim lblCPSTitle As System.Windows.Forms.Label
Dim lblTotalHWTitle As System.Windows.Forms.Label
Dim lblUp1lvlName As System.Windows.Forms.Label
Dim lblUp2lvlName As System.Windows.Forms.Label
Dim lblUp1CostName As System.Windows.Forms.Label
Dim lblUp2CostName As System.Windows.Forms.Label
Me.lblClickValue = New System.Windows.Forms.Label()
Me.lblCPS = New System.Windows.Forms.Label()
Me.lblTotalHW = New System.Windows.Forms.Label()
Me.btnUserClick = New System.Windows.Forms.Button()
Me.timerCPS = New System.Windows.Forms.Timer(Me.components)
Me.lblUp2lvl = New System.Windows.Forms.Label()
Me.btnUp1 = New System.Windows.Forms.Button()
Me.btnUp2 = New System.Windows.Forms.Button()
Me.lblUp1Cost = New System.Windows.Forms.Label()
Me.lblUp2Cost = New System.Windows.Forms.Label()
Me.NotifyIcon1 = New System.Windows.Forms.NotifyIcon(Me.components)
Me.lblUp1lvl = New System.Windows.Forms.Label()
gbStats = New System.Windows.Forms.GroupBox()
lblHWPerClickTitle = New System.Windows.Forms.Label()
lblCPSTitle = New System.Windows.Forms.Label()
lblTotalHWTitle = New System.Windows.Forms.Label()
lblUp1lvlName = New System.Windows.Forms.Label()
lblUp2lvlName = New System.Windows.Forms.Label()
lblUp1CostName = New System.Windows.Forms.Label()
lblUp2CostName = New System.Windows.Forms.Label()
gbStats.SuspendLayout()
Me.SuspendLayout()
'
'gbStats
'
gbStats.Controls.Add(Me.lblClickValue)
gbStats.Controls.Add(Me.lblCPS)
gbStats.Controls.Add(Me.lblTotalHW)
gbStats.Controls.Add(lblHWPerClickTitle)
gbStats.Controls.Add(lblCPSTitle)
gbStats.Controls.Add(lblTotalHWTitle)
gbStats.Location = New System.Drawing.Point(217, 8)
gbStats.Name = "gbStats"
gbStats.Size = New System.Drawing.Size(208, 114)
gbStats.TabIndex = 0
gbStats.TabStop = False
gbStats.Text = "Stats"
'
'lblClickValue
'
Me.lblClickValue.AutoSize = True
Me.lblClickValue.CausesValidation = False
Me.lblClickValue.Location = New System.Drawing.Point(153, 82)
Me.lblClickValue.Name = "lblClickValue"
Me.lblClickValue.Size = New System.Drawing.Size(13, 15)
Me.lblClickValue.TabIndex = 5
Me.lblClickValue.Text = "0"
'
'lblCPS
'
Me.lblCPS.AutoSize = True
Me.lblCPS.Location = New System.Drawing.Point(166, 52)
Me.lblCPS.Name = "lblCPS"
Me.lblCPS.Size = New System.Drawing.Size(13, 15)
Me.lblCPS.TabIndex = 4
Me.lblCPS.Text = "0"
'
'lblTotalHW
'
Me.lblTotalHW.AutoSize = True
Me.lblTotalHW.CausesValidation = False
Me.lblTotalHW.Location = New System.Drawing.Point(132, 21)
Me.lblTotalHW.Name = "lblTotalHW"
Me.lblTotalHW.Size = New System.Drawing.Size(13, 15)
Me.lblTotalHW.TabIndex = 3
Me.lblTotalHW.Text = "0"
'
'lblHWPerClickTitle
'
lblHWPerClickTitle.AutoSize = True
lblHWPerClickTitle.Location = New System.Drawing.Point(14, 82)
lblHWPerClickTitle.Name = "lblHWPerClickTitle"
lblHWPerClickTitle.Size = New System.Drawing.Size(133, 15)
lblHWPerClickTitle.TabIndex = 2
lblHWPerClickTitle.Text = "Hours Wasted Per Click:"
'
'lblCPSTitle
'
lblCPSTitle.AutoSize = True
lblCPSTitle.Location = New System.Drawing.Point(14, 52)
lblCPSTitle.Name = "lblCPSTitle"
lblCPSTitle.Size = New System.Drawing.Size(146, 15)
lblCPSTitle.TabIndex = 1
lblCPSTitle.Text = "Hours Wasted per Second:"
'
'lblTotalHWTitle
'
lblTotalHWTitle.AutoSize = True
lblTotalHWTitle.Location = New System.Drawing.Point(14, 21)
lblTotalHWTitle.Name = "lblTotalHWTitle"
lblTotalHWTitle.Size = New System.Drawing.Size(112, 15)
lblTotalHWTitle.TabIndex = 0
lblTotalHWTitle.Text = "Total Hours Wasted:"
'
'lblUp1lvlName
'
lblUp1lvlName.AutoSize = True
lblUp1lvlName.Location = New System.Drawing.Point(217, 149)
lblUp1lvlName.Name = "lblUp1lvlName"
lblUp1lvlName.Size = New System.Drawing.Size(37, 15)
lblUp1lvlName.TabIndex = 2
lblUp1lvlName.Text = "Level:"
'
'lblUp2lvlName
'
lblUp2lvlName.AutoSize = True
lblUp2lvlName.Location = New System.Drawing.Point(217, 175)
lblUp2lvlName.Name = "lblUp2lvlName"
lblUp2lvlName.Size = New System.Drawing.Size(37, 15)
lblUp2lvlName.TabIndex = 4
lblUp2lvlName.Text = "Level:"
'
'lblUp1CostName
'
lblUp1CostName.AutoSize = True
lblUp1CostName.Location = New System.Drawing.Point(291, 149)
lblUp1CostName.Name = "lblUp1CostName"
lblUp1CostName.Size = New System.Drawing.Size(34, 15)
lblUp1CostName.TabIndex = 8
lblUp1CostName.Text = "Cost:"
'
'lblUp2CostName
'
lblUp2CostName.AutoSize = True
lblUp2CostName.Location = New System.Drawing.Point(291, 175)
lblUp2CostName.Name = "lblUp2CostName"
lblUp2CostName.Size = New System.Drawing.Size(34, 15)
lblUp2CostName.TabIndex = 9
lblUp2CostName.Text = "Cost:"
'
'btnUserClick
'
Me.btnUserClick.Location = New System.Drawing.Point(12, 12)
Me.btnUserClick.Name = "btnUserClick"
Me.btnUserClick.Size = New System.Drawing.Size(199, 110)
Me.btnUserClick.TabIndex = 1
Me.btnUserClick.Text = "Play Idle Game"
Me.btnUserClick.UseVisualStyleBackColor = True
'
'timerCPS
'
'
'lblUp2lvl
'
Me.lblUp2lvl.AutoSize = True
Me.lblUp2lvl.Location = New System.Drawing.Point(260, 175)
Me.lblUp2lvl.Name = "lblUp2lvl"
Me.lblUp2lvl.Size = New System.Drawing.Size(13, 15)
Me.lblUp2lvl.TabIndex = 5
Me.lblUp2lvl.Text = "0"
'
'btnUp1
'
Me.btnUp1.Location = New System.Drawing.Point(12, 143)
Me.btnUp1.Name = "btnUp1"
Me.btnUp1.Size = New System.Drawing.Size(199, 27)
Me.btnUp1.TabIndex = 6
Me.btnUp1.Text = "Upgrade Click"
Me.btnUp1.UseVisualStyleBackColor = True
'
'btnUp2
'
Me.btnUp2.Location = New System.Drawing.Point(12, 169)
Me.btnUp2.Name = "btnUp2"
Me.btnUp2.Size = New System.Drawing.Size(199, 27)
Me.btnUp2.TabIndex = 7
Me.btnUp2.Text = "Upgrade Passive time wasting"
Me.btnUp2.UseVisualStyleBackColor = True
'
'lblUp1Cost
'
Me.lblUp1Cost.AutoSize = True
Me.lblUp1Cost.Location = New System.Drawing.Point(330, 149)
Me.lblUp1Cost.Name = "lblUp1Cost"
Me.lblUp1Cost.Size = New System.Drawing.Size(13, 15)
Me.lblUp1Cost.TabIndex = 10
Me.lblUp1Cost.Text = "0"
'
'lblUp2Cost
'
Me.lblUp2Cost.AutoSize = True
Me.lblUp2Cost.CausesValidation = False
Me.lblUp2Cost.Location = New System.Drawing.Point(331, 175)
Me.lblUp2Cost.Name = "lblUp2Cost"
Me.lblUp2Cost.Size = New System.Drawing.Size(13, 15)
Me.lblUp2Cost.TabIndex = 11
Me.lblUp2Cost.Text = "0"
'
'NotifyIcon1
'
Me.NotifyIcon1.Text = "NotifyIcon1"
Me.NotifyIcon1.Visible = True
'
'lblUp1lvl
'
Me.lblUp1lvl.AutoSize = True
Me.lblUp1lvl.Location = New System.Drawing.Point(260, 149)
Me.lblUp1lvl.Name = "lblUp1lvl"
Me.lblUp1lvl.Size = New System.Drawing.Size(13, 15)
Me.lblUp1lvl.TabIndex = 12
Me.lblUp1lvl.Text = "0"
'
'formIdleTimeWaster
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(7.0!, 15.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(440, 207)
Me.Controls.Add(Me.lblUp1lvl)
Me.Controls.Add(Me.lblUp2Cost)
Me.Controls.Add(Me.lblUp1Cost)
Me.Controls.Add(lblUp2CostName)
Me.Controls.Add(lblUp1CostName)
Me.Controls.Add(Me.btnUp2)
Me.Controls.Add(Me.btnUp1)
Me.Controls.Add(Me.lblUp2lvl)
Me.Controls.Add(lblUp2lvlName)
Me.Controls.Add(lblUp1lvlName)
Me.Controls.Add(Me.btnUserClick)
Me.Controls.Add(gbStats)
Me.Name = "formIdleTimeWaster"
Me.Text = "Idle Time Waster"
gbStats.ResumeLayout(False)
gbStats.PerformLayout()
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Friend WithEvents gbStats As GroupBox
Friend WithEvents lblHWPerClickTitle As Label
Friend WithEvents lblCPSTitle As Label
Friend WithEvents lblTotalHWTitle As Label
Friend WithEvents btnUserClick As Button
Friend WithEvents lblTotalHW As Label
Friend WithEvents lblCPS As Label
Friend WithEvents timerCPS As Timer
Friend WithEvents lblUp1lvlName As Label
Friend WithEvents lblUp2lvlName As Label
Friend WithEvents lblUp2lvl As Label
Friend WithEvents btnUp1 As Button
Friend WithEvents btnUp2 As Button
Friend WithEvents lblUp1CostName As Label
Friend WithEvents lblUp2CostName As Label
Friend WithEvents lblUp1Cost As Label
Friend WithEvents lblUp2Cost As Label
Friend WithEvents NotifyIcon1 As NotifyIcon
Friend WithEvents lblClickValue As Label
Friend WithEvents lblUp1lvl As Label
End Class
this error comes up when i build it:
System.NullReferenceException: 'Object reference not set to an instance of an object.'
Idle_time_Waster.formIdleTimeWaster.lblUp1lvl.get returned Nothing
as of posting this question am going to try seeing if updating VS fixes the problem
I need to sort a dictionary by its key, but the values are class items.
Here is the class:
CLASS Person
PUBLIC PersonID
PUBLIC PersonName
PUBLIC GenderID
PUBLIC PersonAdditional
PRIVATE SUB class_initialize()
PersonID = null
PersonName = null
GenderID = null
PersonAdditional = null
END SUB
END CLASS
And here is my dictionary, filled with data from an array:
Set dict = Server.CreateObject("Scripting.Dictionary")
FOR i = 0 TO UBOUND(arr_People)
key_person = arr_People(i).GenderID & arr_People(i).PersonName
dict.Add key_person, new Person
dict.Item(key_person).PersonName = arr_People(i).PersonName
dict.Item(key_person).GenderID = arr_People(i).GenderID
dict.Item(key_person).PersonID = arr_People(i).PersonID
dict.Item(key_person).PersonAdditional = arr_People(i).PersonAdditional
NEXT
I use this function for sorting, but it doesn't seem to work:
Function SortDictionary(objDict,intSort)
Dim strDict()
Dim objKey
Dim strKey,strItem
Dim X,Y,Z
Z = objDict.Count
If Z > 1 Then
ReDim strDict(Z,2)
X = 0
For Each objKey In objDict
strDict(X,dictKey) = CStr(objKey)
strDict(X,dictItem) = CStr(objDict(objKey))
X = X + 1
Next
For X = 0 to (Z - 2)
For Y = X to (Z - 1)
If StrComp(strDict(X,intSort),strDict(Y,intSort),vbTextCompare) > 0 Then
strKey = strDict(X,dictKey)
strItem = strDict(X,dictItem)
strDict(X,dictKey) = strDict(Y,dictKey)
strDict(X,dictItem) = strDict(Y,dictItem)
strDict(Y,dictKey) = strKey
strDict(Y,dictItem) = strItem
End If
Next
Next
objDict.RemoveAll
For X = 0 to (Z - 1)
objDict.Add strDict(X,dictKey), strDict(X,dictItem)
Next
End If
End Function
It gives me the following error:
Object doesn't support this property or method
on this row:
strDict(X,dictItem) = CStr(objDict(objKey)
I'm assuming that this happens because the values in the dictionary contains class instead of just a string or integer, but I don't know how to handle it.
There's a workaround that you can use:
Create another array containing only the keys of the dictonary
Sort the array
Read the dictionary values by iterating trough the array of keys
And here's the code:
Set dict = Server.CreateObject("Scripting.Dictionary")
Set arr_personKeys = CreateObject("System.Collections.ArrayList")
FOR i = 0 TO UBOUND(arr_People)
key_person = arr_People(i).GenderID & arr_People(i).PersonName
arr_personKeys.Add key_person
dict.Add key_person, new Person
dict.Item(key_person).PersonName = arr_People(i).PersonName
dict.Item(key_person).GenderID = arr_People(i).GenderID
dict.Item(key_person).PersonID = arr_People(i).PersonID
dict.Item(key_person).PersonAdditional = arr_People(i).PersonAdditional
NEXT
arrLength_personKeys = arr_personKeys.count - 2
SortArray arr_personKeys,arrLength_personKeys
And here is the sorting function:
Function SortArray(arrayForSorting, arraySize)
for a = arraySize To 0 Step -1
for j = 0 to a
if arrayForSorting(j)>arrayForSorting(j+1) then
temp=arrayForSorting(j+1)
arrayForSorting(j+1)=arrayForSorting(j)
arrayForSorting(j)=temp
end if
next
next
End Function
Now you can iterate trough your sorted dictionary like this:
For i = 0 To arrLength_personKeys + 1
key = arr_personKeys(i)
Response.write dict(key).PersonID
Response.write dict(key).PersonName
Response.write dict(key).GenderID
Response.write dict(key).PersonAdditional
Next
I am using Dynamic Linq to execute a T-SQL where clause against LINQ. This works great except when trying to convert the LIKE statement which I have manually attempted to convert with a function that I have included at the end of the post. The code is not even close to being perfect, but I stopped programming this when I realized that I would get an error during testing. The code that executes essentially takes this:
"trx_no like '%3500%'"
And converts it to this:
"trx_no.Contains("3500")"
To execute this:
Dim x = y.Where("trx_no.Contains("3500")", Nothing)
The Error:
No applicable method 'Contains' exists in type 'Int32?'
The issue I think is that I need to convert the "trx_no" which is a Nullable(Of Int32) to a String, so after two days of research and book reading I figured that I would need to convert the string in a delegate function which I can not get to work.
I have also tried to use Cast like in this link here, however this fails with an error:
Expression of type 'Boolean' expected
My version looked like this:
Dim x = y.Where("DirectCast(trx_no, System.String) like '%35000%'", Nothing)
If I have not included enough code I am sorry I just did not want to make this to overwhelming. Any suggestions would be much appreciated. Thank You.
`Private Function replaceLike(ByVal str As String) As String
Dim rtn As String = ""
If str.ToUpper.Contains(" LIKE '") Then
Dim firstQuote As Int32 = str.ToUpper.IndexOf(" LIKE '") + 6
If str.ToUpper.Chars(firstQuote + 1) = Chr(37) Then
'If the character after the first single quote is a %, this is a Contains or EndsWith
Dim secondQuote As Int32 = str.ToUpper.IndexOf("'", firstQuote + 1)
If str.ToUpper.Chars(secondQuote - 1) = Chr(37) Then
'Handles '%%', '%value%', '%'
'Found % before the last quote, this is a Contains or has the value of '%'.
Dim val = ""
'See if the value is empty so that we can extract the value
Select Case (secondQuote - 1) - (firstQuote + 1)
Case 0
'Has no value don't add
Case 1
'Has no value don't add
Case Else
val = str.Substring(firstQuote + 2, ((secondQuote - 2) - firstQuote - 1))
End Select
str = str.Remove(firstQuote - 6, secondQuote - (firstQuote - 7))
str = str.Insert(firstQuote - 6, ".Contains(""" & val & """) ")
Else
'Handles '%value'
'Did not find another % before the last quote, this is a EndsWith
Dim val = str.Substring(firstQuote + 2, ((secondQuote - 2) - firstQuote - 1))
str = str.Remove(firstQuote - 6, secondQuote - (firstQuote - 7))
str = str.Insert(firstQuote - 6, ".EndsWith(""" & val & """) ")
End If
Else
'Else the character after the first single quote is not a %, this is a StartWith or is Empty
Dim secondQuote As Int32 = str.ToUpper.IndexOf("'", firstQuote + 1)
If str.ToUpper.Chars(secondQuote - 1) = Chr(37) Then
'Handles 'value%'
'Found a % before the last quote, this is a StartsWith
Dim val = str.Substring(firstQuote + 2, ((secondQuote - 2) - firstQuote - 1))
str = str.Remove(firstQuote - 6, secondQuote - (firstQuote - 7))
str = str.Insert(firstQuote - 6, ".StartsWith(""" & val & """) ")
Else
'Handles ''
'Found no %
str = str.Remove(firstQuote - 6, secondQuote - (firstQuote - 7))
str = str.Insert(firstQuote - 6, ".Contains("""") ")
End If
End If
rtn = replaceLike(str)
Else
Return str
End If
Return rtn
End Function
I found that the predefinedTypes in the Dynamic Linq Library supported Convert, which I used to formulate the following:
"Convert.ToString(" & propertyName & ").Contains(""" & val & """)"
This lead to an issue with converting Nullable(Of ) to a string if the propertyName above was a Nullable type. Editing the Dynamic.vb code in the Dynamic Linq Library for the ParseMemberAccess method allowed the conversion to work. Below is the edit made to the Select Case statement in that method:
Select Case FindMethod(type, id, instance Is Nothing, args, mb)
Case 0
Throw ParseError(errorPos, Res.NoApplicableMethod, id, GetTypeName(type))
Case 1
Dim method = DirectCast(mb, MethodInfo)
If (Not IsPredefinedType(method.DeclaringType)) Then
Throw ParseError(errorPos, Res.MethodsAreInaccessible, GetTypeName(method.DeclaringType))
End If
If method.ReturnType.Equals(GetType(Void)) Then
Throw ParseError(errorPos, Res.MethodIsVoid, id, GetTypeName(method.DeclaringType))
End If
Dim newargs As Expression() = args
For Each a As Expression In args
If a.Type.IsGenericType AndAlso a.Type.GetGenericTypeDefinition = GetType(Nullable(Of )) Then
newargs(Array.IndexOf(args, a)) = System.Linq.Expressions.Expression.Convert(a, GetType(Object))
Else
newargs(Array.IndexOf(args, a)) = a
End If
Next
Return Expression.Call(instance, DirectCast(method, MethodInfo), newargs)
Case Else
Throw ParseError(errorPos, Res.AmbiguousMethodInvocation, id, GetTypeName(type))
End Select
In VBScript, some built in objects use an unnamed property. Some Examples:
Set Dict = Server.CreateObject("Scripting.Dictionary")
Set RS = GetEmloyeesRecordSet()
Dict("Beer") = "Tasty" ' Same as Dict.Item("Beer") = "Tasty"
Dict("Crude Oil") = "Gross" ' Same as Dict.Item("Crude Oil") = "Gross"
Response.Write "The First Employee Is: " & RS("Name") ' Same as RS.Fields("Name")
How can I use this same syntax in my own classes?
UPDATE
Here is a working, stand-alone example of how to do this, a simple wrapper for Scripting.Dictionary. Note the use of "Let" to allow the d("key") = "value" syntax. Of course credit goes to Thom for providing the answer.
<%
Class DictWrapper
Private Dict
Private Sub Class_Initialize()
Set Dict = Server.CreateObject("Scripting.Dictionary")
End Sub
Private Sub Class_Terminate()
Set Dict = Nothing
End Sub
Public Property Get Count
Count = Dict.Count
End Property
Public Default Property Get Item( Key )
Item = Dict(Key)
End Property
Public Property Let Item( Key, Value )
Dict(Key) = Value
End Property
Public Sub Add( Key, Value )
Dict.Add Key, Value
End Sub
End Class
Dim d : Set d = New DictWrapper
d.Add "Beer", "Good"
Response.Write d("Beer") & "<br>"
d("Beer") = "Bad"
Response.Write d("Beer")
%>
You need to declare a property of the class as the default property. As an example, here's part of a String wrapper class I wrote:
class StringClass
private finished_
private data_
private size_
public function init (val)
finished_ = cStr(val)
set init = me
end function
public default property get value
if (size_ > 0) then
finished_ = finished_ & join(data_, vbNullString)
data_ = empty
size_ = 0
end if
value = finished_
end property
public property let value (val)
data_ = empty
size_ = empty
init(val)
end property
public function add (s)
size_ = size_ + 1
if (isEmpty(data_)) then
redim data_(MIN_ARRAY_SIZE)
elseif (size_ > uBound(data_)) then
redim preserve data_(Float(uBound(data_) * GRANTED_HEAD_ROOM).ceil)
end if
data_(size_ - 1) = cStr(s)
end function
end class
Usage:
dim s: set s = new StringClass
s()= "Hello, world!" ' s.value() = "Hello, world!"
Response.Write s ' Response.Write s.value()
You can also have a parametrized default property:
class ListClass
private size_
private data_
private sub CLASS_INITIALIZE
size_ = 0
data_ = Array()
resize_array MIN_ARRAY_SIZE
end sub
public default property get data (index)
if isObject(data) then
set data_(index) = data
else
data_(index) = data
end if
end property
public property let data (index, value)
data_(index) = value
end property
public property set data (index, value)
set data_(index) = value
end property
public function add(datum)
size_ = size_ + 1
if (size_ > uBound(data_) + 1) then expand_array
assign data_(size_ - 1), datum
add = datum
end function
end class
dim l: set l = new ListClass
l.add("Hello, world!")
l(0) = "Goodbye, world!"
Response.Write l(0)
This second example is probably what you were looking for, using default properties to implement collections, but it's worth checking out the first example, using default properties to implement auto-unboxing of wrapper classes.
I have the following format:
Value1 is {0} and Value2 is {1}.
I need to replace the numbers in the brackets with strings. This is easily done in most languages using string.Format or something along those lines. How can I do this using only vbscript?
I've tried:
Replace (strFormat, "{0}", value1)
Replace (strFormat, "{1}", value2)
It does not work. Any solutions?
Replace (strFormat, "{0}", value1)
Based on your code snip, I'm guessing you believe Replace mutates strFormat directly. It doesn't work like that; You assign the result to the original variable like this:
strFormat = Replace (strFormat, "{0}", value1)
You can also assign to another variable to store the changed results, like this:
strFormat2 = Replace (strFormat, "{0}", value1)
I wanted something similar and didn't like any of these answers as they meant multiple lines for each value (Ignoring Beaner's answer is for the wrong language!) so I created the following:
Public Function StrFormat(FormatString, Arguments())
Dim Value, CurArgNum
StrFormat = FormatString
CurArgNum = 0
For Each Value In Arguments
StrFormat = Replace(StrFormat, "{" & CurArgNum & "}", Value)
CurArgNum = CurArgNum + 1
Next
End Function
You can use the following then (note that you need to add "Array()" around your variables):
formatString = "Test '{0}', '{2}', '{1}' and {0} again!"
Response.Write StrFormat(formatString, Array(1, 2, "three", "Unused"))
Response.Write StrFormat(formatString, Array(4, 5, "six", "Unused"))
Which will output what you expect:
Test '1', 'three', '2' and 1 again!
Test '4', 'six', '5' and 4 again!
Hope this feels a bit more natural for people from other languages.
As none of the answers so far addresses the problem of formatting (as opposed
to interpolating/splicing strings into strings):
This simple Class:
Class cFormat
Private m_oSB
Private Sub Class_Initialize()
Set m_oSB = CreateObject("System.Text.StringBuilder")
End Sub ' Class_Initialize
Public Function formatOne(sFmt, vElm)
m_oSB.AppendFormat sFmt, vElm
formatOne = m_oSB.ToString()
m_oSB.Length = 0
End Function ' formatOne
Public Function formatArray(sFmt, aElms)
m_oSB.AppendFormat_4 sFmt, (aElms)
formatArray = m_oSB.ToString()
m_oSB.Length = 0
End Function ' formatArray
End Class ' cFormat
harness .NET formatting for VBScript via COM. Now you can do:
-------- Interpolation
Use |Value1 is {0} and Value2 is {1}.|
to get |Value1 is zero and Value2 is one.|
from |zero one|
Use |{0} x 2 => {0}{0}|
to get |once x 2 => onceonce|
from |once|
-------- Cherrypicking
Use |{6,4}: [{0}, {2}, {4}]|
to get |even: [0, 2, 4]|
from |0 1 2 3 4 5 even odd|
Use |{7,4}: [{5}, {3}, {1}]|
to get | odd: [5, 3, 1]|
from |0 1 2 3 4 5 even odd|
-------- Conversions
Use ||{0:D}| |{0:X}| |{0:N3}| |{0:P2}| (german locale!)|
to get ||123| |7B| |123,000| |12.300,00%| (german locale!)|
from |123|
Use ||{0}| |{0:U}| |{0:u}||
to get ||29.06.2012 14:50:30| |Freitag, 29. Juni 2012 12:50:30| |2012-06-29 14:50:30Z||
from |29.06.2012 14:50:30|
Use ||{0}| |{0:E1}| |{0:N1}| |{0:N2}| |{0:N3}||
to get ||1234,56| |1,2E+003| |1.234,6| |1.234,56| |1.234,560||
from |1234,56|
-------- Alignment
Use ||{0,1:D}| |{0,2:D}| |{0,-2:D}| |{0,5:D}| |{0,-5:D}||
to get ||12| |12| |12| | 12| |12 ||
from |12|
If you are interested in the test/demo script to do some experiments
of your own:
Option Explicit
' Class cFormat ...
Dim oFormat : Set oFormat = New cFormat
Dim aTests : aTests = Array( _
Array("Interpolation" _
, Array( _
Array(True, "Value1 is {0} and Value2 is {1}.", Array("zero", "one")) _
, Array(False, "{0} x 2 => {0}{0}" , "once" ) _
} _
) _
, Array("Cherrypicking" _
, Array( _
Array(True , "{6,4}: [{0}, {2}, {4}]", Array(0, 1, 2, 3, 4, 5, "even", "odd")) _
, Array(True , "{7,4}: [{5}, {3}, {1}]", Array(0, 1, 2, 3, 4, 5, "even", "odd")) _
} _
) _
, Array("Conversions" _
, Array( _
Array(False, "|{0:D}| |{0:X}| |{0:N3}| |{0:P2}| (german locale!)", 123 ) _
, Array(False, "|{0}| |{0:U}| |{0:u}|" , Now ) _
, Array(False, "|{0}| |{0:E1}| |{0:N1}| |{0:N2}| |{0:N3}|" , 1234.56 ) _
} _
) _
, Array("Alignment" _
, Array( _
Array(False, "|{0,1:D}| |{0,2:D}| |{0,-2:D}| |{0,5:D}| |{0,-5:D}|", 12 ) _
} _
) _
)
Dim sFormat : sFormat = "Use |{0}|{3}to get |{1}|{3}from |{2}|{3}"
Dim aData : aData = Array(0, 1, 2, vbCrLf)
Dim aTest
For Each aTest In aTests
WScript.Echo "--------", aTest(0)
Dim aSample
For Each aSample In aTest(1)
aData(0) = aSample(1)
If aSample(0) Then
aData(1) = oFormat.formatArray(aSample(1), aSample(2))
aData(2) = Join(aSample(2))
Else
aData(1) = oFormat.formatOne( aSample(1), aSample(2))
aData(2) = aSample(2)
End If
WScript.Echo oFormat.formatArray(sFormat, aData)
Next
WScript.Echo
Next
To learn about formatting in .NET, start with StringBuilder.AppendFormat Method (String, Object) and Formatting Types.
See here and here for ideas to include (not Copy&Paste) such a Class into your script.
Here's a nice little function that works something like the .NET string.Format function. I did this quickly so adding err handling is up to you. I did this in VB6 and added a reference to Microsoft VBScript Regular Expressions 5.5
Public Function StringFormat(ByVal SourceString As String, ParamArray Arguments() As Variant) As String
Dim objRegEx As RegExp ' regular expression object
Dim objMatch As Match ' regular expression match object
Dim strReturn As String ' the string that will be returned
Set objRegEx = New RegExp
objRegEx.Global = True
objRegEx.Pattern = "(\{)(\d)(\})"
strReturn = SourceString
For Each objMatch In objRegEx.Execute(SourceString)
strReturn = Replace(strReturn, objMatch.Value, Arguments(CInt(objMatch.SubMatches(1))))
Next objMatch
StringFormat = strReturn
End Function
Example:
StringFormat("Hello {0}. I'd like you to meet {1}. They both work for {2}. {0} has worked for {2} for 15 years.", "Bruce", "Chris", "Kyle")
Returns:
Hello Bruce. I'd like you to meet Chris. They both work for Kyle. Bruce has worked for Kyle for 15 years.
Why not? This code works here:
value1 = "1"
value2 = "2"
strFormat = "Value1 is {0} and Value2 is {1}."
strFormat = Replace (strFormat, "{0}", value1)
strFormat = Replace (strFormat, "{1}", value2)
MsgBox strFormat
Note I update my strFormat value for every replace.
If you needs a more flexible implementation, you can go with a regular expression, but doesn't seems required now.
I really liked the functionality of #Ekkehard.Horner's StringBuilder-based solution, but it seemed more complicated than necessary.
For my purposes, I definitely do not need the ceremony of a whole class.
I pared it down to this single function:
Function FormatString(format, args)
dim resultBuilder
set resultBuilder = CreateObject("System.Text.StringBuilder")
if IsArray(args) Then
resultBuilder.AppendFormat_4 format, (args)
else
resultBuilder.AppendFormat format, args
end if
FormatString = resultBuilder.ToString()
End Function
WScript.Echo FormatString("Hello, {0}!", "World")
WScript.Echo FormatString("Hello, {0}! It is {1:H:mm tt}, and we are {2:P2} through the day on {1:dddd, d MMMM, yyyy}.", Array("World", Now, Timer/(24*60*60)))