将列索引转换为Excel列名称

给定一个列索引,如何获得一个Excel列名?

这个问题比听起来更棘手,因为它不仅仅是base-26。 列不像正常数字那样换行。 即使是Microsoft支持示例也不能超越ZZZ。

免责声明:这是我之前做过的一些代码,今天又遇到了我的桌面。 我认为这是值得在这里作为一个预先回答的问题张贴。

这是乔尔的令人敬畏的代码被修改,以处理零基列索引和没有字符数组。

  Public Shared Function GetExcelColumn(ByVal index As Integer) As String Dim quotient As Integer = index \ 26 ''//Truncate If quotient > 0 Then Return GetExcelColumn(quotient - 1) & Chr((index Mod 26) + 64).ToString Else Return Chr(index + 64).ToString End If End Function 

我想到的答案是得到一个小的recursion。 这段代码在VB.Net中:

 Function ColumnName(ByVal index As Integer) As String Static chars() As Char = {"A"c, "B"c, "C"c, "D"c, "E"c, "F"c, "G"c, "H"c, "I"c, "J"c, "K"c, "L"c, "M"c, "N"c, "O"c, "P"c, "Q"c, "R"c, "S"c, "T"c, "U"c, "V"c, "W"c, "X"c, "Y"c, "Z"c} index -= 1 ''//adjust so it matches 0-indexed array rather than 1-indexed column Dim quotient As Integer = index \ 26 ''//normal / operator rounds. \ does integer division, which truncates If quotient > 0 Then ColumnName = ColumnName(quotient) & chars(index Mod 26) Else ColumnName = chars(index Mod 26) End If End Function 

而在C#中:

 string ColumnName(int index) { index -= 1; //adjust so it matches 0-indexed array rather than 1-indexed column int quotient = index / 26; if (quotient > 0) return ColumnName(quotient) + chars[index % 26].ToString(); else return chars[index % 26].ToString(); } private char[] chars = new char[] {'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'}; 

唯一的缺点是它使用1索引列而不是0索引。

正是因为这个原因,我避免了在Excel的编程接口中的列名。 使用列在Cell(r,c)引用和R1C1寻址中工作得非常好。

编辑:范围function也需要单元格引用,如在范围(单元格(r1,c1),单元格(r2,c2))。 此外,您可以使用地址function来获取单元格或范围的A1样式的地址。

编辑2:这是使用Address()函数来检索列名称的VBA函数:

 Function colname(colindex) x = Cells(1, colindex).Address(False, False) ' get the range name (eg AB1) colname = Mid(x, 1, Len(x) - 1) ' return all but last character End Function 
 # Python 2.x, no recursive function calls def colname_from_colx(colx): assert colx >= 0 colname = '' r = colx while 1: r, d = divmod(r, 26) colname = chr(d + ord('A')) + colname if not r: return colname r -= 1 
 public static String translateColumnIndexToName(int index) { //assert (index >= 0); int quotient = (index)/ 26; if (quotient > 0) { return translateColumnIndexToName(quotient-1) + (char) ((index % 26) + 65); } else { return "" + (char) ((index % 26) + 65); } } 

和testing:

 for (int i = 0; i < 100; i++) { System.out.println(i + ": " + translateColumnIndexToName(i)); } 

这里是输出:

 0: A 1: B 2: C 3: D 4: E 5: F 6: G 7: H 8: I 9: J 10: K 11: L 12: M 13: N 14: O 15: P 16: Q 17: R 18: S 19: T 20: U 21: V 22: W 23: X 24: Y 25: Z 26: AA 27: AB 28: AC 

我需要POI为0

从索引到名字的翻译:

 public static int translateComunNameToIndex0(String columnName) { if (columnName == null) { return -1; } columnName = columnName.toUpperCase().trim(); int colNo = -1; switch (columnName.length()) { case 1: colNo = (int) columnName.charAt(0) - 64; break; case 2: colNo = ((int) columnName.charAt(0) - 64) * 26 + ((int) columnName.charAt(1) - 64); break; default: //illegal argument exception throw new IllegalArgumentException(columnName); } return colNo; } 

这是一个旧的post,但看到了一些解决scheme后,我想出了自己的C#版本。 基于0的,没有recursion:

 public static String GetExcelColumnName(int columnIndex) { if (columnIndex < 0) { throw new ArgumentOutOfRangeException("columnIndex: " + columnIndex); } Stack<char> stack = new Stack<char>(); while (columnIndex >= 0) { stack.Push((char)('A' + (columnIndex % 26))); columnIndex = (columnIndex / 26) - 1; } return new String(stack.ToArray()); } 

以下是关键转折点的一些testing结果:

 0: A 1: B 2: C ... 24: Y 25: Z 26: AA 27: AB ... 50: AY 51: AZ 52: BA 53: BB ... 700: ZY 701: ZZ 702: AAA 703: AAB 

PHP的版本,感谢这个职位,帮我弄明白了! ^^

 /** * Get excel column name * @param index : a column index we want to get the value in excel column format * @return (string) : excel column format */ function getexcelcolumnname($index) { //Get the quotient : if the index superior to base 26 max ? $quotient = $index / 26; if ($quotient >= 1) { //If yes, get top level column + the current column code return getexcelcolumnname($quotient-1). chr(($index % 26)+65); } else { //If no just return the current column code return chr(65 + $index); } } 

JavaScript解决scheme

 /** * Calculate the column letter abbreviation from a 0 based index * @param {Number} value * @returns {string} */ getColumnFromIndex = function (value) { var base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''); value++; var remainder, result = ""; do { remainder = value % 26; result = base[(remainder || 26) - 1] + result; value = Math.floor(value / 26); } while (value > 0); return result; }; 

在Python中,与recursion。 从乔伊的回答中转化而来。 到目前为止,它的testing工作到GetExcelByColumn(35)='AI'

 def GetExcelColumn(index): quotient = int(index / 26) if quotient > 0: return GetExcelColumn(quotient) + str(chr((index % 26) + 64)) else: return str(chr(index + 64)) 

我喜欢写recursion函数,但我不认为这是必要的。 这是我在VB中的解决scheme。 它工作到ZZ栏。 如果有人能告诉我,如果它适用于AAA到ZZZ,这将是很好的知道。

 Public Function TranslateColumnIndexToName(index As Integer) As String ' Dim remainder As Integer Dim remainder2 As Integer Dim quotient As Integer Dim quotient2 As Integer ' quotient2 = ((index) / (26 * 26)) - 2 remainder2 = (index Mod (26 * 26)) - 1 quotient = ((remainder2) / 26) - 2 remainder = (index Mod 26) - 1 ' If quotient2 > 0 Then TranslateColumnIndexToName = ChrW(quotient2 + 65) & ChrW(quotient + 65) & ChrW(remainder + 65) ElseIf quotient > 0 Then TranslateColumnIndexToName = ChrW(quotient + 65) & ChrW(remainder + 65) Else TranslateColumnIndexToName = ChrW(remainder + 65) End If 

结束function

这是我在C#中的解决scheme

 // test void Main() { for( var i = 0; i< 1000; i++ ) { var byte_array = code( i ); Console.WriteLine("{0} | {1} | {2}", i, byte_array, offset(byte_array)); } } // Converts an offset to AAA code public string code( int offset ) { List<byte> byte_array = new List<byte>(); while( offset >= 0 ) { byte_array.Add( Convert.ToByte(65 + offset % 26) ); offset = offset / 26 - 1; } return ASCIIEncoding.ASCII.GetString( byte_array.ToArray().Reverse().ToArray()); } // Converts AAA code to an offset public int offset( string code) { var offset = 0; var byte_array = Encoding.ASCII.GetBytes( code ).Reverse().ToArray(); for( var i = 0; i < byte_array.Length; i++ ) { offset += (byte_array[i] - 65 + 1) * Convert.ToInt32(Math.Pow(26.0, Convert.ToDouble(i))); } return offset - 1; } 

这是我在C#中的答案,用于在列索引和列名称之间转换两种方式。

 /// <summary> /// Gets the name of a column given the index, as it would appear in Excel. /// </summary> /// <param name="columnIndex">The zero-based column index number.</param> /// <returns>The name of the column.</returns> /// <example>Column 0 = A, 26 = AA.</example> public static string GetColumnName(int columnIndex) { if (columnIndex < 0) throw new ArgumentOutOfRangeException("columnIndex", "Column index cannot be negative."); var dividend = columnIndex + 1; var columnName = string.Empty; while (dividend > 0) { var modulo = (dividend - 1) % 26; columnName = Convert.ToChar(65 + modulo) + columnName; dividend = (dividend - modulo) / 26; } return columnName; } /// <summary> /// Gets the zero-based column index given a column name. /// </summary> /// <param name="columnName">The column name.</param> /// <returns>The index of the column.</returns> public static int GetColumnIndex(string columnName) { var index = 0; var total = 0; for (var i = columnName.Length - 1; i >= 0; i--) total += (columnName.ToUpperInvariant()[i] - 64) * (int)Math.Pow(26, index++); return total - 1; } 

在Ruby中:

 class Fixnum def col_name quot = self/26 (quot>0 ? (quot-1).col_name : "") + (self%26+65).chr end end puts 0.col_name # => "A" puts 51.col_name # => "AZ" 

这个JavaScript版本显示了它的核心是一个转换到基数26:

 function colName(x) { x = (parseInt("ooooooop0", 26) + x).toString(26); return x.slice(x.indexOf('p') + 1).replace(/./g, function(c) { c = c.charCodeAt(0); return String.fromCharCode(c < 64 ? c + 17 : c - 22); }); } 

.toString(26)显示Joel Coehoorn错误:它是一个简单的基础转换。

(注意:根据Dana的生产答案,我有一个更直接的实现方式,虽然这不会影响到我,但也不会影响到math原理。

PS这里是在重要的地方评估的function:

 0 A 1 B 9 J 10 K 24 Y 25 Z 26 AA 27 AB 700 ZY 701 ZZ 702 AAA 703 AAB 18276 ZZY 18277 ZZZ 18278 AAAA 18279 AAAB 475252 ZZZY 475253 ZZZZ 475254 AAAAA 475255 AAAAB 12356628 ZZZZY 12356629 ZZZZZ 12356630 AAAAAA 12356631 AAAAAB 321272404 ZZZZZY 321272405 ZZZZZZ 321272406 AAAAAAA 321272407 AAAAAAB 8353082580 ZZZZZZY 8353082581 ZZZZZZZ 8353082582 AAAAAAAA 8353082583 AAAAAAAB