13

I'm working with the SysUtils.Format function and variant values, and I found that this function only works if the format string is %s. I checked the documentation about the Format function but there does not exist any reference to how variant values are treated.

Consider this simple application:

{$APPTYPE CONSOLE}

uses
  Variants,
  SysUtils;

procedure TestFormat;
var
  v : Variant;
begin
  v:=100;
  writeln(Format('The VarType of v is %s',[VarTypeAsText(VarType(v))]));
  writeln(Format('The value of v is %s',[v]));//ok

  v:='100';
  writeln(Format('The VarType of v is %s',[VarTypeAsText(VarType(v))]));
  writeln(Format('The value of v is %s',[v]));//ok

  v:=100;
  writeln(Format('The VarType of v is %s',[VarTypeAsText(VarType(v))]));
  writeln(Format('The value of v is %d',[v]));//raise a EConvertError exception EConvertError: Format '%d' invalid or incompatible with argument
end;


begin
  try
     TestFormat;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  readln;
end.

Is this a bug or a simple limitation of this function?

I've checked this behavior in Delphi 5, Delphi 2007 and Delphi XE.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
RRUZ
  • 134,889
  • 20
  • 356
  • 483

2 Answers2

13

It is a limitation of the function. In Delphi XE, the relevant part in SysUtils starts at line 10870, which looks like this:

@CvtVariant:
        CMP     CL,'S'
        JNE     @CvtError

This is called for any variant argument. The CL register have the type required by the format string for that particular argument, for anything different than 'S', the exception is raised.

jachguate
  • 16,976
  • 3
  • 57
  • 98
  • 1
    You're about a minute faster reading assembly than I am; I must be getting rusty. (Or you started sooner. ) +1 – Ken White Apr 04 '11 at 18:15
  • 1
    @Ken, haha, I'm not very proficient in assembler, but I'm trying to improve that... happy to see I'm succeeding. :D – jachguate Apr 04 '11 at 18:16
  • @RRUZ Un gusto, Rodrigo ;). Usualmente me pregunto si se vale hablar un poco de español aquí. :D – jachguate Apr 04 '11 at 18:23
  • se siente un poco extraño postear en español en S.O, pero a veces lo hago tambien en comentarios. ;) – RRUZ Apr 04 '11 at 18:26
10

It's a limitation of the function. For a more feature-rich version of Format, try the WideFormat function from the JCL. (I'm its author.) It supports Variants of various types, Boolean, and TClass. It also accepts character-pointer types for the %p format, and Int64 and Variant values for index arguments.

Despite its extensions, it was removed from the JCL distribution about a year ago because its primary target was Delphi 5, which didn't provide a native WideString version of Format, and the JCL no longer supports Delphi 5. The last revision that included it was 3140.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
  • How can I include it on `Firemonkey`? – Machado Mar 09 '16 at 19:15
  • I assume you'd include it the same way you include anything else in Firemonkey, @Tardoandre. If you're having trouble, please consider [asking a question on Stack Overflow](http://stackoverflow.com/questions/ask). Include the details of what you tried to do, and what specifically went wrong. – Rob Kennedy Mar 09 '16 at 20:33