Compilation error with Flexcel 6.24

Hello

Compiling a program using Flexcel 6.24.0 gived errors, see below

C:\WinSerion\LibraryForAll\LogXLS.pas(124) Fehler: E2251 Doppeldeutiger ?berladener Aufruf von 'SetCellValue'

 + _ExcelAdapter.ExcelFile.pas(1608) Verwandte Methode: procedure TExcelFile.SetCellValue(const Integer; const Integer; const TDateTime; const Integer);

 + _ExcelAdapter.ExcelFile.pas(1595) Verwandte Methode: procedure TExcelFile.SetCellValue(const Integer; const Integer; const Double; const Integer);

with Flexcel 6.23.0 there are no Errors!

Sincerely Peter
Hi,
In FlexCel 6.24 we indeed added an overload for setcellvalue taking a TDateTime, for performance reasons. (If we don't define this overload as in 6.23, you can still enter a TDateTime, but it will be converted to a TCellValue and then the TCellValue entered into the cell).

But in most cases, this new overload shouldn't matter. If you do:

program Project59;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  DateUtils,
  SysUtils,
  VCL.FlexCel.Core,
  FlexCel.XlsAdapter;

var
  date: TDateTime;
  dbl: double;
  v: variant;
  fl: single;
  xls: TExcelFile;
begin
  date :=EncodeDateTime(1900, 1, 1, 10, 20, 0, 0);
  dbl := double(date);
  v := date;
  fl := dbl;

  xls := TXlsFile.Create(1, true);
  try
    xls.SetCellValue(1, 1, date, -1);
    xls.SetCellValue(1, 1, dbl, -1);
    xls.SetCellValue(1, 1, v, -1);
   // xls.SetCellValue(1, 1, fl, -1);

  finally
    xls.Free;
  end;

end.




That should compile fine. But if you uncomment the line:

    xls.SetCellValue(1, 1, fl, -1);


Then indeed you will get an ambiguous error, because for some reason Delphi doesn't know into what to convert a float.

So I wonder, what is the type of the 3rd parameter to SetCellValue in your code? Is it a float, a double, or something else?

Hi Adrian,


I also get a compile error with version 6.24. In this case TCellValue does not accept a single

xls.SetCellValue(idx + 1, 4 + (param * 3), FSpeciesIndicatorsUdf[idx].Indicators[param].Value);

FSpeciesIndicatorsUdf[idx].Indicators[param].Value represents a single.



I think we can add another overload for singles. But in the general case, if you are getting an error like this, just cast the value to a double:


xls.SetCellValue(idx + 1, 4 + (param * 3), double(FSpeciesIndicatorsUdf[idx].Indicators[param].Value));

Hm, I get the error  message Invalid typecast. 

And also Cardinal as data type is not accepted by SetCellValue.

Hi, I think cardinal want' accepted before in 6.23 either. We just can't add overloads to every type out there because there are just too many. We cover the simple ones, the rest you have to cast them. 


About the invalid typecast, sorry, I should have tested this in older Delphi versions. It works in Rio and Tokyo at least (the 2 I've tried here), but when trying it in XE7 it indeed gives an invalid typecast.

So for everyone in Tokyo or newer, the advise stands. Just use: double(var_with_float) or double(var_with_cardinal) and it will  compile.

For older compiler versions where this doesn't work, one simple solution is to use:

var
  Indicator: double;
begin
...
  Indicator := FSpeciesIndicatorsUdf[idx].Indicators[param].Value;
  xls.SetCellValue(idx + 1, 4 + (param * 3), indicator);
  

It is a little more verbose, (even if in this case it might even be a little more clear), but hopefully most of the variables in your code aren't floats/cardinals (or real48, or any other type we didn't cover).

Whatever you do, the number will be converted to a double, since doubles is the only thing Excel uses for numbers. So even if it is an integer, internally the method called will always be SetValue(double).

Thanks for the feedback Adrian. Indeed, I use XE7 and Cardinal is accepted by 6.23!

I will follow your advice and change Cardinal to Integer and Single to Double.
  

Hello,

Also with Verion 6.26 this annoying compilation error occurs
C:\WinSerion\LibraryForAll\LogXLS.pas(124) Fehler: E2251 Doppeldeutiger ?berladener Aufruf von 'SetCellValue'

 + _ExcelAdapter.ExcelFile.pas(1608) Verwandte Methode: procedure TExcelFile.SetCellValue(const Integer; const Integer; const TDateTime; const Integer);

 + _ExcelAdapter.ExcelFile.pas(1595) Verwandte Methode: procedure TExcelFile.SetCellValue(const Integer; const Integer; const Double; const Integer);

What would be a usefull work around.
Or shall we stay at 6.23?

Hi,

As mentioned in the thread before, this happens mostly if you are using single (because for some reason Delphi thinks a single could be casted to a TDateTime, instead of a double).

The workaround is, if you are using a modern delphi, just to cast the value:
  xls.SetCellValue(row, col, double(value));

If your delphi version doesn't allow casting to a double, then you need to define a variable:

var
  d: double;
 begin
  d := value;
  xls.SetCellValue(row, col, d);

I wish we could offer a better solution, but the reality is that the overload for TDateTime makes some stuff faster than it was in 6.23, so we can't roll this back. But that overload causes this issue because now when you have a single or cardinal, Delphi can't decide if you want to call the overload that takes a double or a TDateTime (which doesn't make sense, Delphi should know you want the "double" overload, but that is the way it is).
We could add even more overloads, one for single, one for cardinal, etc, but adding more overloads can make the problem worse, now Delphi has more overloads to choose from, and it will likely be more undecided about what to choose.

Just so I know what is causing the problems for most people, what type of variable is the value you are trying to set? Is it a single? A cardinal?

Hello


I am using actual version Tokyo and it is Cardinal;

As already mentioned, typecast is not possible.

Sincerely Peter

What was mentioned is that typecast is not possible in XE7, but it is possible in Tokyo. I just tried it, and this code compiles fine in Tokyo:


var

  cc: cardinal;
begin
  cc:= 3;
  xls.SetCellValue(1, 1, double(cc));


Doesn't that code work in your machine? If it doesn't, what version of Tokyo are you using (Help->About) I am in version: 

Finally, if for some reason your version of Tokyo doesn't support this or you are in an older version, you can always do the following:



function ToDouble(const c: cardinal): double;
begin
  Result := c;
end;
...


SetCellValue(row, col, ToDouble(some_cardinal));


Sadly we are not likely to add any new overloads in the 6.x series, as we already had this very issue of breaking code using Cardinal when we added an overload for TDateTime, and adding an overload for Cardinal could cause problems with code using other data types. Unless something critical happens (but then critical something is always happening), 6.26 is the last version in the 6.x series. We are already testing 7.0 and no new features or non-critical-fixes are going to the 6.x branch anymore.