views:

769

answers:

3

I am using a DevExpress TdxMemData in memory TDataSet descendant. While it has Filtered: Boolean and Filter: String properties, it doesn't appear to actually do anything with them automatically, instead relying on the result of the OnFilterRecord event's Accept parameter.

So what I am looking for is a way (maybe it is in TdxMemData or somewhere else in DevExpress's suite of code) to parse the filter text and apply it to the Dataset.

Ideally I would like a way to test an individual row against the filter to see if it matches without filtering it out of the dataset (I want to highlight rows that match the filter).

Example filter string:

((Name = 'Jim') and (Rep > 1000)) or (Rep > 5000)

So there is nested and's and or's. It is actually built by the DevExpress TcxDBFilterControl.

I am really hoping there is something simple I am missing.

Update: I opened a ticket with DevExpress to see if they support any kind of solution. I did find their stock answer that they don't support filtering on TdxMemData.

+2  A: 

I know this is not the answer your looking for, but the TdxMemData dataset does not support filter strings. To use filters either code your own OnFilterRecord event or set ProgrammedFilter to true and populate the FilterList with a list of the records which are filtered (at runtime).

One possibility would be to code your own parser to compare the filter string against the current record in the OnFilterRecord event.

skamradt
That is what I ended up doing!
Jim McKeeth
+2  A: 

You might want to look at replacing the TdxMemData with TkbmMemTable. It's free, works similarly to the DX component, and supports filter strings. Would likely take a lot less time to port over than it would to implement a filter string parser in OnFilterRecord! It'll work with the other DX components without problems.

Tim Sullivan
Yes, I was just downloading it right now. I saw that it supports Filter strings. Seems to be a major failing that DevExpress doesn't support that.
Jim McKeeth
@Jim: But you're not looking to FILTER the data, so that won't work. From your original question: "without filtering it out of the dataset (I want to highlight rows that match the filter).", you're looking to display differently. TkbMemTable is a container; it won't do anything to help you display it differently.
Ken White
+1  A: 

What you're looking for is not filtering the data, but a matter of displaying it differently if it meets a condition. If you're using a TDBGrid to display the data, look into the DrawColumnCell() event on the TDBGrid:

procedure TForm1.dbgrd1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
  DBG: TDBGrid;
begin
  DBG := TDBGrid(Sender);
  // Add any other conditions from your 'filter' here in the next line.
  if (YourData.FieldByName('WHATEVER').AsString = 'Jim') and
     (YourData.FieldByName('REP').AsInteger > 1000) then
    Column.Font.Color := clRed;
  DBG.DefaultDrawColumnCell(Rect, DataCol, Column, State);
end;

Since you're using TdxMemData, you're probably using the DevEx grid, too. It has to have a similar way to do something other than the default drawing; you can use a similar technique there. (I haven't used the DevEx stuff in a few years; current employer doesn't like them, and therefore won't spring for the expense. :-( )

Ken White
That would work, but I want to be able to have the criteria come from the dynamic filter string that is being generated through another source.
Jim McKeeth
How are you getting the criteria from the external source? You could parse it yourself into name/value pairs in a TStringList, for example, and then use those comparisons in the DrawColumnCell() event. No filtering aspect of any produt is going to help, because you're not looking to *filter* at all. You're wanting to display differently based on a criteria. If you give info on how you get the criteria, it would help answer your question better.
Ken White
@Ken, your code sample will color all the rows the same since it evaluates the coloring based on the current record in the data set, and not the one that is currently being colored.
Jim McKeeth
Actually, that's not the case. The record pointer in the database is set prior to the row being drawn (that's how the grid gets the data to display). I use almost identical code to draw rows in different colors based on particular status (eg., medical claims denied draw in red, recouped draw in green, approved draw in normal black).
Ken White