본문 바로가기
삽질/델파이

delphi Enum 에서 상수값을 문자열로... 또 반대로..

by rokwha 2025. 3. 17.

델파이에서 열거형( Enum ) 이라는 자료형 이 있는데...

type
	TColor = ( clRed, clYellow, clBlue, ....);

 

요런식 으로 만들어 쓸수 있다.


이를 이용하다 보면 상수값 ( clRed ...) 을 문자열 로 바꾸거나 문자열을 상수로 바꿔야 하는경우가 있는데 다른언어 에 비해서 좀 불편하긴 하다. 

델파이에서는 EnumName, EnumValue 과 같은 함수군이 있는데 이를 이용하면 된다.

 

uses TypInfo, Db;  //FFieldType 는 db 에 GetEnumXXX 는 TypInfo 에..


function FieldTypeToStr( AValue: TFieldType): string;
//TFieldType 를 문자열로
begin
  Result:= GetEnumName( TypeInfo( TFieldType ), Ord( AValue ));
  //Result:= '' 일때 예외 처리..
end;

function StrToFieldType( AValue: string): TFieldType;
//문자열을 TFieldType 로..
begin
  Result:= TFieldType( GetEnumValue( TypeInfo( TFieldType), AValue ));
  //GetEnumValue < 0 일때 예외 처리...
end;

 

뭔가 좀 복잡복잡 하다 -.-;; 

GetEnumName 은 어떤 열거형 에서 어떤 상수를 찾아서 문자열로 이름을 구할때 쓰고

GetEnumValue 는 어떤 열거형 에서  문자열 로 어떤 상수를 구할때 쓴다. 이때 숫자로 돌려 주기때문에 상수값을 가지려면 해당 열거형으로 캐스팅 하면 된다.

열거형은 맨처음 상수가 0 부터 시작해서 순차적으로 1씩 증가하며 인덱스가 매겨져 숫자를 이용해서 사용할수가 있다.

  TFieldType = (ftUnknown, ftString, ftSmallint, ftInteger, ftWord,
    ftBoolean, ftFloat, ftCurrency, ftBCD, ftDate,  ftTime, ftDateTime,
    ftBytes, ftVarBytes, ftAutoInc, ftBlob, ftMemo, ftGraphic, ftFmtMemo,
    ftParadoxOle, ftDBaseOle, ftTypedBinary, ftCursor, ftFixedChar,
    ftWideString, ftLargeint, ftADT, ftArray, ftReference,
    ftDataSet, ftOraBlob, ftOraClob, ftVariant, ftInterface,
    ftIDispatch, ftGuid, ftTimeStamp, ftFMTBcd, ftFixedWideChar, ftWideMemo);

var
  nIndex: integer;
  nFT: TFieldType;
begin
  nFT:= ftInteger;
  nFT:= 3; 			             //error Incompatible types
  nFT:= TFieldType( 4 );         //ftWord
  nIndex:= Integer( nFT ); //4
  nFT:= Succ( nFT); //ftBoolean
  nIndex:= Ord( nFT );     //5

end;


ftUnknown 이 0, ftString 는 1, ftWideMemo 는 39 이다. 그러면 시작은 0 인데 마지막 번호는 어떻게 알까?

var
  nLow, nHigh, nMax: integer;
  nFT: TFieldType;
begin
  nFT:= Low( TFieldType ); 	// Low 함수로 첫번째 값을.. ftUnknown;
  nFT:= High( TFieldType ); 	// High 함수로 마지막 값을.. ftWideMemo;
    
  //ftUnknown, ftWideMemo 를 숫자로 바꿀려면 Ord 함수를 사용하자.
  nLow:= Ord( Low( TFieldType )); 	//0;
  nHigh:= Ord( High( TFieldType )); 	//39;
    
  //좀 어럽게 최대값을 구해보자
  nMax:= GetTypeData( TypeInfo( TFieldType ))^.MaxValue;	//nHigh
    
  //어라 보다 전용함수가 있네?
  nMax:= GetEnumNameCount( TypeInfo( TFieldType ));	//nHigh+1;
end;

 

High 와 GetTypeData()^.MaxValue 는 마지막 인덱스 번호 이고 GetEnumNameCount 는 전체 갯수 이니 혼동하지 말자.

참고로 다음과 같이 열겨형을 만들때 번호를 임의로 붙혀서 만들수도 있다.

type
  TenumTest1 = ( et11 = 1, et12, et13 );
  TenumTest2 = ( et21 = 1, et21 = 100, et23 = 200 );

//et11 = 1, et12 = 2 , et13 = 3;
//et21 = 1, et21 = 100, et23 = 200;


그냥 할수는 있다 정도고 실제로 저렇게 써야 할 때가 있을지는 모르겟다.

이제까지 예로 TFieldType 를 가지고 GetEnumName, GetEnumValue 을 써봤는데 다른것을 사용할때는? 또 각각 만들어야 하나? 범용적으로 사용하도록 해보자.

function EnumToString(ATypeInfo:PTypeInfo; AValueIndex:integer):string;
//상수를 문자열로
begin
  Result:= GetEnumName( ATypeInfo, AValueIndex);
end;

function StringToEnum(ATypeInfo:PTypeInfo; AValueName:string):integer;
//문자열을 상수로 ( 인덱스번호 )
begin
  Result:= GetEnumValue( ATypeInfo, AValueName);
end;

function GetEnumCount(ATypeInfo:PTypeInfo):integer;
//갯수 구하기
begin
  Result:= GetEnumNameCount( ATypeInfo );
end;

//사용예
begin
 EnumToString( TypeInfo( TFieldType ), 1); //result:= 'ftString';
 EnumToString( TypeInfo( TFieldType ), Integer( ftInteger )); //ftInteger = 3, result:= 'ftInteger';
 StringToEnum( TypeInfo( TFieldType ), 'ftWideMemo'); // result:= 39;
 
 nLC:= GetEnumCount( TypeInfo( TAlign )); //result:= 7;
 for nLI:= 0 to nLC -1 do
 	EnumToString( TypeInfo( TAlign )), nLI); //alNone , alTop, .... alCustom;

 

제네릭 버전 과 헬퍼 로 잘 꾸미는건... 알아서 잘...

반응형