![]() | ![]() Products ![]() ![]() ![]() ![]() |
Home » Technical Support » Elevate Web Builder Technical Support » Support Forums » Elevate Web Builder General » View Thread |
Messages 1 to 7 of 7 total |
![]() |
Fri, Oct 8 2021 2:37 PM | Permanent Link |
Gyro Cosmic | I'm looking for a way to change the font/background of a cell in a TGrid based on a value outside of the cell. For example, I'd like to change the background of a cell based on the cell in the row above it in the grid or a cell to the left in the current row. (I was assuming I'd be able to do this in the OnCellUpdate event but I can't figure out how to get "outside" of the cell in order to look around.)
Has any one been able to or know of a way to do this? Thanks, GCR |
Sun, Oct 17 2021 10:23 PM | Permanent Link |
Richard Harding Wise Nutrition Coaching | Gyro
I had a similar problem. On Tim's suggestion, I created a "Shadow Table". "esStockSummary3" is the shadow table that determines if the row is a "HEADER". The customer stores stock items in a database. Stock items with the same identity are equivalent and can be substituted. The first item that has the same identity is a "header" that needs to be highlighted. The Delphi version of the program did this. The customer considered this essential. It works - the customer is happy. Each cell of the grid calls OnCellUpdate. When there is activity on the grid, there is about 5 or 6 "rounds" of OnCellUpdate called. The first "round" or "group" of OnCellUpdate events does not have ACell.Data defined so you need to check that ACellData is assigned. In the AfterLoad event for the lookup dataset (or the "shadow table"), you need to add Grid1.DataSet.First. This will force another set of OnCellUpdate events that will perform the formatting. Otherwise, the cells will not be formatted until you scroll the items in the grid. Let me know if it does not make any sense. Richard //================================================================================== procedure TfmMenu.GridColumn5CellUpdate(Sender: TObject; ACell: TGridCell); //Called for the first column of the grid var isHeader: boolean; Number: integer; H1: integer; begin if (ACell.Data > '') then begin if grStockItems.DataSet = esStockSummary2 then begin if esStockSummary3.Find(['StockNumber'], [ACell.Data], false, true, true)then begin number := esStockSummary3.Columns['Number'].AsInteger; H1 := esStockSummary3.Columns['H1'].AsInteger; isHeader := (Number = H1); end else begin isHeader := false; end; end else begin isHeader := false; end; if grStockItems.DataSet = esStockSummary then begin ACell.Font.Style.Bold := false; ACell.Font.Color := clBlack; ACell.Background.Fill.Color := clWhiteSmoke; end else if (isHeader) then begin ACell.Font.Style.Bold := true; ACell.Font.Color := clBlack; ACell.Background.Fill.Color := clLightGray; end else begin ACell.Font.Style.Bold := false; ACell.Font.Color := clBlack; ACell.Background.Fill.Color := clWhiteSmoke; end; end; // if assigned end; procedure TfmMenu.GridColumn6CellUpdate(Sender: TObject; ACell: TGridCell); //Called for all columns of the grid except for the first begin if (ACell.index mod 2 = 0) and (SameText(ACell.InterfaceState, NORMAL_STATE_NAME)) then begin ACell.Font.Color := clBlack; ACell.Background.Fill.Color := clWhite; end else if (SameText(ACell.InterfaceState, NORMAL_STATE_NAME)) then begin ACell.Font.Color := clBlack; ACell.Background.Fill.Color := clGhostWhite; end; end; //============================================================================== Attachments: Stock Grid with Headers.jpg |
Wed, Oct 20 2021 5:13 PM | Permanent Link |
Gyro Cosmic | Hi Richard ... thanks for the reply.
In my case this won't work. But I like the approach and I'm going to try the shadow table for another use: to flatten out a row oriented DataTable into columns. I'll switch the shadow table and live table though as I want the flattened table to be associated with the grid. We'll see how it works out. The problem I have, which you don't, is that my ACell.Data wasn't unique and I can't tie it back to a particular row in the grid's datatable. The cell's data may appear in many different rows. After an email from Tim it turns out there is a solution. The ACell.Index value is a relative row but that combined with the Grids RowOffset property can get me to the grid row. Then with a bit of manipulation I can get to other data to figure things out. It's not intuitive but not too bad. I'll work up a generic example and post in in a follow-up so others can see it if they're searching the forum. Again, thanks for the reply. The shadow table method does look useful. --GCR |
Wed, Oct 20 2021 6:30 PM | Permanent Link |
erickengelke | Richard Harding wrote:
> I had a similar problem. On Tim's suggestion, I created a "Shadow Table". "esStockSummary3" is the shadow > table that determines if the row is a "HEADER". I've solved this in a couple of ways on different occaisions. A shadow table works... until someone resorts the rows and they are out of order. A second solution I've used on other occasions is to add an invisible character chr(1), chr(2), etc. to the data field. EWB doesn't print the first 31 of them if I recall correctly, and you can have multiple characters. eg. chr(1)+chr(31) + data. first digit is foreground, second digit is background code. Then in your on cell draw handler, you look at the first few characters and set the font or background appropriately. It would be nice if EWB let gave you a cell's rowID and columnID, or had a Tag integer you could use. But this hack/solution lets you create very complex solutions and nobody knows better. Erick EWB Programming Books and Component Library http://www.erickengelke.com |
Wed, Oct 20 2021 6:36 PM | Permanent Link |
erickengelke | erickengelke wrote:
>A second solution I've used on other occasions is to add an invisible character chr(1), chr(2), etc. to the data >field.EWB doesn't print the first 31 of them if I recall correctly, and you can have multiple characters. It works well if you declare a 'virtual field'. By that I mean, suppose you have a DataSet with a field named Userid, Make a second VUserid of char, then after reading the table, set Userid = chr(1)+chr(31) + data and display VUserid, processing the whole table. Then have an OnCellDraw handler which looks at the first two characters to determine the foreground and background color or italics or whatever. . Good luck, Erick Erick EWB Programming Books and Component Library http://www.erickengelke.com EWB Programming Books and Component Library http://www.erickengelke.com |
Thu, Oct 21 2021 7:56 AM | Permanent Link |
Gyro Cosmic | Based on Tim's comments (via email) here's the solution it looks like I'm going to use.
Within the OnCellUpdate event handler You can get a TGrid's database row number by using the ACell.Index value. This returns the relative ROW number from the first row being shown in the grid. The index value is not a column number as I'd first thought. To get the absolute row number you can use the following: rowNo := TGridColumn(Sender).ParentGrid.RowOffset + ACell.Index + 1; You can get column information by TGridColumn(Sender).TheWantedProperty. Using this here's sample code to set a cell's background color based on data in the same dataset row. procedure TMyForm.colMyCellUpdate(Sender: TObject; ACell: TGridCell); var gridRowNo: Integer; // the DataTable row the grid is looking at. ds: TDataSet; begin // This is where the grid is looking into the DataTable. // Not necessarily the active DataTable row. gridRowNo := TGridColumn(Sender).ParentGrid.RowOffset + ACell.Index + 1; ds := TGrid(TGridColumn(Sender).ParentGrid).DataSet; // the grid's dataset ds.SaveBookmark; try ds.RowNo := gridRowNo; // make sure you're on the expected row! // put your test/evaluation and cell formatting code here: if ds.Columns['AColumn'].AsBoolean then begin ACell.Background.Fill.Color := clRed; end; finally ds.GotoBookmark; end; end; And here's a more complex example for checking a value from the previous row. procedure TMyForm.colMyCellUpdate(Sender: TObject; ACell: TGridCell); var gridRowNo: Integer; // the DataTable row the grid is looking at. ds: TDataSet; currRowValue, aboveRowValue: string; begin // is appropriate, exit if the cell hasn't been filled yet. // (event may be triggered before data is populated) if ACell.Data = '' then exit; // This is where the grid is looking into the DataTable. // Not necessarily the active DataTable row. gridRowNo := TGridColumn(Sender).ParentGrid.RowOffset + ACell.Index + 1; if gridRowNo = 1 then exit; // skip if checking "above row" and on first row ds := TGrid(TGridColumn(Sender).ParentGrid).DataSet; ds.SaveBookmark; try ds.RowNo := gridRowNo-1; // move to the above row aboveRowValue := ds.Columns['AColumn'].AsString; ds.RowNo := gridRowNo; // move to the current row currRowValue := ds.Columns['AColumn'].AsString;; if currRowValue = aboveRowValue then begin ACell.Background.Fill.Color := clRed; end; finally ds.GotoBookmark; end; end; Note that there are a number of edge cases you may have to code around. For example if you allow grid inserts or column sorting. |
Tue, Mar 14 2023 11:12 AM | Permanent Link |
erickengelke | Gyro Cosmic wrote:
>Within the OnCellUpdate event handler You can get a TGrid's database row number by using the >ACell.Index value. This returns the relative ROW number from the first row being shown in the grid. The >index value is not a column number as I'd first thought. To get the absolute row number you can use >the following: > >rowNo := TGridColumn(Sender).ParentGrid.RowOffset + ACell.Index + 1; > ... > Note that there are a number of edge cases you may have to code around. > For example if you allow grid inserts or column sorting. It would be a real benefit to programmers if ACell included a RowID or similar so that all edge cases could be handled with a simple line of code. Thanks Erick EWB Programming Books and Component Library http://www.erickengelke.com |
This web page was last updated on Thursday, March 23, 2023 at 02:07 AM | Privacy Policy![]() © 2023 Elevate Software, Inc. All Rights Reserved Questions or comments ? ![]() |