How to find out the range of records displayed in

Hi all, Let’s say we have a form which displays some records from a table. Filters may be set or not. The user resizes the form and scrolls up and down. How can I find out (can I?) in C/AL which records are currently visible in the form? Or maybe just which record is currently the first one?

Hmmm, this would be quite complex. The only way I can see, is to measure the size and position of the form, row height etc, and from this find how many records are displayed on the screen, the start counting. I once did this to try and find the last record displayed, so that I could put sub totals on a list form. In the end, I just put code in the table to tgenerate the sub totals on the fly, because counting form sizes is very complex (User changed for height, header height, row height etc). In the end it may be easier to talk with the client and redesign this.

Hello Heinz! Hmmm … I don’t know how this could be done … but I think you could use somehow the OnFormat-Trigger, because this one is only executet when a record is shown … [^] Regards, Jörg

Jörg, I thought of this too - the problem with OnFormat is to determine when it is called for the first row. There is no “OnRefresh” or the like which could tell the beginning or end of a complete “refresh cycle”. I could be wrong, but it seems to me as if the OnFormat and OnNext etc. triggers just get executed one after another without a way to determine if it’s the first (or last) execution in a consecutive series of trigger calls fired by a scroll operation. If there is some trigger that gets executed only once after a complete refresh, this would solve my problem. David, is there a way to determine the form’s geometry at runtime? Not that it would be of any help, just out of interest [;)] The problem is that I’m trying to do this on the Date table in a Matrix box, so there is no first record to start calculating but an infinite range of records… The client is ourselves, btw [8D] I’ll provide the details, maybe someone has a different approach for solving this: What we are trying to accomplish is the following: We want to do some resource planning. There are resources and resource groups. The main form with source table resource groups contains a Matrix control with the Date table, and a subform. The subform has the resource table as source table and again a Matrix control with the Date table. Now I want to synchronize the time scale in these two Matrix controls. If the user selects e.g. March to November in the main form, the subform should automatically show the same time scale. To do this, I need to know which month (or day, or whatever) is displayed at the left border of the main form’s matrix.

Hi Joerg Good hint. I just played with it. It works. The problem is: The OnFormat- Trigger is executed only once for each record (and then for each new record on the form). But Heinz wants to find the first record on the form. @Heinz: You have just mentioned Ecxel in the other thread [:D]. I’m sure you don’t want to hear something like this but you could use Excel to solve this [8D]. bye André


Originally posted by Andre DDB
@Heinz: I’m sure you don’t want to hear something like this but you could use Excel to solve this [8D].

Ok, Andre, it’s 1 - 1 between us now [8D] Hm, how could Excel help in solving this task? Perhaps I could write some clever VBA routines that extract the column labels from the main form using the window ID, then send key press events to the subform until its column labels (once again extracted by using the window ID) match those of the main form. Then they will come and carry me away in a straight jacket, screaming. [:D]

Hi Heinz


… then send key press events …

Oh [:D]! It is the right direction [;)]. I have not enough time in the moment. Thats why here in advance what I have yet. When you open the form you can easy get the displayed range with the OnFormat- Trigger (Thank you to Joerg [:)]) with something like that (example Item list): **OnFormat(VAR Text : Text[1024];)** IF MinX = '' THEN MinX := "No."; IF MaxX = '' THEN MaxX := "No."; IF "No." < MinX THEN MinX := "No." ELSE IF "No." > MinX THEN IF "No." > MaxX THEN MaxX:= "No."; MESSAGE(FORMAT(MinX)+' - '+FORMAT(MaxX));// Remove! Only for testing. Now my idea (not really tested yet) how to get the range if the user moves to another record: If the pointer is within the current range no action is needed (check in OnAfterCurrentRecord). If the pointer is out of the current range you have to check the new range. Then (so my idea) you may do the following: CLEAR(MyXL); IF CREATE(MyXL,TRUE)THEN; MyXL.SendKeys('{PGUP}'); //The pointer jumps to the first record on the form and //fires the Onformat- trigger of this record. MyXL.SendKeys('{PGDN}'); //The pointer jumps to the last record on the form and //fires the Onformat- trigger of this record. My problem now is: how can I execute both jumps (with running the OnFormat-trigger). Perhaps I can play a little at the weekend. You will get a notice if I found a solution [:)]. bye André

Hi Andre! Cool idea [:D]! Using the OnFormat trigger in the way you suggested will give me the range of records currently displayed in the form. Now it boils down to finding the correct moment for calling a function on the subform to set its first record. This could happen in OnAfterGetRecord, depending on the execution order of this trigger and OnFormat. If OnFormat is called first, you will never find out if the current record is out of range, as the range has already been updated. [B)] I will have to check this out. Another point is how to set the range on the subform. I’m not sure if you really need Excel to do this, at least not in my special application. It might be sufficient to set filters on the Date table so that only the current range of the main form will be displayed. Thank you all! This forum never fails to amaze me with great answers to weird problems! [8D]

OK, here it is [8D], I am not sure how you would want to use it, but the Form below should definitely get you going. Go-Live Determine Displayed

David, thanks a lot for your objects! They look very promising, although I will have to modify them a bit to make them run on my system - if I try to run them, an error about some variable reference pops up, but I have examined the code and it seems that this is probably what I was looking for. Thanks again for your help!

Anytime… Please let me know how it goes. Also there is one thing I could not resolve, and that was using the scroll button on a wheel mouse, the form just did not ract to that. (Thus the code in onNext and OnFind from my testing). If you get that working, let me know.

Hi All, Your solution sounds very good, but, does this work, if the user sets another filter or change the sorting by choosing another key? Regards, Frank

Folks, it works! [:D] There are two important things to consider: First, use the OnFormat trigger to determine the current range with a Minimum-Maximum search, like Jörg suggested. Second: Find the right moment to discard the values you found in step 1! David’s code was very helpful with this part. If you forget step 2, your range will only get wider and wider as the user scrolls back and forth. [B)] In my Matrix form, the right moment is the OnActivate trigger of the Matrix box. There are two slight problems I’m still working on: Currently, the code requires a call to the subform’s range setting function upon each OnFormat call, slowing down things dramatically. I created an option to turn off synchronization, and anyways, my PC is not the fastest [;)] A bit more annoying is that clicking on the scroll arrows will not make the main form activated again after the subform was active. You have to click into the text boxes to have the OnActivate trigger called. The OnActivateForm trigger doesn’t help, I already tried this one. So step 2 from above gets bypassed on these occasions. Did I already mention that this forum is great? [8D]