loopsfor-loopdelphialphabetmemo

Delphi create letters with for loop


As you know in Excel column names are letters. When it reaches Z it continues with AA-AB-AC. Is it possible to make a similar function in Delphi XE7 + for loop?

I've tried:

var
i:integer;
str:string;
begin
str:='a';
for i := 0 to 26-1 do
begin
inc (str,1);
memo1.Lines.Add(str);
end;

but it returned:

[dcc32 Error] FBarkodsuzIndesignVerisiOlustur.pas(249): E2064 Left side cannot be assigned to

I assume that's because str is not an integer.

I can convert numbers to letters with this function:

function numberToString(number: Integer): String;
begin
    Result := '';
    if (number < 1) or (number > 26) then
        Exit;

    Result := 'abcdefghijklmnopqrstuvwxyz'[number];
end;

But I have no idea how we can create letters like AA when it exceeds 26.

Also with below approach, it creates 26 letters just fine but when it exceeds 26 it starts to use characters like brackets:

  for i := 0 to 27-1 do
  begin
   memo1.Lines.Add(Char(Ord('a') + i));
  end;

Output of it:

a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
{

when it reach to Z it'll continue as "AA" "BB" "CC" and so on like Excel creates column names.


Solution

  • This is the function that I use for the task.

    function SpreadSheetColName(const Col: Integer): string;
    var
      c: Char;
    begin
      Assert(Col >= 0);
      if Col<26 then begin
        c := 'A';
        Inc(c, Col);
        Result := c;
      end else begin
        Result := SpreadSheetColName(Col div 26 - 1) + SpreadSheetColName(Col mod 26);
      end;
    end;
    

    Note that it uses zero based indices. I would suggest that you also use zero based indices as a general rule throughout your programming.

    If you can't bring yourself to do that, then a one based version would look like this:

    function SpreadSheetColName(const Col: Integer): string;
    
      function SpreadSheetColNameZeroBased(const Col: Integer): string;
      var
        c: Char;
      begin
        Assert(Col >= 0);
        if Col<26 then begin
          c := 'A';
          Inc(c, Col);
          Result := c;
        end else begin
          Result := SpreadSheetColNameZeroBased(Col div 26 - 1) + SpreadSheetColNameZeroBased(Col mod 26);
        end;
      end;
    
    begin
      Result := SpreadSheetColNameZeroBased(Col - 1);
    end;