How to convert a column number (eg. 127) into an excel column (eg. AA)
在不使用自动从Excel直接获取值的情况下,如何在C中将数字转换为Excel列名?
Excel2007的可能范围是1到16384,这是它支持的列数。结果值应采用Excel列名的形式,例如A、AA、AAA等。
我是这样做的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | private string GetExcelColumnName(int columnNumber) { int dividend = columnNumber; string columnName = String.Empty; int modulo; while (dividend > 0) { modulo = (dividend - 1) % 26; columnName = Convert.ToChar(65 + modulo).ToString() + columnName; dividend = (int)((dividend - modulo) / 26); } return columnName; } |
如果有人需要在不带VBA的Excel中执行此操作,请使用以下方法:
1 | =SUBSTITUTE(ADDRESS(1;colNum;4);"1";"") |
其中colnum是列号
在VBA中:
1 2 3 4 5 6 7 8 9 10 11 12 13 | Function GetColumnName(colNum As Integer) As String Dim d As Integer Dim m As Integer Dim name As String d = colNum name ="" Do While (d > 0) m = (d - 1) Mod 26 name = Chr(65 + m) + name d = Int((d - m) / 26) Loop GetColumnName = name End Function |
抱歉,这是python而不是c,但至少结果是正确的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | def ColIdxToXlName(idx): if idx < 1: raise ValueError("Index is too small") result ="" while True: if idx > 26: idx, r = divmod(idx - 1, 26) result = chr(r + ord('A')) + result else: return chr(idx + ord('A') - 1) + result for i in xrange(1, 1024): print"%4d : %s" % (i, ColIdxToXlName(i)) |
您可能需要通过两种方式进行转换,例如从Excel列地址(如aaz)转换为整数,从任何整数转换为Excel。下面的两种方法就可以做到这一点。假设基于1的索引,"数组"中的第一个元素是元素1。这里没有大小限制,所以您可以使用像错误这样的地址,列号为2613824…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | public static string ColumnAdress(int col) { if (col <= 26) { return Convert.ToChar(col + 64).ToString(); } int div = col / 26; int mod = col % 26; if (mod == 0) {mod = 26;div--;} return ColumnAdress(div) + ColumnAdress(mod); } public static int ColumnNumber(string colAdress) { int[] digits = new int[colAdress.Length]; for (int i = 0; i < colAdress.Length; ++i) { digits[i] = Convert.ToInt32(colAdress[i]) - 64; } int mul=1;int res=0; for (int pos = digits.Length - 1; pos >= 0; --pos) { res += digits[pos] * mul; mul *= 26; } return res; } |
我在第一篇文章中发现了一个错误,所以我决定坐下来计算。我发现用于标识Excel列的数字系统不是另一个人发布的以26为基数的系统。以10为基数考虑以下内容。你也可以用字母表中的字母来做这个。
空间:s1,s2,s3:s1,s2,s30,00,000:…A、AA、AAA1,01,001:…B,AB,AAB…………………………………,…,……:…………第9、99、999页:Z,ZZ,ZZZ空间状态总数:10、100、1000:26、676、17576州总数:1110年18278年
Excel用26为每个字母空间中的列编号。你可以看到,一般情况下,状态空间级数是A,A^2,A^3,…,对于某个碱基A,状态总数是A+A^2+A^3+……
假设您想在前n个空格中找到状态A的总数。这样做的公式是a=(a)(a^n-1)/(a-1)。这一点很重要,因为我们需要找到与索引k对应的空格n。如果我想找出k在数字系统中的位置,我需要用k替换a并求解n。解是n=log base a(a(a-1)/a+1。如果我使用a=10和k=192的例子,我知道n=2.23804….这告诉我K位于第三个空间的开头,因为它略大于两个。
下一步是精确地找到我们在当前空间的距离。要找到这个,用n的底减去k生成的a。在这个例子中,n的底是2。因此,A=(10)(10^2–1)/(10-1)=110,正如您合并前两个空格的状态时所预期的那样。这需要从k中减去,因为前110个状态已经在前两个空格中说明了。这给我们留下了82个州。所以,在这个数字系统中,以10为基数的192的表示是082。
使用基索引0的C代码是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | private string ExcelColumnIndexToName(int Index) { string range = string.Empty; if (Index < 0 ) return range; int a = 26; int x = (int)Math.Floor(Math.Log((Index) * (a - 1) / a + 1, a)); Index -= (int)(Math.Pow(a, x) - 1) * a / (a - 1); for (int i = x+1; Index + i > 0; i--) { range = ((char)(65 + Index % a)).ToString() + range; Index /= a; } return range; } |
/旧职位
C中基于零的解决方案。
1 2 3 4 5 6 7 8 9 10 11 12 | private string ExcelColumnIndexToName(int Index) { string range =""; if (Index < 0 ) return range; for(int i=1;Index + i > 0;i=0) { range = ((char)(65 + Index % 26)).ToString() + range; Index /= 26; } if (range.Length > 1) range = ((char)((int)range[0] - 1)).ToString() + range.Substring(1); return range; } |
使用递归很容易。
21 2 3 4 5 6 7 8 9 10 11 | int nCol = 127; string sChars ="ABCDEFGHIJKLMNOPQRSTUVWXYZ"; string sCol =""; while (nCol >= 26) { int nChar = nCol % 26; nCol = (nCol - nChar) / 26; // You could do some trick with using nChar as offset from 'A', but I am lazy to do it right now. sCol = sChars[nChar] + sCol; } sCol = sChars[nCol] + sCol; |
更新:彼得的评论是对的。这就是我在浏览器中编写代码所得到的。:-)我的解决方案没有编译,它缺少最左边的字母,它正在以相反的顺序构建字符串-现在都已修复。
撇开错误不谈,该算法基本上是将数字从10进制转换为26进制。
更新2:joel coehoorn是对的-上面的代码将返回ab 27。如果是实数基26,a a等于a,z之后的下一个数是ba。
1 2 3 4 5 6 7 8 9 10 11 12 13 | int nCol = 127; string sChars ="0ABCDEFGHIJKLMNOPQRSTUVWXYZ"; string sCol =""; while (nCol > 26) { int nChar = nCol % 26; if (nChar == 0) nChar = 26; nCol = (nCol - nChar) / 26; sCol = sChars[nChar] + sCol; } if (nCol != 0) sCol = sChars[nCol] + sCol; |
我很惊讶到目前为止所有的解决方案都包含迭代或递归。
这是我的解决方案,它在恒定时间内运行(没有循环)。此解决方案适用于所有可能的Excel列,并检查输入是否可以转换为Excel列。可能的列在[a,xfd]或[1,16384]范围内。(这取决于您的Excel版本)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | private static string Turn(uint col) { if (col < 1 || col > 16384) //Excel columns are one-based (one = 'A') throw new ArgumentException("col must be >= 1 and <= 16384"); if (col <= 26) //one character return ((char)(col + 'A' - 1)).ToString(); else if (col <= 702) //two characters { char firstChar = (char)((int)((col - 1) / 26) + 'A' - 1); char secondChar = (char)(col % 26 + 'A' - 1); if (secondChar == '@') //Excel is one-based, but modulo operations are zero-based secondChar = 'Z'; //convert one-based to zero-based return string.Format("{0}{1}", firstChar, secondChar); } else //three characters { char firstChar = (char)((int)((col - 1) / 702) + 'A' - 1); char secondChar = (char)((col - 1) / 26 % 26 + 'A' - 1); char thirdChar = (char)(col % 26 + 'A' - 1); if (thirdChar == '@') //Excel is one-based, but modulo operations are zero-based thirdChar = 'Z'; //convert one-based to zero-based return string.Format("{0}{1}{2}", firstChar, secondChar, thirdChar); } } |
这个答案是用javascript编写的:
1 2 3 4 5 6 7 8 9 10 11 12 13 | function getCharFromNumber(columnNumber){ var dividend = columnNumber; var columnName =""; var modulo; while (dividend > 0) { modulo = (dividend - 1) % 26; columnName = String.fromCharCode(65 + modulo).toString() + columnName; dividend = parseInt((dividend - modulo) / 26); } return columnName; } |
只是使用递归插入一个简单的两行C实现,因为这里的所有答案看起来都比必要的复杂得多。
1 2 3 4 5 6 7 8 9 | /// <summary> /// Gets the column letter(s) corresponding to the given column number. /// </summary> /// <param name="column">The one-based column index. Must be greater than zero.</param> /// <returns>The desired column letter, or an empty string if the column number was invalid.</returns> public static string GetColumnLetter(int column) { if (column < 1) return String.Empty; return GetColumnLetter((column - 1) / 26) + (char)('A' + (column - 1) % 26); } |
…并转换为php:
1 2 3 4 5 6 7 8 9 | function GetExcelColumnName($columnNumber) { $columnName = ''; while ($columnNumber > 0) { $modulo = ($columnNumber - 1) % 26; $columnName = chr(65 + $modulo) . $columnName; $columnNumber = (int)(($columnNumber - $modulo) / 26); } return $columnName; } |
Java中的相同实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public String getExcelColumnName (int columnNumber) { int dividend = columnNumber; int i; String columnName =""; int modulo; while (dividend > 0) { modulo = (dividend - 1) % 26; i = 65 + modulo; columnName = new Character((char)i).toString() + columnName; dividend = (int)((dividend - modulo) / 26); } return columnName; } |
游戏开始有点晚了,但我使用的代码(在C)如下:
1 2 3 4 5 6 7 8 | private static readonly string _Alphabet ="ABCDEFGHIJKLMNOPQRSTUVWXYZ"; public static int ColumnNameParse(string value) { // assumes value.Length is [1,3] // assumes value is uppercase var digits = value.PadLeft(3).Select(x => _Alphabet.IndexOf(x)); return digits.Aggregate(0, (current, index) => (current * 26) + (index + 1)); } |
为了在col index和col label之间进行互操作,我想加入我使用的静态类。我的columnLabel方法使用了一个修改后的接受答案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | public static class Extensions { public static string ColumnLabel(this int col) { var dividend = col; var columnLabel = string.Empty; int modulo; while (dividend > 0) { modulo = (dividend - 1) % 26; columnLabel = Convert.ToChar(65 + modulo).ToString() + columnLabel; dividend = (int)((dividend - modulo) / 26); } return columnLabel; } public static int ColumnIndex(this string colLabel) { //"AD" (1 * 26^1) + (4 * 26^0) ... var colIndex = 0; for(int ind = 0, pow = colLabel.Count()-1; ind < colLabel.Count(); ++ind, --pow) { var cVal = Convert.ToInt32(colLabel[ind]) - 64; //col A is index 1 colIndex += cVal * ((int)Math.Pow(26, pow)); } return colIndex; } } |
像这样使用…
1 2 | 30.ColumnLabel(); //"AD" "AD".ColumnIndex(); // 30 |
在查看了这里提供的所有版本之后,我描述了自己使用递归来做一个版本。
这是我的vb.net版本:
1 2 3 4 5 6 7 | Function CL(ByVal x As Integer) As String If x >= 1 And x <= 26 Then CL = Chr(x + 64) Else CL = CL((x - x Mod 26) / 26) & Chr((x Mod 26) + 1 + 64) End If End Function |
如果你只想得到一个没有代码的单元格公式,这里有一个公式:
2在Delphi(帕斯卡)中:
1 2 3 4 5 6 7 8 9 10 11 12 | function GetExcelColumnName(columnNumber: integer): string; var dividend, modulo: integer; begin Result := ''; dividend := columnNumber; while dividend > 0 do begin modulo := (dividend - 1) mod 26; Result := Chr(65 + modulo) + Result; dividend := (dividend - modulo) div 26; end; end; |
1 2 3 4 5 6 7 8 | private String getColumn(int c) { String s =""; do { s = (char)('A' + (c % 26)) + s; c /= 26; } while (c-- > 0); return s; } |
它不完全是基26,系统中没有0。如果有的话,"z"后面跟着"ba",而不是"aa"。
以下是ActionScript版本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | private var columnNumbers:Array = ['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']; private function getExcelColumnName(columnNumber:int) : String{ var dividend:int = columnNumber; var columnName:String =""; var modulo:int; while (dividend > 0) { modulo = (dividend - 1) % 26; columnName = columnNumbers[modulo] + columnName; dividend = int((dividend - modulo) / 26); } return columnName; } |
在Perl中,对于1(a)、27(aa)等的输入。
1 2 3 4 5 6 7 8 9 10 | sub excel_colname { my ($idx) = @_; # one-based column number --$idx; # zero-based column index my $name =""; while ($idx >= 0) { $name .= chr(ord("A") + ($idx % 26)); $idx = int($idx / 26) - 1; } return scalar reverse $name; } |
精炼原始溶液(C):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | public static class ExcelHelper { private static Dictionary<UInt16, String> l_DictionaryOfColumns; public static ExcelHelper() { l_DictionaryOfColumns = new Dictionary<ushort, string>(256); } public static String GetExcelColumnName(UInt16 l_Column) { UInt16 l_ColumnCopy = l_Column; String l_Chars ="0ABCDEFGHIJKLMNOPQRSTUVWXYZ"; String l_rVal =""; UInt16 l_Char; if (l_DictionaryOfColumns.ContainsKey(l_Column) == true) { l_rVal = l_DictionaryOfColumns[l_Column]; } else { while (l_ColumnCopy > 26) { l_Char = l_ColumnCopy % 26; if (l_Char == 0) l_Char = 26; l_ColumnCopy = (l_ColumnCopy - l_Char) / 26; l_rVal = l_Chars[l_Char] + l_rVal; } if (l_ColumnCopy != 0) l_rVal = l_Chars[l_ColumnCopy] + l_rVal; l_DictionaryOfColumns.ContainsKey(l_Column) = l_rVal; } return l_rVal; } } |
javascript解决方案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | /** * Calculate the column letter abbreviation from a 1 based index * @param {Number} value * @returns {string} */ getColumnFromIndex = function (value) { var base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''); var remainder, result =""; do { remainder = value % 26; result = base[(remainder || 26) - 1] + result; value = Math.floor(value / 26); } while (value > 0); return result; }; |
另一种VBA方式
1 2 3 | Public Function GetColumnName(TargetCell As Range) As String GetColumnName = Split(CStr(TargetCell.Address),"$")(1) End Function |
我试着在Java中做同样的事情…我写了以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | private String getExcelColumnName(int columnNumber) { int dividend = columnNumber; String columnName =""; int modulo; while (dividend > 0) { modulo = (dividend - 1) % 26; char val = Character.valueOf((char)(65 + modulo)); columnName += val; dividend = (int)((dividend - modulo) / 26); } return columnName; } |
现在,一旦我用columnnumber=29运行它,它就会给出结果"ca"(而不是"ac")。有什么评论我遗漏了什么?我知道我可以通过StringBuilder逆转它…但是看着格雷厄姆的回答,我有点困惑……
根据格雷厄姆的代码,这是一个javascript版本
1 2 3 4 5 6 7 8 9 10 11 12 13 | function (columnNumber) { var dividend = columnNumber; var columnName =""; var modulo; while (dividend > 0) { modulo = (dividend - 1) % 26; columnName = String.fromCharCode(65 + modulo) + columnName; dividend = parseInt((dividend - modulo) / 26); } return columnName; }; |
这些"我的代码"用于将特定数字(索引从1开始)转换为Excel列。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | public static string NumberToExcelColumn(uint number) { uint originalNumber = number; uint numChars = 1; while (Math.Pow(26, numChars) < number) { numChars++; if (Math.Pow(26, numChars) + 26 >= number) { break; } } string toRet =""; uint lastValue = 0; do { number -= lastValue; double powerVal = Math.Pow(26, numChars - 1); byte thisCharIdx = (byte)Math.Truncate((columnNumber - 1) / powerVal); lastValue = (int)powerVal * thisCharIdx; if (numChars - 2 >= 0) { double powerVal_next = Math.Pow(26, numChars - 2); byte thisCharIdx_next = (byte)Math.Truncate((columnNumber - lastValue - 1) / powerVal_next); int lastValue_next = (int)Math.Pow(26, numChars - 2) * thisCharIdx_next; if (thisCharIdx_next == 0 && lastValue_next == 0 && powerVal_next == 26) { thisCharIdx--; lastValue = (int)powerVal * thisCharIdx; } } toRet += (char)((byte)'A' + thisCharIdx + ((numChars > 1) ? -1 : 0)); numChars--; } while (numChars > 0); return toRet; } |
我的单元测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | [TestMethod] public void Test() { Assert.AreEqual("A", NumberToExcelColumn(1)); Assert.AreEqual("Z", NumberToExcelColumn(26)); Assert.AreEqual("AA", NumberToExcelColumn(27)); Assert.AreEqual("AO", NumberToExcelColumn(41)); Assert.AreEqual("AZ", NumberToExcelColumn(52)); Assert.AreEqual("BA", NumberToExcelColumn(53)); Assert.AreEqual("ZZ", NumberToExcelColumn(702)); Assert.AreEqual("AAA", NumberToExcelColumn(703)); Assert.AreEqual("ABC", NumberToExcelColumn(731)); Assert.AreEqual("ACQ", NumberToExcelColumn(771)); Assert.AreEqual("AYZ", NumberToExcelColumn(1352)); Assert.AreEqual("AZA", NumberToExcelColumn(1353)); Assert.AreEqual("AZB", NumberToExcelColumn(1354)); Assert.AreEqual("BAA", NumberToExcelColumn(1379)); Assert.AreEqual("CNU", NumberToExcelColumn(2413)); Assert.AreEqual("GCM", NumberToExcelColumn(4823)); Assert.AreEqual("MSR", NumberToExcelColumn(9300)); Assert.AreEqual("OMB", NumberToExcelColumn(10480)); Assert.AreEqual("ULV", NumberToExcelColumn(14530)); Assert.AreEqual("XFD", NumberToExcelColumn(16384)); } |
抱歉,这是python而不是c,但至少结果是正确的:
1 2 3 4 5 6 7 8 9 10 11 12 13 | def excel_column_number_to_name(column_number): output ="" index = column_number-1 while index >= 0: character = chr((index%26)+ord('A')) output = output + character index = index/26 - 1 return output[::-1] for i in xrange(1, 1024): print"%4d : %s" % (i, excel_column_number_to_name(i)) |
通过了这些测试案例:
- 列号:494286=>abcdz
- 列号:27=>AA
- 列号:52=>az
尽管我迟到了,格雷厄姆的回答远不是最佳答案。特别是,您不必使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public static string GetColumnName(int index) // zero-based { const byte BASE = 'Z' - 'A' + 1; string name = String.Empty; do { name = Convert.ToChar('A' + index % BASE) + name; index = index / BASE - 1; } while (index >= 0); return name; } |
这是我在PHP中的最新实现。这是递归的。我是在找到这篇文章之前写的。我想看看其他人是否已经解决了这个问题…
2这是所有其他人以及谷歌重定向到的问题,所以我在这里发布这个。
这些答案中的许多都是正确的,但对于简单的情况来说过于繁琐,例如当您没有超过26列时。如果您对是否可以进入双字符列有任何疑问,那么忽略这个答案,但是如果您确定不会,那么您可以在C中这样简单地进行:
1 2 3 4 5 | public static char ColIndexToLetter(short index) { if (index < 0 || index > 25) throw new ArgumentException("Index must be between 0 and 25."); return (char)('A' + index); } |
如果您对传入的内容有信心,甚至可以删除验证并使用此内联:
2这在许多语言中都非常相似,因此您可以根据需要对其进行调整。
同样,只有当你100%确信你的列不会超过26列时才使用这个。
谢谢你的回答!!帮助我设计了这些帮助器函数,以便与我在elixir/phoenix中工作的Google Sheets API进行一些交互。
以下是我想到的(可能需要一些额外的验证和错误处理)
Elixir:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | def number_to_column(number) do cond do (number > 0 && number <= 26) -> to_string([(number + 64)]) (number > 26) -> div_col = number_to_column(div(number - 1, 26)) remainder = rem(number, 26) rem_col = cond do (remainder == 0) -> number_to_column(26) true -> number_to_column(remainder) end div_col <> rem_col true -> "" end end |
反函数:
1 2 3 4 5 6 7 8 9 10 | def column_to_number(column) do column |> to_charlist |> Enum.reverse |> Enum.with_index |> Enum.reduce(0, fn({char, idx}, acc) -> ((char - 64) * :math.pow(26,idx)) + acc end) |> round end |
一些测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | describe"test excel functions" do @excelTestData [{"A", 1}, {"Z",26}, {"AA", 27}, {"AB", 28}, {"AZ", 52},{"BA", 53}, {"AAA", 703}] test"column to number" do Enum.each(@excelTestData, fn({input, expected_result}) -> actual_result = BulkOnboardingController.column_to_number(input) assert actual_result == expected_result end) end test"number to column" do Enum.each(@excelTestData, fn({expected_result, input}) -> actual_result = BulkOnboardingController.number_to_column(input) assert actual_result == expected_result end) end end |
每种方式的F版本
1 | let rec getExcelColumnName x = if x<26 then int 'A'+x|>char|>string else (x/26-1|>c)+ c(x%26) |
请原谅,最小化是为了更好的版本https://stackoverflow.com/a/4500043/57883
相反的方向:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // return values start at 0 let getIndexFromExcelColumnName (x:string) = let a = int 'A' let fPow len i = Math.Pow(26., len - 1 - i |> float) |> int let getValue len i c = int c - a + 1 * fPow len i let f i = getValue x.Length i x.[i] [0 .. x.Length - 1] |> Seq.map f |> Seq.sum |> fun x -> x - 1 |
在vb.net 2005中使用它:
1 2 3 4 5 6 7 8 9 10 | Private Function ColumnName(ByVal ColumnIndex As Integer) As String Dim Name As String ="" Name = (New Microsoft.Office.Interop.Owc11.Spreadsheet).Columns.Item(ColumnIndex).Address(False, False, Microsoft.Office.Interop.Owc11.XlReferenceStyle.xlA1) Name = Split(Name,":")(0) Return Name End Function |
另一个解决方案:
1 2 3 4 5 6 | private void Foo() { l_ExcelApp = new Excel.ApplicationClass(); l_ExcelApp.ReferenceStyle = Excel.XlReferenceStyle.xlR1C1; // ... now reference by R[row]C[column], Ex. A1 <==> R1C1, C6 <==> R3C6, ... } |
请参阅此处的更多信息-Excel中的单元格引用,适用于所有人!作者:Nitin Paranjape博士
我在vb.net 2003中使用了这个,它运行得很好…
1 2 3 4 5 6 7 8 9 10 | Private Function GetExcelColumnName(ByVal aiColNumber As Integer) As String Dim BaseValue As Integer = Convert.ToInt32(("A").Chars(0)) - 1 Dim lsReturn As String = String.Empty If (aiColNumber > 26) Then lsReturn = GetExcelColumnName(Convert.ToInt32((Format(aiColNumber / 26,"0.0").Split("."))(0))) End If GetExcelColumnName = lsReturn + Convert.ToChar(BaseValue + (aiColNumber Mod 26)) End Function |
值得一提的是,下面是Graham在PowerShell中的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | function ConvertTo-ExcelColumnID { param ( [parameter(Position = 0, HelpMessage ="A 1-based index to convert to an excel column ID. e.g. 2 => 'B', 29 => 'AC'", Mandatory = $true)] [int]$index ); [string]$result = ''; if ($index -le 0 ) { return $result; } while ($index -gt 0) { [int]$modulo = ($index - 1) % 26; $character = [char]($modulo + [int][char]'A'); $result = $character + $result; [int]$index = ($index - $modulo) / 26; } return $result; |
}
如果您希望通过编程方式引用单元格,那么如果使用工作表的cells方法,您将获得更可读的代码。它采用行和列索引,而不是传统的单元格引用。它与偏移法非常相似。
看到另一个VBA答案-这可以在Excel VBA中用一行UDF完成:
1 2 3 | Function GetColLetter(ByVal colID As Integer) As String GetColLetter = Split(Cells(1, colID).Address,"$")(1) End Function |
nodejs实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /** * getColumnFromIndex * Helper that returns a column value (A-XFD) for an index value (integer). * The column follows the Common Spreadsheet Format e.g., A, AA, AAA. * See https://stackoverflow.com/questions/181596/how-to-convert-a-column-number-eg-127-into-an-excel-column-eg-aa/3444285#3444285 * @param numVal: Integer * @return String */ getColumnFromIndex: function(numVal){ var dividend = parseInt(numVal); var columnName = ''; var modulo; while (dividend > 0) { modulo = (dividend - 1) % 26; columnName = String.fromCharCode(65 + modulo) + columnName; dividend = parseInt((dividend - modulo) / 26); } return columnName; }, |
感谢您将Excel列字母表(例如aa)转换为数字(例如25)。反过来说:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | /** * getIndexFromColumn * Helper that returns an index value (integer) for a column value (A-XFD). * The column follows the Common Spreadsheet Format e.g., A, AA, AAA. * See https://stackoverflow.com/questions/9905533/convert-excel-column-alphabet-e-g-aa-to-number-e-g-25 * @param strVal: String * @return Integer */ getIndexFromColumn: function(val){ var base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', i, j, result = 0; for (i = 0, j = val.length - 1; i < val.length; i += 1, j -= 1) { result += Math.pow(base.length, j) * (base.indexOf(val[i]) + 1); } return result; } |
目标C实施:
1 2 3 4 5 6 7 8 9 | -(NSString*)getColumnName:(int)n { NSString *name = @""; while (n>0) { n--; char c = (char)('A' + n%26); name = [NSString stringWithFormat:@"%c%@",c,name]; n = n/26; } return name; |
}
Swift实施:
1 2 3 4 5 6 7 8 9 10 | func getColumnName(n:Int)->String{ var columnName ="" var index = n while index>0 { index-- let char = Character(UnicodeScalar(65 + index%26)) columnName ="\(char)\(columnName)" index = index / 26 } return columnName |
}
答案基于:https://stackoverflow.com/a/4532562/2231118
我今天刚要做这个工作,我的实现使用递归:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | private static string GetColumnLetter(string colNumber) { if (string.IsNullOrEmpty(colNumber)) { throw new ArgumentNullException(colNumber); } string colName = String.Empty; try { var colNum = Convert.ToInt32(colNumber); var mod = colNum % 26; var div = Math.Floor((double)(colNum)/26); colName = ((div > 0) ? GetColumnLetter((div - 1).ToString()) : String.Empty) + Convert.ToChar(mod + 65); } finally { colName = colName == String.Empty ?"A" : colName; } return colName; } |
这将把作为字符串的数字、方法和以"0"开头的数字(a=0)考虑在内。
精致典雅的红宝石版:
1 2 3 4 5 6 7 8 9 | def col_name(col_idx) name ="" while col_idx>0 mod = (col_idx-1)%26 name = (65+mod).chr + name col_idx = ((col_idx-mod)/26).to_i end name end |
下面是我在python中的方法。算法解释如下:
1 2 3 4 5 6 7 8 9 | alph = ('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') def labelrec(n, res): if n<26: return alph[n]+res else: rem = n%26 res = alph[rem]+res n = n/26-1 return labelrec(n, res) |
可以使用数字和空字符串调用函数labelrec,如:
1 | print labelrec(16383, '') |
这就是它工作的原因:如果十进制数字的书写方式与Excel工作表列相同,则数字0-9将正常书写,但10将变为"00",然后20将变为"10",依此类推。映射少数数字:
0—0
9—9
10—00
20—10
100—90
110—000
1110—0000
所以,模式是清晰的。从单位所在地开始,如果一个数字小于10,它的表示形式与数字本身相同,否则您需要通过减去1来调整剩余的数字并递归。当数字小于10时,可以停止。
同样的逻辑也适用于上述解决方案中以26为基数的数字。
p.s.如果您希望数字从1开始,请在输入数字减1后对其调用相同的函数。
(我意识到这个问题与C语言有关,但是,如果有人阅读需要用Java做同样的事情,那么下面的话可能会有用)
事实证明,使用雅加达POI中的"cellReference"类很容易做到这一点。此外,转换可以通过两种方式进行。
1 2 3 4 5 6 7 | // Convert row and column numbers (0-based) to an Excel cell reference CellReference numbers = new CellReference(3, 28); System.out.println(numbers.formatAsString()); // Convert an Excel cell reference back into digits CellReference reference = new CellReference("AC4"); System.out.println(reference.getRow() +"," + reference.getCol()); |
以前的大多数答案都是正确的。这里还有一种将列号转换为Excel列的方法。如果我们把它看作一个基转换,解决方案就相当简单了。简单地说,因为只有26个字母,所以将列号转换为基26。您可以这样做:
步骤:
将列设置为商
从商变量(上一步)中减去一个,因为我们需要以97为a的ASCII表结束。
除以26得到余数。
- 将+97添加到余数并转换为char(因为97在ASCII表中是"a")。
- 商成为新的商/26(因为我们可能会超过26列)
- 继续执行此操作,直到商大于0,然后返回结果
这是执行此操作的代码:)
1 2 3 4 5 6 7 8 9 10 11 12 | def convert_num_to_column(column_num): result ="" quotient = column_num remainder = 0 while (quotient >0): quotient = quotient -1 remainder = quotient%26 result = chr(int(remainder)+97)+result quotient = int(quotient/26) return result print("--",convert_num_to_column(1).upper()) |
1 2 3 4 5 6 7 8 9 10 11 12 | public static string ConvertToAlphaColumnReferenceFromInteger(int columnReference) { int baseValue = ((int)('A')) - 1 ; string lsReturn = String.Empty; if (columnReference > 26) { lsReturn = ConvertToAlphaColumnReferenceFromInteger(Convert.ToInt32(Convert.ToDouble(columnReference / 26).ToString().Split('.')[0])); } return lsReturn + Convert.ToChar(baseValue + (columnReference % 26)); } |
Microsoft Excel微型、快速、脏的公式。
你好,
以下是从数字中获取Excel字符列标题的一种方法…
我为Excel单元格创建了一个公式。
(即我采用了不使用VBA编程的方法。)
公式会查看一个单元格,其中包含一个数字,并告诉您该列是什么——以字母表示。
在所附图像中:
- 我把1,2,3等放在最上面一行,一直放到abs列。
- 我把公式贴在第二排,一直贴到abs。
- 我的公式查看第1行,并将数字转换为Excel的列标题ID。
- 我的公式适用于702(zz)以外的所有数字。
我这样做是为了证明公式是有效的,这样您就可以查看公式的输出并查看上面的列标题,并且可以很容易地从视觉上验证公式是否有效。-)
=concatenate(mid("u abcdefghijklmnopqrstuvwxyz",(if(mod(k1,26)>0,int(k1/26)+1,(int(k1/26))),1),mid("abcdefghijklmnopqrstuvwxyz",if(mod(k1,26)=0,26,mod(k1,26)),1))
下划线用于调试目的——让您知道有一个实际的空间,并且它工作正常。
有了上面的这个公式——无论你在k1中放了什么——这个公式将告诉你列标题是什么。
该公式在其当前格式中只能输出到2位数字(zz),但可以修改为添加第3个字母(zzz)。
1 2 3 4 5 6 7 8 9 10 11 | public string ToBase26(int number) { if (number < 0) return String.Empty; int remainder = number % 26; int value = number / 26; return value == 0 ? String.Format("{0}", Convert.ToChar(65 + remainder)) : String.Format("{0}{1}", ToBase26(value - 1), Convert.ToChar(65 + remainder)); } |