Welcome to the SRP Forum! Please refer to the SRP Forum FAQ post if you have any questions regarding how the forum works.

Autofill, match anywhere, searching

A subclassed combo has the awesome feature of being able to define multiple columns for autofill and the ability to match anywhere within those strings, within those columns.

Am wondering if it is possible to get access to that logic for use outside of an object/combo?

Not after the code, just the functionality via a function call or some other interface.

In other words, armed with a multi-dimension array and somethingToSearchFor can I hand these two things to something and have a subset of the array returned or a set of values from a specified column or something indicating where there are matches within the array?

Comments

  • Mark,

    I really have no idea how easy it would be to separate that functionality from Subclass/EditTable UI. I seem to recall discussing this with Kevin already and learning that this is not a trivial feat. Suffice to say, this is not a feature that already exists.

    A possible alternative (mind you, kind of a kludge) would be to populate a hidden SRP Tree control and use the custom fields and the filter technology to perform the searching for you. This was described in our SRP ActiveX Controls 4.0 announcement.

    Unfortunately, while the filter property does wonders for the UI, as far as I know there is no property that reports which SRP Tree items are currently visible. I think you would have to use the ItemList property to get the array of items, extract the item Keys, and then get the visible property for each. Kind of a chore and why I consider this a kludge. Of course, if you put this in a wrapper then you need not have to worry about the code again. If the list of items is sufficiently large, it might not perform very well (although I think it would have to be rather large indeed for you to notice any delays...especially with the SRP array utilities to help make quick work of the ItemList property.

    Perhaps Kevin will surprise us both with a much better idea. He can easily dash all of our hopes against the rocks as well. :)
  • Thanks Don. I'll put my wetsuit and helmet on in anticipation of Kevin.
  • edited February 2016
    I'm so nice. I've updated SRP Utilities to support this feature. First, you have to download a pre-release build of SRP Utilities here. The zip file contains a standard OI RDK. Extract the files and RUN RDKINSTALL to get the changes.

    There are two new functions: SRP_List_MatchAnywhere and SRP_FastArray_MatchAnywhere. These methods are not yet documented on the wiki, so I'll explain them below. If you are unfamiliar with SRP_List or SRP_FastArray, see the documentation to learn how to use them. SRP_List is documented here. SRP_FastArray is documented here.

    For SRP_List_MatchAnywhere, one you have created a list, simply call this method to find the first element that contains the given string anywhere within the item's text. This finds any partial match. The code looks like this:

    Pos = SRP_List_MatchAnywhere(hList, "test")

    The above code will search an SRP_List (identified by the hList handle) for the first instance of "test" it finds. The search is case-insensitive, and it will find anything containing the word "test". The return value is the position within the list, or 0 if not found.

    SRP_FastArray_MatchAnywhere has the same behavior, but the syntax is a bit different to account for the fact that Fast Arrays are 3-dimensional. Here's the code to match the "test" string:

    FieldPos = 0 ValuePos = 0 SubvaluePos = 0 SRP_FastArray_MatchAnywhere(hArray, "test", FieldPos, ValuePos, SubvaluePos)

    Notice how we have to preset the positions to 0 and pass them as parameters. When the function completes, the positions will be set to the field, value, and subvalue in which the text was found. If not found, they should all be zero.

    Give it a try and let me know if this is what you were after or if there are any further questions I can answer.
  • To locate a value in an array and then substitute that value with a value from a substitution array list, you have to create 2 arrays and do a locate in the values array and then use the pos to pull the value from the substitution array.

    If you could create an array
    Tab<-1>= "test1:@vm:"sub1"
    Tab<-1>="test2":@vm:"sub2"
    Tab<-1>="test3":@vm:"sub3"

    add then do:

    Where FieldPos=1 indicates that you only want to search the @fm elements in the array.

    FieldPos = 1
    ValuePos = 0
    SubvaluePos = 0
    SRP_FastArray_MatchAnywhere(hArray, "test2", FieldPos, ValuePos, SubvaluePos)

    where FieldPos=2 is returned to indicate the FM pos of the array, would be helpful


  • I appreciate the sentiment behind the request, but I like to keep SRP Utilities tools generic in such way as to keep them flexible and simple. Since what you are asking only saves a you couple lines of code to meet your particular needs, I'm going to decline to add that feature for now.

    Otherwise, I get the impression the new method is working?
  • Kevin, like your work and I'm sure it will come in useful. Not quite what I was looking for though.
    Perhaps with some thought I could use it to achieve the intended result but allow me to expand a little in case my example triggers some easier approach in your mind.

    If I have an array of people for example:

    John:@vm:Smith:@vm:23 Jackson Pde:@fm
    Joe:@vm:Blow:@vm:12 Miranda Ave:@fm
    Mary:@vm:Jane:@vm:436 Smith St:@fm

    If I search this array for 'Smith' I want to have returned

    John:@vm:Smith:@vm:23 Jackson Pde:@fm
    Mary:@vm:Jane:@vm:436 Smith St:@fm

    or at least some indicator to tell me it is rows 1 & 3

    My understanding without testing is that SRP_FastArray_MatchAnywhere would be called like this

    SRP_FastArray_MatchAnywhere(myArrayHandle, 'Smith', 0, 0, 0)

    and in this example, return like this

    SRP_FastArray_MatchAnywhere(myArrayHandle, 'Smith', 1, 2, 0)

    That's good but poor old Mary Jane never gets found.

    If I was in a combo where the above was my list, the editfieldwould autofill based on the first selection but the dropdown would filter the list to all those potential matches.

    I'm after the filtered list rather than the first match.

    What's my chances?
  • Mark,

    I think I understand your goal. You want a programmatic equivalent of what the SRP Subclass control does as a UI. With the combobox, the visual results are paired down as the text is matched up. As a non-UI utility, you merely want to have this result returned to you as an array. Kevin and I have not had a chance to catch up on things, so we have not had the opportunity to review the update he just made. But, based on my understanding of his documentation this appears to be a "match anywhere, but only return the first match" proposition. Unless the preset values can be used to find the next match, I'm not sure this can be packaged up in a way to suit your goals.

    Am I following you so far?
  • That you are Don.
  • You might have to loop, build new, remove old repeat until 0
  • Then, if SRP_FastArray_MatchAnywhere could be preset with the last known matching values, and subsequent calls would return the next matching values, do you think this would provide you a utility that would be sufficient since it would be a small matter to create a wrapper that loops until the arguments reset to all 0s?
  • Barry,

    Not a bad idea, especially if you use the SRP_FastArray_Delete to remove the prior field data.

    However, as I think about this I am questioning whether creating our own BASIC+ wrapper really offers much of an advantage versus a pure BASIC+ solution. I mean, I wonder how much faster (if at all) such a wrapper would perform versus a simply looping through a standard dynamic array and using the IndexC function to see if there are any partial matches.

    Aside from benchmarking this, I think for this to really be worthwhile we would want a single high-performant utility that allows us to populate a 2-dimensional array and text to match against, and it returns a smaller 2-dimensional array based on those "rows" that match.
  • I had considered this and whilst I have no problem with writing a wrapper I suspect we might lose any potential benefit.
    The ultimate goal is efficiency.
    If SRP_FastArray_MatchAnywhere could be preset with the last known matching values and that would save me from modifying the array then I think we're in business. A wrapper with a loop that simply repeats until 0, 0, 0 would likely work.

    If I have to use a find, remove, build new array to find first match in new array type loop then the value is lost.

    The UI is great and seemingly instantaneous. I suspect even with srp_fastarray, building smaller and smaller arrays to search within would not be so instantaneous.
  • A new build, 1.5.5 RC5, can be downloaded here.

    First, I altered the MatchAnywhere routines. They now have the following signatures:
    SRP_FastArray_Match(Handle, Field, Value, Subvalue, MatchAnywhereFlag) Pos = SRP_List_Match(Handle, StartPos, MatchAnywhereFlag)
    So, it's not MatchAnywhere, just Match. The "anywhere" is now a flag. So, setting the flag to 1 allows it to match anywhere in any element. Setting it to 0 means the string has to match an entire element. So, "test" will only find "test" and not "testing". It is still a case insensitive search.

    Also, you can preset the Field, Value, and Subvalue positions to tell the routine to start searching there. So, setting Field to 11 means the search for a match will start in field 11. As always, the returned value is either the positions where the match was found or 0 if not found. For Lists, there is now a StartPos parameter so you can tell it where to start. Set it to 1 or 0 to start at the beginning.

    I also added two new functions for Mark's needs: SRP_FastArray_Reduce and SRP_List_Reduce. Each one takes a handle to an existing array/list, a search string, and a MatchAnywhere flag. The returned value is a handle to a new array/list containing only those elements that matched the string. Here's an example for reducing a Fast Array:
    TestArray = Xlate("SYSREPOSWINS", "EXAMPLES**CUST_ENTRY", "", "X") TestArray = Field(TestArray, @RM, 3) Handle = SRP_FastArray_Create(TestArray) HandleReduced = SRP_FastArray_Reduce(Handle, "PHONE_", 1) ReducedArray = SRP_FastArray_GetVariable(HandleReduced) SRP_FastArray_Release(Handle) SRP_FastArray_Release(HandleReduced)
    Here's an example reducing a List:
    Total = 9999 hList = SRP_List_Create() For i = 1 to Total SRP_List_Add(hList, i) next i hListReduced = SRP_List_Reduce(hList, "777", 1) ReducedList = SRP_List_GetVariable(hListReduced, @FM) SRP_List_Release(hList) SRP_List_Release(hListReduced)
    I hope this scratches the itch.
  • I hope this scratches the itch.

    I already sent him some cream for that little problem of his.
  • Mark,

    Are you saying you don't see his code within the post? If so, are you able to see the code in his previous posts?
  • I'm saying I couldn't see the code within the post.
    I took the screenshot, posted it, the browser refreshed and then I could see the code.
    So I went to delete/edit my post and my machine crashed leaving I suspect a somewhat confusing post
  • Okay. I just needed to confirm because there have been other reports that the code doesn't display and we are trying to sort this out. It isn't consistent, as you just bore witness to.
  • and by the way, thanks for the cream though next time I might read the label before I begin brushing my teeth.
  • Kevin,

    I just tested your sample code. Works a charm.

    Legend.
Sign In or Register to comment.