Strings are NOT arraysStrings have no indexesAlthough arrays of strings have indexesA single string variable has no indexArray indexes can have base of 0 or 1Strings positions ALWAYS begin at 1 String functions report errors for position=0
Mid() functionMyString = "Mid Function Demo" ' Create text string. FirstWord = Mid(MyString, 1, 3) ' Returns "Mid". LastWord = Mid(MyString, 14, 4) ' Returns "Demo". MidWords = Mid(MyString, 5) ' Returns "Function Demo".
InStr() functionstrHaystack ="XXpXXpXXPXXPstrNeedle = "p"
intWhere = Instr(1, strHaystack, "W") Returns 0
intWhere = Instr(4, strHaystack, strNeedle) Returns 6
Other FunctionsMid() statement (not the mid function)strX = "Hello, Jane" ' example of mid() statementMid(strX, 8, 4) = "Bill (creates Hello, Bill)Left(strX,n) and Right() returns L/R sectionsUcase() and Lcase() changes Up/Low caseTrim(), Rtrim() and Ltrim() removes blanksLen() returns number of characters
Intro to ArraysLists (e.g.,states, income levels, schedules)Private, Public, fixed or dynamic size!Example:Dim strMonthNames(0 to 11) As String
strMonth(0) = "January"strMonth(1) = "February"strMonth(2) = "March"strMonth(3) = "April"strMonth(4) = "May"
intInput = InputBox("Enter a month number (1-12)")-1 MsgBox You entered & strMonth(intInput)
String example: base 0
Which Array to Go?Option Base 1 or Option Base 0?Public strState(0 to 49) As StringPublic strState(1 to 50) As StringPublic strState(50) As String
Flexible ArrayDynamicDim curLevel() As CurrencyExpands and contractsGood for uncertain run-time conditionsCan loose contents unlessRedim Preserve curLevel(7)Can erase dynamic arrays: Erase curLevel
Referencing locations by field and recordExample Dim varDataSet(0 to 4, 0 to 9)5 fields (columns)10 records (rows)First field of the last record: varDataSet(0,9)
Multidimensional arraysThis array has 6 columns and 7 rows : Dim varContributor(0 to 5,0 to 6) as variantColumns before rows (alpha order)June Nguyen's contribution is varContributor(5,2)Think of multidimension arrays as datasheets.
Sizing up arrays
Your subs and functions will be more reusable if they work for any size arrays.Lbound(),Ubound() return lower, upper bound of one dimension, regardless of BASE.Lbound(varData, 1 or 2),Ubound(varData, 1 or 2)Use 1 for fields count (columns first again) Use 2 for records count (rows second again)How many columns are there in varData?Ubound(varData,1) Lbound(varData,1) + 1
Example: summarize salariesDim curSalary(0 to 7, 0 to 10)If column 7 of this array is $ salarySummarize the salaries
For intRow = Lbound(curSalary,2) to Ubound(curSalary,2) curSum = curSum + curSalary(7, intRow) intN = intN + 1 Next MsgBox "Total Amount=" & Format(curSum,"Currency") MsgBox "Average Amount=" & Format( _ iif(intN>0,curSum/intN,0), "Currency")
Memory ConsiderationsstrAbsentMinded(0 to 9) uses 22 times less memory than varAbsentMinded(1 to 10) when they hold the identical dataintArray(0 to 9, 0 to 19, 0 to 29) reserves 6,000 integer locations, or about 12,000 (plus) bytes. 10 * 20 * 30 = 6,000 * 2 bytes/integer = 12,000 bytes
Parameter Arrays in ProcsExtremely useful and powerfulThe arguments are treated as one arrayVBA forces Option Base 0, so use Lbound() and Ubound()Example: a general utility to calculate class averages on quizzes, exams, and assignments after dropping your lowest score. The number of scores is unpredictable.
- Parameter Arrays: ExampleFunction DropAvg(ParamArray varScore() as Variant) as VariantDim varAverage as Variant, varLowest as VariantDim varValue as Variant' requires at least two scores in the arrayvarLowest = 99999if UBound(varScore, 1)
- Arrays: ExampleFunction DropAverage(dblScore() As Double) As Variant Dim varAverage As Variant, varLow As Variant Dim varValue As Variant, intI As Integer, intCount As Integer ' requires at least two scores in the array varLow = 99999 intCount = UBound(dblScore, 1) - LBound(dblScore, 1) If intCount
Creating ArraysThe Array functionYour Option Base is observed
Option Base 0Public Function DayOfWeek(intDay As Integer) As String Dim WeekDay As Variant WeekDay = _ Array("Sun","Mon","Tue","Wed","Thu","Fri","Sat") DayOfWeek = WeekDay(intDay)End FunctionIn the Immediate Window?DayOfWeek(1)Mon
Creating ArraysThe GetRows MethodForces Option Base 0Public Function Sum() Dim intRow as Integer, intN as Integer Dim varDataSet() As Variant Dim cnn As ADODB.Connection Set cnn = CurrentProject.Connection rst.Open "tblEmployee", cnn, adOpenDynamic, , adCmdTable varDataSet = rst.GetRows rst.Close For intRow = LBound(varDataSet, 2) To UBound(varDataSet, 2) Sum = Sum + varDataSet(3, intRow) : intN = intN+1 Next Sum = iif(intN > 0,Sum/intN , 0) Debug.Print "Average Amount=" & Format( Sum, "Currency")End Function
Detecting what data is in a VariantVarType(variable)TypeName(variable)
Useful for detectingCalculation dataArrays (VarType=8192+)Valid dates
Receiving ArgumentsDefault is by reference (ByRef)Send the address of the argumentThe contents of the address can be changed by either the caller or the procedure.Option is by value (ByVal)Send a copy of the argumentThe variable cannot be changed by the proc because it only has a copy.
Receiving Arguments: Example' build in the protection at design time (formal args)Sub AllNames (ByVal BothNames as String, ByRef LastName as String, ByRef FirstName as String)
' or use this actual argument format at run time' it forces ByVal and sends a copy of the variableCall AllNames ((Names), First, Last)
' But, an array cannot be passed ByValCall Average (varDatSet, 6)
Type structureA named data structurePlace in Declarations ModuleInstantiate when neededResult: A data object
Type ContributionFormError FirstName As Boolean LastName As Boolean Date As Boolean Party As Boolean Sex As Boolean Amount As BooleanEnd TypeDefine the structure in the Declarations Module
' create a module-level structure in ' the Declarations section of your Form ModulePrivate ErrorIn As ContributionFormError
' in the error checking code set these flagsErrorIn.FirstName = True ErrorIn.Amount = True
' example on next slide showsPassing a data structure as an argumentUse of the WithEnd structure
Instantiate ErrorIn structure in the Form Module
MsgBox "The following errors must be corrected:" & vbCR & _ ErrorList(ErrorIn)",vbExclamation,"Mayor Minimum"
Function ErrorList(AnyErr As ContributionFormError) As String With AnyErr If .FirstName Then ErrorList = ErrorList + vbCr & "First Name" If .LastName Then ErrorList = ErrorList + vbCr & "Last Name" If .Party Then ErrorList = ErrorList + vbCr & "Party" If .Sex Then ErrorList = ErrorList + vbCr & "Sex" If .Date Then ErrorList = ErrorList + vbCr & "Date" If .Amount Then ErrorList = ErrorList + vbCr & "Amount" End WithEnd Function
Use the structure to build a message
Use the structure to build a better messageIf IsError(ErrorIn) Then MsgBox "There are " & _ IsError(ErrorIn) & " errors." & vbCR & _ ErrorList(ErrorIn)",vbExclamation,"Mayor Minimum"Private Function IsError(ErrorStructure As _ ContributionFormError) As Integer IsError = 0 If ErrorStructure.FirstName Then IsError = IsError + 1 If ErrorStructure.LastName Then IsError = IsError + 1 If ErrorStructure.Party Then IsError = IsError + 1 If ErrorStructure.Sex Then IsError = IsError + 1 If ErrorStructure.Date Then IsError = IsError + 1 If ErrorStructure.Amount Then IsError = IsError + 1End Function
Modulus VBA and many other languages have this built in function for finding the remainder of a division. For example, 5 mod 2 equals 1 (5/2=2 with 1 left over) 6 mod 2 equals 0 (6/2=3 with 0 left over) anynumber mod 2 = 1 if anynumber is odd anynumber mod 2 = 0 if anynumber is evenOdd and even are the usual reasons for programming with mod. And there is another handy use for the function: controlling sequences by limiting the range of a counter.
Using the Modulus: SequencingMod is also useful when you want to limit a series of numbers to a range. Say you want users to be presented with a sequence of three choices, or five choices, or seven choices and not do a lot of programming logic. choice = 1 + (choice mod N) The line of code above will limit the values taken on by the variable choice. They will be in the range of 1, 2,, N. The starting value of choice has to be inside the particular range. An example is next.
Using the Modulus: Program ExamplePublic Sub RangeOfChoices()' initialize the variablesDim strChoice(1 to 3) As StringDim intChoice As IntegerDim intTrip As IntegerintChoice = 1strChoice(1) = "the beach?"strChoice(2) = "the mountains?"strChoice(3) = "Philadelphia?"' body of your logicDo intTrip = MsgBox("Would you like to go to " & _ strChoice(intChoice), vbYesNo, "This Summer") intChoice = (intChoice Mod 3) + 1Loop Until intTrip = vbYesEnd Sub