Subject | Re: [IBO] BufferFieldByName & Co. |
---|---|
Author | Mark Pickersgill |
Post date | 2005-05-08T12:16:48Z |
Jason,
Keeping running totals for grids/line entry data is quite a common
request from users and also useful.
If I understand Eyal correctly, a scenario may be entering in line items
for an invoice, or entering in payment dissections for a cheque and
wanting to keep a running total and check against the entered cheque amount.
Eyal, I have found that the only way to implement such a running total
is to use the BufferXXXX properties and methods. Something along the
lines of (pseudo Delphi):
procedure GetTotals;
var
total : Currency;
bm : string;
begin
bm := BufferBookmark;
BufferFirst
total := 0.0;
while not BufferEof do begin
total := total + BufferFieldByName('amount').AsCurrency;
BufferNext;
end;
BufferBookmark := bm;
// Display the totals on some non-data-aware control
end;
This can then be called from a DataSource's OnDataChange event, and
probably the initialization of the form or record entry (to get the 0
values). The tricky bit is hooking up the display of the totals.
It gets even trickier when you need to display instant row total (eg
#items * amount) AND an instant sum of each row (Total Items, Total
Amount, Grand Total) whenever the user changes a value in one of the
edit boxes. It can be a bit much for users to understand that they have
to move to another edit box before their data entry changes flow
through...and then move back again if the entry needs refining. Two
extra keystrokes when it can be done in 0 doesn't cut it for some
data-entry needs.
When this is needed, you have to hook each of the OnChange events of the
edit controls and call your totaling function, BUT, you need to use the
values from the edit boxes for the current row, as the BufferFields seem
to get updated AFTER the OnChange event is called. This also means that
you have to ignore the current row in the BufferField list.
Jason, it might be useful if there was another kind of calculated field
that was more of a Calcuated Column, and you could do the above totals
in an OnCalculateColumn method. eg
IB_Query.CalculatedColumns.Add('ITEM_TOTAL=DECIMAL(18,2)');
procedure IB_QueryOnCalculateColumn
begin
// do totaling for the ITEM_TOTAL field
end;
The all you would have to do is hook up the ITEM_TOTAL field to an
IB_Edit box and the display would take care of itself.
cheers
Mark
Jason Wharton wrote:
Keeping running totals for grids/line entry data is quite a common
request from users and also useful.
If I understand Eyal correctly, a scenario may be entering in line items
for an invoice, or entering in payment dissections for a cheque and
wanting to keep a running total and check against the entered cheque amount.
Eyal, I have found that the only way to implement such a running total
is to use the BufferXXXX properties and methods. Something along the
lines of (pseudo Delphi):
procedure GetTotals;
var
total : Currency;
bm : string;
begin
bm := BufferBookmark;
BufferFirst
total := 0.0;
while not BufferEof do begin
total := total + BufferFieldByName('amount').AsCurrency;
BufferNext;
end;
BufferBookmark := bm;
// Display the totals on some non-data-aware control
end;
This can then be called from a DataSource's OnDataChange event, and
probably the initialization of the form or record entry (to get the 0
values). The tricky bit is hooking up the display of the totals.
It gets even trickier when you need to display instant row total (eg
#items * amount) AND an instant sum of each row (Total Items, Total
Amount, Grand Total) whenever the user changes a value in one of the
edit boxes. It can be a bit much for users to understand that they have
to move to another edit box before their data entry changes flow
through...and then move back again if the entry needs refining. Two
extra keystrokes when it can be done in 0 doesn't cut it for some
data-entry needs.
When this is needed, you have to hook each of the OnChange events of the
edit controls and call your totaling function, BUT, you need to use the
values from the edit boxes for the current row, as the BufferFields seem
to get updated AFTER the OnChange event is called. This also means that
you have to ignore the current row in the BufferField list.
Jason, it might be useful if there was another kind of calculated field
that was more of a Calcuated Column, and you could do the above totals
in an OnCalculateColumn method. eg
IB_Query.CalculatedColumns.Add('ITEM_TOTAL=DECIMAL(18,2)');
procedure IB_QueryOnCalculateColumn
begin
// do totaling for the ITEM_TOTAL field
end;
The all you would have to do is hook up the ITEM_TOTAL field to an
IB_Edit box and the display would take care of itself.
cheers
Mark
Jason Wharton wrote:
>Yes, you can interate through the buffer using all the BufferXXXX methods
>and properties. This has been touched on heavily in the archives.
>
>As for your other issues of keeping a running total in a grid, I don't know
>what to suggest. It sounds to me like a very awkward element in your user
>interface design. It might benefit us all if you gave us a view of your
>project from a little higher up and perhaps we can give you other ideas to
>try. Something bothers me about what I am hearing so far.
>
>Jason Wharton
>
>
>
>
>>-----Original Message-----
>>From: IBObjects@yahoogroups.com [mailto:IBObjects@yahoogroups.com]On
>>Behalf Of Eyal
>>Sent: Wednesday, April 27, 2005 5:02 PM
>>To: IBObjects@yahoogroups.com
>>Subject: Re: [IBO] BufferFieldByName & Co.
>>
>>
>>
>>
>>Jason Wharton wrote:
>>
>>
>>
>>>>3. If not, is there any other way to make the update pass
>>>>through to the dataset (so data aware controls will see it),
>>>>but still without triggering a server update?
>>>>
>>>>
>>>Please clarify what you mean here. I'm not clear on what
>>>benefit you are looking for.
>>>
>>>
>>Jason -
>>
>>Thanks and you're right that it's better if I explain what I'm trying
>>to achieve rather than shoot (questions) in the dark.
>>
>>Here is the main problem:
>>
>>I need to display a running total in a grid. So far I couldn't find
>>any way to read the rows into a dataset, then calculate the running
>>total and store it in a field that, so the grid can display the
>>running total column like any other column.
>>
>>I thought that the buffer methods can serve as a back door to change
>>the dataset without triggering the overhead of dataset validations
>>and/or server SQL.
>>
>>A lesser problem:
>>
>>I need to let the user select rows in the grid and display some
>>statistics for the selected rows (the stats are "live" as the user
>>selects and de-selects rows). So I try something like this:
>>- DisableControls.
>>- Save the current active row.
>>- Iterate the active row over the selected (bookmarked) rows.
>>- Restore the active row.
>>- EnableControls.
>>
>>However the grid that I use (EhLib) detects the change of the active
>>row and re-adjusts the grid so the active row is in the center. This
>>is very distrubing visually.
>>
>>I hoped that the buffer methods can access the selected rows without
>>disturbing the "official" active row of the dataset, and so I can
>>avoid the visual disturbance.
>>
>>Any ideas?
>>
>>Thanks,
>>
>>Eyal.
>>
>>