|
code
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Advice on storage and retrievaltwo part question part1 I have a simple app to search files Enter string in text box, pick commandbutton, it searches certain files for matching text. Now I thought to add a feature, Save list of previous searches change from textbox to combo box, combo loads with previous saved (somehow) list, pick from list or enter new search, save new search to list if not already on list (similar to recent sites list in browser target combo box, ) so i thought of saving to ini file [SavedSearchesSection] Search0=FirstSearch Search1=SecondSearch etc question1 is that a normal way to setup incremental/indexed keynames? or am i using ini in wrong way? come to think of it, the search term itself could become the key and I wouldn't need even a value!??? part2 thinking out loud ....<g> - seems too small a need to bother with a database solution - could also just use simple text file - suppose I could create a class, make persistable, save prop list with prop bag, ??? haven't tried that yet, that might be fun it fits in with my desire to become more object oriented <g> also fits with my recent contemplations of how to create a generic Key/Data storage class In nearly every tool i write I need to save key/data pairs for various reasons. have used arrays, collections, scripting.dicitionaries, Olaf's dhSortedDictionary (very nice, thanks Olaf!!!), databases, ini files etc. I'd like to structure a class that I could reuse with very simple calls and not worry about re-implementing storage functions in every different app... If Not cStore.Exists(SearchTerm) Then cStore.Add(SearchTerm) or If Not cStore.Exists(Key) Then cStore.Add(Key, Data) or something like that And if i created an interface, i could make various implementations to use various storage methods, ini, database, etc according to different need levels(eg is persistance req'd or in-memory sufficient, ...simple key/data pair adequate or do we need tables/fields/records detail...) question2 any thoughts / advice? Show quoteHide quote :-) Mark "MP" <NoSpam@Thanks.Com> wrote in message well, here's a first attempt at an interface and implementation usingnews:OqznbHpkHHA.1532@TK2MSFTNGP03.phx.gbl... > part2 > also fits with my recent contemplations of how to create a generic Key/Data > storage class collection probably not efficient but seems to work in limited test shown below other implementations could use arrays/etc to improve efficiency i'm sure also need to add .Save property to persist data somehow and .Restore to retrieve saved data....??? comments welcome Thanks Mark '----------------------------------------- IDataStore.cls Option Explicit Public Property Get Count() As Long End Property Public Property Get Keys() As Variant End Property Public Property Get Values() As Variant End Property Public Property Get Data(Key As String) As Variant End Property Public Sub Add(Key As String, Data As Variant) End Sub Public Sub Remove(Key As String) End Sub Public Function Exists(Key As String) As Boolean End Function '----------------------------------------- '----------------------------------------- cDataStore.cls Option Explicit Implements IDataStore Private mcolKeys As Collection Private mcolData As Collection Private Sub Class_Initialize() Set mcolKeys = New Collection Set mcolData = New Collection End Sub Private Sub Class_Terminate() Set mcolKeys = Nothing Set mcolData = Nothing End Sub Private Sub IDataStore_Add(Key As String, Data As Variant) Dim sTest As Variant On Error Resume Next sTest = mcolKeys.Item(Key) If Err Then Err.Clear mcolKeys.Add Key, Key mcolData.Add Data, Key Else mcolData.Remove Key mcolData.Add Data, Key End If On Error GoTo 0 End Sub Private Property Get IDataStore_Count() As Long IDataStore_Count = mcolData.Count End Property Private Property Get IDataStore_Data(Key As String) As Variant IDataStore_Data = mcolData.Item(Key) End Property Private Function IDataStore_Exists(Key As String) As Boolean Dim s As String On Error Resume Next s = mcolKeys.Item(Key) If Err Then Err.Clear Else IDataStore_Exists = True End If On Error GoTo 0 End Function Private Property Get IDataStore_Keys() As Variant Dim i As Long Dim a() As String ReDim a(mcolKeys.Count - 1) For i = 1 To mcolKeys.Count a(i - 1) = mcolKeys.Item(i) Next i IDataStore_Keys = a End Property Private Sub IDataStore_Remove(Key As String) On Error Resume Next mcolData.Remove Key If Err Then Err.Clear Else mcolKeys.Remove Key End If On Error GoTo 0 End Sub Private Property Get IDataStore_Values() As Variant Dim i As Long Dim a() As Variant ReDim a(mcolData.Count - 1) For i = 1 To mcolData.Count a(i - 1) = mcolData.Item(i) Next i IDataStore_Values = a End Property '----------------------------------------- '----------------------------------------- 'test.bas '(replace LogEntry with Debug.Print) Sub testdatastore() 'LogIn "testdatastore", True Dim ostore As IDataStore Set ostore = New cDataStore Dim i As Integer Dim j As Integer Dim v As Variant Dim sKey As String Dim lMax As Long Dim bReport As Boolean 'bReport = True ' to see keys/values but of course slows it way down lMax = 250 'test add For i = 0 To lMax ostore.Add CStr(i), "Test" & i Next i 'test keys/values If bReport Then LogEntry "List Keys" For Each v In ostore.Keys LogEntry "Key: " & CStr(v) Next LogEntry "List values" For Each v In ostore.Values LogEntry "Val: " & CStr(v) Next End If 'test remove For j = 1 To lMax Step 2 ostore.Remove CStr(j) Next If bReport Then LogEntry "After remove" LogEntry "List Keys" For Each v In ostore.Keys LogEntry "Key: " & CStr(v) Next LogEntry "List values" For Each v In ostore.Values LogEntry "Val: " & CStr(v) Next End If 'test exists sKey = "28" If ostore.Exists(sKey) Then LogEntry "Found key " & sKey LogEntry ostore.Data(sKey) Else LogEntry "Key not found " & sKey End If Set ostore = Nothing 'LogOut End Sub
Show quote
Hide quote
"MP" <NoSpam@Thanks.Com> wrote in message Here's a tip on using a collection. The above would be more efficent if you made news:%23Sfcy3rkHHA.1624@TK2MSFTNGP02.phx.gbl... > > "MP" <NoSpam@Thanks.Com> wrote in message > news:OqznbHpkHHA.1532@TK2MSFTNGP03.phx.gbl... > >> part2 > > well, here's a first attempt at an interface and implementation using > collection > probably not efficient but seems to work in limited test shown below > Private Property Get IDataStore_Values() As Variant > Dim i As Long > Dim a() As Variant > ReDim a(mcolData.Count - 1) > > For i = 1 To mcolData.Count > a(i - 1) = mcolData.Item(i) > Next i > > IDataStore_Values = a > > End Property this change: Dim v As Variant i = 0 For Each v In mcolData a(i) = v i = i + 1 Next v The For Each construct is much faster than indexing your way through a collection.
Show quote
Hide quote
"Steve Gerrard" <mynameh***@comcast.net> wrote in message Thanks, I always forget that somehow because early on I learned thatnews:d_6dnacv4uxKXN_bnZ2dnUVZ_gCdnZ2d@comcast.com... > > "MP" <NoSpam@Thanks.Com> wrote in message > news:%23Sfcy3rkHHA.1624@TK2MSFTNGP02.phx.gbl... > > > > "MP" <NoSpam@Thanks.Com> wrote in message > > news:OqznbHpkHHA.1532@TK2MSFTNGP03.phx.gbl... > > > >> part2 > > > > Here's a tip on using a collection. The above would be more efficent if you made > this change: > > Dim v As Variant > > i = 0 > For Each v In mcolData > a(i) = v > i = i + 1 > Next v > > The For Each construct is much faster than indexing your way through a > collection. > variants were bad (inefficient) and since the iterator had to be a variant I got away from doing that. Mark "MP" <NoSpam@Thanks.Com> wrote in message For someone who wants to get more OO, you seem to like Variants a lot. Are you news:%23Sfcy3rkHHA.1624@TK2MSFTNGP02.phx.gbl... > > > well, here's a first attempt at an interface > > '----------------------------------------- > IDataStore.cls > Option Explicit > Public Property Get Keys() As Variant > Public Property Get Values() As Variant > Public Property Get Data(Key As String) As Variant > Public Sub Add(Key As String, Data As Variant) really VO? :) For your pondering: I have done an entire engineering app around objects that implement this simple interface: ' IListItem Public Property Get Key() As Long End Property Public Function CompareTo(Item As IListItem) As Long End Property These can be added to a custom CList class object. The list can contain objects that are all the same class, or a mixture, as long as they all implement IListItem. The list can be sorted, using the CompareTo function of each object (it uses a QuickSort and an index internally). It knows how to get the key of each object, since they are all IListItems. It can quickly return the next or previous item from any object in the list. I chose Long keys for performance reasons, but you could certainly use String keys if you preferred. It might seem silly to create a Class that just has one string property called Text, and implements IListItem. I wouldn't hesitate for a second to do it, though, for three reasons: 1) I would instantly have a nicely managed, sortable list of strings by using a CList; 2) I could add them to any CList, including one that had other classes of objects in it; 3) Every class I have ever made ends up aquiring more properties over time, and usually it doesn't take long. Abbr (abbreviation); Caption; MaxLength, etc. I found it more useful not to have a list interface, but rather to embed a CList inside any class that needed one. For example, CMaterials manages a list of materials, by using an embedded CList object. It is easy to pass through to CList when appropriate, and it can intervene and do material-related things whenever needed. This is the low-tech way to do inheritance in VB.
Show quote
Hide quote
"Steve Gerrard" <mynameh***@comcast.net> wrote in message well, i was just looking to get a list of the keys/ and or data/ if that wasnews:K6WdnTPPrOg9Vt_bnZ2dnUVZ_sSmnZ2d@comcast.com... > > "MP" <NoSpam@Thanks.Com> wrote in message > news:%23Sfcy3rkHHA.1624@TK2MSFTNGP02.phx.gbl... > > > > > > well, here's a first attempt at an interface > > > > '----------------------------------------- > > IDataStore.cls > > Option Explicit > > Public Property Get Keys() As Variant > > Public Property Get Values() As Variant > > Public Property Get Data(Key As String) As Variant > > Public Sub Add(Key As String, Data As Variant) > > For someone who wants to get more OO, you seem to like Variants a lot. Are you > really VO? :) > :-) sure looks like that eh? required by calling operation, since you can't assign to an array I've always seen variant used for return, then i was thinking to store "anything" in the data, the Data item property had to be variant also to avoid type mismatch or ETC I guess in that interface i was already thinking about implemening using collections and since collection items are variant...and so on.... <g> > For your pondering: I assume that's just part of the interface???> > I have done an entire engineering app around objects that implement this simple > interface: > > ' IListItem > Public Property Get Key() As Long > End Property > > Public Function CompareTo(Item As IListItem) As Long > End Property > Doesnt' there have to be an .Item property also? otherwise how do you get at the actual thing in itself? wouldn't that have to be As Variant to allow any object? and an .Add etc.... Show quoteHide quote > These can be added to a custom CList class object. The list can contain I assume you mean inside the cMaterials you haveobjects > that are all the same class, or a mixture, as long as they all implement > IListItem. The list can be sorted, using the CompareTo function of each object > (it uses a QuickSort and an index internally). It knows how to get the key of > each object, since they are all IListItems. It can quickly return the next or > previous item from any object in the list. I chose Long keys for performance > reasons, but you could certainly use String keys if you preferred. > > It might seem silly to create a Class that just has one string property called > Text, and implements IListItem. I wouldn't hesitate for a second to do it, > though, for three reasons: > 1) I would instantly have a nicely managed, sortable list of strings by using a > CList; > 2) I could add them to any CList, including one that had other classes of > objects in it; > 3) Every class I have ever made ends up aquiring more properties over time, and > usually it doesn't take long. Abbr (abbreviation); Caption; MaxLength, etc. > > I found it more useful not to have a list interface, but rather to embed a CList > inside any class that needed one. For example, CMaterials manages a list of > materials, by using an embedded CList object. It is easy to pass through to > CList when appropriate, and it can intervene and do material-related things > whenever needed. This is the low-tech way to do inheritance in VB. Private oList as cList .... Sub Initialize() Set oList = New cList ...or something similar where cList is a collection class of type IListItem? Thanks for the food for thought, Show quoteHide quote :-) Mark > > > >
Show quote
Hide quote
"MP" <NoSpam@Thanks.Com> wrote in message I think my points werenews:ekb%231PwkHHA.3704@TK2MSFTNGP02.phx.gbl... > > > :-) sure looks like that eh? > well, i was just looking to get a list of the keys/ and or data/ if that was > required by calling operation, > since you can't assign to an array I've always seen variant used for return, > then i was thinking to store "anything" in the data, the Data item property > had to be variant also to avoid type mismatch or ETC > I guess in that interface i was already thinking about implemening using > collections and since collection items are variant...and so on.... > <g> > 1) you may get more use out of an interface if you think about using it for the things being added to the collection or list, rather than for the list or collection class itself 2) you can make classes for storing "anything", and if they implement the right interface, you can store any of them in your collection or list.
Show quote
Hide quote
"Steve Gerrard" <mynameh***@comcast.net> wrote in message Hi Steve,news:msadnVf-gZR1qt7bnZ2dnUVZ_hynnZ2d@comcast.com... > > "MP" <NoSpam@Thanks.Com> wrote in message > news:ekb%231PwkHHA.3704@TK2MSFTNGP02.phx.gbl... > > > > > > :-) sure looks like that eh? > > well, i was just looking to get a list of the keys/ and or data/ if that was > > required by calling operation, > > since you can't assign to an array I've always seen variant used for return, > > then i was thinking to store "anything" in the data, the Data item property > > had to be variant also to avoid type mismatch or ETC > > I guess in that interface i was already thinking about implemening using > > collections and since collection items are variant...and so on.... > > <g> > > > > I think my points were > > 1) you may get more use out of an interface if you think about using it for the > things being added to the collection or list, rather than for the list or > collection class itself > > 2) you can make classes for storing "anything", and if they implement the right > interface, you can store any of them in your collection or list. > appreciate your hanging in there with me... trying to understand it all and get it in my pea brain <g> to go with your idea Interface: IListItem Properties Key as Long (or string) ' here I'm still confused.... ...don't I need Item (as variant) to store and return the actual "thing" that was stored???? ... and doens't it have to be as Variant so different implementations can store different types??? cIntList, cStringList, cObjectList, etc???? or are you saying the .Item property only goes in the concrete class implementation? so in cStringList for example I'd have ..Item as String ??? then in the implementation class are you still using Collection to store the cListItems???? what about a Save and Restore method pair for persistence? would that also want to live in the IListItem interface??? sorry just a little dense here... appreciate your help and ideas! Show quoteHide quote :-) Mark
Show quote
Hide quote
"MP" <NoSpam@Thanks.Com> wrote in message Closer, but no cigar yet :)news:ek99%23BykHHA.4248@TK2MSFTNGP06.phx.gbl... > > "Steve Gerrard" <mynameh***@comcast.net> wrote in message > news:msadnVf-gZR1qt7bnZ2dnUVZ_hynnZ2d@comcast.com... >> >> "MP" <NoSpam@Thanks.Com> wrote in message >> news:ekb%231PwkHHA.3704@TK2MSFTNGP02.phx.gbl... >> > >> > > Hi Steve, > appreciate your hanging in there with me... > trying to understand it all and get it in my pea brain <g> > > to go with your idea > Interface: > IListItem > Properties > Key as Long (or string) > ' here I'm still confused.... > ...don't I need Item (as variant) to store and return the actual "thing" > that was stored???? > ... and doens't it have to be as Variant so different > implementations can store different types??? > cIntList, cStringList, cObjectList, etc???? > > > or are you saying the .Item property only goes in the concrete class > implementation? > so in cStringList for example I'd have > .Item as String > ??? > > then in the implementation class are you still using Collection to store the > cListItems???? > what about a Save and Restore method pair for persistence? > would that also want to live in the IListItem interface??? > (And by the way, this is but one of many ways to skin this cat, I'm not suggesting it is the one and only). You are mixing up the IListItem group of classes (things that go into the list), with the List class itself. There would be no cStringList, or cWidgetList, or whatever. There is just CList. Rather, the objects getting put in the list implement an interface. This means that only objects can be added; hence the other post on why I would bother to create a class that had just a single string property. So you would have your own CString class, and a CWidget class, and what have you. As long as each of these classes implements IListItem, they can be added to any CList, and retrieved, and removed, etc. CList would have the Item method, which would retrieve an object from the list by key. And it would return it as an IListItem, since that is what it knows it to be. Clear as mud yet?
Show quote
Hide quote
"Steve Gerrard" <mynameh***@comcast.net> wrote in message Perhaps its time to explain the difference between "is a kind of" and "usesnews:BI2dnfcxbeXOdt7bnZ2dnUVZ_rCsnZ2d@comcast.com... > > "MP" <NoSpam@Thanks.Com> wrote in message > news:ek99%23BykHHA.4248@TK2MSFTNGP06.phx.gbl... > > > > "Steve Gerrard" <mynameh***@comcast.net> wrote in message > > news:msadnVf-gZR1qt7bnZ2dnUVZ_hynnZ2d@comcast.com... > >> > >> "MP" <NoSpam@Thanks.Com> wrote in message > >> news:ekb%231PwkHHA.3704@TK2MSFTNGP02.phx.gbl... > >> > > >> > > > Hi Steve, > > appreciate your hanging in there with me... > > trying to understand it all and get it in my pea brain <g> > > > > to go with your idea > > Interface: > > IListItem > > Properties > > Key as Long (or string) > > ' here I'm still confused.... > > ...don't I need Item (as variant) to store and return the actual "thing" > > that was stored???? > > ... and doens't it have to be as Variant so different > > implementations can store different types??? > > cIntList, cStringList, cObjectList, etc???? > > > > > > or are you saying the .Item property only goes in the concrete class > > implementation? > > so in cStringList for example I'd have > > .Item as String > > ??? > > > > then in the implementation class are you still using Collection to store the > > cListItems???? > > what about a Save and Restore method pair for persistence? > > would that also want to live in the IListItem interface??? > > > > Closer, but no cigar yet :) > > (And by the way, this is but one of many ways to skin this cat, I'm not > suggesting it is the one and only). > > You are mixing up the IListItem group of classes (things that go into the list), > with the List class itself. > There would be no cStringList, or cWidgetList, or whatever. There is just CList. > > Rather, the objects getting put in the list implement an interface. This means > that only objects can be added; hence the other post on why I would bother to > create a class that had just a single string property. > > So you would have your own CString class, and a CWidget class, and what have > you. As long as each of these classes implements IListItem, they can be added to > any CList, and retrieved, and removed, etc. CList would have the Item method, > which would retrieve an object from the list by key. And it would return it as > an IListItem, since that is what it knows it to be. > > Clear as mud yet? > a"? -ralph <g>
Show quote
Hide quote
"Steve Gerrard" <mynameh***@comcast.net> wrote in message Ah now I see, as the blind carpenter said...news:BI2dnfcxbeXOdt7bnZ2dnUVZ_rCsnZ2d@comcast.com... > > > > So you would have your own CString class, and a CWidget class, and what have > you. As long as each of these classes implements IListItem, they can be added to > any CList, and retrieved, and removed, etc. CList would have the Item method, > which would retrieve an object from the list by key. And it would return it as > an IListItem, since that is what it knows it to be. > > Clear as mud yet? > :-) ThanksMark
Show quote
Hide quote
"MP" <NoSpam@Thanks.Com> wrote in message More generally, I find it much more useful to have interfaces for the small item news:eTqVuMjlHHA.3760@TK2MSFTNGP05.phx.gbl... > > "Steve Gerrard" <mynameh***@comcast.net> wrote in message > news:BI2dnfcxbeXOdt7bnZ2dnUVZ_rCsnZ2d@comcast.com... >> > > > >> So you would have your own CString class, and a CWidget class, and what >> >> Clear as mud yet? >> > > Ah now I see, as the blind carpenter said... > :-) > classes, than to have them for collection classes. Once you have a collection of items, you can pass that around to various other widgets for processing. If you made a class called CStoreTextFile, for instance, it could have a method called StoreThis(List as CList, FileName As String) that would store the contents of the list in a text file. Make another class called CStoreIniFile, with a method called StoreThis(List as CList, IniName As String), that stores the list in an ini file. And another called CStoreMDB, with a method called StoreThis(List as CList, MDBName as String), etc. You don't really need an interface to the storage classes, or to the list classes. You end up with just a few of those anyway. What you need is interfaces to the item classes, because you may have hundreds or thousands of such objects.
Show quote
Hide quote
"Steve Gerrard" <mynameh***@comcast.net> wrote in message Got it.news:hvqdnR0ai6zDG9XbnZ2dnUVZ_segnZ2d@comcast.com... > > "MP" <NoSpam@Thanks.Com> wrote in message > news:eTqVuMjlHHA.3760@TK2MSFTNGP05.phx.gbl... > > > > "Steve Gerrard" <mynameh***@comcast.net> wrote in message > > news:BI2dnfcxbeXOdt7bnZ2dnUVZ_rCsnZ2d@comcast.com... > >> > > > > > >> So you would have your own CString class, and a CWidget class, and what > >> > >> Clear as mud yet? > >> > > > > Ah now I see, as the blind carpenter said... > > :-) > > > > More generally, I find it much more useful to have interfaces for the small item > classes, than to have them for collection classes. > > Once you have a collection of items, you can pass that around to various other > widgets for processing. > > If you made a class called CStoreTextFile, for instance, it could have a method > called StoreThis(List as CList, FileName As String) that would store the > contents of the list in a text file. Make another class called CStoreIniFile, > with a method called StoreThis(List as CList, IniName As String), that stores > the list in an ini file. And another called CStoreMDB, with a method called > StoreThis(List as CList, MDBName as String), etc. > > You don't really need an interface to the storage classes, or to the list > classes. You end up with just a few of those anyway. What you need is interfaces > to the item classes, because you may have hundreds or thousands of such objects. > > Thanks again Mark "Steve Gerrard" <mynameh***@comcast.net> wrote <snipped for brievity>> More generally, I find it much more useful to have interfaces for the small item > classes, than to have them for collection classes. > You don't really need an interface to the storage classes, or to the list What I hear you saying is that over a few years time, where a person might use a> classes. You end up with just a few of those anyway. What you need is interfaces > to the item classes, because you may have hundreds or thousands of such objects. few hundred different types of UDTs (list items) they could use a class that implements the IListItem, customized to include the needed members. The downside to that is the case where you need only a simple list of intrinsic types. If you want to store a 2, for example, you wrap it up in an object, if you want to store a string, it also gets wrapped up in an object. You loose the ability to provide the most efficient storage method for the data type, because everything is held in an object. Also, if you have items that have multiple unique members, you need a custom storage class to store those members. You may very well end up with as many storage classes as you have ListItem classes. For the 'generic list interface' method I mentioned, each implementation can store the data in whatever structure is best suited for the job, and can provide access to multiple members directly from the data. If I were to use your IListItem idea, it would also include LineData property that would serialize and de-serialize the item for easy storage to and from the disk. With that property included, any component that used a collection of list items, would also be able to easily load and save the list to a file. That would not eliminate the need to store everything in an object, but it would reduce the number of different storage classes needed to store lists of different items.... FWIW LFS
Show quote
Hide quote
"Larry Serflaten" <serfla***@usinternet.com> wrote in message Yup.news:O30XKNplHHA.568@TK2MSFTNGP02.phx.gbl... > > "Steve Gerrard" <mynameh***@comcast.net> wrote > >> More generally, I find it much more useful to have interfaces for the small >> item >> classes, than to have them for collection classes. > > <snipped for brievity> > >> You don't really need an interface to the storage classes, or to the list >> classes. You end up with just a few of those anyway. What you need is >> interfaces >> to the item classes, because you may have hundreds or thousands of such >> objects. > > What I hear you saying is that over a few years time, where a person might use > a > few hundred different types of UDTs (list items) they could use a class that > implements > the IListItem, customized to include the needed members. > > The downside to that is the case where you need only a simple list of Yup. I claimed in an earlier post that it might make sense to make a class for a > intrinsic types. > If you want to store a 2, for example, you wrap it up in an object, if you > want to store > a string, it also gets wrapped up in an object. You loose the ability to > provide the > most efficient storage method for the data type, because everything is held in > an object. > string, if in time you end up needing a caption, an abbreviation, or other such "additional" properties of the string. But the concept is not much use for intrinsic data types. I guess I find that I rarely have a bit of data that is really "all by itself". > Have you been peeking at my code? :)> If I were to use your IListItem idea, it would also include LineData property > that would > serialize and de-serialize the item for easy storage to and from the disk. > With that property > included, any component that used a collection of list items, would also be > able to easily > load and save the list to a file. That would not eliminate the need to store > everything in > an object, but it would reduce the number of different storage classes needed > to store > lists of different items.... > I indeed have expanded IListItem to include data storage and retrieval interfacing. I went with a method called MapProperties. My big axe to grind was that I was sick of having two places to specify the mapping of between the string name and the actual variable in the class. Too many debugging sessions finding where the spelling was one character different going out than coming in. So MapProperties works for both reading the class data from storage, and writing the data out to storage. I'm happy to give details if anyone is interested, but it is a bit elaborate. Works like a charm though. I have been storing in an mdb file, since I can store multiple collections by using a suitable GroupID, and use queries to retrieve the one of interest. I'm sure it could be done with text files or ini files the same way.
Show quote
Hide quote
On Wed, 9 May 2007 18:29:13 -0500, "MP" <NoSpam@Thanks.Com> wrote: Either would be fine>Hi, >two part question >part1 >I have a simple app to search files >Enter string in text box, pick commandbutton, it searches certain files for >matching text. >Now I thought to add a feature, Save list of previous searches >change from textbox to combo box, combo loads with previous saved (somehow) >list, pick from list or enter new search, save new search to list if not >already on list >(similar to recent sites list in browser target combo box, ) >so i thought of saving to ini file > >[SavedSearchesSection] > Search0=FirstSearch > Search1=SecondSearch > etc > >question1 >is that a normal way to setup incremental/indexed keynames? or am i using >ini in wrong way? >come to think of it, the search term itself could become the key and I >wouldn't need even a value!??? Your only decision is whether to use a standard INI file format or something of your own (call it CFG) - there are advantages in using your own format, one of which is having multiple fields with the same key name. Personally I would not use the Win APIs for INI file management Show quoteHide quote >part2 I would not use anything more complicated than needed>thinking out loud ....<g> >- seems too small a need to bother with a database solution >- could also just use simple text file >- suppose I could create a class, make persistable, save prop list with prop >bag, ??? > haven't tried that yet, that might be fun >it fits in with my desire to become more object oriented <g> >also fits with my recent contemplations of how to create a generic Key/Data >storage class >In nearly every tool i write I need to save key/data pairs for various >reasons. >have used arrays, collections, scripting.dicitionaries, Olaf's >dhSortedDictionary (very nice, thanks Olaf!!!), databases, ini files etc. >I'd like to structure a class that I could reuse with very simple calls and >not worry about re-implementing storage functions in every different app... >If Not cStore.Exists(SearchTerm) Then cStore.Add(SearchTerm) >or >If Not cStore.Exists(Key) Then cStore.Add(Key, Data) or something like that >And if i created an interface, i could make various implementations to use >various storage methods, ini, database, etc according to different need >levels(eg is persistance req'd or in-memory sufficient, ...simple key/data >pair adequate or do we need tables/fields/records detail...) - initially keep all the data in a vbCrLf delineated String and write a few routines for inserting, getting, removing the data It is just InStr Mid$ etc Eventually you'll probably wrap that in a Class, but mostly you'll just use it directly Storage, at its crudest are two Functions/Subs Data$ = FileStr( FileName$ ) and Call StrFile( Data$, FileName$ ) IMO one needs to work on the 'little' utilities that one will use all over the place - gradually, as needed, one writes wrappers around them, but really useful re-useable utilities tend to be pretty simple In short, Apps should be designed from top down, but generic utilities should be designed from the bottom up. - that way you get more re-useability Hi J
Thanks for the response and sage advice. if I had a blackboard I would write this 10,000 times "I would not use anything more complicated than needed" maybe then I'd learn <g> Show quoteHide quote "J French" <erew***@nowhere.uk> wrote in message think I found the way to just retrieve entries under a section withoutnews:4642b13a.4070352@news.btopenworld.com... > On Wed, 9 May 2007 18:29:13 -0500, "MP" <NoSpam@Thanks.Com> wrote: > > >Hi, > >two part question > >part1 > >so i thought of saving to ini file > > > >[SavedSearchesSection] > > Search0=FirstSearch > > Search1=SecondSearch > > etc > > > >question1 > >is that a normal way to setup incremental/indexed keynames? or am i using > >ini in wrong way? > >come to think of it, the search term itself could become the key and I > >wouldn't need even a value!??? needing keys use GetPrivateProfileSection and Split to create an array i'd still have to find the way to store them that way(without key)...google is my friend :-) except with your following advice now i don't need ini at all! :-) hmmm... hadn't thought of that....thought ini was the "cool" way <vbg> .. I> > Either would be fine > Your only decision is whether to use a standard INI file format or > something of your own (call it CFG) was all gettin ready to go out an buy some cheap sunglasses, get a tattoo and pierce some body parts....damn > - there are advantages in using your own format, one of which is ....sounds like TableName: FieldNames.... <g>> having multiple fields with the same key name. so you're meaning like I'd build a string sTosave = "SectionName" & delim & Key & delim & Field1 & delim & val1 & delim & Field2 & delim & Val2 & etc ??? I've always heard string concatenation was to be avoided in vb if possible....course I could use Karl's cStringBuilder > well,originally I didn't want to reinvent the wheel, just learn how to> Personally I would not use the Win APIs for INI file management > drive, but now you got my curiousity up... didnt' know ini 's were 'to stay away from' ... so much for the tattoos...<g> > >it fits in with my desire to become more object oriented <g> aww come on....I always have to do things the hardest way....<g>> >also fits with my recent contemplations of how to create a generic Key/Data > >storage class > > I would not use anything more complicated than needed > - initially keep all the data in a vbCrLf delineated String and write you mean then store that to a std txt file as .cfg file you mentioned?> a few routines for inserting, getting, removing the data then read and write with std io functions ? and search with the instr/mid combo Show quoteHide quote > that does sound simple...ouch....i'm starting to think out of the> It is just InStr Mid$ etc > > Eventually you'll probably wrap that in a Class, but mostly you'll > just use it directly > > Storage, at its crudest are two Functions/Subs > > Data$ = FileStr( FileName$ ) > and > Call StrFile( Data$, FileName$ ) > > IMO one needs to work on the 'little' utilities that one will use all > over the place > - gradually, as needed, one writes wrappers around them, but really > useful re-useable utilities tend to be pretty simple > > In short, Apps should be designed from top down, but generic utilities > should be designed from the bottom up. > - that way you get more re-useability box...<vbg> Thanks Mark On Thu, 10 May 2007 01:40:43 -0500, "MP" <NoSpam@Thanks.Com> wrote: It is not a problem, you are just tackling things the wrong way round>Hi J >Thanks for the response and sage advice. >if I had a blackboard I would write this 10,000 times >"I would not use anything more complicated than needed" >maybe then I'd learn <g> - coming up with the 'house' before you have the 'bricks' Just to digress about 1989 I realized that the most versatile and fundamental thing in the BASIC language is the String - it is really a little Object with very few properties, and is something that can contain anything - realistically it is one step up from raw memory, because it is a lot easier to manipulate, duplicate and generally mess around with. Strings are also extraordinarily efficient for data storage, with named pairs if something is not there then nothing is stored. If one is a bit careful, they can be human readable, which makes debugging so much easier. Just about anything can be reduced to a string containing what looks like a single section of an INI file You are on the right track "J French" <erew***@nowhere.uk> wrote in message <snipped>news:4642b13a.4070352@news.btopenworld.com... > On Wed, 9 May 2007 18:29:13 -0500, "MP" <NoSpam@Thanks.Com> wrote: > Show quoteHide quote > > In general I would agree, but one shouldn't forget other possible benefits.> >question1 > >is that a normal way to setup incremental/indexed keynames? or am i using > >ini in wrong way? > >come to think of it, the search term itself could become the key and I > >wouldn't need even a value!??? > > Either would be fine > Your only decision is whether to use a standard INI file format or > something of your own (call it CFG) > - there are advantages in using your own format, one of which is > having multiple fields with the same key name. > > Personally I would not use the Win APIs for INI file management > Using an INI file format through the API guarantees a separate cache (for lack of a better word) outside the File I/O of your application. IIRC Mr. Butler posted a reply explaining how valuable this can be, especially for error logging. It also aids in managing collisions if multiple applications should be accessing the same file. Of course, if one doesn't need these services, one can cut to the quick and roll their own. -ralph On Thu, 10 May 2007 11:39:05 -0500, "Ralph"
<nt_consultin***@yahoo.com> wrote: Show quoteHide quote > Yes, I spotted that post, it really made me raise an eyebrow>"J French" <erew***@nowhere.uk> wrote in message >news:4642b13a.4070352@news.btopenworld.com... >> On Wed, 9 May 2007 18:29:13 -0500, "MP" <NoSpam@Thanks.Com> wrote: >> ><snipped> >> Either would be fine >> Your only decision is whether to use a standard INI file format or >> something of your own (call it CFG) >> - there are advantages in using your own format, one of which is >> having multiple fields with the same key name. >> Personally I would not use the Win APIs for INI file management >In general I would agree, but one shouldn't forget other possible benefits. >Using an INI file format through the API guarantees a separate cache (for >lack of a better word) outside the File I/O of your application. IIRC Mr. >Butler posted a reply explaining how valuable this can be, especially for >error logging. - potentially very interesting >It also aids in managing collisions if multiple applications should be True>accessing the same file. >Of course, if one doesn't need these services, one can cut to the quick and Yes>roll their own. >-ralph Under Win16 I once wrote a TSR that monitored file access, it wasalaming seeing the disk activity for even reputable Apps. "J French" <erew***@nowhere.uk> wrote in message <cut>news:464405d8.1391994@news.btopenworld.com... > On Thu, 10 May 2007 11:39:05 -0500, "Ralph" > <nt_consultin***@yahoo.com> wrote: >>Using an INI file format through the API guarantees a separate cache (for I did? Don't remember that; not sure I'd ever use an INI for error >>lack of a better word) outside the File I/O of your application. IIRC Mr. >>Butler posted a reply explaining how valuable this can be, especially for >>error logging. > > Yes, I spotted that post, it really made me raise an eyebrow > - potentially very interesting logging...
Show quote
Hide quote
"Bob Butler" <noway@nospam.ever> wrote in message Oops!news:%236wMrr8kHHA.3928@TK2MSFTNGP02.phx.gbl... > "J French" <erew***@nowhere.uk> wrote in message > news:464405d8.1391994@news.btopenworld.com... > > On Thu, 10 May 2007 11:39:05 -0500, "Ralph" > > <nt_consultin***@yahoo.com> wrote: > <cut> > >>Using an INI file format through the API guarantees a separate cache (for > >>lack of a better word) outside the File I/O of your application. IIRC Mr. > >>Butler posted a reply explaining how valuable this can be, especially for > >>error logging. > > > > Yes, I spotted that post, it really made me raise an eyebrow > > - potentially very interesting > > I did? Don't remember that; not sure I'd ever use an INI for error > logging... > I think a google search is calling me. <g> -ralph
Show quote
Hide quote
"Bob Butler" <noway@nospam.ever> wrote in message I'm sorry. Wrong "Bob".news:%236wMrr8kHHA.3928@TK2MSFTNGP02.phx.gbl... > "J French" <erew***@nowhere.uk> wrote in message > news:464405d8.1391994@news.btopenworld.com... > > On Thu, 10 May 2007 11:39:05 -0500, "Ralph" > > <nt_consultin***@yahoo.com> wrote: > <cut> > >>Using an INI file format through the API guarantees a separate cache (for > >>lack of a better word) outside the File I/O of your application. IIRC Mr. > >>Butler posted a reply explaining how valuable this can be, especially for > >>error logging. > > > > Yes, I spotted that post, it really made me raise an eyebrow > > - potentially very interesting > > I did? Don't remember that; not sure I'd ever use an INI for error > logging... > http://groups.google.com/group/microsoft.public.vb.general.discussion/browse_thread/thread/5b29e1c1e68a1a36/aee7073429066524?lnk=st&q=&rnum=1&hl=en#aee7073429066524 I know I insulted one or both of you, but it wasn't done with malice. <g> -ralph "MP" <NoSpam@Thanks.Com> wrote in message While having an Exists method and an Add method are perfectly all right, you news:OqznbHpkHHA.1532@TK2MSFTNGP03.phx.gbl... > I'd like to structure a class that I could reuse with very simple calls and > not worry about re-implementing storage functions in every different app... > If Not cStore.Exists(Key) Then cStore.Add(Key, Data) or something like that could also add a method such as cStore.CheckAdd(Key, Data) that would combine the two for you. That way you don't have to write that line over and over. Push the work into the class...
Show quote
Hide quote
"Steve Gerrard" <mynameh***@comcast.net> wrote in message coolnews:zICdnaQbbsEuX9_bnZ2dnUVZ_tOmnZ2d@comcast.com... > > "MP" <NoSpam@Thanks.Com> wrote in message > news:OqznbHpkHHA.1532@TK2MSFTNGP03.phx.gbl... > > > I'd like to structure a class that I could reuse with very simple calls and > > not worry about re-implementing storage functions in every different app... > > If Not cStore.Exists(Key) Then cStore.Add(Key, Data) or something like that > > While having an Exists method and an Add method are perfectly all right, you > could also add a method such as > cStore.CheckAdd(Key, Data) > that would combine the two for you. That way you don't have to write that line > over and over. > > Push the work into the class... > I was just thinking that .Add would overwrite if it existed, so if you didn't want that behaviour you'd check for exist. so I guess I could use your suggestion when you don't want to overwrite and ..Add when you do, 'if for some reason you want to know if key already existed, could add a rtn val bAlreadyExists = cStore.CheckAdd(Key, Data)'don't overwrite if exists or Call cStore.CheckAdd(Key, Data) 'if you don't care bAlreadyExists = cStore.Add(Key, Data) 'write or overwrite or Call cStore.Add(Key, Data) or instead of two functions, add an optional boolean arg for bOverwrite so bAlreadyExists = Not cStore.Add (Key, Data, False) ' if key existed, and bOver is false, call returns false so bAlreadyExists = True bAlreadyExists = Not cStore.Add (Key, Data, False) ' if key didn't exist, write succeeds and returns true so bAlreadyExists = False (looks really ugly, eh?) or Call cStore.Add (Key, Data, True) 'write key if exists or not could make optional default to whatever way you wanted. just a thought Thanks for the input Mark On Thu, 10 May 2007 02:38:06 -0500, "MP" <NoSpam@Thanks.Com> wrote: ..Default is a property you could consider
Show quote
Hide quote
"MP" <NoSpam@Thanks.Com> wrote For another 2 cents....> I was just thinking that .Add would overwrite if it existed, so if you > didn't want that behaviour you'd check for exist. > so I guess I could use your suggestion when you don't want to overwrite and > .Add when you do, > 'if for some reason you want to know if key already existed, could add a rtn > val > bAlreadyExists = cStore.CheckAdd(Key, Data)'don't overwrite if exists > or > Call cStore.CheckAdd(Key, Data) 'if you don't care > > bAlreadyExists = cStore.Add(Key, Data) 'write or overwrite > or Call cStore.Add(Key, Data) > > > or instead of two functions, add an optional boolean arg for bOverwrite > so > bAlreadyExists = Not cStore.Add (Key, Data, False) ' if key existed, and > bOver is false, call returns false so bAlreadyExists = True > bAlreadyExists = Not cStore.Add (Key, Data, False) ' if key didn't exist, > write succeeds and returns true so bAlreadyExists = False > (looks really ugly, eh?) > > or > Call cStore.Add (Key, Data, True) 'write key if exists or not > > could make optional default to whatever way you wanted. > > just a thought You could create a simple list interface containing just two methods and a property. Public Sub Load(Optional Source As String) Public Sub Save(Optional Destination As String) Public Property Get Item(ByVal Name As String) As Variant Public Property Let Item(ByVal Name As String, ByVal Value As Variant) Load and Save initialize and persist the data store, respectively, and Item allows access to the list items. The source and destination could be filenames, or the source could be a connection string to a DB, or whatever else you need it to be. You don't need an Add method because simply assigning a value to a new name would add it to the list. And, you could use 'Nothing' as an indicator to remove an item from the list: Public Property Let Item(ByVal Name As String, ByVal Value As Variant) If IsObject(Value) Then If Value Is Nothing Then ' Remove object/value Else ' Add/Replace object End If Else ' Add/Replace value End If End Property The above might be used in an implementing class inteneded for 'generic' use (allows either objects or values) but for more specific use you would already decide if the item will be an object or a value. For example, in an implementing class that is designed to hold intrinsic values (Longs, Strings...): Public Property Let Item(ByVal Name As String, ByVal Value As Variant) If VarType(Value) Or vbObject Or vbNull Then ' Remove value Else ' Add value End If End Property Here either assigning Nothing or Null would remove the item. Assigning a value to a name would 'overwrite' the old value by default, but your if your needs require a check first, that could be handled in the implementing class. The key here is that the interface is very small, and it has the fundamental functions you need from a 'generic' list: A method to indicate where the datastore is, and when to load it. A method to indicate where the datastore should go, and when to save it. And a means to create new items and recall them from the list. Other more specific functions would be left to the implementing class tailored to suit each application or need.... LFS
Show quote
Hide quote
"Larry Serflaten" <serfla***@usinternet.com> wrote in message thats exactly what i've been thinking, just much clearer when you lay it outnews:%23UkM3j2kHHA.4900@TK2MSFTNGP05.phx.gbl... > > "MP" <NoSpam@Thanks.Com> wrote > > > I was just thinking that .Add would overwrite if it existed, so if you > > didn't want that behaviour you'd check for exist. > > so I guess I could use your suggestion when you don't want to overwrite and > > .Add when you do, > > 'if for some reason you want to know if key already existed, could add a rtn > > val > > bAlreadyExists = cStore.CheckAdd(Key, Data)'don't overwrite if exists > > or > > Call cStore.CheckAdd(Key, Data) 'if you don't care > > > > bAlreadyExists = cStore.Add(Key, Data) 'write or overwrite > > or Call cStore.Add(Key, Data) > > > > > > or instead of two functions, add an optional boolean arg for bOverwrite > > so > > bAlreadyExists = Not cStore.Add (Key, Data, False) ' if key existed, and > > bOver is false, call returns false so bAlreadyExists = True > > bAlreadyExists = Not cStore.Add (Key, Data, False) ' if key didn't exist, > > write succeeds and returns true so bAlreadyExists = False > > (looks really ugly, eh?) > > > > or > > Call cStore.Add (Key, Data, True) 'write key if exists or not > > > > could make optional default to whatever way you wanted. > > > > just a thought > > > For another 2 cents.... > > You could create a simple list interface containing just two methods and a property. > > Public Sub Load(Optional Source As String) > Public Sub Save(Optional Destination As String) > > Public Property Get Item(ByVal Name As String) As Variant > Public Property Let Item(ByVal Name As String, ByVal Value As Variant) > > Load and Save initialize and persist the data store, respectively, and Item > allows access to the list items. The source and destination could be > filenames, or the source could be a connection string to a DB, or whatever > else you need it to be. like that > beautiful, so simple> You don't need an Add method because simply assigning a value to a > new name would add it to the list. And, you could use 'Nothing' as an > indicator to remove an item from the list: Show quoteHide quote > I like it, sounds great, nice and simple> Public Property Let Item(ByVal Name As String, ByVal Value As Variant) > If IsObject(Value) Then > If Value Is Nothing Then > ' Remove object/value > Else > ' Add/Replace object > End If > Else > ' Add/Replace value > End If > End Property > > The above might be used in an implementing class inteneded for 'generic' > use (allows either objects or values) but for more specific use you would > already decide if the item will be an object or a value. For example, in an > implementing class that is designed to hold intrinsic values (Longs, Strings...): > > Public Property Let Item(ByVal Name As String, ByVal Value As Variant) > If VarType(Value) Or vbObject Or vbNull Then > ' Remove value > Else > ' Add value > End If > End Property > > Here either assigning Nothing or Null would remove the item. > > Assigning a value to a name would 'overwrite' the old value by default, > but your if your needs require a check first, that could be handled in the > implementing class. The key here is that the interface is very small, and > it has the fundamental functions you need from a 'generic' list: > > A method to indicate where the datastore is, and when to load it. > A method to indicate where the datastore should go, and when to save it. > And a means to create new items and recall them from the list. > > Other more specific functions would be left to the implementing class > tailored to suit each application or need.... > > LFS > > where do I mail the check for 2c?....and really you've got to adjust your rates...look at the price of gas these days!!! <g> :-) I also like your previous idea of storing data in a string ( I think thatwas your suggestion earlier) but haven't had time to think through exactly how to implement it totally, using fields/keys/data/delims....using instr for Exists and Mid for Item...neat idea, just everything takes me so long to think through and get implemented and working, sadly I'm not one of those genius types that just gets stuff instantly and is running with it before the sentence is half finished...<g> started working on it then got distracted by actual job...yuck...:-) Thanks again for your valued contributions :-) Mark "MP" <NoSpam@Thanks.Com> wrote in message oops, sorry it was J frenchnews:uLSIZU3kHHA.208@TK2MSFTNGP05.phx.gbl... > > "Larry Serflaten" <serfla***@usinternet.com> wrote in message > news:%23UkM3j2kHHA.4900@TK2MSFTNGP05.phx.gbl... > > > > "MP" <NoSpam@Thanks.Com> wrote > > > > I also like your previous idea of storing data in a string ( I think that > was your suggestion earlier)
A bit of Maths help with arrays
Right syntax for EXPRESSION Collection Capabilities How to control button in the form if i have more than 1 user profi Closing recordset Excuting a command line program from within VB Sending email from app in vb6 to hotmail Type mismatch error Variants I have a problem with Microsoft Multimedia control |
|||||||||||||||||||||||