1. Dan Cooperstock
  2. PowerBuilder
  3. Tuesday, 21 September 2021 16:54 PM UTC

I thought this would be easy, but I'm stuck trying to find code to scroll a given row to become the top row of a DataWindow. I can get the desired row into the display with ScrollToRow(row) but nothing I have tried (including some proposed solutions at https://answers.sap.com/questions/12112836/how-to-view-a-specific-row-as-the-first-row-on-pag.html) has worked.

Once suggestion was to use dw.Scroll(n) to scroll the window up, but it doesn't seem to actually do that. The docs for the DW Scroll method actually seem really confused (this is PB 2019) saying you call it on a DW, then saying it "Scrolls the edit control of a DataWindow a specified number of lines up or down" (what edit control)? And the example code at the bottom of that Help topic calls it on an MLE, not a DW!

You can't use further calls to ScrollToRow() on rows that are out of view, because that tends to scroll the passed-in row to the middle of the visible rows, not to a specific desired position.

I also tried ScrollNextRow(), but if you call it when the current row is the last row on the page (dw.Object.DataWindow.LastRowOnPage), it does nothing. If you call it again right after that, the row below that last row currently displayed  moves up to become the first row displayed, rather than scrolling up by one row!

So I really can't see that there's any DW API function that I haven't tried yet that ought to do this properly. Any bright ideas?

Thanks.

Dan Cooperstock Accepted Answer Pending Moderation
  1. Wednesday, 22 September 2021 14:15 PM UTC
  2. PowerBuilder
  3. # 1

OK, I have figured out when ScrollNextRow() fails (by sometimes jumping instead of scrolling one row): it seems to be when there is a group break with a group header. I have submitted a small sample like that to Appeon as a bug: https://www.appeon.com/standardsupport/search/view?id=7282

Comment
There are no comments made yet.
Benjamin Gaesslein Accepted Answer Pending Moderation
  1. Wednesday, 22 September 2021 08:47 AM UTC
  2. PowerBuilder
  3. # 2

Hi Dan,

scrollPerRow = Int(scrollMax / dw.RowCount())

^ this calculation is actually incorrect. While VerticalScrollMaximum is indeed the maximum scroll position, it is not usually possible to scroll so far that the last row is also the first row on page. Thus, the divisor will be off by the number of rows displayed on the last possible page of the DW. The result might be just accurate enough if you have a large enough number of rows in your DW but on low rowcounts it will be *way* off.
Now we could calculate the scroll value per row this way but this is much easier to solve because the scroll value per row is actually equivalent to DataWindow.Detail.Height.

Hence, this code should do the trick:

long scrollMax
long detailHeight

scrollMax = Integer( dw.Describe( "DataWindow.VerticalScrollMaximum" ) )
detailHeight = Integer( dw.Describe ( "DataWindow.Detail.Height" ) )
dw.Modify( "DataWindow.VerticalScrollPosition='" + String( min( scrollMax , ( row - 1 ) * detailHeight ) ) + "'" )

The check for values above scrollMax is optional. From my experience, trying to set VerticalScrollPosition to anything above the VerticalScrollMaximum will just set it to the maximum instead. But safety first, I guess. :) 

But if you'd like, you could reduce the whole thing to a one-liner:

dw.Modify( "DataWindow.VerticalScrollPosition='" + String( ( row - 1 ) * Integer( dw.Object.DataWindow.Detail.Height ) ) + "'" )

This will obviously fall apart if there's any dynamic resizing or AutoHeight going on, though.

Comment
  1. Dan Cooperstock
  2. Wednesday, 22 September 2021 14:14 PM UTC
Thanks, it definitely seems you are right. However, I have group breaks with a group header so I can't just do that calculation. Instead I kept my basic logic I posted with changing the VerticalScrollPosition by one "row" at a time, but used your suggestion (DataWindow.Detail.Height) instead of my division. Seems to be correct!
  1. Helpful
  1. Benjamin Gaesslein
  2. Wednesday, 22 September 2021 14:21 PM UTC
Yeah, group breaks will complicate things. You could probably cook something up using FindGroupChange() and accommodating for the group headers but the row-by-row approach works just fine.
  1. Helpful
There are no comments made yet.
Ronnie Po Accepted Answer Pending Moderation
  1. Tuesday, 21 September 2021 20:11 PM UTC
  2. PowerBuilder
  3. # 3

Hi Dan,

Here's a workaround that I've used:

 

// Assume that ll_desiredRow is the row you want to appear at the top of the DW control

long ll_row

// First get the row on the page to minimize the number of iterations of the loop below

dw_list.scrollToRow(ll_desiredRow)

ll_row = long(dw_list.describe("datawindow.firstRowOnPage"))

DO WHILE ll_row <> ll_desiredRow

  dw_list.scrollNextRow()

  ll_row = long(dw_list.describe("datawindow.firstRowOnPage"))

LOOP

 

Comment
  1. Dan Cooperstock
  2. Tuesday, 21 September 2021 20:20 PM UTC
Thanks Ronnie but as I mentioned elsewhere in this post, when I tried basically that code, the 2nd time the loop called ScrollNextRow(), instead of scrolling it up by one row, it jumped the row that had been just off-screen below the last displayed row up to be the center displayed row, rather than actually scrolling the DW up by just one row. So that method was unusable, because it actually moved my desired row up above the first row on the screen! And because that problem means that ll_row in your code never equals ll_desiredRow, it's an infinite loop too. :(
  1. Helpful
There are no comments made yet.
Dan Cooperstock Accepted Answer Pending Moderation
  1. Tuesday, 21 September 2021 20:02 PM UTC
  2. PowerBuilder
  3. # 4

OK finally came up with a solution after a hint from Mike Searer offline (thanks!) and using something I had been reluctant to use because it seemed so unconnected from the actual rows:

// make row number "row" the first shown row in the DW, if possible
DWObject dwo
long scrollPos, scrollMax, scrollPerRow, firstRow, i

dwo = dw.Object
dw.ScrollToRow(row)

scrollPos = Integer(dwo.DataWindow.VerticalScrollPosition)
scrollMax = Integer(dwo.DataWindow.VerticalScrollMaximum)
scrollPerRow = Int(scrollMax / dw.RowCount())
firstRow = Integer(dwo.DataWindow.FirstRowOnPage)

for i = firstRow to row + 1
    scrollPos += scrollPerRow
    if scrollPos < 1 then EXIT
    dwo.DataWindow.VerticalScrollPosition = String(scrollPos)
    // make sure we haven't gone too far
    if row < Integer(dwo.DataWindow.FirstRowOnPage) then
        dwo.DataWindow.VerticalScrollPosition = String(scrollPos - scrollPerRow)
        EXIT
    end if
next

 

Comment
There are no comments made yet.
Chris Pollach @Appeon Accepted Answer Pending Moderation
  1. Tuesday, 21 September 2021 18:54 PM UTC
  2. PowerBuilder
  3. # 5

Hi Dan;

  Have you tried ... for example, say the first row on the last page, as follows;

  • String ls_row
  • DC.ScrollToRow ( DC.RowCount() )
  • ls_row = DC.Describe("DataWindow.FirstRowOnPage")
  • DC.ScrollToRow ( Long (ls_row) )

Regards ... Chris

Comment
  1. Dan Cooperstock
  2. Tuesday, 21 September 2021 19:01 PM UTC
Chris, surely that last ScrollToRow in your example above would do nothing, since that row is already visible? So I'm not sure how any version of that code would help me get (say) row 100 out of 200 to be the first row shown in a 16-row DW area. That's the type of problem I'm trying to solve. I can get it to be visible somewhere in those 16 rows, but not to be the first row.
  1. Helpful
  1. Chris Pollach @Appeon
  2. Tuesday, 21 September 2021 20:03 PM UTC
Hi Dan ... I just tested this code and it works perfectly for me ... scrolls & highlights the 1st row on the last page. ;-)



Case "cb_last"

String ls_row

THIS.ScrollToRow ( THIS.RowCount() )

ls_row = THIS.Describe("DataWindow.FirstRowOnPage")

THIS.ScrollToRow ( Long (ls_row) )

  1. Helpful 1
There are no comments made yet.
Roland Smith Accepted Answer Pending Moderation
  1. Tuesday, 21 September 2021 17:07 PM UTC
  2. PowerBuilder
  3. # 6

If you know how many rows fit in the control, you could calculate the row number to pass to ScrollToRow.

Comment
  1. Roland Smith
  2. Tuesday, 21 September 2021 17:29 PM UTC
I think I ran into this a long time ago. If I am remembering correctly, I scrolled to the last row and then scrolled to the row that I wanted to be first shown.
  1. Helpful
  1. Dan Cooperstock
  2. Tuesday, 21 September 2021 18:06 PM UTC
OK I tried that and now the ScrollToRow on the calculated row (my desired row plus half the number of rows in the display) is NOT scrolling to the middle of the display, but rather towards the end of the display! So my desired row is still a number of rows from the top. Any further ideas? There just doesn't seem to be much control of all this in the API!
  1. Helpful
  1. Dan Cooperstock
  2. Tuesday, 21 September 2021 18:46 PM UTC
Hi Roland. I also tried your idea of scrolling to the last row first (before I saw your further comment about it), that didn't change anything.
  1. Helpful
There are no comments made yet.
  • Page :
  • 1


There are no replies made for this question yet.
However, you are not allowed to reply to this question.