Stuart McCall's Microsoft Access Pages - Strings
Home
Append Item to delimiter-separated list
Public Sub ListAddItem(List$, ByVal Item$, Optional Delimiter = ",", Optional Unique As Boolean)
'Appends Item to List.
'If Unique is True, prevents duplicate entries
If Unique And InStr(1, List & Delimiter, Item & Delimiter) > 0 Then Exit Sub
If List <> "" Then List = List & Delimiter
List = List & Item
End Sub
|
Insert Item into delimiter-separated list at index [n]
Public Sub ListInsertItem(List$, ByVal Item$, idx&, Optional Delimiter = ",")
'Inserts Item into List at element index idx
Dim i As Long, ix As Long, a As Variant
ix = idx - 1
ListAddItem List, "*", Delimiter
a = Split(List, Delimiter)
For i = UBound(a) To ix + 1 Step -1
a(i) = a(i - 1)
Next
a(ix) = Item
List = Join(a, Delimiter)
Erase a
End Sub
|
Edit Item in delimiter-separated list at index [n]
Public Sub ListEditItem(List$, ByVal idx&, ByVal Value$, Optional Delimiter = ",")
'Edits the Item at element index idx
Dim ix As Long, a As Variant
ix = idx - 1
a = Split(List, Delimiter)
a(ix) = Item
List = Join(a, Delimiter)
Erase a
End Sub
|
Delete Item from delimiter-separated list at index [n]
Public Sub ListDelItem(List$, idx&, Optional Delimiter = ",")
'Deletes the Item at element index idx
Dim i As Long, ix As Long, a As Variant, t As String
ix = idx - 1
a = Split(List, Delimiter)
For i = ix To UBound(a) - 1
a(i) = a(i + 1)
Next
a(i) = ""
t = Join(a, Delimiter)
List = Left$(t, Len(t) - 1)
Erase a
End Sub
|
Sort Items in a delimiter-separated list
Public Sub ListSort(List$, Optional Delimiter = ",")
'Sorts the List
Dim a As Variant, l As Long, r As Long, s As Long
a = Split(List, Delimiter)
l = UBound(a)
For r = LBound(a) To l
s = r
For i = r + 1 To l
If a(i) < a(s) Then
s = i
End If
Next
If s > r Then
t = a(r)
a(r) = a(s)
a(s) = t
End If
Next
List = Join(a, Delimiter)
Erase a
End Sub
|
Obtain the element index of an Item a delimiter-separated list
Public Function ListItemIndex(List$, ByVal Item$, Optional Delimiter = ",") As Long
Returns the element index of Item
Dim a As Variant, i As Long
a = Split(List, Delimiter)
For i = LBound(a) To UBound(a)
If a(i) = Item Then
ListItemIndex = i + 1
Exit For
End If
Next
Erase a
End Function
|
Obtain an Item from a delimiter-separated list at element index [n]
Public Function ListItem(List$, idx&, Optional Delimiter = ",") As String
'Returns the Item at element index idx
ListItem = Split(List, Delimiter)(idx - 1)
End Function
|
Determine the number of elements in a delimiter-separated list
Public Function ListItemCount(List$, Optional Delimiter = ",") As Long
'Returns the element count
ListItemCount = UBound(Split(List, Delimiter)) + 1
End Function
|
All the delimited list functions as a complete Module
Option Compare Database
Option Explicit
Public Sub ListAddItem(List$, ByVal Item$, Optional Delimiter = ",", Optional Unique As Boolean)
'Appends Item to List.
'If Unique is True, prevents duplicate entries
If Unique And InStr(1, List & Delimiter, Item & Delimiter) > 0 Then Exit Sub
If List <> "" Then List = List & Delimiter
List = List & Item
End Sub
Public Sub ListInsertItem(List$, ByVal Item$, idx&, Optional Delimiter = ",")
'Inserts Item into List at element index idx
Dim i As Long, ix As Long, a As Variant
ix = idx - 1
ListAddItem List, "*", Delimiter
a = Split(List, Delimiter)
For i = UBound(a) To ix + 1 Step -1
a(i) = a(i - 1)
Next
a(ix) = Item
List = Join(a, Delimiter)
Erase a
End Sub
Public Sub ListEditItem(List$, ByVal idx&, ByVal Value$, Optional Delimiter = ",")
'Edits the Item at element index idx
Dim ix As Long, a As Variant
ix = idx - 1
a = Split(List, Delimiter)
a(ix) = Item
List = Join(a, Delimiter)
Erase a
End Sub
Public Sub ListDelItem(List$, idx&, Optional Delimiter = ",")
'Deletes the Item at element index idx
Dim i As Long, ix As Long, a As Variant, t As String
ix = idx - 1
a = Split(List, Delimiter)
For i = ix To UBound(a) - 1
a(i) = a(i + 1)
Next
a(i) = ""
t = Join(a, Delimiter)
List = Left$(t, Len(t) - 1)
Erase a
End Sub
Public Sub ListSort(List$, Optional Delimiter = ",")
'Sorts the List
Dim a As Variant, l As Long, r As Long, s As Long
a = Split(List, Delimiter)
l = UBound(a)
For r = LBound(a) To l
s = r
For i = r + 1 To l
If a(i) < a(s) Then
s = i
End If
Next
If s > r Then
t = a(r)
a(r) = a(s)
a(s) = t
End If
Next
List = Join(a, Delimiter)
Erase a
End Sub
Public Function ListItemIndex(List$, ByVal Item$, Optional Delimiter = ",") As Long
Returns the element index of Item
Dim a As Variant, i As Long
a = Split(List, Delimiter)
For i = LBound(a) To UBound(a)
If a(i) = Item Then
ListItemIndex = i + 1
Exit For
End If
Next
Erase a
End Function
Public Function ListItem(List$, idx&, Optional Delimiter = ",") As String
'Returns the Item at element index idx
ListItem = Split(List, Delimiter)(idx - 1)
End Function
Public Function ListItemCount(List$, Optional Delimiter = ",") As Long
'Returns the element count
ListItemCount = UBound(Split(List, Delimiter)) + 1
End Function
|
Functions for use with file paths
Public Function DrivePart(ByVal FullPath$) As String
' Returns the Drive only from a fully qualified filename
DrivePart = Left$(FullPath, 2)
End Function
Public Function PathPart(ByVal FullPath$) As String
' Returns the path only from a fully qualified filename
PathPart = Left$(FullPath, InStrRev(FullPath, "\"))
End Function
Public Function FilePart(ByVal FullPath$) As String
' Returns the filename only from a fully qualified filename
FilePart = Mid$(FullPath, Len(PathPart(FullPath)) + 1)
End Function
Public Function FileNamePart(ByVal FullPath$) As String
' Returns the filename only (no extension) from a fully qualified filename
Dim t As String
t = FilePart(FullPath)
FileNamePart = Left$(t, InStrRev(t, ".") - 1)
End Function
Public Function ExtensionPart(ByVal FullPath$) As String
' Returns the extension only from a fully qualified filename
ExtensionPart = Mid$(FullPath, InStrRev(FullPath, ".") + 1)
End Function
Public Function DbPath() As String
' Returns the current db's path (includes trailing \)
DbPath = PathPart(CurrentDb.Name)
End Function
Public Function IsPath(ByVal Path As String) As Boolean
' Returns True if path exists
IsPath = (Len(Dir$(Path, vbDirectory)) > 0)
End Function
Public Function AddSlash(ByVal Path$) As String
' Ensures path$ is terminated with a slash
If Right$(Path, 1) <> "\" Then
Path = Path & "\"
End If
AddSlash = Path
End Function
Public Function NoSlash(ByVal Path$) As String
' Ensures path$ is not terminated with a slash
If Right$(Path, 1) = "\" Then
Path = Left$(Path, Len(Path) - 1)
End If
NoSlash = Path
End Function
|
Create complete path if it doesn't already exist
Public Function CreatePath(ByVal pstrPath As String) As Long
' Creates complete path pstrPath if it doesn't already exist
' Returns 0 for success, or error number
' Accepts 'normal' (DOS) or UNC paths
'
' eg: ErrNum = CreatePath("c:\access\newpath")
'
' or: ErrNum = CreatePath("\\server\share\access\newpath")
'
'Requires: IsPath function (included below)
Const SLASH As String = "\"
Const TWOSLASH As String = "\\"
Dim i As Integer, j As Integer
Dim strBuild As String
On Error GoTo CreatePath_Err
' Bail out now if path already exists
If IsPath(pstrPath) Then Exit Function
'Ensure path is terminated properly
If Right$(pstrPath, 1) <> SLASH Then pstrPath = pstrPath & SLASH
'Find starting point
If InStr(1, pstrPath, ":") = 2 Then
'Normal path
j = 4
ElseIf InStr(1, pstrPath, TWOSLASH) = 1 Then
'UNC path
j = InStr(3, pstrPath, SLASH) + 1 'Skip server name
j = InStr(j, pstrPath, SLASH) + 1 'Skip share name
Else
'Illegal path - return 'Path/file access error'
Err.Raise 75
End If
'Start accumulating
strBuild = Left$(pstrPath, j - 1)
Do
i = InStr(j, pstrPath, SLASH)
'Bail out if no more slashes
If i = 0 Then Exit Do
'Accumulate next part of path
strBuild = strBuild & Mid$(pstrPath, j, i - j)
'If it doesn't already exist
If Not IsPath(strBuild) Then
'Create it
MkDir strBuild
End If
strBuild = strBuild & SLASH
j = i + 1
Loop
CreatePath_Exit:
Exit Function
CreatePath_Err:
'Return error
CreatePath = Err.Number
Resume CreatePath_Exit
End Function
Public Function IsPath(ByVal Path As String) As Boolean
' Returns True if path exists
IsPath = (Len(Dir$(Path, vbDirectory)) > 0)
End Function
|
Obtain a file's short (8.3) filename from it's long filename
Private Declare Function GetShortPathNameA Lib "Kernel32" (ByVal lpszLongPath As String, ByVal lpszShortPath As String, ByVal cchBuffer As Long) As Long
|
Function ShortPath(ByVal pstrPath As String) As String
' Returns the short DOS path from a LFN path
Dim buffer As String * 255
Dim fLen As Long
fLen = GetShortPathNameA(pstrPath, buffer, 255&)
ShortPath = Left(buffer, fLen)
End Function
|
Usage:
Debug.Print ShortPath("C:\Program Files\Outlook Express\msoe.txt")
Result: C:\PROGRA~1\OUTLOO~1\msoe.txt
Obtain a file path from a Special Folder location
Public Enum sfTarget
CSIDL_DESKTOP = &H0 '(desktop)
CSIDL_INTERNET = &H1 'Internet Explorer (icon on desktop)
CSIDL_PROGRAMS = &H2 'Start Menu\Programs
CSIDL_CONTROLS = &H3 'My Computer\Control Panel
CSIDL_PRINTERS = &H4 'My Computer\Printers
CSIDL_PERSONAL = &H5 'My Documents
CSIDL_FAVORITES = &H6 '(user name)\Favorites
CSIDL_STARTUP = &H7 'Start Menu\Programs\Startup
CSIDL_RECENT = &H8 '(user name)\Recent
CSIDL_SENDTO = &H9 '(user name)\SendTo
CSIDL_BITBUCKET = &HA '(desktop)\Recycle Bin
CSIDL_STARTMENU = &HB '(user name)\Start Menu
CSIDL_DESKTOPDIRECTORY = &H10 '(user name)\Desktop
CSIDL_DRIVES = &H11 'My Computer
CSIDL_NETWORK = &H12 'Network Neighborhood
CSIDL_NETHOOD = &H13 '(user name)\nethood
CSIDL_FONTS = &H14 'windows\fonts
CSIDL_TEMPLATES = &H15 '(user name)\Templates
CSIDL_COMMON_STARTMENU = &H16 'All Users\Start Menu
CSIDL_COMMON_PROGRAMS = &H17 'All Users\Programs
CSIDL_COMMON_STARTUP = &H18 'All Users\Startup
CSIDL_COMMON_DESKTOPDIRECTORY = &H19 'All Users\Desktop
CSIDL_APPDATA = &H1A '(user name)\Application Data
CSIDL_PRINTHOOD = &H1B '(user name)\PrintHood
CSIDL_LOCAL_APPDATA = &H1C '(user name)\Local Settings\Application Data (non roaming)
CSIDL_ALTSTARTUP = &H1D 'non localized startup
CSIDL_COMMON_ALTSTARTUP = &H1E 'non localized common startup
CSIDL_COMMON_FAVORITES = &H1F 'All Users\favorites
CSIDL_INTERNET_CACHE = &H20 'Internet Explorer cache
CSIDL_COOKIES = &H21 'Internet Explorer cookie files
CSIDL_HISTORY = &H22 'Internet Explorer history data
CSIDL_COMMON_APPDATA = &H23 'All Users\Application Data
CSIDL_WINDOWS = &H24 'GetWindowsDirectory()
CSIDL_SYSTEM = &H25 'GetSystemDirectory()
CSIDL_PROGRAM_FILES = &H26 'C:\Program Files
CSIDL_MYPICTURES = &H27 'My Documents\My Pictures
CSIDL_PROFILE = &H28 'User Profile
CSIDL_PROGRAM_FILES_COMMON = &H2B 'C:\Program Files\Common
CSIDL_COMMON_TEMPLATES = &H2D 'All Users\Templates
CSIDL_COMMON_DOCUMENTS = &H2E 'All Users\Documents
CSIDL_COMMON_ADMINTOOLS = &H2F 'All Users\Start Menu\Programs\Administrative Tools
CSIDL_ADMINTOOLS = &H30 '(user name)\Start Menu\Programs\Administrative Tools
CSIDL_FLAG_CREATE = &H8000 'combine with CSIDL_ value to force create on SHGetSpecialFolderLocation()
CSIDL_FLAG_DONT_VERIFY = &H4000 'combine with CSIDL_ value to force create on SHGetSpecialFolderLocation()
CSIDL_FLAG_MASK = &HFF00 'mask for all possible flag values
End Enum
'
Private Type SHITEMID
cb As Long
abID As Byte
End Type
'
Private Type ITEMIDLIST
mkid As SHITEMID
End Type
'
Private Declare Function SHGetSpecialFolderLocation Lib "shell32.dll" (ByVal hWndOwner As Long, ByVal nFolder As Long, pidl As ITEMIDLIST) As Long
Private Declare Function SHGetPathFromIDList Lib "shell32.dll" Alias "SHGetPathFromIDListA" (ByVal pidl As Long, ByVal pszPath As String) As Long
|
Public Function SpecialFolder(Target As sfTarget) As String
Dim IDL As ITEMIDLIST, Path$
'
If SHGetSpecialFolderLocation(100&, Target, IDL) = 0 Then
Path = Space$(512)
SHGetPathFromIDList ByVal IDL.mkid.cb, ByVal Path
SpecialFolder = Left$(Path, Instr(1, Path, vbNullChar) - 1)
End If
End Function
|
Usage:
Debug.Print SpecialFolder(CSIDL_FONTS)
Result: C:\WINDOWS\Fonts
Obtain the Windows and System folders
Private Declare Function GetWindowsDirectoryA Lib "Kernel32" (ByVal lpBuffer As String, ByVal nSize As Long) As Long
Private Declare Function GetSystemDirectoryA Lib "Kernel32" (ByVal lpBuffer As String, ByVal nSize As Long) As Long
|
Public Function WindowsDir() As String
Dim buf As String * 255, l&
l = GetWindowsDirectoryA(buf, 254&)
If l Then WindowsDir = Left$(buf, l) & "\"
End Function
Public Function SystemDir() As String
Dim buf As String * 255, l&
l = GetSystemDirectoryA(buf, 254&)
If l Then SystemDir = Left$(buf, l) & "\"
End Function
|
Usage:
Debug.Print SystemDir()
Result: C:\WINDOWS\system32\
Add/Remove brackets [.] to/from a field name
Public Function Bracketed(ByVal s$) As String
If Asc(s) <> 91 Then
s = "[" & s & "]"
s = Replace(s, ".", "].[")
End If
Bracketed = s
End Function
Public Function UnBracket(ByVal s$) As String
s = Replace(s, "[", "")
s = Replace(s, "]", "")
UnBracket = Replace(s, "].[", ".")
End Function
|
Usage:
Debug.Print Bracketed("TableName.Field1")
Result: [TableName].[Field1]
Debug.Print UnBracket("[TableName].[Field1]")
Result: TableName.Field1
Sort a string array
Public Sub SortArray(Item$())
Dim lastItem&, SmallestRow&, row&, i&, tmp$
lastItem = UBound(Item)
For row = 1 To lastItem
SmallestRow = row
For i = row + 1 To lastItem
If Item(i) < Item(SmallestRow) Then
SmallestRow = i
End If
Next
'
If SmallestRow > row Then
tmp = Item(row)
Item(row) = Item(SmallestRow)
Item(SmallestRow) = tmp
End If
Next
End Sub
|
Usage:
ReDim a(1 To 3) As String, i&
a(1) = "Oranges"
a(2) = "Apples"
a(3) = "Pears
SortArray a
For i = Lbound(a) To Ubound(a)
Debug.Print a(i)
Next
Result:
Apples
Oranges
Pears
Text block sans blank rows
Public Function ShrinkLines(ParamArray values()) As String
'Returns a formatted text block from separate values.
'Null or zero-length values are stripped out.
'
'eg: Debug.Print ShrinkLines([Field1], [Field2], [Field3])
'
'If Field1 contains 'Stuart', Field2 is Null, and Field3
'contains 'McCall', the result would be:
'
'Stuart
'McCall
Dim v As Variant, r As String
For Each v In values
If Len(v & "") > 0 Then
r = r & v & vbcrlf
End If
Next
ShrinkLines = r
End Function
|
Replace ordinal tokens in a string
Public Function nReplace(Template, ParamArray Values()) As String
Dim i&, s$
s = Template
For i = LBound(Values) To UBound(Values)
s = Replace(s, "%" & i + 1, Values(i))
Next
nReplace = s
End Function
|
Usage:
Const ConnectTemplate = "DBQ=%1;DSN=%2;UID=%3;PWD=%4;DESCRIPTION=%5;DIR=%6"
Dim s As String
s = nReplace(ConnectTemplate, Database, DSN, UserID, Password, Description, Path)
Debug.Print s
Replace item/value pairs in a string
Public Function ReplaceList(ByVal Template$, ParamArray ItemValuePairs()) As String
Dim i&
For i = LBound(ItemValuePairs) To UBound(ItemValuePairs) Step 2
Template = Replace(Template, ItemValuePairs(i), ItemValuePairs(i + 1))
Next
ReplaceList = Template
End Function
|
Usage:
Const ConnectTemplate = "DBQ=<DBQ>;DSN=<DSN>;UID=<UID>;PWD=<PWD>;DESCRIPTION=<DESC>;DIR=<DIR>"
Dim s As String
s = ReplaceList(ConnectTemplate, "<DBQ>", Database, "<DSN>", DSN, "<UID>", UserID, _
"<PWD>", Password, "<DESC>", Description, "<DIR>", Path)
Debug.Print s
Format values correctly for use in criteria
Public Function Cv(Value, Num_Text_or_Date As String) As Variant
'CriteriaValue - correctly quote Value
'for use as a criteria string
'The Num_Text_or_Date parameter accepts:
' N, Num or Number for Boolean,Byte,Integer,Long,Currency,Single,Double
' T, Text or String for Text, Memo
' D or Date for Date/Time
If Not IsNull(Value) Then
Select Case Num_Text_or_Date
Case "N", "Num", "Number"
Cv = Value
Case "T", "Text", "String"
Cv = Chr(34) & Replace(Value, "'", "''") & Chr(34)
Case "D", "Date"
Cv = "#" & Format(Value, "mm/dd/yyyy") & "#"
Case Else
MsgBox "Unrecognised data type passed", vbExclamation
End Select
End If
End Function
|
Usage:
'Given a form containing 2 controls: DateControl & TextControl,
'DateControl contains 1/1/08 and TextControl contains Stuart's code
Dim SQL As String
SQL = "SELECT * FROM tblCustomers WHERE DateField = " & Cv(DateControl, "D")
SQL = SQL & " AND TextField = " & Cv(TextControl, "T")
Debug.Print SQL
Result:
SELECT * FROM tblCustomers WHERE DateField = #01/01/2008# AND TextField = "Stuart''s code"
Delete all files from a folder tree, leaving the folders in place
Public Sub EmptyFolderTree(ByVal Path As String)
Dim s As String
Dim thisFdr As String
Dim fdrList As New Collection
If Right$(Path, 1) <> "\" Then Path = Path & "\"
fdrList.Add Path
Do While fdrList.Count
'remove this folder from folder list
thisFdr = fdrList.item(1)
fdrList.Remove 1
'find all files and folders in current & add to list
s = Dir$(thisFdr, vbDirectory)
Do While Len(s)
If Asc(s) <> 46 Then 'Exclude "." and ".."
If GetAttr(thisFdr & s) = vbDirectory Then
fdrList.Add thisFdr & s & "\" 'add the folder
Else
Kill thisFdr & s
End If
End If
s = Dir$
Loop
Loop
End Sub
|