
Some very basic but handy tips for newbies (and maybe not so newbies). Hope you learn something.
I've added quite a bit more to the article, mostly very basic info on the vb language, but we all had to learn this stuff when we started out.
A Brief History of Basic
- BASIC - Beginner's All-purpose Symbolic Instruction Code.
- This language was developed in the early 1960's at Dartmouth College.
- Answer to complicated programming languages (FORTRAN, Algol, Cobol...). First timeshare language.
- In the mid-1970's, two college students write first Basic for a microcomputer (Altair) - cost $350 on cassette tape. You may have heard of them: Bill Gates and Paul Allen.
- Every Basic since then is essentially based on that early version. Examples include: GW-Basic, QBasic, QuickBasic.
- Visual Basic was introduced in 1991.
Tips
In VB's Tools > Options > Editor Format tab > Code Colors
Select Identifier Text > then Foreground > Dark Red!
I recommend that you uncheck:
Tools > Options > Editor tab > Auto Syntax Check
Syntax checking is still enabled but instead of freezing the editor until you dismiss the msgbox and correct the error, the offending code is simply displayed in red, allowing you to continue coding unhindered, and can return to the 'red devil' when finnished what you're doing. Rd.
I often see this:
Dim var1, var2, var3 As StringThis initializes 2 variants and 1 string, it's the same as this:
Dim var1 As Variant, var2 As Variant, var3 As StringI assume the coder desires:
Dim var1 As String, var2 As String, var3 As StringUse VarType or TypeName to see for yourself.
Added this bit thanks to Timothy Marin. Some say not to use these (and james kahl has a point) but it's up to you:
Dim fff$ ' Declares a String variable Dim hhh% ' Declares a Integer variable Dim ggg& ' Declares a Long variable Dim iii! ' Declares a Single variable Dim jjj# ' Declares a Double variable Dim kkk@ ' Declares a Currency variable
I often see this:
If Dir$(sFileName) <> "" Then ' I believe I have a file, ' do some work on it End IfThis code will fail if sFileName = "" because Dir will return the name of the first file found (with any name) You can do this instead:
If sFileName <> "" Then If Dir$(sFileName) <> "" Then ' We have a file, do some work on it End If End IfOr as Luke H so rightly pointed out, you should do this:
If LenB(sFileName) <> 0 Then If LenB(Dir$(sFileName)) <> 0 Then ' We have a file, do some work on it End If End IfThis lot's from Bruce McKinney's book 'Hardcore VB'
That statement works until you specify a file on an empty floppy or CD-ROM drive. Then you’re stuck in a message box. Here’s another common one:
fExist = FileLen(sFullPath)It fails on 0-length files — uncommon but certainly not unheard of. My theory is that the only reliable way to check for file existence in VB (without benefit of API calls) is to use error trapping. I’ve challenged many Visual Basic programmers to give me an alternative, but so far no joy. Here’s the shortest way I know:
Function FileExists(sSpec As String) As Integer On Error Resume Next Call FileLen(sSpec) FileExists = (Err = 0) End FunctionThis can’t be very efficient. Error trapping is designed to be fast for the no fail case, but this function is as likely to hit errors as not. Perhaps you’ll be the one to send me a Basic-only ExistFile function with no error trapping that I can’t break. Until then, here’s an API alternative:
Function ExistFileDir(sSpec As String) As Boolean Dim af As Long af = GetFileAttributes(sSpec) ExistFileDir = (af <> -1) End FunctionI didn’t think there would be any way to break this one, but it turns out that certain filenames containing control characters are legal on Windows 95 but illegal on Windows NT. Or is it the other way around? Anyway, I have seen this function fail in situations too obscure to describe here. Bruce McKinney.
Here's my solution:
Function FileExists(sFileSpec As String) As Boolean If (sFileSpec = vbNullString) Then Err.Raise 5 On Error GoTo NoGo Dim Attribs As Long Attribs = FileSystem.GetAttr(sFileSpec) If (Attribs <> -1) Then FileExists = ((Attribs And vbDirectory) <> vbDirectory) End If NoGo: End FunctionFunction DirExists(sPath As String) As Boolean If (sPath = vbNullString) Then Err.Raise 5 On Error GoTo NoGo Dim Attribs As Long Attribs = FileSystem.GetAttr(sPath) If (Attribs <> -1) Then DirExists = ((Attribs And vbDirectory) = vbDirectory) End If NoGo: End Function
Data types in VB
Numeric Data : Integers (whole numbers without decimal places) and Real (decimals, or floating-point numbers).
Suf Type Storage Range Byte 1 byte 0 to 255 % Integer 2 bytes -32,768 to 32,767 & Long 4 bytes -2,147,483,648 to 2,147,483,647 ! Single 4 bytes -3.42823E+38 to -1.401298E-45 (neg) and
1.401298E-45 to 3.42823E+38 (pos)# Double 8 bytes -1.79769313486232E+308 to
-4.94065645841247E-324 (negative) and
4.94065645841247E-324 to
1.79769313486232E+308 (positive)@ Currency 8 bytes -922,337,203,685,477.5808 to
922,337,203,685,477.5807 (the extra
precision ensures accuracy to 2 dec places)Decimal 12 bytes +/-79,228,162,514,264,337,593,543,950,335
(with no decimal, or up to 28 decimal places)
+/-7.9228162514264337593543950335Shift State
Constant Value Description vbShiftMask 1 SHIFT key bit mask. vbCtrlMask 2 CTRL key bit mask. vbAltMask 4 ALT key bit mask. Presently, only three of the 32 bits in the Shift parameter
are used. In future versions of Visual Basic, however, these
other bits may be used. Therefore, as a precaution against
future problems, you should mask these values appropriately
before performing any comparisons. Use a bitwise And to mask
the Shift parameter:Dim ShiftState As Integer ShiftState = Shift And vbShiftMaskIn the above example ShiftState will hold zero if the Shift
key was not pressed, or one if pressed (in any combination
with the Ctrl and Alt keys). Likewise, you can mask the Shift
parameter against vbCtrlMask to return zero or two, and
vbAltMask to return zero or four.Dim ShiftDown As Boolean Dim CtrlDown As Boolean Dim AltDown As BooleanShiftDown = (Shift And vbShiftMask) = vbShiftMask CtrlDown = (Shift And vbCtrlMask) = vbCtrlMask AltDown = (Shift And vbAltMask) = vbAltMask
True-conditions perform faster. So, if you can make assumptions about your conditions, set up the code so that the test returns True.
Before continuing, SAVE your project to disk for safety!
Max Path Length
Const MAX_PATH As Long = 260The maximum length, in characters, of a file path supported by the specified file system. A filename component is actually that portion of a file path between backslashes.
Under NT (Intel) and Win95 it can be up to 259 (MAX_PATH - 1) characters long. This length must include the drive, path, filename, commandline arguments and quotes (if the string is quoted).
Notice that the MAX_PATH constant is assigned 260 on Windows 9x systems. This is because it combines the root ("x:\"), the Maximum Component Length value (255), plus a possible trailing backslash ("\") character.
Len(sPath) <= 3 + 255 + 1 or Len(sPath) < MAX_PATHThe complete path must be less than MAX_PATH characters.
Logical Operators
The logical operators enable you to combine two or more sets of conditional comparisons.
And Both sides must be True (to return True) Or Only one side need be True, or both Xor Only one side must be True, not both Not Reverses (inverts) boolean condition The And logical operator requires both sides to be True to return True.
If (x >= 1) And (x <= 10) Then ...The Or logical operator needs only one side to be True to return True. This operator is really an Inclusive Or.
If (y = 0) Or (z <> 10) Then ...The Xor logical operator requires that only one side CAN be True to return True. Therefore, its is an Exclusive Or.
If (count1 = limit) Xor (count2 = limit) Then CountSyncErrorOccured End IfThe Not logical operator inverts the boolean value.
The following two code examples both reverse the value:
result = Not (expression) result = (expression) Xor TrueBe careful with the Xor and Not operators, as they only work (as you might expect) with boolean True and False values. So expression must evaluate to a boolean True or False value.
Note - True equates to -1, and False equates to 0.
Because zero equates to False, and all other numbers equate to True when tested within a conditional (an If statement for example) you can generally do this:
If iNum Then 'Do something End IfIf iNum is not zero it will equate to True, including negative values:
3 = True 2 = True 1 = True 0 = False -1 = True -2 = True -3 = TrueBut if you wanted to reverse the condition as follows, it may not work as you expect:
If Not iNum Then 'Do something End IfOnly if iNum is -1 will the conditional equate to False. Any other value including zero will equate to True:
Not 3 = -4 ' True Not 2 = -3 ' True Not 1 = -2 ' True Not 0 = -1 ' True (Not False) Not -1 = 0 ' False (Not True) Not -2 = 1 ' True Not -3 = 2 ' TrueSo do the following when using Not with numeric values:
If Not CBool(iNum) Then 'Do something End IfNot CBool(3) = False ' Not True Not CBool(2) = False ' Not True Not CBool(1) = False ' Not True Not CBool(0) = True ' Not False Not CBool(-1) = False ' Not True Not CBool(-2) = False ' Not True Not CBool(-3) = False ' Not TrueNote that Xor works the same.
Conditional Operators
VB supports six conditional operators:
= Equal to > Greater than < Less than >= Greater than or equal to <= Less than or equal to <> Not equal toVB also supports a special kind of conditional operator:
Like Performs comparisons using wildcardsHere are the widcards that can be used with Like:
* Any character or characters ? Any alpha character (letters) # Any numeric character (numbers) [] Encloses possible characters - Specifies a rangee.g:
"This string" Like "This*" returns True "This string" Like "This ???ing" returns True "Numeric 123" Like "Numeric ###" returns True "Version 2 b" Like "Version [123] *" returns True "" Like "[]" returns True "E" Like "[C-H]" returns TrueUse the [] to test for a possible character within a group.
By using a hyphen (–) to separate the upper and lower bounds of the range, charlist can specify a range of characters. The meaning of a specified range depends on the character ordering valid at run time (as determined by Option Compare and the locale setting of the system the code is running on). Using the Option Compare Binary, the range [A–E] matches A, B, C, D, E. With Option Compare Text, [A–E] matches A, a, À, à, B, b,... E, e. The range does not match Ê or ê because accented characters fall after unaccented characters in the sort order.
Mathematical Operators
The mathematical operators perform calculations on numerical values:
() Parenthesis ^ Exponentiation (Power Of) * Multiplication / Division \ Integer Division Mod Modulus + Addition - SubtractionOperator Precedence
Precedence is the order of importance given to operators in VB. In other words, precedence determines which part of an expression will be executed first.
The following is the order of precedence from highest to lowest:
() Parenthesis ^ Exponentiation (Power Of) * / \ Mod Multiplication, Division, Int Division and Modulus + - Addition and Subtraction Like Performs comparisons using wildcards Not Reverses (negates) boolean condition And Both sides must be true Or Only one side need be true, or both Xor One side must be true, but not both
Before continuing, SAVE your project to disk for safety!
Byte arrays are the only way to store binary data in a stable format that won't be modified by Unicode conversion.
To Add a text file or other non-standard file into a VB project edit the .vbp file and insert a line similar to this:
RelatedDoc=readme.txtThe file will be displayed in the Resources section of the project explorer.
A loop used to remove selected items from a list without error:
For i = lstData.ListCount - 1 To 0 Step -1 If lstData.Selected(i) Then lstData.RemoveItem i Next
Option buttons use the property .Value = True|False while Checkboxes use the property .Value = 0|1|2 to specify checked.
You can put more than one statement on a line by separating them with a colon :
Dim myInt%: myInt = 0Thanks Timothy Marin for this tip.
Before continuing, SAVE your project to disk for safety!
If you want to place controls in a frame but already have the controls on the form, just select all controls (with selection tool or hold down the CTRL key as you click each control), and CUT, then place the frame on the form, then with the frame selected, PASTE.
KeyPress and KeyDown Events
The KeyPress event occurs when the user presses the Uppercase and Lowercase letters, Numeric digits, Punctuation keys, and the Enter, Tab, and Backspace keys.
Some VB Constants are: vbKeyReturn, vbKeyTab and vbKeyBack.
KeyPress events capture just the main ASCII characters (letters, numbers and punctuation) plus Backspace, Enter and Tab.
KeyPress handles the shift state itself, passing the event procedure the correct code. The event object recieves the keycode (as was or modified) AFTER the procedure ends.
This makes KeyPress the event handler to use when you wish to process and/or modify the characters before they are displayed in the form's event object.
KeyDown events capture ALL keyboard keys, but only recognize letters in all caps, so you must test for shift state as well for lowercase. KeyUp (like KeyDown) receives only uppercase keycodes.
KeyDown does not wait to pass the key code on to the form object, while KeyPress passes the key code on to the event object after the procedure ends.
With KeyDown the event object handles the shift state itself, so the event object receives upper or lowercase according to the shift and caps lock key states - then the KeyDown event procedure runs.
You might think that you could save space by declaring a variable As Byte or As Integer instead of As Long. However, on 32-bit operating systems the code to load a Long is faster and more compact than the code to load shorter data types.
Not only could the extra code exceed the space saved, but there might not be any space saved to begin with — because of alignment requirements (32-bit) for modules and data.
Subs and Funcs
A subroutine does not return a value.
Private Sub cmdSubCalculate_Click() Call multiply1(2, 3) End SubPrivate Sub multiply1(ByVal x As Integer, ByVal y As Integer) Dim z As Integer z = x * y txtResult.Text = z End SubA function returns a value by assigning the resulting
value of its processing to a 'variable' (the name of the
function) which is returned to the calling subroutine or
function.Private Sub cmdFuncCalculate_Click() txtResult.Text = Multiply2(2, 3) End SubPrivate Function Multiply2(ByVal x As Integer, ByVal y As Integer) As Integer Dim z As Integer z = x * y Multiply2 = z End FunctionBoth subs and functions can have arguments passed by
reference, allowing the source variable to be modified
by the procedure.Private Sub cmdByRefCalculate_Click() Dim z As Integer If (Multiply3(2, 3, z) Then txtResult.Text = z End If End SubPrivate Function Multiply3(ByVal x As Integer, ByVal y As Integer, ByRef z As Integer) As Boolean z = x * y Multiply3 = True End Function
You can add quit confirmation to a windows standard exit methods:
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer) ' A forms QueryUnload event occurs immediately before the ' form unloads. ' UnloadMode is zero when a window is closed by using any ' of the standard exit methods (by clicking the [x] close button, ' by selecting close from the windows context menu, by pressing ' ALT-F4, or by double-clicking the window icon in the top-left ' corner). ' Cancel (passed by reference to the event) is zero (False), and ' so the form will unload; False means 'not to Cancel the unload'. ' You can cancel the unloading of the form by setting Cancel to ' one (True); so saying 'yes to Cancel the unload'. If UnloadMode = 0 Then Dim dialogtype As Integer Dim title, msg As String Dim response As Integer dialogtype = vbYesNo + vbQuestion title = "Name of program" msg = "Are you sure?" response = MsgBox(msg, dialogtype, title) If response = vbNo Then Cancel = True End If End If End Sub
The UnloadMode variable in the Query_Unload event indicates how this event was triggered by containing one of the five values in the following table.
QueryUnloadConstants: vbFormControlMenu = 0 The user chose the Close command on the Control-menu box. vbFormCode = 1 The application used the Query_Unload method itself. vbAppWindows = 2 The operating system is being shut down, or the user is logging off. vbAppTaskManager = 3 The application is being shut down by the Task Manager. vbFormMDIForm = 4 An MDI form, which closes all child forms belonging to it, is being closed. vbFormOwner = 5 The owner of the form is closing.
Select Case Statement
Executes one of several groups of statements, depending on the value of an expression.
Select Case Index Case 0 Grade = "first" Case 1 Grade = "second" Case 2 Grade = "third" Case 3 Grade = "fourth" Case 4 Grade = "fifth" Case 5 Grade = "sixth" End SelectThe same Case Statement using colons:
Select Case Index Case 0 : Grade = "first" Case 1 : Grade = "second" Case 2 : Grade = "third" Case 3 : Grade = "fourth" Case 4 : Grade = "fifth" Case 5 : Grade = "sixth" End SelectVB also offers a way of testing for a condition with the Is keyword added to Case:
Select Case testscore Case Is >= 80 student_grade = "A" Case Is >= 65 student_grade = "B" Case Is >= 50 student_grade = "C" Case Else student_grade = "F" End SelectSo the following two examples are the same:
Select Case Format(today, "mmmm") Case "January": optjan.Value = True Case "February": optfeb.Value = True Case "March": optmar.Value = True Case "April": optapr.Value = True Case "May": optmay.Value = True Case "June": optjun.Value = True Case "July": optjul.Value = True Case "August": optaug.Value = True Case "September": optsep.Value = True Case "October": optoct.Value = True Case "November": optnov.Value = True Case "December": optdec.Value = True End SelectSelect Case Format(today, "mmmm") Case Is = "January": optjan.Value = True Case Is = "February": optfeb.Value = True Case Is = "March": optmar.Value = True Case Is = "April": optapr.Value = True Case Is = "May": optmay.Value = True Case Is = "June": optjun.Value = True Case Is = "July": optjul.Value = True Case Is = "August": optaug.Value = True Case Is = "September": optsep.Value = True Case Is = "October": optoct.Value = True Case Is = "November": optnov.Value = True Case Is = "December": optdec.Value = True End SelectThe usage for the Case Is format allows the testing of conditions that don't have to be an exact match (=), but can also be other conditions (>, <, >=, <=, etc). Only the use of simple comparisons are allowed, so no logical operators (And, Or, Xor, or Not) can be used.
Select Case varInteger Case Is <= 150: MsgBox "Is 150 or less" Case Is <= 200: MsgBox "Is between 151 and 200 inclusive" Case Else: MsgBox "Is 201 or greater" End SelectIt is important to realize that with such conditional tests the order of each Case Is matters. Consider if the above Case statement was like this:
Select Case varInteger Case Is <= 200: MsgBox "Is 200 or less" Case Is <= 150: MsgBox "Is 150 or less" Case Else: MsgBox "Is 201 or greater" End SelectEven if the integer value was below 150 the condition would still execute only the code corresponding to the first Case tested.
In addition to the formats used above, Select Case statements can also include the To keyword, as follows:
Select Case Asc(Char) Case 65 To 90: MsgBox "Uppercase 'A' to 'Z' inclusive" Case 97 To 122: MsgBox "Lowercase 'a' to 'z' inclusive" End SelectYou can combine the different formats into a single Case statement:
Select Case varInteger Case 100 To 130, 140 MsgBox "Is between 100 and 130 inclusive, or is 140" Case 150 To 180, 190, Is >= 200 MsgBox "Is between 150 and 180 inclusive, or is 190, or is 200 or greater" Case Else MsgBox "All else (below 100, 131 to 139, etc)" End SelectYou also can specify ranges and multiple expressions for character strings.
In the following example, Case matches strings that are exactly equal to everything, strings that fall between nuts and soup in alphabetic order, and the current value of TestItem:
Case "everything", "nuts" To "soup", TestItem
Gaussian Rounding
A remark by René Rhéaume, 21.09.01
This "Banker's" method uses the Gauss rule that if you are in an perfect half case, you must round to the nereast digit that can be divided by 2 (0,2,4,6,8). This rule is important to obtain more accurate results with rounded numbers after operation.
Now, an example :
2 digits 2 digits Unrounded "Standard" rounding "Gaussian" rounding 54.1754 54.18 54.18 343.2050 343.21 343.20 +106.2038 +106.20 +106.20 ========= ======= ======= 503.5842 503.59 503.58Which one is nearer from unrounded result? The "Gaussian" one (Difference of 0.0042 with "Gaussian/Banker" and 0.0058 with "Standard" rounding.)
Another example with half-round cases only:
1 digit 1 digit Unrounded "Standard" Rounding "Gaussian rounding" 27.25 27.3 27.2 27.45 27.5 27.4 + 27.55 + 27.6 + 27.6 ======= ====== ====== 82.25 82.4 82.2Again, the "Gaussian" rounding result is nearer from the unrounded result than the "Standard" one.
René Rhéaume
[email protected]
Rd.