VB & VBA in a Nutshell by Paul Lomax Unconfirmed error reports are from readers. They have not yet been approved or disproved by the author or editor and represent solely the opinion of the reader. If you have any error reports or technical questions, you can send them to booktech@oreilly.com. (Please specify the printing date of your copy.) This page was last updated July 29, 2004. Here's a key to the markup: [page-number]: serious technical mistake {page-number}: minor technical mistake : important language/formatting problem (page-number): language change or minor formatting problem ?page-number?: reader question or request for clarification UNCONFIRMED errors and comments from readers: (16) 1st sentence of paragraph after "At startup"; "When Excel starts. it automatically" should read "When Excel starts, it automatically". {19, 24} Example Sub Main() procedure for starting a VB app. The line "oForm.Show vbModal" works for a regular form, but not for an MDI form, since MDI forms can't be shown modally. [27] Date description; What is the precision of Date? The range is specified in days, but the default value is specified in time, with a 1 second precision. Which day is default? The range and default should match in precision. {28} Integer description; The line "One bit represents the sign (either positive or negative)." should read, "The number is represented as a 16 bit two-complement number. This incorporates the sign in its range." The statement as it stands is inaccurate because it implies that the bit string &h8000 is negative zero, not -32,768. {28} in Chapter 3 - VBA Variables and Data Types You have the Range of a long integer having a maximum of 2,147,486,647 It should read 2,147,483,647 [39] Before "Nothing keyword"; From your examples, "Empty" is also a keyword. There should be an "Empty keyword" section between the "vbEmpty" section and the "Nothing keyword" section. {39} "Nothing Keyword" section: For: Set objvar = Nothing Read: Set objVar = Nothing {46} Beginning of second paragraph of "Variable Scope and Lifetime" section; "... module using the Private keyword ..." should read "... module using the Dim or Private keywords ...". {47} In the "Friend Scope" paragraph; This item now reads: "The Friend keyword can only be used for variables and procedure declarations within an object module..." Alas, the Friend keyword is valid ONLY for procedures (or properties) and NOT for variables... [51, 541] These pages contradict each other. Page 51, penultimate paragraph states: ... ByRef is much faster than ByVal. Page 541, last paragraph states: In general, ByRef arguments ... within class modules take longer to perform [than ByVal arguments] ... {52} "Optional Arguments" section. Add an example at the end: Public Sub Msg (Optional ByVal Message as Variant) Debug.Print "Message = " & Iif(IsMissing(Message),"",Message) End Sub [53] Before Intrinsic Constants section; A section named "Literal Constants" needs to be added describing how to form literal strings (Enclosed in "s and embedded "s are represented by "". \ means nothing.), date literals (Enclosed in #s. Must look like a date -- but what exactly does THAT mean?), hexadecimal constants (Preceded by &h and in upper or lower case). The on- line documentation is rather mute about this. I picked up most of this from examples. Other language definitions usually mention this quite explicitly. See chap. 3 of JavaScript, The Definitive Guide, examples in chap. 2 of Programming Perl, 6.1.3.4 of the C language standard, etc. {54} third paragraph, first line: For: COM interface Read: COM (Component Object Model) interface {85-86} Between lines 2 and 3 of example code; While the description of this code snippet suggests "you can seamlessly use Microsoft Word to print output from your VB program without the user knowing that you have actually used Microsoft Word," this is only true if you insert this line immediately after the line "Set oWordSel = Nothing" and before the line "Set oWordActiveDoc = Nothing": oWordActiveDoc.Close SaveChanges:=wdDoNotSaveChanges Otherwise, if Word is already running, the document created by your code will appear as a window which the user may activate and view, or, on shutdown, the user will be prompted to save the document. Either case will destroy the "illusion" that you are trying to achieve. (127) Fourth bulleted tip; Second line of the example reads: Title = Array("Mr", "Mrs", "Miss", "Ms") I think it should read Titles = Array("Mr", "Mrs", "Miss", "Ms") {129} "See Also" section at top of page: Add: IsArray Function ?129? In the "Return Value" section, explain the abbreviation DBC. {132} Add a new entry: Assert Method See Debug.Assert method. (140) 8th paragraph: The Gregorian calendar year of 1998 (which is based on the birth of Christ) is roughly equivalent to the Hijri year of 1418 (which is based on the birth of Mohamed). The Hijri calendar is not based on the birth of Mohamed. The year 0 in the Hijri calendar is the year when Mohamed moved from Mecca to Medina. (141) 2nd paragraph (Ch. 7 > Calendar Property > Programming tips & gotchas); This section should mention the limits of any Hijri calendar algorithm, and specify (if possible) the coordinates (latitude and longitude) used for the VB/VBA conversion. For more details, see: http://www.cs.pitt.edu/~tawfig/convert/introduction.html. {146} Add a new entry: Case Statement See Select Case statement. {157} last text paragraph: For: ... using the Choose function to handle the an option button selection ... Read: ... using the Choose function to handle an option button selection ... {158} "See Also" section: For: ... Switch Statement Read: ... Switch Function {163} "See Also" section: Add: Reset Statement {168} Collection.Count is actually a method, not a property -- at least that's what I see in the Object Browser. (Am I pedantic or what?) {175} For the Command Function, add a new section: Add: See Also Shell Function [175] "Syntax" section: For: [Public|Private] Const constantname = constantvalue Read: [Public|Private] Const constantname [As datatype] = constantvalue Also, modify the rest of this entry to reflect the availability of the "As" clause. {178} "Description" section, add a final sentence: Add: CreateObject causes the object's Initialize event to be raised. {182} "Return Value" section and "Description" section: For: ... current path. Read: ... current directory path {182} "Rules at a Glance" section, first bullet: For: ... returns the path for the current drive. Read: ... returns the current directory path for the current drive. {185} "See Also" section: Add: Error Statement [194] "Programming Tips & Gotchas" section, add another bulleted tip: Add: Date and Date$ do not honour locale settings other than the USA locale. Workaround 1: DateAdd("d",0,Now) Workaround 2: Format(Now,"dddddd") {225} The Dictionary.Add method Takes a parameter called "item," does not require "item" to be String data type as listed at the top of the page, but of course any data type -- as you correctly state six lines later. {227} "Programming Tips & Gotchas: section: For: ... or assign a new key to a nonexistent key ... Read: ... or assign a new item to a nonexistent key ... {236} "Description" section, add a second sentence: Add: Can be used to determine whether a disc object (file or folder/directory) exists. {237} "Rules at a Glance" section continued from the preceding page, second full bulleted item on this page: For: If attributes isn't specified, files matching pathname ... Read: If attributes isn't specified, non-directory files matching pathname ... {237} "Rules at a Glance" section continued from the preceding page, add a further bulleted item: Add: Use CurDir to get the current directory's path. {242} example following third bulleted item: For: If lngCtr / 1000 = Int(lngctr / 1000) Then Read: If lngCtr Mod 1000 = 0 Then {245} Add a new entry: Empty Keyword Description A data subtype automatically assigned to Variant variables before they are assigned a value. [245] "Syntax" section, add a further entry to the list: add: End [245] "Description" section: For: Ends a procedure or a block of code. Read: Terminates program execution, or ends a procedure or a block of code. {246} "See Also" section: Add: Stop Statement {250} "Example" section: For: LineInput #iFile, sDataLine Read: Line Input #iFile, sDataLine {266} Add a new entry: Error Keyword Description A data subtype of a Variant variable used to store an error number {266} "Syntax" section of Event Statement: For: Public Event eventName [(arglist)] Read: [Public] Event eventName [(arglist)] [269] Add a new entry: False Keyword Named Arguments No Syntax False Description The False keyword has a value of 0. Programming Tips & Gotchas The True keyword has a value of -1. {272} "Named Parameters" section: For: Named Parameters Read: Named Arguments {278} "See Also" section: Add: GetAttr Function {282} "Methods" section: For: GetSpecialFolderd Read: GetSpecialFolder {288} 5th item in Rules at a Glance; The default value of the Overwrite argument to the FileSystemObject.CreateTextFile method is true, not false. (294) 5th line from the top; If ofs.fileExists("\\NTSERV1\d$\TestPath\") Then should be: If ofs.folderExists("\\NTSERV1\d$\TestPath\") Then {299} "Programming Tips & Gotchas" section, first bulleted item: For: ... such as coping or moving files ... Read: ... such as copying or moving files ... {325} "Syntax" section, "format" subsection: Add: Data Type: String [327] Examples for 'Medium Time' and 'Short time'; The first parameter should be a time, not a date {333} "Programming Tips & Gotchas" section, first bulleted item, last sentence: For: sMyString = Format(rsMyRecordSet!myValue) Read: sMyString = "" & rsMyRecordSet!myValue (But this now removes the purpose of this bulleted item which was to illustrate Format().) [335] "Rules at a Glance" section, second bulleted item: For: The Tristate constant values are TristateTrue, TristateFalse, and TristateUseDefault Read: The Tristate constant values are vbTrue, vbFalse and vbUseDefault [See page 604] {335} "Programming Tips & Gotchas" section, add an example: Add: Example FormatCurrency("18062.1",2,,vbTrue) returns $18,062.10 {337} "Description" section: Add: If you have been using FreeFile to supply file numbers, checking its value will reveal how many files have been opened. (338) Syntax of Function statement; | Friend] should read: | [Friend] [351] Rules at a Glance section, sixth bulleted item: For: Dim hFile As long hFile = FreeFile() Open sFileName For Random as #hFile Do While Not EOF(1) Get #1,,myVar Loop Close #hFile Read: Dim hFile As Long Dim myVar as String hFile = FreeFile() Open sFileName For Binary as #hFile myVar = Space$(LOF(#hFile)) ' Make room for file Get #hFile,,myVar Close #hFile {355} Add a "See Also" section: Add: See Also FileAttr Function, SetAttr Function {361} "Programming Tips & Gotchas" section, add an example: Add: Example GetSetting("myApp", "Prefs", "Velocity") {379} "Syntax" section, "xpos" and "ypos" subsections: For: The distance from the ... Read: The distance in twips from the ... {384} "Syntax" section, "start" subsection: Add: If start > Len(sourcestring), InstrRev returns 0. [385] "Programming Tips & Gotchas" section: For: The usefulness of a function ... isn't immediately apparent. Read: InstrRev is useful for extracting the rightmost substring of a string, for example, extracting a filename from a pathname: myFile = Mid$(myPath,InstrRev(myPath,"\")+1) {395} "Programming Tips & Gotchas" section, add another bulleted entry: Add: If expression is "" then IsNumeric returns false. {397} Add a "See Also" section for the Join Function: Add: See Also Split Function {397} "Rules at a Glance" section for Kill Statement, last bulleted item: For: If the file is open or is set to read-only, an error is generated. Read: If the file is open or is set to read-only, an error is generated. To delete a read-only file, either use SetAttr statement to first clear the read-only bit, or use the FileSystemObject.DeleteFile method with the Force flag set. [399] "Programming Tips & Gotchas" section, delete the second bulleted entry [see page 126] [407] first paragraph: For: The new controls inherit all the properties of the original control, including it's size and position Read: The new controls inherit most of the properties of the original control, including size and position. The properties not inherited are Index, TabIndex, and Visible (see below). {411-412} "Syntax" section, "resID" subsection: Add: Resource ID 1 is reserved for an application's icon. {415} "See Also" section: Add: Seek Function [415] "Syntax" section, "filenumber" subsection of Lock Statement: For: Any valid file number. Read: Any valid file number. The file must be open shared. {416} "Syntax" section, "recordrange" subsection: For: A range of records. Read: A range of records; the default is the entire file. {426} "Return Value" section: For: A Double representing the modified internal rate of return. Read: A Double representing the modified internal rate of return on a cash flow. {427} "Rules at a Glance" section, second bulleted item: For: ... or it's UNC name. Read: ... or it's UNC (Universal Naming Code) name. [430] "Rules at a Glance" section, fourth bulleted item: For: ... a Help button is automatically placed on the MsgBox dialog ... Read: ... you must include vbMsgBoxHelpButton in the buttons argument ... [431] "Button Display Constants" table, add an extra line: Add: vbMsgBoxHelpButton 16384 Help {435} Add a new entry: Nothing Keyword Description Used with object variables to determine whether a variable has a valid object reference, e.g., If Not objVar Is Nothing Then or to destroy a valid object reference (thus releasing resources), e.g., Set objVar = Nothing. {437} "Return Value" section: For: A Double indicating the number of payments. Read: A Double indicating the number of payments (periods) in an annuity. {439} Add a new entry: Null Keyword Description A data subtype used to indicate a Variant variable doesn't contain any valid data. {442} "Syntax" section, "access" subsection: For: Specifies the allowable operations by the current process. Read: Specifies the allowable file operations by the current process: Read or Write or Read Write. {443} "Rules at a Glance" section, first bulleted item: For: ... or a UNC path. Read: ... or a UNC (Universal Naming Code) path. {444} "See Also" section: Add: FileAttr Function {445} "See Also" section of Option Base Statement: Add: LBound Function {445} For the Option Compare Statement, add a new section: Add: See Also StrComp Function [447] Add a new entry: Partition Function (VB6) Named Arguments Yes Syntax Partition(number, start, stop, interval) Number Use: Required Data Type: Long ? Number that you want to evaluate against the ranges. start Use : Required Data Type: Long ? Start of the first range. stop Use: Required Data Type: Long ? End of the last range. interval Use: Required Data Type: Long ? Width of each range. Return Value A Variant of subtype String indicating where number occurs within a series of ranges. Description The Partition function identifies the particular range (within a series of ranges) in which the number argument falls. The start and stop arguments specify the overall range of numbers, which is split up into smaller ranges as specified by the interval argument. The Partition function returns a string representation of the smaller range in which the number can be found, such as " 1: 10" for a number that falls in the range of 1 to 10. Rules at a Glance * 0 <= start < end. * 0 Timer: DoEvents: Loop End Sub {557} "Programming Tips & Gotchas" section, add an extra bulleted item: Add: Note that the hardware real-time clock on an Intel PC has a granularity of only 1/18th of a second. Times and time intervals cannot be measured more accurately than the hardware permits. [559] Add a new entry: True Keyword Named Arguments No Syntax True Description The True keyword has a value of -1. Programming Tips & Gotchas The False keyword has a value of 0. {563} "See Also" section: Add: Get Statement, Put Statement [567] "Syntax" section, "filenumber" subsection of Unlock Statement: For: Any valid file number. Read: Any valid file number. The file must be open shared. {571} "Rules at a Glance" section, add a further bulleted item: Add: If firstdayofweek is omitted, it defaults to vbSunday {575} "Rules at a Glance" section of "Width Statement", first bulleted item: For: width defines the number of characters ... Read: width defines the maximum number of characters ... {579} "See Also" section of "Write # Statement": Add: Put Statement [611] line just above "Operator Precedence" section: For: 10111100 = 00001111 Imp 10110011 Read: 10111100 = 00001111 Xor 10110011 INDEX: {624} Add an extra entry to the index: Add: Global keyword, 176 {627} Amend the index entry "object models": For: File system object model, 275-276 Read: File system object model, 275-276, 550-555 {631} Add an extra entry to the index: Add: TypeOf keyword, 368