CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 14 of 14
  1. #1
    Join Date
    May 2005
    Posts
    49

    [RESOLVED] Wait for remote user input with pagination

    Hi All,

    I have a project that monitors a 3rd party chat program through API calls for the text from users in the chat room. One of the functions of my program allows a key word search through the database that my vb app is linked to. The problem is, sometimes the results are large enough to overload the input maximum for the chat program. I think its a total of 350 chars or so. And I want to paginate the resulting search responses so that 10 or 15 responses get sent back to the user at a time and that user can decide if they want more or not.

    I believe I have several options for this but nothing seems to really work well. I think the easiest way to do this is to just take the first 15 results and send them, then say that there were more but you need to refine your search. Or I could check the record count and if its more than 10 or so send it to a separate process but that still leaves me with the pagination problem. I would like to allow the user to type say a "more" command and they get their responses in groups of 10 or 15 at a time till either they don't want any more responses and type a "stop" command or the resulting searched recordset is eof or a timer has elapsed.

    The communication between my app and the chat room is not an issue. That works perfectly fine. The only problem I am running into is breaking up a resulting recordset into chunks that can be held for a specific user for a specific amount of time or the recordset is eof.

    I am looking for any suggestions, examples, advice. I have considered sleepex or waitfor but not sure how they would react. I would really like the app active for other users while this search result is held for a specific user.

  2. #2
    Join Date
    Jul 2006
    Location
    Germany
    Posts
    3,725

    Re: Wait for remote user input with pagination

    An adequate answer to that would greatly depend on the implementation of your program.
    It is easy to say:
    Well, I'd put all lines in a dynamic string array and let the user type "more" to get them in tenth or fifteenth. You keep a counter tracking how many you have already sent.
    Or:
    Write a class which has such an array to hold the result strings, a counter and a pointer (or reference) to the user who requested that search.

    Maybe you need a timer which frequently looks if the user has typed such a request and sends the next 15 lines. It also can destroy this object if the user is through with it.

    I can't give more useful suggestion when not knowing more about your program structure, because in the end there lies the crux for a sophisticated implementation of what you want.

  3. #3
    Join Date
    May 2005
    Posts
    49

    Re: Wait for remote user input with pagination

    Ok, I do have a timer event running and it watches for various commands. Here is the command that starts the keyword search:
    Code:
     
    Case TrigPos = InStr(1, RichTextBox2.Text, ": $Key", vbTextCompare)
    Trigger = ": $key"
    And here is the sub it calls now:

    Code:
    Private Sub KeyWordSearch()
    
    Dim tmpStr, SQLStr, sString As String
    Dim sPath As String
    Dim Counter As Long
    
    Dim iHnd As Long
         iHnd = getPalSubForm(WindowClass, Combo1.Text, RoomOutboundTextBoxClass, SendTxtIndex)
         iHnd = SendTextHnd
    Trigger = "$key"
    
    cmdPos = InStr(1, RichTextBox2.Text, Trigger, vbBinaryCompare)
    If cmdPos = 0 Then Exit Sub
    
    cmdVer = Trim$(Right$(RichTextBox2.Text, (Len(RichTextBox2.Text) - cmdPos) - 4))
    
    RichTextBox4.Text = Right(cmdVer, Len(cmdVer))
    
    sString = RichTextBox4.Text
    
    SQLStr = "Select tblBook.*,tblQUOTE.* From tblBook,tblQUOTE Where (tblQUOTE.Quote Like '%" & sString & "%') And tblBook.Book_ID=tblQUOTE.Book_ID Order by tblQUOTE.Book_ID,tblQUOTE.Chapter ASC"
    
    Dim db1 As Connection
    Set db1 = New Connection
    db1.CursorLocation = adUseClient
    sPath = App.Path & "\kjvbible.mdb"
    db1.Open "PROVIDER=Microsoft.Jet.OLEDB.4.0;Data Source=" & sPath
    Set adoPrimaryRS1 = New Recordset
    Set adoPrimaryRS1 = db1.Execute(SQLStr, , adCmdText)
    
    While Not adoPrimaryRS1.EOF
    
    tmpStr = adoPrimaryRS1!Book_Title & " " & adoPrimaryRS1!Chapter & ":" & adoPrimaryRS1!Verse
    
    adoPrimaryRS1.MoveNext
    
    RichTextBox1.Text = RichTextBox1.Text & tmpStr & " $$ "
    
    Counter = (Counter + 1)
    
    If Counter > 14 Then
    GoTo Sendit:
    Else
    End If
    
    Wend
    
    RTB5 = Text1.Text & " Your Keyword or Phrase Search Results Are:  " & Counter & "  Verse(s)  " & RichTextBox1.Text
    RTB5.SelLength = Len(RTB5.Text)
    
    With RTB5
         .SelBold = True
         .SelFontSize = 8
         .SelColor = RGB(101, 0, 192)
    End With
    
    Call SendMessageByString(iHnd, WM_SETTEXT, 0&, RTB5)
    Call SendMessage(iHnd, WM_KEYDOWN, 13, 0)
    
    
    ' Close RecordSet and Database
    adoPrimaryRS1.Close
    db1.Close
    
    RTB5 = ""
    Trigger = ""
    RichTextBox1.Text = ""
    RichTextBox2.Text = ""
    RichTextBox4.Text = ""
    
    Exit Sub
    
    Sendit:
    RTB5 = Text1.Text & " Your Keyword or Phrase Search Results Are:  " & Counter & "  Verse(s)  " & RichTextBox1.Text & " There were more responses, please narrow your search"
    RTB5.SelLength = Len(RTB5.Text)
    
    With RTB5
         .SelBold = True
         .SelFontSize = 8
         .SelColor = RGB(101, 0, 192)
    End With
    
    Call SendMessageByString(iHnd, WM_SETTEXT, 0&, RTB5)
    Call SendMessage(iHnd, WM_KEYDOWN, 13, 0)
    
    
    ' Close RecordSet and Database
    adoPrimaryRS1.Close
    db1.Close
    
    RTB5 = ""
    Trigger = ""
    RichTextBox1.Text = ""
    RichTextBox2.Text = ""
    RichTextBox4.Text = ""
    
    Exit Sub
    
    End Sub
    What I have chosen to do so far is to count up and if it exceeds 14 to send it to the bit of code with adds the tag that there were more results and to narrow the search.

    Also, as you can see, I use a case statement in my timer event that watches for the particular command and then launches the sub. I can add the $more command to the timer sub. That is not a problem. I also do capture and separate the user name in a different container. Now I just need help getting started with something to utilize everything I do get into some code that will accomplish the idea of being able to allow them to use the more command.
    Last edited by intercepter; May 3rd, 2009 at 09:54 AM. Reason: clarification

  4. #4
    Join Date
    Jul 2006
    Location
    Germany
    Posts
    3,725

    Re: Wait for remote user input with pagination

    Ok.
    If this routine is reentered from another users search, it seems the previous results are lost to the user who requested it in the first place.
    What I'd do is:
    Write a class SearchResult which has a dynamic string array, a counter reflecting the lines already sent.
    Declare a public collection where you can store objects of this class.
    In your routine, before you get the search results, you create an object of this class and put it into the collection. Then you read all of the results into this object and then you send the first 15 lines.
    The object definition (class) will contain a dynamic string array for the results, and a counter.
    You need a Private colSearches as New Collection where you store the searchresults.
    Code:
    'after establishing the database connection
    Dim sr as new SearchResult
    Set sr = New SearchResult
    colSearches.add sr, Username
    While Not adoPrimaryRS1.EOF
    
      tmpStr = adoPrimaryRS1!Book_Title & " " & adoPrimaryRS1!Chapter & ":" & adoPrimaryRS1!Verse
      sr.Add tmpStr
      adoPrimaryRS1.MoveNext
    Wend
    adding and counting might be handled within the class.

    When sending another 15 lines you can do this in a sub

    Code:
    Sub SendMore(Username as string)
      dim i%, r$
      for i=1 to 15
         a$ = colSearches(Username).NextLine
         'then your procedure to send the line to the user
      next
    End Sub
    When all lines were sent, or the user quits it, you simply remove the object from the collection.

    Such handling allows to deal with multiple search requests of any number of users without interfering.

    If you feel unsure in writing a class with these properties such a SearchResult object should have, I will surely help you with it.

  5. #5
    Join Date
    May 2005
    Posts
    49

    Re: Wait for remote user input with pagination

    Thanks for your help. I have a feeling that this next bit of code is missing something, but I am not sure what yet.

    I have created SearchResult.cls and here is the code:

    Code:
    Option Explicit
    
    'local variable to hold collection
    Private colSearches As New Collection
    
    Public Function Add(colSearchResult As String, Optional sKey As String) As SearchResult
        'create a new object
        Dim objNewMember As SearchResult
        Set objNewMember = New SearchResult
    
    
        'set the properties passed into the method
        objNewMember.colSearchResult = colSearchResult
        If Len(sKey) = 0 Then
            colSearches.Add objNewMember
        Else
            colSearches.Add objNewMember, sKey
        End If
    
    
        'return the object created
        Set Add = objNewMember
        Set objNewMember = Nothing
    
    
    End Function
    
    Public Property Get Item(vntIndexKey As Variant) As SearchResult
        'used when referencing an element in the collection
        'vntIndexKey contains either the Index or Key to the collection,
        'this is why it is declared as a Variant
        'Syntax: Set foo = x.Item(xyz) or Set foo = x.Item(5)
      Set Item = colSearches(vntIndexKey)
    End Property
    
    
    
    Public Property Get Count() As Long
        'used when retrieving the number of elements in the
        'collection. Syntax: Debug.Print x.Count
        Count = colSearches.Count
    End Property
    
    
    Public Sub Remove(vntIndexKey As Variant)
        'used when removing an element from the collection
        'vntIndexKey contains either the Index or Key, which is why
        'it is declared as a Variant
        'Syntax: x.Remove(xyz)
    
    
        colSearches.Remove vntIndexKey
    End Sub
    
    
    Public Property Get NewEnum() As IUnknown
        'this property allows you to enumerate
        'this collection with the For...Each syntax
        Set NewEnum = colSearches.[_NewEnum]
    End Property
    
    
    Private Sub Class_Initialize()
        'creates the collection when this class is created
        Set colSearches = New Collection
    End Sub
    
    
    Private Sub Class_Terminate()
        'destroys collection when this class is terminated
        Set colSearches = Nothing
    End Sub
    I am a bit confused because I thought you set the properties in the class and then call them in the various subs. Also, do I set up something to show the different items for each search sorted by the username?

  6. #6
    Join Date
    Jul 2006
    Location
    Germany
    Posts
    3,725

    Re: Wait for remote user input with pagination

    Hmmmm... hmmm.
    No, no. You misunderstood some of my suggestions. The collection of search results may never be part of the class SearchResult at all. It should be defined within your main program.
    It is a means of storing many search results ordered by independant users, handled by your program.
    The class SearchResult is supposed to be rather simple instead.
    Look.
    I attached a little demo program, where I defined a class SearchResult like I was proposing it.
    It will hold any number of search result strings and return them in any amount of lines as you wish.
    To make this demo work, you have to create a file "C:\Test\Test.txt" which contains lots of lines as searchresults, or figure out how to work this example into your own program, because I have no database giving search results.
    Clicking the first button will create a dummy search result object in the collection and indicate it in the ListBox.
    Clicking on the entry in the ListBox requires a page of search results to be displayed in the left hand TextBox.
    Repeatedly clicking (or clicking on the second button) gets the next page of results to be shown.

    If you have further problems in understanding, please let me know. I try to explain closer.
    Please check the attached sample.
    To make it work you create a file "C:\Test\Test.txt", containing more than 30 lines of text, simply.
    Attached Files Attached Files

  7. #7
    Join Date
    May 2005
    Posts
    49

    Re: Wait for remote user input with pagination

    Thanks again for all your help. I believe I have it now. Here is the code I came up with.

    This is the initial keyword search code I modified:
    Code:
    Dim sr As New SearchResult
    Dim a$
    UserName = Text1.Text
    colSearches.Add sr, UserName
    
    
    While Not adoPrimaryRS1.EOF
    
    tmpStr = adoPrimaryRS1!Book_Title & " " & adoPrimaryRS1!Chapter & ":" & adoPrimaryRS1!Verse
    a$ = tmpStr
    sr.Add a$
    adoPrimaryRS1.MoveNext
    
    RichTextBox1.Text = RichTextBox1.Text & tmpStr & " $$ "
    
    Wend
    
    Count = sr.LinesCount
    
    If Count > 14 Then
    Call SendMore((Text1.Text), 15)
    Else
    End If
    Text1.text holds the UserName

    Here is the SendMore Sub:
    Code:
    Private Sub SendMore(UserName As String, NumLines As Integer)
    Dim r$, i%
    Dim a$, sr As SearchResult
    If UserName = "" Then Exit Sub
    On Error GoTo NoResultsForThisUserName
    Set sr = colSearches(UserName)
    
      For i = 1 To NumLines
          a$ = sr.NextLine
          r$ = r$ + a$ + " $$ "
      Next
    
    RichTextBox1.Text = r$
    
    NoResultsForThisUserName:
    
    End Sub
    And here is my more command:

    Code:
    Private Sub MoreVer()
    Dim iHnd As Long
         iHnd = getPalSubForm(WindowClass, Combo1.Text, RoomOutboundTextBoxClass, SendTxtIndex)
         iHnd = SendTextHnd
    
    Dim u$
      u$ = Text1.Text
      If u$ <> "" Then SendMore u$, 15
    
    RTB5 = Text1.Text & " Your Keyword or Phrase Search Results Are:  " & Count & "  Verse(s)  " & RichTextBox1.Text & " Type $more for more results, "
    RTB5.SelLength = Len(RTB5.Text)
    
    With RTB5
         .SelBold = True
         .SelFontSize = 8
         .SelColor = RGB(101, 0, 192)
    End With
    
    Call SendMessageByString(iHnd, WM_SETTEXT, 0&, RTB5)
    Call SendMessage(iHnd, WM_KEYDOWN, 13, 0)
    
    RichTextBox1.Text = ""
    
    End Sub
    My only problem is code to remove a usernames search from the collection.

    This is what I have tried:

    Code:
    Private Sub StopVer()
    
    colSearches.Remove (Text1.Text)
    set colSearches(UserName) = Nothing
    
    End Sub
    I have also tried sr.remove and just set sr(username) = Nothing without success. I get an object error 424 for most of the things I have tried. Or I get object required error 424.
    Any ideas?

    The other thing I noticed was in your SearchResults.cls, it loops back around on me so I just changed this property:

    Code:
    Public Property Get NextLine() As String
      If LinesSent < LinesCount Then
         NextLine = Lines(LinesSent)
         LinesSent = LinesSent + 1
         LinesLeft = LinesSent - LinesCount
      Else
         NextLine = "End of Results." + vbCrLf
         LinesSent = LinesCount + 1
      End If
    End Property
    The way you had it, started the whole thing over again and caused a loop, so I changed it so that it at least would not start over. I also added a LinesLeft for implantation a bit later when I clean some other things up.

  8. #8
    Join Date
    Jan 2006
    Location
    Fox Lake, IL
    Posts
    15,007

    Re: Wait for remote user input with pagination

    Remove removes a Integer pointing to the current row

    Code:
    colSearches.Remove Val(Text1.Text)
    would convert it back to a number, but will remove characters
    David

    CodeGuru Article: Bound Controls are Evil-VB6
    2013 Samples: MS CODE Samples

    CodeGuru Reviewer
    2006 Dell CSP
    2006, 2007 & 2008 MVP Visual Basic
    If your question has been answered satisfactorily, and it has been helpful, then, please, Rate this Post!

  9. #9
    Join Date
    May 2005
    Posts
    49

    Re: Wait for remote user input with pagination

    Thanks for your reply, But I get a Runtime error:9 subscript out of range, when I try that option.

  10. #10
    Join Date
    Jan 2006
    Location
    Fox Lake, IL
    Posts
    15,007

    Re: Wait for remote user input with pagination

    See what the value is:
    Code:
    Debug.Print Val(Text1.Text)
    Lists are ZERO BASED, so you might have to subtract one to ge the right answer
    David

    CodeGuru Article: Bound Controls are Evil-VB6
    2013 Samples: MS CODE Samples

    CodeGuru Reviewer
    2006 Dell CSP
    2006, 2007 & 2008 MVP Visual Basic
    If your question has been answered satisfactorily, and it has been helpful, then, please, Rate this Post!

  11. #11
    Join Date
    May 2005
    Posts
    49

    Re: Wait for remote user input with pagination

    Yep, I see where your coming from. However, I did get it working for now. I have not tested the stop command with more than one search running. But I was able to do this,

    Code:
    Set colSearches = Nothing
    However, I believe this would kill the entire collection, and thus any other users search in the collection would also be lost.

    But the value is when I just tried it Val(Text1.Text) is 0 and when I hover over it, the username is in there.

  12. #12
    Join Date
    Jul 2006
    Location
    Germany
    Posts
    3,725

    Re: Wait for remote user input with pagination

    Yes this kills the entire collection.

    If you .Add something, KeyString
    then you can always .Remove KeyString, provided it is the same string.
    You must not put the text in brackets, though.
    If Text1.Text holds your key string, then simply colSearches.Remove Text1.Text. No brackets.

    This must remove the so named item.

    Certainly each item has an index, but we don't use it to delete the item, because we have used the Key to identify it.
    If Text1.Text were to hold "User1", then a .Remove Val(Text1.Text) will always remove the collections first item colSearches(0). That's not what we want.

    You have to understand that the items in a collection can be either addressed by their index, or by their key.
    colSearches(0) delivers the first item
    colSearches("User1") delivers the item we put in with this name of "User1"
    colSearches.Remove "User1" removes the very same
    colSearches.Remove Text1.Text removes the item with the key stored in Text1.Text

    When running with multiple users, the contents of the collection might hold any number of SearchResults.
    Say it contains 5 such items and you .Remove 0, then the first item is deleted and the index of all other items is changed so that we have no gaps in the sequence of indexes.
    Therefore we better use the Key to identify items in the collection and do not have to care for the numerical index. That's why the collection git this feature.
    Only thing is you cannot have 2 items with the same Key. But that's ok, because one user will only be allowed to have one SearchResult object.

  13. #13
    Join Date
    May 2005
    Posts
    49

    Re: Wait for remote user input with pagination

    And with that, It is all resolved and working as expected. Thank you very much for your assistance in this.

  14. #14
    Join Date
    Jul 2006
    Location
    Germany
    Posts
    3,725

    Re: [RESOLVED] Wait for remote user input with pagination

    Fine.
    And, @David, Lists ARE zero based (starting with element 0), collections, however are NOT. Their first element is col(1).
    So in my above explanation about the collection I'd have to correct this, too:
    colSearches.Remove 0 will give an error index out of range.
    colSearches.Remove 1 would remove the first item.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured