False Alignment by AutoNumAlign

After Updating to Delphi 10 Seattle and the corresponding new GridPack I encounter an error with the auto alignment in my grids. It should be easy to reproduce by dropping a TAdvGrid on a Form, enable AutoNumAlign and enable editing.

The FormatSettings.DecimalSeperator is "." on my system. When I type certain numbers/text I get the following alignment:

Text --> Alignment
sssdf --> left
33 --> right
-33 --> right
3,4 --> right
3.4 --> left
-3.4 --> right
-3,4 --> right

The most annoying thing is: For positive values the point is not interpreted as decimal separator. Instead the whole cell is interpreted as text.
Additionally, the comma is interpreted as decimal separator instead, which should not be the case.

Is that a bug in the Grid Pack? Or am I doing something wrong?

Was retested with a default grid on the form initialized with:

procedure TForm1.FormCreate(Sender: TObject);
begin
  advstringgrid1.Autonumalign := true;
  formatsettings.DecimalSeparator := '.';
  advstringgrid1.Cells[1,1] := '3.4';
  advstringgrid1.Cells[1,2] := '-3.4';
  advstringgrid1.Cells[1,3] := '-33';
  advstringgrid1.Cells[1,4] := '33';
  advstringgrid1.Cells[1,5] := 'abc';
  advstringgrid1.Cells[1,6] := '3,4';
  advstringgrid1.Cells[1,7] := '-3,4';
end;

and this problem cannot be reproduced.

Thanks for your quick response! Unfortunately, the error persists with my system config, even if I do exactly the same as you did.

I use now the dynamic approach as workaround:

procedure TForm1.AdvStringGrid1GetAlignment(Sender: TObject; ARow,
  ACol: Integer; var HAlign: TAlignment; var VAlign: TVAlignment);
var
  myFloat : double;
  myInt   : integer;
begin
  if ( (TryStrToInt(advstringgrid1.Cells[ACol, ARow], myInt)) OR
       (TryStrToFloat(advstringgrid1.Cells[ACol, ARow], myFloat))  ) then
    HAlign := taRightJustify
  else
    HAlign := taCenter;

end;

This works fine!

It is unclear why my test code works here and not for you. Are you sure you effectively compile & link with the latest version?

I am quite sure that compiling and linking works well. I digged a bit deeper and found this:

In the function TAdvStringGrid.GetCellAlignment in AdvGrid Unit the IsType function is used (27966):

      if IsType(SysUtils.Trim(s)) in [AdvUtil.atNumeric,AdvUtil.atFloat,AdvUtil.atScientific] then
      begin
        HAlign := taRightJustify;
      end;

With s='3.4' the IsType function returns atDate as type. Consequently, I jump to unit AdvUtil where IsType function is defined (I attached a copy of my IsType function at the end of this post).

For reproduction I give you my system variables that are taken at runtime in debug mode from this function:

ThousandSeparator = ','
DecimalSeparator = '.'
DateSeparator = '.'
TimeSeparator = ':'

As far as I can see the problem seems to be that the DateSeparator and DecimalSeparator are both the same. Hence, both booleans isD and isF are true after looping through the string in the first part of the function. And date is always preferred against floats.

Can you reproduce this behaviour? I think it should be possible to use the same sign as decimal and date separator. Thanks!

---------------
My IsType function (v6.3.8.0):
---------------
function IsType(s:string): TAutoType;
var
  i: Integer;
  isI,isF,isS,isD,isT: Boolean;
  th,de,mi,ds,ts,ld,lt: Integer;
  isE: boolean;

begin
  Result := atString;
  if s = '' then Exit;

  isI := True;
  isF := True;
  isS := True;
  isE := False;
  isD := Pos(DateSeparator,s) > 0;
  isT := Pos(TimeSeparator,s) > 0;

  th := -1;
  ld := -1;
  lt := -1;
  de := 0;
  mi := 0;
  ds := 0;
  ts := 0;

  for i := 1 to Length(s) do
  begin
    if not CheckSignedNum(s) then
      isI := False;

    if (s = 'e') or (s = 'E') then
    begin
      if isE then
        isS := false;
      isE := true;
    end;

    // - sign must be first char
    if (i > 1) and (s = '-') then
    begin
      isI := false;
      isF := false;
    end;

    if (i = 1) and ((s = 'e') or (s = 'E')) then
      isS := false;

    if (i = 1) and not CheckNum(s) then
    begin
      isT := false;
      isD := false;
    end;

    if (i = length(s)) and ( (s = 'e') or (s = 'E') or (s = '+') or (s = '-') ) then
      isS := false;
     
    if not (CheckNum(s) or (s = '-') or (s = ThousandSeparator) or (s = DecimalSeparator) ) then
      isF := False;

    if not (CheckNum(s) or (s = DateSeparator)) then
      isD := False;

    if not (CheckNum(s) or (s = TimeSeparator)) then
      isT := False;

    if not (CheckSignedFloatNum(s) and (s <> ThousandSeparator)) then
      isS := False;

    if (s = ThousandSeparator) and (i - th < 4) and (th <> -1) then
      isF := False;

    if (s = ThousandSeparator) then
      th := i;

    if (s = DateSeparator) then
    begin
      inc(ds);
      if (ds > 2) or (ld = i - 1) then
        isD := false;
      ld := i;
    end;

    if (s = TimeSeparator) then
    begin
      inc(ts);
      if (ts > 2) or (lt = i - 1) then
        isT := false;
      lt := i;
    end;

    if (s = DecimalSeparator) then
      Inc(de);

    if (s = '-') then
      Inc(mi);
  end;

  if isI then
    Result := atNumeric
  else
  begin
    if isF and not isE then
      Result := atFloat;
    if isS and isE then
    begin
      if mi = 2 then
        mi := 1;
      Result := atScientific;
    end;
  end;

  if isT then
    Result := atTime
  else
    if isD then
      Result := atDate
    else
     if (mi > 1) or (de > 1) then
       Result := atString;
end;

We've applied a fix for this exceptional case. Next update will have this fix.