How to wash/validate a string to assign it to a componentname?

delphi

Solution

Component names are validated using the `IsValidIdent` function from SysUtils, which simply checks whether the first character is alphabetic or an underscore and whether all subsequent characters are alphanumeric or an underscore.

To create a string that fits those rules, simply remove any characters that don't qualify, and then add a qualifying character if the result starts with a number.

That transformation might yield the same result for similar names. If that's not something you want, then you can add something unique to the end of the string, such as a checksum computed from the input string, or your department ID.

function MakeValidIdent(const s: string): string;
var
  len: Integer;
  x: Integer;
  c: Char;
begin
  SetLength(Result, Length(s));
  x := 0;
  for c in s do
    if c in ['A'..'Z', 'a'..'z', '0'..'9', '_'] then begin
      Inc(x);
      Result[x] := c;
    end;
  SetLength(Result, x);
  if x = 0 then
    Result := '_'
  else if Result[1] in ['0'..'9'] then
    Result := '_' + Result;
  // Optional uniqueness protection follows. Choose one.
  Result := Result + IntToStr(Checksum(s));
  Result := Result + GetDepartment(s).ID;
end;

In Delphi 2009 and later, replace the second two `in` operators with calls to the `CharInSet` function. (Unicode characters don't work well with Delphi sets.) In Delphi 8 and earlier, change the first `in` operator to a classic `for` loop and index into `s`.

Problem

I have a submenu that list departments. Behind this each department have an action who's name is assigned 'actPlan' + department.name. Now I realize this was a bad idea because the name can contain any strange character in the world but the action.name cannot contain international characters. Obviously Delphi IDE itself call some method to validate if a string is a valid componentname. Anyone know more about this ? I have also an idea to use ``` Action.name := 'actPlan' + department.departmentID; ``` instead. The advantage is that departmentID is a known format, 'xxxxx-x' (where x is 1-9), so I have only to replace '-' with for example underscore. The problem here is that those old actionnames are already persisted in a personal textfile. It will be exceptions if I suddenly change from using departments name to the ID. I could of course eat the exception first time and then call a method that search replace that textfile with the right data and reload it. So basically I search the most elegant and futureproof method to solve this :) I use D2007.

Original source