Is there a way to use the Live Binding Designer to concatenate 2 database fields to a component?
For example I have a MemTable for client, I want to concatenate the FirstName and LastName (fullname) to a label.
If there is a way to do that, I understand that the binding will be in one direction only (Database fields --> ComponentProperty).
The easyest way to do with LiveBinding, is to use the CustomFormat property of the LinkFillControlToField :
Just use this format text as the example is the question:
Self.Owner.FirstName.text + " " + Self.Owner.LastName.text
For something simple like this...you can use the AfterScroll Event of your Dataset
if Dataset.Active and (Dataset.RecordCount > 0) then
label1.Caption :=Dataset.FieldByName('FirstName').AsString + ' ' + Dataset.FieldByName('LastName').AsString;
Related
There are three records in clientdataset
123+%1
123+%
123+&
I use the filter
DataSet.Filter := ' Column LIKE ''%123+%'' '
And the result show three records.
How can i filter to get item 1, 2 items instead of the third one?
Since "%" in SQL is usually used as a wildcard character, you will have to escape it if you want to search for the character itself.
So
DataSet.Filter := ' Column LIKE ''%123+\%%''
should do it.
The first "\%" escaped % means, it will be looking for the character itself, and the second one after that, that anything else ( in your example the "1") can come after that.
I know how to pull information from ADO query based on a unique ID. Is there a way to do that with a memtable, but with no unique ID to establish the record to pull for edit. Can you use just the currently selected item in the memtable?
Edit:
It is a Tkbmmemtable it is a third part component, but I assume it works similar to whatever is embedded in Delphi. Long story short, there is a form that comes up that receives data from the user. Everytime you hit ok it adds it to a tkbmmemtable (which is displayed to the user in a grid) and is stored there until you the user hits "write to database" and then it is written to a backend with a unique ID. I am trying to enable the ability to double click on a record in the grid and have a screen come up where they can edit the data and then post it back to the memtable.
Can you use just the currently selected item in the memtable?
The short answer is "Yes", as #KenWhite has incisively explained.
The reason the answer is "Yes" is because of the way TDataSet and its descendants like TKbmMemtable work.
Is you probably know, the defined behaviour of TDataSet et al is that it models an internal "cursor" which points to exactly one record in the dataset, and that record is treated by TDataSet and all the db-aware controls as the "active" record: you navigate the dataset by moving the logical cursor by methods such as First, Last, Next, Locate etc.
Internally, when a TDataSet is open, it has an array of "buffers", which are pointers to dynamically allocated memory blocks which each store the data of one of a contiguous range of the records in the dataset. The number of buffers is fixed when the dataset is opened and is determined by what db-aware components are connected to the dataset; usually there are a sufficient number of them to hold the rows in a TDbGrid.
TDataSet has a method (function) ActiveBuffer which is defined in DB.Pas as
function TDataSet.ActiveBuffer: PChar;
begin
Result := FBuffers[FActiveRecord];
end;
Any editing operation on the dataset's data operates on the record data in the ActiveBuffer It is identified simply by the pointer which TDataSet.ActiveBuffer returns. That's all that's needed and is why editing operations on a record in an in-memory dataset work fine without any ID/PK/SequenceNumber or whatever field.
That's it, really.
the logic would be :
1. pull the data using adoquery
2. put the data to memtable
3. user will edit values
4. save changes
treat your memtable as container. so when saving to database your code will be more like this :
var
script : string;
begin
if insert then
begin
script :=
'insert into table(c1, c2, c3) values (' +
QuotedStr(memTable.FieldByName('c1').AsString) + ',' +
QuotedStr(memTable.FieldByName('c1').AsString) + ',' +
QuotedStr(memTable.FieldByName('c1').AsString) + ' ' +
')';
end
else
begin
script :=
'update table set ' +
'c1='+ QuotedStr(memTable.FieldByName('c1').AsString) + ',' +
'c1='+ QuotedStr(memTable.FieldByName('c1').AsString) + ',' +
'c1='+ QuotedStr(memTable.FieldByName('c1').AsString) + ',' +
'where id = ' + IntToStr(memTable.FieldByName('id').AsInteger);
end;
// adoQuery.Execute(script);
end;
Is it possible to filter on other properties in the datasource attached to a combobox?
For example, I have combobox with a list of customers, I want to be able to search on the customer name, First Name, Last Name and email.
It is posible if you concatenate the fields you want to search in one.
ie: concatField = FirstName + " " + LastName + " " + email.
You could show just the name if you want, but the textfield should be concatField.
Working with a legacy project that has a date stored as a string in the format
'6/1/2013'
Example of the date range filter I'm trying to do:
table.filter := 'stringdate >= ' + QuotedStr(adatepicker.text) + ' and ' +
'stringdate <= ' + QuotedStr(enddatepicker.text);
Obviously this doesn't work. When setting a date range filter the data is incorrect because we're string sorting a date.
What are some ways I can quickly hack this to make it work while planning a later migration to a proper date data type?
You don't indicate what the underlying DBMS is, so you can probably do this in the SQL instead of a filter.
If you can't do that and the dataset isn't too large, you can convert the database date values to real dates and use them in the OnFilterRecord event:
procedure TForm3.Table1FilterRecord(DataSet: TDataSet; var Accept: Boolean);
var
TableDate: TDateTime;
begin
TableDate := StrToDate(Table1DateField.AsString);
Accept := (TableDate >= ADatePicker.Date) and
(TableDate <= EndDatePicker.Date);
end;
I think, you can still compare a date stored as a string or varchar, but this is certainly a bad practice because you will need to convert this strings into dates data type to be able to compare between them. If you have indexes defined on the column, they cannot be used anymore since the column will be converted and it will cause slow performance on large database.
An example on comparing dates (from the SQL standpoint) is like this:
SELECT *
FROM tableName
WHERE CONVERT(DATETIME, dateSTRColumn, XXX) > GETDATE()
where XXX is the current format of the date stored as string.
or in other terms:-
SELECT convert(varchar(20), dateSTRColumn, 121) FROM tableName
this should give you some ideas.
Otherwise, you might have to write a simple custom function yourself.
Or change database.
on delphi and adotables and .filter property you can code:
mytable.filter:='mydatefield=#2018-12-31#';
mytable.fittered:=true;
I'm storing dates on MS ACCESS database along with other information. But I can't seem to search them as I please. I'd like to search by: year, month. I'm using a datetimepicker
Currently I'm using this code to do so:
ADOTable1.Filter := 'Date > ' +
Edit1.Text;
ADOTable1.Filtered := True;
end;
Could anyone help me?
You have two options: your solution uses the less preferable one of passing string literals to a query. In this case, you have to 'escape' the value that you are passing, eg
ADOTable1.Filter := 'Date > ''' + Edit1.Text + '''';
This will result in a line like
ADOTable1.Filter := 'Date > ''27-Sep-69'''
The better solution is to use a parameterised query
select <whatever> from table
where date > :p1
You pass the parameter in the following manner
ADOTable.parambyname ('p1').asdate:= strtodate (edit1.text);
I admit that I don't use ADO components so that syntax may be slightly off, but it's the syntax used for Firebird.
Parameters are better than using raw text values because you don't have to worry about adding the correct number of quotation marks, and no one can pass in a bad value. Imagine what would happen if edit1.text contained '27-Sep-65;Drop table1'; - this could delete your table from the database!