OK,
So I'm still working with the ReportView control and am wondering if there is a way to store which column has been sorted so that this can be reapplied if I update the contents of the control?
When I update the contents of the control, sorting defaults to the first column and the user has to re-click the column header to restore sort.
As I have a number of filtering options for the control contents which update its contents, I was hoping there was a way for me to store which column was sorted and then apply that sort again after updating. Barring that, can I tell in the dialog callback which header was clicked so that I can store that, then pre-sort the array accordingly before updating the control? From what I can see, I cannot tell which header was clicked. I'm using the following TechDB derived code to handle clicks to headers:
;Determine Current sorting style: ascending or descending
style = dialogControlState( requestInfo_Handle, "ReportView_RequestList", DCSTATE_QUERYSTYLE, "" )
; If no style is assigned assume ascending
if style == 0 then style = DCSTYLE_SORTASC
; Toggle Sort Order
if style == DCSTYLE_SORTDESC
dialogControlState( requestInfo_Handle, "ReportView_RequestList", DCSTATE_REMOVESTYLE, DCSTYLE_SORTDESC )
dialogControlState( requestInfo_Handle, "ReportView_RequestList", DCSTATE_ADDSTYLE, DCSTYLE_SORTASC )
elseif style == DCSTYLE_SORTASC
dialogControlState( requestInfo_Handle, "ReportView_RequestList", DCSTATE_REMOVESTYLE, DCSTYLE_SORTASC )
dialogControlState( requestInfo_Handle, "ReportView_RequestList", DCSTATE_ADDSTYLE, DCSTYLE_SORTDESC )
endif
Otherwise, I suppose I could supply a "Sort By ... " right click menu option with sub-menu items for the columns. This would allow me to determine which column to sort by and store it, then read the contents of the control, sort the array by the appropriate column and update the control ...
But is there a better way?
Thanks!
Micheal
The one based column number of the clicked column is passed to the callback UDF/UDS in the callback's fifth parameter. The event is fired before the indicated column is sorted so the sort direction can be controlled by setting or changing the sort direction style of the control during the callback. Sorting is effectively cancelled by removing both sorting related styles from the control.
Case MSG_RVHEADER ; ID "ReportView_1" rvVariable1
Message('Column Clicked is',MyDialog_ChangeInfo) ; Callback's fifth parameter
;Determine Current sorting style: ascending or descending
style = DialogControlState( MyDialog_Handle, "ReportView_1", DCSTATE_QUERYSTYLE, "")
Message('Sort Style',style) ;
The MyDialog_ChangeInfo & Style variables contain the information you are looking for.
Thanks very much for that information Deana - very helpful, as always. I didn't know about that
Is there a way to specify a column to sort a ReportView on programmatically, based on the index of the column? Or is that something I should be prepared to implement via ArraySort()?
Regards,
Micheal
Quote from: mhall on April 04, 2014, 07:35:11 PM
Thanks very much for that information Deana - very helpful, as always. I didn't know about that
Is there a way to specify a column to sort a ReportView on programmatically, based on the index of the column? Or is that something I should be prepared to implement via ArraySort()?
Regards,
Micheal
Michael,
Yes you got it. the ArraySort function can be used to sort a specific column. Keep in mind that you will need to subtract one from the clicked column, because the clicked column is one based and arrays are zero based.
Thanks Deana,
I did go ahead and implement that according to your suggestions and it's working quite well.
Regards,
Micheal
If you simply want to sort your data on a specific column when the column's header is clicked, you don't need to use ArraySort. You just need to turn on the sorting style when the column header click event for the column is passed to your dialog callback and make sure that it is off for all other column's header click events.
The only time you need to use ArraySort is when you want to load data into the control for the first time and you want it sorted by some column other than the first. After that it is more efficient to do as described above rather than constantly reloading the control with sorted data.
Hi Tony,
In the end, I ended up implemented sort using ArraySort() simply because I often update the contents of the control ( filter it, edit a cell value, change column order, etc. ) and need to restore a previously set sort when I update it.
It's my understanding that, under those circumstances, I need to supply a presorted array to the control in order to have my data presented the way I want. Is my understanding of that correct?
Regards,
~Micheal
It depends on what you mean by 'edit'. The control will preserve the sort order based on the current sort column when you add rows to or remove them from the control when one of the sorting styles is enabled. If you mean edit the first column value of a row manually using the edit box provided by the control's edit style and the first column is your sort column then you would need to resort the column by either clicking the header or performing a manual sort using ArraySort.
The way I implemented "edit" is with a function that accepts the array contents of the reportview, the value of the first cell in the target row as an id, the column name and a new value. I then iterate through the array until I find the matching row, set the value and update the contents of the reportview. Obviously it's not edit-in-place, but it works for my needs at the moment.
It does mean a somewhat clumsy replacement of the entire contents of the reportView and then scroll the control to get the edited item back into view (it'd nice to be able to reset the scroll position exactly).
Regards,
Micheal
DialogControlSet Option 10 can be used to scroll a REPORTVIEW control row into view. Use the function's set-info (fourth) parameter to indicate the first column text of the row to scroll into view.
Hi Deana,
I am indeed using that option. However, it's only "scroll into view" ... I haven't seen a DialogControl code such as DC_ITEMSCROLLPOS for saving the current scroll position of the reportView so that it can be restored exactly. This causes the selected item to "jump" (usually down a bit ) in the display after updating the reportView since the item is simply being scrolled into view. It makes for a somewhat choppy user experience.
Not a dealbreaker, just ... abrupt. :)
Regards,
Micheal
Quote from: mhall on April 08, 2014, 06:30:38 PM
Hi Deana,
I am indeed using that option. However, it's only "scroll into view" ... I haven't seen a DialogControl code such as DC_ITEMSCROLLPOS for saving the current scroll position of the reportView so that it can be restored exactly. This causes the selected item to "jump" (usually down a bit ) in the display after updating the reportView since the item is simply being scrolled into view. It makes for a somewhat choppy user experience.
Not a dealbreaker, just ... abrupt. :)
Regards,
Micheal
Yes the Dialog does not provide a scroll position. How about using the DialogControlGet option 6 to save the selected row(s) of a REPORTVIEW control. Or is that what you are current doing that causes the "jump"?
If it is worth the hassle I posted a ComControl extender a while back which allows you to do a bit more with ReportViews. Might solve your problem and help with some of the other stuff you are doing.
Jim
Jim,
The Dialog Control Extender you created is located here: http://techsupt.winbatch.com/webcgi/webbatch.exe?techsupt/tsleft.web+WIL~Extenders/_Third~Party~Extenders/Dialog~Controls~Extender+Dialog~Controls~Extender.txt
Thanks.
Jim
Quote from: mhall on April 08, 2014, 03:32:51 PM
The way I implemented "edit" is with a function that accepts the array contents of the reportview, the value of the first cell in the target row as an id, the column name and a new value. I then iterate through the array until I find the matching row, set the value and update the contents of the reportview. Obviously it's not edit-in-place, but it works for my needs at the moment.
It does mean a somewhat clumsy replacement of the entire contents of the reportView and then scroll the control to get the edited item back into view (it'd nice to be able to reset the scroll position exactly).
If I understand your description correctly that form of editing can be done without reloading the contents of the control.
Hi Deana,
Yes, I'm using control code 6 to pull the contents of the reportView into an array, modifying it and then refreshing the contents of the view. That's the only way to change the contents, if I want to change anything other than the first column, correct?
Jim,
Thanks very much for the reminder, I'll be sure to check that out! (And thanks for posting the link Deana!)
Regards,
Micheal
Tony,
Really? I'm updating the contents of a cell row other than the first column. From the docs, I was under the impression that wasn't possible ... I'll fiddle some more but it'll be a few days. :)
~Micheal
It can be done but if you are performing a search on any column other than the first, you would still need to perform the dump so you could use the ArraySearch function to find the row to target. However, if you are getting the targeted row via user input or a first column search, you don't need to dump the contents to an array.
To modify one or more columns of the targeted row, you can extract the row, replace any column values of your choosing in the extracted row's array, delete the existing row, and add the modified row back into the control. Assuming your first column values are unique, this takes three lines in your script plus whatever column modification lines you are already using. If your first row values are not unique, you would need to do a little more work in your script.
To say the least this is approach is not elegant but it can have performance advantages over dumping and reloading the entire contents of the control when the data set is sufficiently large. However, if your existing approach is working for you, there is no reason to change it. Just suggesting that there are other ways to perform the task.
Thanks Tony.
I had wondered about that approach - I'll try it out. Is sort updated/maintained in that case - even when not sorting on the first column? So the new row returns to the same location?
I'm out of town for a bit, but will try it out when I return.
Regards,
Micheal
Here is a very simple example demonstrating one way to perform in place editing of an off-column's content. Have no idea how applicable it is to your situation.
;;;;;;;;;;;;;;;;;;;;;;;
;; Demonstrates simple RV control sub item editing technique.
InitDialogConstants() ; Initialize Dialog Constants (need only be done once usually)
aSample = ArrayFromStr("1abcdefghijklmnopqrstuvwxyz")
ArrayRedim(aSample, -1, 2)
aSample[0,0] = "Letter"
aSample[0,1] = "Number"
for i = 1 to ArrInfo(aSample, 1) - 1
aSample[i, 1] = i
next
#DefineSubroutine EditCallbackProc(Edit_Handle,Edit_Message,Edit_Name,Edit_EventInfo,Edit_ChangeInfo)
switch Edit_Message
case MSG_INIT
DialogProcOptions(Edit_Handle,MSG_RVITEMSELROW,@TRUE)
return(RET_DO_DEFAULT)
case MSG_RVITEMSELROW ; "ReportView_1"
aTarget = DialogControlGet(Edit_Handle, "ReportView_1", DC_RVMATCHCOL, Edit_ChangeInfo)
DialogControlSet(Edit_Handle, "ReportView_1", DC_ITEMBOXREMOVE, Edit_ChangeInfo)
aTarget[0,1] = "Selected"
DialogControlSet(Edit_Handle, "ReportView_1", DC_ITEMBOXADD, aTarget)
return(RET_DO_DEFAULT)
endswitch
return(RET_DO_DEFAULT)
#EndSubroutine
ColEditFormat=`WWWDLGED,6.2`
ColEditCaption=`Simple Column Editing`
ColEditX=882
ColEditY=085
ColEditWidth=302
ColEditHeight=206
ColEditNumControls=002
ColEditProcedure=`EditCallbackProc`
ColEditFont=`DEFAULT`
ColEditTextColor=`DEFAULT`
ColEditBackground=`DEFAULT,DEFAULT`
ColEditConfig=0
ColEdit001=`124,186,033,011,PUSHBUTTON,"PushButton_OK",DEFAULT,"OK",1,10,32,DEFAULT,DEFAULT,DEFAULT`
ColEdit002=`006,007,282,171,REPORTVIEW,"ReportView_1",aSample,DEFAULT,DEFAULT,20,32505856,DEFAULT,DEFAULT,DEFAULT`
ButtonPushed=Dialog("ColEdit")
Hi Tony,
Just wanted to say that method works well, once I update the sort of the reportView and highlight/scroll to the replaced item.
Thanks for the help,
Micheal