In "An Improved GUI Component for Data Entry," January 2002, InstantDoc ID 23369, I showed you a GUI component for improving users' data-entry experience. Historically, both Microsoft and other developers have neglected to provide much data-entry scripting help. In VBScript and Windows Script Host (WSH), you can rely only on the InputBox function. My component—VbsInput.InputBox—provides for password and number-only text boxes. It also supports multiline text so that you can collect larger amounts of text easily.
This month, I show you another COM object, wshextra.dll, that improves WSH's basic functionality. (You can download wshextra.dll from the Code Library on the Windows Scripting Solutions Web site at http://www.winscripting solutions.com.) Wshextra.dll consists of three components, each of which fills a gap in the WSH programming interface. The first component—the Clipboard object—lets your WSH application move data to and from the clipboard. The other two components—the FileQuery object and the FileChooser object— make up for missing but useful functionality in the Scripting.FileSystemObject object. The Scripting.FileSystemObject object provides a collection-based interface for accessing individual files in a given folder, but you can't filter the enumerated files based on a pattern. For example, using the Scripting.FileSystemObject object's methods, you can't select only the .bmp files in a folder. Instead, the methods will return all the files in a folder, then you must choose the files you want.
The Clipboard Object
The clipboard is a Windows component that works as a systemwide mailbox on which any application can store and retrieve data of a certain type. The clipboard repository is common to all applications running at any time. WSH applications are no exception, but the WSH object model doesn't provide for moving data to and from the clipboard.
Being able to access the clipboard is important because it represents yet another way to synchronize scripts and share information among scripts. (For more details about the synchronization of concurrently running scripts, see "Emulating Windows Synchronization Objects," November 2001, InstantDoc ID 22709.) For example, a script could calculate some values and make them available to other scripts through the clipboard rather than a disk file. Similarly, a script could easily retrieve data that any running application (e.g., Microsoft Word) might have stored.
Because the clipboard is open to all applications on the system, the contents are somewhat volatile. You can't be sure that one application will effectively read what another application has copied to the clipboard or that another application won't overwrite the clipboard data in the meantime. The clipboard isn't a list, and any new application that copies data ends up overwriting existing data.
Clipboard content is organized by data formats. The clipboard uses a data-type system that's different from the one you find in the common programming languages. For example, no numeric type or date type exists. Allowed types are mostly variations of two basic types: text and image. If needed, you can also create and register custom formats.
The WshExtra.Clipboard object that I illustrate supports only one data format: raw text. Usually, applications copy information to the clipboard in multiple formats to be able to reach a wider range of clients. For example, when you select text from a Word file and press Ctrl+C, the program copies the data to the clipboard as raw text, Rich Text Format (RTF), and HTML. Client applications use the format they know how to process. The WshExtra.Clipboard object can read only raw text and write only raw ASCII text. Let's see how this process works in practice.
After you've successfully registered the wshextra.dll library with the system, you use the code
Dim clip Set clip = CreateObject _ ("WshExtra.Clipboard")
to create a new instance of the Clipboard object. The Clipboard object features only two methods—Copy and Paste—whose signature is straightforward. The Copy method takes the text that you want to copy to the clipboard as a string argument:
clip.Copy "Hello, world"
The Paste method reads any text content it finds in the clipboard and returns it as a string:
Dim strText strText = clip.Paste()
Listing 1 demonstrates a WSH utility called CopyClipboard.vbs that writes to disk the text that it reads from the clipboard. If you improve the code slightly to create files with a unique name and put the code file on the Taskbar, you have a quick tool to make persistent any text you find interesting while scrolling through documents. You just select the text, copy it to the clipboard, then click the Taskbar button to run the script. The result is a new text file, created in a given folder, that holds all your notes.
The FileQuery Object
The Scripting.FileSystemObject object's methods represent the typical way in which a WSH application walks through the subfolders and files of a given folder. The code in Listing 2 demonstrates how to enumerate all the files on the C drive. The code to process all subfolders of a given folder is nearly identical to the code in Listing 2. You simply use the SubFolders property instead of the Files property on the object that represents the folder.
Having files and subfolders available through distinct collection is helpful in some cases, but the Scripting.FileSystemObject object's programming interface doesn't allow for any kind of pattern matching. If you need to access only files with a given extension or files whose name matches a certain pattern, you must start with the code in Listing 2, then verify whether each filename has the characteristics that you want. Instead, what about a new object that accepts a filename description, including wildcards, and automatically returns only the files that match? Furthermore, what if this object made no distinction between files and subfolders? The FileQuery object works in just this way. This set of features makes the FileQuery object a sort of COM counterpart of the Dir command.
To create a new instance of the FileQuery object, you use the code
Dim fileQuery Set fileQuery = CreateObject _ ("WshExtra.FileQuery")
The FileQuery object provides two properties: FileSpec and Count. The FileSpec property lets you specify the expression that the selected file and folder names have to match (e.g., .bmp). The expression can also include folder names and use the question mark (?) wildcard. For example, C:\?y* is a valid pattern that would select files and folders with a name that begins with any single character followed by a y and has any trailing substring. Such an expression picks up files and folders such as C:\system volume information and C:\my apps. The Count property is a read-only attribute that returns the number of elements selected. FileSpec is a read-write attribute.
To walk through the collection of retrieved elements, you use VBScript's For Each...Next statement. The code in Listing 3 shows how to use the FileQuery object. The code concatenates the names of the files found along the way and adds the value of the Count property. The element returned at each iteration is a simple string consisting of the filename or folder name. However, when you know the name of a file, you can create an instance of the File object within the Scripting.FileSystemObject library and exploit the library's full set of properties and methods to retrieve a Dir-style listing with name and size. The code in Listing 4 creates such a list. (Note that the code in Listing 4 fails if the user specifies a filter that returns folders in addition to files because folders aren't a valid input for the FileSystemObject object's GetFile method. For example, the code will fail if the user specifies all files (*.*).
The FileChooser Object
The FileQuery object lets you select only those files that match certain criteria. But what if the application requires the selection of individual files that don't obey common criteria? What if you make the selection interactively? In this case, the FileQuery object isn't enough—you need the FileChooser object. This object's UI lets you browse for and select files in a Windows Explorertype window. To create a new instance of the FileChooser object, you use the code
Dim fileChooser Set fileChooser = CreateObject _ ("WshExtra.FileChooser")
The FileChooser object provides three properties: Title, Filter, and FileCount. The Title property lets you get and set the browser window's caption. The Filter property lets you customize the Files of type drop-down list with the file types you want to display in the window. This window usually contains a pattern such as All files (*.*). The FileCount property is a read-only property that returns the number of selected files.
The Filter property is a string made up of description-and-pattern pairs. You define a new pair for each type of file you want to appear in the filter drop-down list. You must separate each element of the pair (and each pair) with a pipe (|) character:
Because the FileChooser object parses the string and populates the filter drop-down list, the string must terminate with a pipe character. If you want to use multiple file extensions for a particular file type, use a semicolon (;) to separate the extensions. For example, to fill the filter drop-down list with "Picture files (*.jpg;*.gif)" and "All files (*.*)", the Filter property must take the form
fileChooser.Filter = _ "Picture files|*.jpg;*.gif|" _ & "All files|*.*|"
The FileChooser object's Browse method displays the system's common dialog box for file selection and allows for multiple file selection. The method accepts a string as the folder to search, as in
sFiles = _ fileChooser.Browse("c:\")
and returns a specially formatted string. If you specify only one file, the Browse method's return string is simply the file's fully qualified name. If you specify more than one file, the return string contains the name of the folder that contains all the selected files plus their filenames. A pipe character separates each item name from the others. The folder name is important because the dialog box's UI lets you dynamically change the folder. Thus, there's no guarantee that the folder passed as the call's argument is also the folder from which you've selected files. The code in Listing 5 demonstrates how to process the string that the Browse method returns.
You use VBScript's Split function to parse the body of the string, extract the pipe-separated items, and populate an array. If you've selected more than one file, the first item in the array must end with a backslash (\) and consist of the folder's path. Subsequent items are the name and extension of each file. The FileChooser object doesn't support file selection across multiple folders.
Beyond Native WSH Functionality
The Clipboard, FileQuery, and FileChooser objects provide three functionalities that WSH doesn't natively provide. They let you move data to and from the clipboard, select files interactively through a system dialog box, and filter a folder's content, respectively. The average WSH application probably doesn't need these rather advanced functionalities, but you can't achieve their functionality in any other way.