Delphi - DBGrid does not display UTF8 calculated field - delphi

I have a TDBGrid linked to a TDataSource with a TFibDataSet behind. On the OnCalcFields of the dataset I'm trying to add the string 'Russisch (русский)'.
procedure TForm1.pFIBDataSet1CalcFields(DataSet: TDataSet);
begin
DataSource1.DataSet.FieldByName('Language').AsString := ('Russisch (русский)');
The problem is that in the grid the result is displayed as :Russisch(????????)
DataSource1.DataSet.FieldByName('Language').AsWideString :=('Russisch (русский)');
has the same result
FibDataBase component has ConnectParams.Charset set to UTF-8. Also I set in the DBParams value lc_ctype=UTF8.
What I'm doing wrong here?
LE: Delphi XE, Firebird and UTF8 - this does not solve my problem.
LE1: Problem occurs only with calculated fields. Live data 'Russisch (русский)' is displayed correctly.

I guess you made the same mistake I always make. When you create a field like this:
it's ANSI. You have to select WideString for it to be unicode:

Related

Listbox does not show the changes made to the Dataset

I have a FMX ComboBox connected through LiveBindings to a ClientDataset. Everything works fine, until I needed to filter the data from the ClientDataset. After applying the filter, ComboBox.Items and ComboBox.ListItems are ok, i.e., it is the data contained in the filtered ClientDataset. But the data that the ComboBox listbox shows is always the same: the data that the ClientDataset contained the first time the listbox was displayed.
procedure TForm14.Button1Click(Sender: TObject);
begin
LinkFillControlToField1.Active := False;
ClientDataset1.Filter := 'TYPE = ''N''';
Clientdataset1.Filtered := not ClientDataset1.Filtered;
// Deactivate and Reactivate the link is necessary to refresh the data
LinkFillControlToField1.Active := True;
end;
In that code I change the filter to the ClientDataset and I deactivate the LinkFillControlToField and after applying the filter I activate it again to refresh the data. It works without problems with TListBox and other controls, but not with a TComboBox, although ComboBox.Items and ComboBox.ListItems do contain the correct data, but it is not the one shown in the combobox listbox.
Is there a way to solve this, using LiveBindings ? I have looked for properties and methods of the ComboBox (Repaint for example), the LinkFillControlToField and the BindSourceDB, but nothing has worked for me.
I use Delphi 10.4 Update 2, Firemonkey Windows application (32 or 64) running on Windows 10.
TIA.,
Ricardo
I had the same problem. My data source was TFireDAC TQuery. I submitted a change to a parma contained in the query.
My solution to my problem was to insert the line to explicitly clear the list of items.
if (SCM != NULL && SCM->qrySession->Active) {
SCM->qrySession->DisableControls();
// remove all the strings held in the combobox
// note cmbSessionList->Clear() doesn't work here.
cmbSessionList->Items->Clear();
SCM->qrySession->Close();
// ASSIGN PARAM to display or hide CLOSED sessions
SCM->qrySession->ParamByName("HIDECLOSED")->AsBoolean = fHideClosedSessions;
SCM->qrySession->Prepare();
SCM->qrySession->Open();
SCM->qrySession->EnableControls();
}

Delphi 7 to XE8 assigning binary ADO parameter values

I'm converting a report that resides in a DLL to XE8 so that I can update our report control, which is problematic in Windows 10. In doing this, I've had to replace our ADO data access controls with the built-in ADO controls.
The issues is that our data uses binary keys, and I've run into an issue assigning values to query parameters. In our code, the keys are passed around as strings, and assigned to the parameters and converted by the control at runtime.
Previously, utilizing the old control, it utilized the Delphi DB unit which contains a method .AsBlob which was used in the assignment. See below...
Qry.Close;
Qry.ParamByName('#Id').AsBlob := IdStringValue;
Qry.Open;
In the control's implementation it handled setting the property, which called into SetAsBlob. See below...
Type TBlobData = string;
...
procedure TQryParameter.SetAsBlob(const Value: TBlobData);
begin
Self.DataType := ftVarBytes;
Self.Value := StringToVarArray(Value);
end;
Part of the issue is that Data.DB has changed TBlobData = string; to TBlobData = TArray<Byte>;.
I've tried assigning these values to the query parameters following the same method used in the previous implementation, but it doesn't work.
Qry.Close;
Qry.Parameters.ParamByName('#Id').DataType := ftVarBytes;
Qry.Parameters.ParamByName('#Id').Value := ADODB.StringToVarArray(IdStringValue);
Qry.Open;
I get a fairly generic MSSQL error due to the parameter mismatch, "Application uses a value of the wrong type for the current operation."
The ADO query parameter is defined as VarBytes and the stored procedure accepts BINARY(6) for its only parameter so everything appears to be correct.
I've tried casting IdStringValue from String to AnsiString prior to calling StringToVarArray but it makes no difference.
Anyone know of a way to deal with this? Thank you.
Convert the string value to array of bytes when assigning the parameter.
Qry.Parameters.ParamByName('#Id').AsBlob := TEncoding.Default.GetBytes(StringValue);

Delphi: ADOConnection, DBASE3 and character set (bug?)

Delphi XE3, Win7 Prof.
I need to write into DBASE 3 (old format) files to export data for a DOS-like application (Clipper?).
Ok, I thought: MS DBASE driver can do this.
But I have problem with hungarian accents.
I tried this connection string:
Driver={Microsoft dBASE Driver (*.dbf)};DriverID=21;Dbq=c:\temp;Extended Properties=dBASE III;charSet=CP 852;Locale Identifier=1038;Character Set=CP 852;CODEPAGE=852
As I saw it cannot write only ANSI files (the DOS app accepts CP852 chars).
I tried to convert the content with AnsiToOEM, but some characters lost on save. In the record I see good content, but the saved file contains wrong accents.
The test text is "árvíztűrő tükörfúrógép".
The "í", "ó", "Ó" is missing from the result.
And I found some strange thing!
If the main form have an opened ADOConnection (the connected property is true in the DFM) then I will read good characters from the DBASE files, and I can write them into the file - the ANSI characters will be converted correctly. "í" is ok, "ó" is ok.
This ADOConnection object could be different than the reader.
If I close this ADOConnection in IDE mode, the opened files won't be converted, so I will see some strange accented chars, and I won't write good text into the file.
It is strange, because if I open this connection on FormCreate by code, the problem will appear...
I can read and write the ADOQuery records if the resource streamer read the ADOConnection's active (True value) "connected" property from the DFM!
I don't know what happened in the background, and how to force this ADO character transformation routine to work, but I wasted more days to find a working DBASE III exporter, and I have found only a buglike thing...
Does anyone know what is this? Why the ADO character encoder/decoder works only if I had a connected ADOConnection in DFM?
Or how I can use ADODB.Connection instead of ADOConnection object to avoid this side effect?
Thanks for every idea!
As I see I need to set the code page to fix the string for ADO.
var
s: string;
aStr1, aStr2: AnsiString;
begin
...
s := 'árvíztûrõ tükörfúrógép';
aStr1 := s;
SetLength(aStr2, Length(aStr1));
AnsiToOemBuff(PAnsiChar(aStr1), PAnsiChar(aStr2), Length(aStr1));
SetCodePage(RawbyteString(aStr2), 852, False); // THIS IS THE SOLUTION
ADOQuery1.FieldBYName('name').AsAnsiString := aStr2;
Otherwise something is converting my AnsiString again in the background.

Set a "TEXT" in Rave Report to a Edit1.text on a Delphi form when printing

Is there a way to set a certain text like text1 on a Rave Report to a certain Edit.text on a Delphi form you print from in your Delphi application.
I want to create an application form in a delphi application where each block represents a certain letter of a word... for example - Edit1.text := Surname
On my Rave Report text1 should show Edit1.text[1] (S), text2 should show Edit1.text[2] (u) ... and so forth. I know how to use the datatext function in Rave Report... but that would mean I have to save each letter of each field in a database column separately first... :(
Please help me if you can... coz I'm very stupid when it comes to this sort of thing.
Since this looks quite strange for me and I would strongly consider to set your TEdit.Text directly from your application not from the report and since it's not quite clear what you are asking here I'll try to show you how to get or set the text from or to the Text component in Rave Reports.
Let's pretend you have the Report1 with Page1 where the text component named Text1 is placed somewhere. All of this is by Rave Reports designer saved in the C:\YourRaveProject.rav file. Then assume you have in your Delphi project a button with the following code in its OnClick event handler and two edit boxes, Edit1, where we load the text from our Text1 component and Edit2 from which we set our Text1 component text.
uses
RpRave, RpDefine, RpBase, RpSystem, RvCsStd;
procedure TForm1.Button1Click(Sender: TObject);
var
RaveProject: TRvProject;
begin
RaveProject := TRvProject.Create(nil);
RaveProject.ProjectFile := 'C:\YourRaveProject.rav';
try
RaveProject.Open;
RaveProject.SelectReport('Report1', False);
// get the text from the Text1 component from the report
Edit1.Text := (RaveProject.ProjMan.FindRaveComponent('Page1.Text1', nil) as TRaveText).Text;
// set the text of the Text1 component on the report
(RaveProject.ProjMan.FindRaveComponent('Page1.Text1', nil) as TRaveText).Text := Edit2.Text;
// and execute the report for showing the result of setting the text
// note, this can be omitted of course if you want only to get the value
RaveProject.ExecuteReport('Report1');
RaveProject.Close;
finally
RaveProject.Free;
end;
end;
Please, take this as an example, not as a real answer to your question because IMHO it's unanswerable at this time. If you specify the exact question then we might be able to help you with your real problem.
Tested on Delphi 2009 with Rave Reports 7.6.2.

Delphi BDE Double type Field changed to a String type

I'm using a BDE TTable which had certain fields which were originally ftDouble.
Because the input to be stored is sometimes non-numeric, I now changed the field type to ftString.
Input into the field is done with a TEdit. When the code gets to:
with tblDM do
begin
Edit;
FieldByName('s01_amt').AsString := Edit1.Text;
Post;
end;
if the entry is not a number, I get the BDE error:
'a' is not a valid floating point
value for field 's01_amt'.
That error message is only created by fields of type TFloatField, which is only created when the TFieldDef has a DataType value of ftFloat. Double-check that you've changed the property think you did.
The field definitions can be populated from the fields themselves. Make sure you've changed the underlying database schema and not just your TTable component.
I would just convert it to a float:
var
dFloat : double;
begin
try dFloat := strToFloat(edit1.txt); except dFloat := 0; end;
edit;
FieldByName('s01_amt').AsFloat := dFloat;
post;
end;
When you changed the field type, did you also change the database's field in the schema (structure in xBASE/Clipper)? If not, you're trying to assign a non-numeric value to a numeric type field, and that's what's causing the exception.
If you're still using DBF style files, you need to change the type of the field in the database from NUMERIC to CHARACTER. You can do it using SQL from the Database Desktop, IIRC, with the BDE's DBASE support.
Just changing the TField's type from ftFloat to ftString won't alter the database storage for that field automatically; you have to do it in both places yourself.

Resources