Monday, March 16, 2026

Continuing the migration, supplemental

Today I will write about something that I meant to include in the previous post but forgot: when does one need a TFDMemTable (hereinafter, TMT)? After all, one can define a TFDQuery, include an SQL query to retrieve data from the database, connect the query to a datasource and thence to a grid: the data will be displayed. Also, in a simple 'edit' form, there's no need for a TMT.

I have identified two cases when a TMT is required:

  1. If the grid that displays the data has an OnTitleClick event - this allows the user to sort the data.
  2. If the form allows the addition or deletion of data.
According to CoPilot, a TFDQuery doesn't have indexes whereas a TMT does. So when I migrate units with a grid, I first check to see whether the grid has an OnTitleClick event; if so, I know that I need to a TMT. Incidentally, there is a new flag that has to be set in the grid's options - OnTitleClick. This flag didn't exist in Delphi 7, and I came across it in one of the first units that I migrated. I was clicking on the title bar but the event did not fire ... because this new flag was not set.

If the grid does not have an OnTitleClick event, I check whether the form has a qGetOne query - this means that data has to be added - or a qDelete query. In the case of qGetOne, previously I used to iterate over the fields of the query and add them one by one to the clientdataset. A TMT has a new method, AppendRecord, that allows for the data to be added in one statement (never mind that beneath the hood, the data is still being added field by field). I have used this everywhere, apart from one or two special cases where AppendRecord seemed not to be appropriate.

The TMT comes 'naked' without fields. Here is my methodology for adding them (this may not be optimal). First I check that the query can be opened - it frequently happens that fields are defined automatically as ftString when they should be defined as ftWideString. So I fix all these before I even start with the TMT. When the query is defined properly, I open the 'fielddefs' property of the TMT and begin to add fields. The size of the fields is very important when the field in the query is a ftWideString; the default size is 20 but this should be changed to match the size of the query's field. When all the fields have been defined in the 'fielddefs' property, I then open the TMT's fields editor. This will be empty so I press on 'add all fields' and the fields that I added in the 'fielddefs' property now become persistent fields. I then iterate over the fields in the query, copying their displaynames to the TMT's fields, and finally I delete all the persistent fields of the query. I do this in order to highlight any use in the code of these persistent fields - it has happened that I received bizarre results when debugging and I discovered that these came from usage of the query's persistent fields. As the grid displays data coming from the TMT and not the query, progressing through the TMT gives different data in the persistent fields, whereas the query's persistent fields stay the same.

I wrote about changing column widths in a grid and saving them. I came across a very interesting problem with this: every form has a minimum width that is hard coded. I changed the column widths of one grid so much that the new width was less than the minimum width; as a result, there was a huge space on the left hand side of the grid before data appeared. How could I fix this? I made two additions: I converted the procedure that saves the column widths into a function that returns the total width with an extra 72 pixels for the scroll bar. I then wrote a procedure in the ancestor form that saves this new width. When the form is opened, this new width is compared to the minimum width, and if it is less, then the minimum width becomes this new width. Slightly messy but it works. Part of the problem is that the code for saving and restoring column widths is in a different unit from the ancestor form. Maybe I should move this code to the ancestor form - but not every form descends from this ancestor and maybe I would want to save column widths on such a form (unlikely).



This day in blog history:

Blog #Date TitleTags
11916/03/2008Back to bloggingOffice automation, Meta-blogging
12016/03/2008Chava AlbersteinChava Alberstein
46416/03/2012Rubber duck debuggingProgramming
148016/03/2022My first year as a Londoner, part 1 - being a studentPersonal, 1975, 1974
159316/03/2023I contain multitudesFood science, Non-fiction books

No comments: