처음 직장다닐때, 직장 동료였떤 slypuma군이, 엑셀의 OLE Automation을 이용하여 Excel을 제어하던 도중에 컬럼명에 'A'가 들어간 컬럼을 알 수 있는 방법이 없겠느냐고 질문을 해 왔다.
OLE Automation을 이용하여 Excel의 Cell을 접근할때 영문명이 아닌, 숫자 Index값을 이용하여 접근하는 방식이기 때문에, 컬럼명을 알아야 하고, 해당 컬럼명에 'A'가 들어 있는지도 알아야 하는 2가지 문제....
'A' => Index[0] , 'B' => Index[1]......... 의 형태로 진행되고 있고 영문 A~Z까지 사용하는 형태. Index가 25가 넘어가게 되면 컬럼명은 'AA' => Index[26], 'AB' => Index[27]....의 형태로 계속해서 증가하고 있다.
엑셀의 영문 컬럼값을 숫자 Index값으로 변환하거나, 숫자 Index값을 영문 컬럼값으로 변환하는 함수를 델파이로 만들어 보았다.
현재의 함수는 2자리 영문 컬럼까지만 계산이 가능하다. 숫자 인덱스 값으로는 701까지.....
영문 컬럼 값을 숫자 인덱스로 바꾸는거는 가능한데, 숫자를 영문 컬럼값으로 바꾸는건 조금 복잡해서, 기존의 MS에서 제공하는 방식으로 함수를 구현하였고, 현재 3자리 이상의 컬럼명을 상호 변환하는 함수는 차후 다시 공개해야겠다.
아래는 해당 함수 코드이며 JAVA 버젼을 보고 Delphi 버젼으로 만든 것이다.
※ Delphi 버젼
// Index값을 영문 컬럼네임명으로 변환하여 반환 Function ColNumToName(ColNum : Integer) : String; Var iCycleNum : Integer; iWithinNum : Integer; Begin Result := ''; iCycleNum := ColNum Div 26; iWithinNum := ColNum - (iCycleNum * 26); If (iCycleNum > 0) Then Result := Result + Char((iCycleNum - 1) + Ord('A')); Result := Result + Char(iWithinNum + Ord('A')); End; // 영문 컬럼명을 숫자 Index값으로 변환하여 반환 Function ColNameToNum(In_StrColName : String) : Integer; Var I : Integer; Begin Result := 0; In_StrColName := UpperCase(In_StrColName); For I := 1 To Length(In_StrColName) Do Begin Result := (Result * 26) + (Ord(In_StrColName[I]) - Ord('A') + 1); End; Dec(Result); End;
※ JAVA 버젼
private int colNameToNum(final String colName) { int result = 0; String lcColName = colName.toLowerCase(); for (int ctr = 0; ctr < lcColName.length(); ++ ctr) result = (result * 26) + (lcColName.charAt(ctr) - 'a' + 1); -- result; return (result); } private String colNumToName(int colNum) { StringBuffer sb = new StringBuffer(); int cycleNum = colNum / 26; int withinNum = colNum - (cycleNum * 26); if (cycleNum > 0) sb.append((char) ((cycleNum - 1) + 'a')); sb.append((char) (withinNum + 'a')); return (sb.toString()); }
※ VisualBasic 버젼
Function GetExcelColumn(ByVal iCellNo As Integer) As String Dim iBeg, iEnd As Integer ' If 1-26, then this is an easy conversion If iCellNo < 27 Then GetExcelColumn = Chr$(iCellNo + 64) Else ' Now we have to account for AA-ZZ iBeg = iCellNo \ 26 ' Get the first letter iEnd = iCellNo Mod 26 ' Get the second letter If iEnd = 0 Then ' If iEnd is 0, then it is Z, which should be 26 iEnd = 26 '** you need to subtract 1 from the initial letter otherwise your lettering will be the next letter in the alphabet iBeg = iBeg - 1 End If GetExcelColumn = Chr$(iBeg + 64) & Chr$(iEnd + 64) End If End Function