This lesson concentrates on Visual Basic controls and the ways of creating and implementing the. It also helps us to understand the concept of Control Arrays. Controls are used to recieve user input and display output and has its own set of properties, methods and events. Let us discuss few of these controls in this lesson.
A control is an object that can be drawn on a Form object to enable or enhance user interaction with an application. Controls have properties that define aspects their appearance, such as position, size and colour, and aspects of their behavior, such as their response to the user input. They can respond to events initiated by the user or set off by thesystem. For instance, a code could be written in a CommandButton control’s click event procedure that would load a file or display a result.
In addition to properties and events, methods can also be used to manipulate controls from code. For instance, the move method can be used with some controls to change their location and size.
Most of the controls provide choices to users that can be in the form of OptionButton or CheckBox controls, ListBox entries or ScrollBars to select a value. Let us discuss these controls by means of a few simple applications in the following lessons.
Visual Basic cojntrols are broadly classified as standard controls, ActiveX controls and insertable objects. Standard controls such as CommandButton, Label and Frame controls are contained inside .EXE file and are always included in the ToolBox which cannot be removed. ActiveX controls exist as separate files with either .VBX or .OCX extension. They include specialized controls such as;
Some of these objects support OLE Automation, which allow programming another application’s object from within Visual Basic application.
I would like to stress that knowing how and when to set the objects’ properties is very important as it can help you to write a good program or you may fail to write a good program. So, I advice you to spend a lot of time playing with the objects’ properties
Here are some important points about setting up the properties
You should set the Caption Property of a control clearly so that a user knows what to do with that command. For example, in the calculator program, all the captions of the command buttons such as +, – , MC, MR are commonly found in an ordinary calculator, a user should have no problem in manipulating the buttons.
Visual Basic uses the TabIndex property to determine the control that would receive the focus next when a tab key is pressed. Every time a tab key is pressed, Visual Basic looks at the value of the TabIndex for the control that has focus and then it scans through the controls searching for the next highest TabIndex number. When there are no more controls with higher TabIndex value, Visual Basic starts all over again with 0 and looks for the first control with TabIndex of 0 or higher that can accept keyboard input.
By default, Visual Basic assigns a tab order to control as we draw the controls on the Form, except for Menu, Timer, Data, Image, Line and Shape controls, which are not included in tab order. At run time, invisible or disabled controls also cannot receive the focus although a TabIndex value is given. Setting the TabIndex property of controls is compulsory in development environment.
In most cases, you don’t need any special functions to perform date arithmetic. All you need to know is that the integer part in a Date variable holds the date information, and the fractional part holds the time information:
‘ 2 days and 12 hours from now
Print Now + 2 + #12:00# ‘ Displays “8/17/2008 8:35:48 A.M.”
For more sophisticated date math, you can use the DateAdd function, for which the syntax is the following:
NewDate = DateAdd(interval, number, date)
The interval is a string that indicates a date or time unit (see table below), number is the number of units you are adding, and date is the starting date. You can use this function to add and subtract date and time values:
‘ The date three months from now
Print DateAdd(“m”, 3, Now) ‘ Displays “11/14/2008 8:35:48 P.M.”
‘ One year ago (automatically accounts for leap years)
Print DateAdd(“yyyy”, -1, Now) ‘ Displays “8/14/2007 8:35:48 P.M.”
‘ The number of months since Jan 30, 2008
Print DateDiff(“m”, #1/30/2008#, Now) ‘ Displays “7″
‘ The number of days since Jan 30, 2008 _ you can use “d” or “y”.
Print DateDiff(“y”, #1/30/2008#, Now) ‘ Displays “196″
‘ The number of entire weeks since Jan 30, 2008
Print DateDiff(“w”, #1/30/2008#, Now) ‘ Displays “28″
‘ The number of weekends before 21st century – value <0 means
‘ future dates.
‘ Note: use “ww” to return the number of Sundays in the date interval.
Print DateDiff(“ww”, #1/1/2000#, Now) ‘ Displays “-72″
When you have two dates and you want to evaluate the difference between them—that is, the time elapsed between one date and the next—you should use the DateDiff function, for which the syntax is
Result = DateDiff(interval, startdate, enddate _
[, FirstDayOfWeek[, FirstWeekOfYear]])
where interval has the meaning shown in the previous page Building and Extracting Date and Time Values’s table,FirstDayOfWeek is an optional argument that you can use to specify which weekday should be considered as the first day of the week (you can use the constants vbSunday, vbMonday, and so on), and FirstWeekOfYear is another optional argument that lets you specify which week should be considered as the first week of the year.
There are many ways to assemble a Date value. For example, you can use a Date constant, such as the following:
StartDate = #10/17/2008 9:25:33 P.M.#
but more often you’ll build a Date value using one of the many functions that VBA gives you. The DateSerial function builds a Date value from its year/month/day components; similarly, the TimeSerial function builds a Time value from its hour/minute/second components:
Print DateSerial(2008, 10, 17) ‘ Displays “10/17/2008″
Print TimeSerial(12, 20, 30) ‘ Displays “12:20:30 P.M.”
‘ Note that they don’t raise errors with invalid arguments.
Print DateSerial(2008, 4, 31) ‘ Displays “5/1/2008″
The DateSerial function is also useful for determining indirectly whether a particular year is a leap year:
Function IsLeapYear(year As Integer) As Boolean
‘ Are February 29 and March 1 different dates?
IsLeapYear = DateSerial(year, 2, 29) <> DateSerial(year, 3, 1)
End Function
The DateValue and TimeValue functions return the date or time portions of their argument, which can be a string or a Date expression:
‘ The date a week from now
Print DateValue(Now + 7) ‘ Displays “10/17/2008″
A bunch of VBA functions let you extract date and time information from a Date expression or variable. The Day, Month, and Year functions return date values, whereas the Hour, Minute, and Second functions return time values:
‘ Get information about today’s date.
y = Year(Now): m = Month(Now): d = Day(Now)
‘ These functions also support any valid date format.
Print Year(“10/17/2008 9:25:33 P.M.”) ‘ Displays “2008″
The Weekday function returns a number in the range 1 through 7, which corresponds to the day of the week of a given Date argument:
Print Weekday(“10/17/2008″) ‘ Displays “6″ (= vbFriday)
The Weekday function returns 1 when the date is the first day of the week. This function is locale aware, which means that under different localizations of Microsoft Windows it could consider the first day of the week to be different from vbSunday. In most cases, this condition doesn’t affect the structure of your code. But if you want to be sure that 1 means Sunday, 2 means Monday, and so on, you can force the function to return a consistent value under all Windows systems, as follows:
Print Weekday(Now, vbSunday)
Although using the optional second argument forces the function to return the correct value, it doesn’t change the system localization. If you next call the Weekday function without the second argument, it will still consider the first day of the week to be what it was before.
Finally you can extract any date and time information from a Date value or expression using the DatePart function, for which the syntax is
Result = DatePart(Interval, Date, [FirstDayOfWeek], [FirstWeekOfYear])
You’ll rarely need to resort to this function because you can do most of your calculations using the other functions I’ve shown you so far. In two cases, however, this function is really useful:
‘ The quarter we are in
Print DatePart(“q”, Now) ‘ Displays “3″
‘ The week number we are in (# of weeks since Jan 1st)
Print DatePart(“ww”, Now) ‘ Displays “33″
The first argument can be one of the String constants listed in the following table. For more information about the two optional arguments, see the description of the DateAdd function in the next section.
Strictly speaking, Date and Time aren’t functions: They’re properties. In fact, you can use them to either retrieve the current date and time (as Date values) or assign new values to them to modify the system settings:
Print Date & ” ” & Time ‘ Displays “8/14/98 8:35:48 P.M.”.
‘ Set a new system date using any valid date format.
Date = “10/14/98″
Date = “October 14, 1998″
To help you compare the outcome of all date and time functions, all the examples in this section assume that they’re executed at the date and time shown in the preceding code snippet: October 17, 2008, 9:25:33 p.m.
The outdated Date$ and Time$ properties can also be used for the same task. They’re String properties, however, and therefore recognize only the mm/dd/yy or mm/dd/yyyy formats and the hh:mm:ss and hh:mm formats, respectively. For this reason, it’s usually better to use the new $-less functions.
The Now function returns a Date value that contains the current date and time:
Print Now ‘ Displays “10/17/2008 9:25:33 P.M.”.
But the time-honored Timer function returns the number of seconds elapsed from midnight and is more accurate than Now because the Timer function includes fractional parts of seconds. (The actual accuracy depends on the system.) This function is often used for benchmarking a portion of code:
StartTime = Timer
‘ Insert the code to be benchmarked here.
Print Timer – StartTime
The preceding code suffers from some inaccuracy: The StartTime variable might be assigned when the system tick is about to expire, so your routine could appear to take longer than it actually does. Here’s a slightly better approach:
StartTime = NextTimerTick
‘ Insert the code to be benchmarked here.
Print Timer _ StartTime
‘ Wait for the current timer tick to elapse.
Function NextTimerTick() As Single
Dim t As Single
t = Timer
Do: Loop While t = Timer
NextTimerTick = Timer
End Function
If you’re using the Timer function in production code, you should be aware that it’s reset at midnight, so you always run the risk of introducing unlikely but potentially serious errors. Try to spot the bug in this routine, which adds a CPU-independent pause in your code:
‘ WARNING: this procedure has a bug.
Sub BuggedPause(seconds As Integer)
Dim start As Single
start = Timer
Do: Loop Until Timer _ start >= seconds
End Sub
The bug manifests itself very rarely—for example, if the program asks for a 2-second pause at 11:59:59 p.m. Even if this probability is small, the effect of this minor bug is devastating and you’ll have to press Ctrl+Alt+Del to kill your compiled application. Here’s a way to work around this issue:
‘ The correct version of the procedure
Sub Pause(seconds As Integer)
Const SECS_INDAY = 24! * 60 * 60 ‘ Seconds per day
Dim start As Single
start = Timer
Do: Loop Until (Timer + SECS_INDAY – start) Mod SECS_INDAY >= seconds
End Sub
Not only does Visual Basic let you store date and time information in the specific Date data type, it also provides a lot of date- and time-related functions. These functions are very important in all business applications and deserve an in-depth look. Date and Time are internally stored as numbers in Visual Basic. The decimal points represents the time between 0:00:00 and 23:59:59 hours inclusive.
The system’s current date and time can be retrieved using the Now, Date and Time functions in Visual Basic. The Now function retrieves the date and time, while Date function retrieves only date and Time function retrieves only the time.
To display both the date and time together a message box is displayed use the statement given below.
MsgBox “The current date and time of the system is” & Now
Here & is used as a concatenation operator to concentrate the string and the Now function. Selective portions of the date and time value can be extracted using the below listedfunctions.
Function Extracted Portion
Year ( ) Year (Now)
Month ( ) Month (Now)
Day ( ) Day (Now)
WeekDay ( ) WeekDay (Now)
Hour ( ) Hour (Now)
Minute ( ) Minute (Now)
Second ( ) Second (Now)
The calculation and conversion functions related to date and time functions are listed below.
Function Description
DateAdd ( ) Returns a date to which a specific interval has been added
DateDiff ( ) Returns a Long data type value specifying the interval between the two values
DatePart ( ) Returns an Integer containing the specified part of a given date
DateValue ( ) Converts a string to a Date
TimeValue ( ) Converts a string to a time
DateSerial ( ) Returns a date for specified year, month and day
The DateDiff function returns the intervals between two dates in terms of years, months or days. The syntax for this is given below.
DateDiff (interval, date1, date2[, firstdayofweek[, firstweekofyear]])
The format function accepts a numeric value and converts it to a string in the format specified by the format argument. The syntax for this is given below.
Format (expression[, format[, firstdayofweek[, firstweekofyear]]])
The Format function syntax has these parts:
Part Description
Expression Required any valid expression
format Optional. A valid named or user-defined format expression.
firstdayofweek Optional. A contant that specifies the first day of the week.
firstweekofyear Optional. A contant that specifies the first week of the year
Constants are named storage locations in memory, the value of which does not change during program Execution. They remain the same throughout the program execution. When the user wants to use a value that never changes, a constant can be declared and created. The Const statement is used to create a constant. Constants can be declared in local, form, module or global scope and can be public or private as for variables. Constants can be declared as illustrated below.
Public Const gravityconstant As Single = 9.81
The predefined constants can be used anywhere in the code in place of the actual numeric values. This makes the code easier to read and write.
For example consider a statement that will set the window state of a form to be maximized.
Form1.Windowstate = 2
The same task can be performed using a Visual Basic constant
Form1.WindowState = vbMaximized
Many built-in functions are offered by Visual Basic fall under various categories. These functions are procedures that return a value. The functions fall into the following basic categories that will be discussed in the follwing sections at length.
Variables of different data types when combined as a single variable to hold several related informations is called a User-Defined data type.
A Type statement is used to define a user-defined type in the General declaration section of a form or module. User-defined data types can only be private in form while in standard modules can be public or private. An example for a user defined data type to hold the product details is as given below.
Private Type ProductDetails
ProdID as String
ProdName as String
Price as Currency
End Type
The user defined data type can be declared with a variable using the Dim statement as in any other variable declaration statement. An array of these user-defined data types can also be declared. An example to consolidate these two features is given below.
Dim ElectronicGoods as ProductDetails ‘ One Record
Dim ElectronicGoods(10) as ProductDetails ‘ An array of 11 records
A User-Defined data type can be referenced in an application by using the variable name in the procedure along with the item name in the Type block. Say, for example if the text property of a TextBox namely text1 is to be assigned the name of the electronic good, the statement can be written as given below.
Text1.Text = ElectronicGoods.ProdName
If the same is implemented as an array, then the statement becomes
Text1.Text = ElectronicGoods(i).ProdName
User-defined data types can also be passed to procedures to allow many related items as one argument.
Sub ProdData( ElectronicGoods as ProductDetails)
Text1.Text = ElectronicGoods.ProdName
Text1.Text = ElectronicGoods.Price
End Sub
While you can create two-dimensional arrays in Visual Basic, their structure isn’t really flexible for at least two reasons: All rows in the array must have the same number of elements, and you can use ReDim Preserve to change the number of columns but you can’t add new rows. The first point is especially important because it often leads you to declare an array that’s far too large for your needs, thus allocating a lot of memory that in most cases remains largely unused. You can solve both problems using a structure known as an array of arrays.
The technique is conceptually simple: Since you can store an array in a Variant variable, you can build an array of Variants, where each item holds an array. Each subarray—a row of this pseudo-array—can hold a different number of elements, and you don’t need to use more memory than is strictly necessary.
Here’s an example, based on an imaginary PIM (Personal Information Manager) program. In this program, you need to keep track of a list of appointments for each day of the year. The simplest solution would be to use an array in which each row corresponds to a day in the year and each column to a possible appointment. (For the sake of simplicity, let’s assume that each appointment’s data can be held in a string.)
ReDim apps(1 To 366, 1 To MAX_APPOINTMENTS) As String
Of course, you now have the problem of setting a reasonable value for the MAX_APPOINTMENTS symbolic constant. It should be high enough to account for all possible appointments in a day but not too high because you might be wasting a lot of memory without any real reason. Let’s see how the array of arrays technique can help us save memory without posing any artificial limit to your application:
‘ A module-level variable
Dim apps(1 To 366) As Variant
‘ Add an appointment for a given day.
Sub AddNewAppointment(day As Integer, description As String)
Dim arr As Variant
If IsEmpty(apps(day)) Then
‘ This is the first appointment for this day.
apps(day) = Array(description)
Else
‘ Add the appointment to those already scheduled.
arr = apps(day)
ReDim Preserve arr(0 To UBound(arr) + 1) As Variant
arr(UBound(arr)) = description
apps(day) = arr
End If
End Sub
‘ Extract all the appointments for a given day.
Sub ListAppointments(day As Integer, lst As ListBox)
Dim i As Long
For i = 0 To UBound(apps(1))
lst.AddItem apps(1)(i)
Next
End Sub
In this example, I kept the code as simple as possible and used an array of Variant arrays. You could save even more memory if each row of this array were built using an array of a more specific data type (String, in this case). Note the special syntax used to address an item in an array of arrays:
‘ Change the description for the Nth appointment.
apps(day)(n) = newDescription
Nothing keeps you from extending this concept further, introducing an array of arrays of arrays, and so on. If you’re dealing with arrays in which each row can vary considerably in length, this approach is going to save you a lot of memory and, in most cases, improve your overall performance too. A key feature of an array of arrays is that you can process entire rows of your pseudo-array as if they were single entities. For example, you can swap them, replace them, add and delete them, and so on.
‘ Move the January 1st appointments to January 2nd.
apps(2) = apps(1)
apps(1) = Empty
Finally, an important advantage of this technique is that you can add new rows without losing the current contents of the array. (Remember that you can use ReDim Preserve on regular arrays only to modify the number of columns, not the number of rows.)
‘ Extend the appointment book for another nonleap year.
ReDim Preserve apps(1 to UBound(apps) + 365) As Variant
Sorting is an operation that you often perform on arrays. As you probably know, there are dozens of different sort algorithms, each one with its strengths and weaknesses. I found that the Shell Sort algorithm works well in most cases, and I’ve prepared a generic routine that sorts any one-dimensional array of a data type compatible with the Variant type, either in ascending or descending order:
Sub ShellSortAny(arr As Variant, numEls As Long, descending As Boolean)
Dim index As Long, index2 As Long, firstItem As Long
Dim distance As Long, value As Variant
‘ Exit if it is not an array.
If VarType(arr) < vbArray Then Exit Sub
firstItem = LBound(arr)
‘ Find the best value for distance.
Do
distance = distance * 3 + 1
Loop Until distance > numEls
‘ Sort the array.
Do
distance = distance \ 3
For index = distance + firstItem To numEls + firstItem – 1
value = arr(index)
index2 = index
Do While (arr(index2 – distance) > value) Xor descending
arr(index2) = arr(index2 – distance)
index2 = index2 – distance
If index2 – distance < firstItem Then Exit Do
Loop
arr(index2) = value
Next
Loop Until distance = 1
End Sub
Some of the most common operations you perform on arrays are inserting and deleting items, shifting all the remaining elements toward higher indices to make room or toward lower indices to fill the “hole” a deletion has left. You usually do this with a For…Next loop, and you can even write generic array procedures that work with any type of array (with the usual restrictions about arrays of UDTs and fixed-length strings that can’t be passed to a Variant parameter):
Sub InsertArrayItem(arr As Variant, index As Long, newValue As Variant)
Dim i As Long
For i = UBound(arr) – 1 To index Step -1
arr(i + 1) = arr(i)
Next
arr(index) = newValue
End Sub
Sub DeleteArrayItem(arr As Variant, index As Long)
Dim i As Long
For i = index To UBound(arr) – 1
arr(i) = arr(i + 1)
Next
‘ VB will convert this to 0 or to an empty string.
arr(UBound(arr)) = Empty
End Sub
If your application works intensively with arrays, you might find that an approach based on For…Next loops is too slow. In some cases, you can considerably speed up these operations by using the RtlMoveMemory API function, which many Visual Basic programmers know under its popular alias name, CopyMemory.1 This function lets you move a block of bytes from one memory address to another memory address and works correctly even if the two areas partially overlap. Here’s the code that inserts a new item in an array of Longs:
Private Declare Sub CopyMemory Lib “kernel32″ Alias “RtlMoveMemory” _
(dest As Any, source As Any, ByVal numBytes As Long)
Sub InsertArrayItemLong(arr() As Long, index As Long, newValue As Long)
‘ We let VB evaluate the size of each item using LenB().
If index < UBound(arr) Then
CopyMemory arr(index + 1), arr(index), _
(UBound(arr) _ index) * LenB(arr(index))
End If
arr(index) = newValue
End Sub
Sub DeleteArrayItemLong(arr() As Long, index As Long)
If index < UBound(arr) Then
CopyMemory arr(index), arr(index + 1), _
(UBound(arr) _ index) * LenB(arr(index))
End If
arr(index) = Empty
End Sub
IMPORTANT NOTE: The prerequisite for using the CopyMemory API function is that data must be stored in contiguous memory locations, so you absolutely can’t use it to insert or remove elements in String and Object arrays, nor in arrays of UDTs that contain conventional strings, object references, or dynamic arrays. (Fixed-length strings and static arrays in UDTs are OK, though.)
Note that while you can’t use the preceding routines for arrays other than Long arrays, the statements in the procedure body can be recycled for another data type without any change, thanks to the use of the LenB function. Therefore, you can derive new array functions that work for other data types by simply modifying the procedure’s name and its parameter list. For example, you can create a new function that deletes an item in a Double array by editing just the first line of code (shown in boldface):
Sub DeleteArrayItemDouble(arr() As Double, index As Long)
‘ All the other statements here are the same as in DeleteArrayItemLong
‘ …
End Sub

Categories
Tag Cloud
Blog RSS
Comments RSS
Last 50 Posts
Back
Back
Back
Void « Default
Life
Earth
Wind
Water
Fire
Light 