We are currently using Delphi with Borland database. We are planning to move from borland to Firebird libraries, (borland lib has mem leaks).
The problem that we are having now is, Firebird library returns a char with trailing spaces, which was somehow handled borland library. We have huge code written without any trimming.
So now if 'abc' is stored in char(10) field, it returns 'abc '. and our code fails. I was wondering if there is some configuration that I can do on the DB or firebird library to automatically trim char fields.
This is per the requirements laid down in the SQL standards: CHAR fields should be returned padded with spaces to the maximum defined length. If you don't want that behaviour, you need to use VARCHAR instead of CHAR.
Update: Not sure if it is helpful, but according to this message you could create a workaround if you are using IBX.
Why don't you just change fields types in a database from CHAR to VARCHAR?
You can use TRIM() function in SELECT statement.
You can put a couple of changes into IBX source codes in order to right trim CHAR
strings.
Related
I know that if I want to add an ASCII character in a string like a black space, for example, all I need to do is to add with a call to CHAR(32) and the space will be added to the string.
But what if I want to put the infinite symbol ∞ (U+221E) how should I do it?
If I paste it into a literal string like 'infinite is ∞' then Delphi wants to change the file to UTF8.
Char is a data type, so Char() is a typecast, not a function. Chr() is a function.
In D2009+, you can use either:
Char($221E) or Char(8734) (in earlier versions, use WideChar() instead)
Chr($221E) or Chr(8734)
#$221E or #8734 character constants
TCharacter.ConvertFromUtf32()
TCharHelper.ConvertFromUtf32()
'∞'. There is nothing wrong with using this in code and letting the IDE decide how to save it. This is actually the preferred solution. The only time you would need to avoid this is if you are using other tools to process your source files and they don't support UTF-8 files.
I've done my homework, and specifically:
1) Read the whole FASTREPORT 4 manual. It does not mention UTF8, nor Unicode support
2) Looked for an answer here on SO
3) Googled it around
If I set a Text field and fill it with Thai characters, they are perfectly printed, so FastReport CAN handle Unicode characters, at least it can print them.
If I try to "pass" a value using the callbacks provided by the frxUserDataSet, then what I see is some garbled not-unicode text. In particular, if I pass e.g. a string made with the same 10 Thai characters, I see the same "set" of 3 or 4 garbled characters repeated ten times, so I am sure the data is passed correctly, but then FastReport has probably no way to know that they should be handled as Unicode.
The callback requires the data passed back to be of "variant" type, so I guess it's totally useless to cast them to any type, because variant will accept any of them.
I forgot to mention that I get the strings from a MySql DB and the data is stored as UTF8, and I do not even copy the data in a local variable: what I get from the DB is put into the variant.
Is there a way to force FastReport to print the data received as Unicode?
Thank you
Yes, FR4 with Delphi7 supports UTF8 using frxUserDataSet.
Just for future reference:
1) You MUST set your DB (MySql in my case) to use UTF8
2) You MUST set the character set in the component you use to access the DB to utf8 ("DAC for MySql" in my case, and the property is called ConnectionCharacterSet)
3) In all the frxUserDataSet callbacks, before setting the "value" variable, you MUST CONVERT whatever you have using the Utf8decode Delphi system routine, like this:
value := Utf8decode(fReports.q1.FieldValueByFieldName('yourDBfield'));
where fReports is the form name, and q1 the component used to access the DB.
I keep reading that using D7 and UniCode is almost impossible, but - as long as you use XP and up - it's only harder from what I am seeing. Unfortunately, I must use XP, D7 and cannot upgrade. But, as said, I am quickly becoming used to solve these problems so, in the future, I hope to be able to give back some help in the same way everybody has always helped me here :)
We have a database where the character set is set to WE8MSWIN1252 which I understand is a single byte character set.
We created a schema and its tables by running a script with the following:
ALTER SYSTEM SET NLS_LENGTH_SEMANTICS=CHAR
Could we possibly lose data since we are using VARCHAR2 columns with character semantics while the underlying character set is single byte?
If you are using a single-byte character set like Windows-1252, it is irrelevant whether you are using character or byte semantics. Each character occupies exactly one byte so it doesn't matter whether a column is declared VARCHAR2(10 CHAR) or VARCHAR2(10 BYTE). In either case, up to 10 bytes of storage for up to 10 characters will be allocated.
Since you gain no benefit from changing the NLS_LENGTH_SEMANTICS setting, you ought to keep the setting at the default (BYTE) since that is less likely to cause issues with other scripts that you might need to run (such as those from Oracle).
Excellent question. Multi-byte characters will take up the number of bytes required, which could use more storage than you expect. If you store a 4-byte character in a varchar2(4) column, you have used all 4 bytes. If you store a 4-byte character in a varchar2(4 char) column, you have only used 1 character. Many foreign languages and special characters use 2-byte character sets, so it's best to 'know your data' and make your database column definitions accordingly. Oracle does NOT recommend changing NLS_LENGTH_SEMANTICS to CHAR because it will affect every new column defined as CHAR or VARCHAR2, possibly including your catalog tables when you do an in-place upgrade. You can see why this is probably not a good idea. Other Oracle toolsets and interfaces may present issues as well.
I have an old programm which was programmed in Delphi 1 (or 2, I'm not sure) and I want to build a 64-bit version of it (I use the Delphi XE2). Now the problem is that in the source code there are on the one hand strings and on the other arrays of strings (I guess to limit the string length).
Now there are a lot of errors while compiling because of incompatible types.
Above all there are procedures which should handle both types.
Is there an easy way to solve this problem (without changing every variable)?
Short answer
Search and replace : string => : ansistring
make sure you use length(astring) and setLength(astring) instead of manipulating string[0].
Long answer
Delphi 1 has only one type of string.
The old-skool ShortString that has a maximum length of 255 chars and a declared maximum length.
It looks and feels like an array of char, but it has a leading length byte.
var
ShortString: string[100];
In Delphi 2 longstrings (aka AnsiString) were introduced, these replace the shortstring. They do not have a fixed length, but are allocated dynamically instead and automatically grow and shrink as needed.
They are automatically created and destroyed.
var
Longstring: string; //AnsiString, can have any length up to 2GB.
In Delphi 2009 Unicode was introduced.
This changes the longstring because now each char no langer takes up 1 byte, but takes 2 bytes(*).
Additionally you can specify a character set to an AnsiString, whereas the new Unicode longstring uses UTF-16.
What you need to do depends on your needs:
If you just want the old code to work as before and you don't care about supporting all the multilingual stuff Unicode supports, you will need to replace all your string keywords with AnsiString (for all strings that are longstrings).
If you have Delphi 1 code, you can rename the string to ShortString.
I would recommend that you refactor the code to always use longstrings (read: AnsiString) though.
Delphi will automatically translate the UnicodeStrings that all return values of functions (Unicode string) are translated into AnsiStrings and visa versa, however this may include loss of data if your users enter symbols in a editbox that your AnsiString cannot store.
Also all that translation takes a bit of time (I doubt you will notice this though).
In Delphi 1 up to Delphi 2007 this problem did not exist, because controls did not allow Unicode characters to be entered.
(*) gross oversimplification
I'm trying to insert a symbol - white square (Unicode 25A1) into Excel spreadsheet but keep getting errors:
I tried following with no avail:
1. WorkSheet.Cells[CurrRow,CurrCol].Formula := '=ChrW(&H25A1)';
2. WorkSheet.Cells[CurrRow,CurrCol].Formula := '=Char(25A1)';
And running macro didn't help either as it said '?'
Really hoping someone could help me with this
The COM interface to Excel is a Unicode API. Excel works internally with Unicode strings. Just pass your special character to Excel in a Delphi WideString. You don't need an Excel formula.
WorkSheet.Cells[CurrRow,CurrCol].Value := WideString(#$25A1);
If you are using a Unicode version of Delphi (i.e. 2009 or later) then you can include the Unicode character in your source code if you make your source code a UTF-8 file.
WorkSheet.Cells[CurrRow,CurrCol].Value := WideString('□');
The IDE will convert your source file to UTF-8 if you start adding non-ANSI characters.
You are probably getting an error message which in Excel would be displayed in the Cell as #VALUE!. For one you are feeding it a hex string while it wants a normal number. For another you are giving the Char function a number outside of its acceptable range. The Excel help for CHAR specifically states:
a number between 1 and 255 specifying
which character you want. The
character is from the character set
used by your computer
It appears that Excel does not have any ChrW function. And I can't find any function that takes a numeric value and converts it to its Unicode character equivalent.
Looking through the help, the way you insert Unicode characters is by using the numeric value from the keyboard (holding down alt) or by using the menu: Insert, text, symbol, Unicode (hex). You should be able to simulate the keyboard input, and the menu should be available through the COM model, but not sure whether the character selection then is.
Having said all that, if you are looking for a way to insert Unicode text from Delphi into Excel cells, then all you should need to do, is:
WorkSheet.Cells[CurrRow, CurrCol].Value := Chr(#$25A1);
And I am only using the Delphi (!) Chr function because you did. You could simply enter assign a text string containing the character you need to the cell in the Delphi source.