Click here to Skip to main content
Licence 
First Posted 16 Sep 2001
Views 55,747
Bookmarked 12 times

Static String List Manager

By | 20 Sep 2001 | Article
A reusable component to manage static string lists in your programs

Introduction

We often need to use static data in our programs. By static, I mean our programs do not modify the data. For example, we can insert the list of the 50 US state names into a combobox so that the user can select his/her state using a mouse. The same goes with the names of months, the names of weekdays, etc. On other occasions, we need to "translate" between two different lists of static data. Say, we have to find the full name of a US state, given a two-character code, we may also have to find the corresponding name of the month, given a numeric value between 1 and 12.

In more complicated situations, our project may consist of multiple exes, DLLs, ActiveX controls, ASP pages, and they all share the same set of static data lists. I once worked on a project that uses 500+ static string lists. How do we efficiently manage these lists? Storing the static data lists in the source code may be inefficient or even impossible. For example, a single static list may have 1000+ items and has to be used in multiple components (VC++, VB, ASP pages, etc.).

An ideal solution would be to store the static data lists in various databases and write a single reusable component that manages all of them. In this article, I will introduce a tiny utility called XYListMan that does exactly that. I am sure people can think of many other ways to do the same thing and XYListMan isnot the most efficient way in all circumstances.

XYListMan

XYListMan is a COM object implemented in XYStaticListManager.dll. It is extremely easy to use. Suppose we have entered all the static data we need into a database and configured a data source called MyDataSource for this database. Here is how XYListMan works. First we need to open the database and load the static lists. Lets assume that there are two tables in the database called StateNames and WeekDays, and each table has two fields called name and code. Here is the sample code in VB script that loads the data into memory:

dim obj;
set obj = CreateObject("XYListMan.1")
obj.OpenDB("MyDataSource","MyName","MyPassword")
dim nStateNameList
nStateNameList = obj.LoadList("StateNameList", _
    "select name, code from StateNames order by code")
dim nWeekDayList
nWeekDayList = obj.LoadList("WeekDayList", _
    "select name, code from WeekDays order by code")

You can specify user name and password for your database with the OpenDB method. It returns true, if the database is opened successfully. In the LoadList method, you need to give a name for your list and a SQL statement that loads data from the database. The LoadList method returns a zero based integer index that can be used to access the list later. It returns -1 when the operation fails. The SQL statement in general has the following format:

select data_field, key_field from table_or_view_name order by key_field

The GetListIndex method can be used to obtain the index of a previously loaded list, it returns -1 if the list is not yet loaded:

dim nListIndex
nListIndex = obj.GetListIndex("StateNameList")

Once the data lists are loaded into the memory, we can use the GetData, GetKey, GetDataFromKey methods to access the items in the lists. The first parameter of these methods, nListIndex, is the return value of a previous call to the LoadList or the GetListIndex method. The GetData and GetKey methods also take the index of the requested item in the list as its second parameter. The GetDataFromKey method takes a key string as its second parameter. Here is the sample code in VB script (continue from the above code) that accesses data items in the lists:

dim strStateA
' retrieve the name of the first state in the list
strStateA = obj.GetData(nStateNameList,0)
dim strStateB
' retrieve the name of the 23rd state in the list
strStateB = obj.GetData(nStateNameList,22)
dim strStateC
' retrieve the name of the state with code "MD" (Maryland)
strStateC = obj.GetDataFromKey(nStateNameList,"MD")
dim strCodeA
' retrieve the code of the fifth state
strCodeA = obj.GetKey(nStateNameList,4)
dim strCodeB
' retrieve the code of the 39th state
strCodeB = obj.GetKey(nStateNameList,38)

Note that the GetDataFromKey method uses a binary search algorithm to find the data string with the given key string, therefore the list has to be sorted on the key field in order for this method to work correctly.

Some More Details

The data lists loaded into memory are global to the process

That is, if you call LoadList using an XYListMan object somewhere in a process, the loaded data can be accessed later anywhere in the process using another XYListMan object, as long as you specify the correct list name or list index. By the way, the methods of XYListMan are thread-safe.

How do I use this utility on numeric data types?

This is not a problem except that the SQL statement used in the LoadList method has to be sorted on alphabetic order (instead of numeric order). The following SQL statement cannot be used in the LoadList method (the GetDataFromKey method will not work correctly) if the key_field is of numeric type:

select data_field, key_field from table_or_view_name order by key_field

However, if the database is MS Access, then we can easily fix the statement as:

select data_field, format(key_field) from 
    table_or_view_name order by format(key_field)

What if my static data lists are stored in multiple databases?

No problem. You can call OpenDB to open one of the databases and call LoadList to load some data, then you can call OpenDB again to open another database and call LoadList to load more data .... If you don't want to keep the database connection open, you can call the CloseDB method after loading all the data you need.

We have seen examples of getting state name using the two-character code, how do we do the opposite: getting the code using state name?

A straight forward way to do this is load another list using the following SQL statement and call GetDataFromKey passing the state name as the key string:

select code, name from StateNames order by name

The GetListSize method returns the total number of elements in a list. The UnloadList method can be called to save memory if you no longer need the data. Runtime errors are written to log file XYListMan_yyyymmddHHMMSS_xxxx.log in the current working directory, where yyyymmddHHMMSS is a timestamp string and xxxx is the current process ID.

The implementation

XYListMan is implemented with VC++ 5.0 using ATL and MFC. The main reason for using MFC is that I want to take advantage of the CDatabase and CRecordset classes and I am not that familiar with string operations in ATL. In case you are interested in details, you need only to read one source file XYListMan.cpp, all the other files in the project are generated by the AppWizard. For your convenience, I have included a file XYListManWrapper.h, which contains a C++ wrapper class. If you want to use XYListMan in a C++ program, you need only to do the following: include this header file, declare a XYListManWrapper object, and call its methods.

Conclusion

Thank you for reading this article. Please visit my home page for my other articles and programs.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Xiangyang Liu 刘向阳



United States United States

Member



Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralRe: Why not use WTL CString? PinmemberXiangyang Liu6:13 13 Mar '03  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web01 | 2.5.120517.1 | Last Updated 21 Sep 2001
Article Copyright 2001 by Xiangyang Liu 刘向阳
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid