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.