如何将Excel列字母转换成对应的数字?算法是什么?

75

我需要一个算法,将Excel列字母转换成相应的数字。

这个算法会用C#编写,但是任何语言都可以,甚至伪代码也可以。

请注意,我将把它放入C#中,我不想使用Office dll。

'A'对应的数字应该是1

'AH'对应的数字应该是34

'XFD'对应的数字应该是16384


7
如需将数字转化为Excel列字母,请参考以下链接:https://dev59.com/QHVC5IYBdhLWcg3wykej。 - surfmuggle
11个回答

127
public static int ExcelColumnNameToNumber(string columnName)
{
    if (string.IsNullOrEmpty(columnName)) throw new ArgumentNullException("columnName");

    columnName = columnName.ToUpperInvariant();

    int sum = 0;

    for (int i = 0; i < columnName.Length; i++)
    {
        sum *= 26;
        sum += (columnName[i] - 'A' + 1);
    }

    return sum;
}

7
使用 Math.Pow 实际上并不是最好的选择(浮点数问题、性能等)。可以使用 'sum*=26;sum+=(characters[i]-'A'+1);' 来代替。 - ackb
我很好奇,字符数组的目的是什么?它似乎通过直接索引字符串来工作:sum += (columnName[i] - 'A' + 1)。 - RyanW
1
对于那些无法使上述内容正常工作或需要PHP版本的人:http://ideone.com/rE2xi4 - Seldom 'Where's Monica' Needy
我正在使用Open XML SDK 2.0,我认为UInt32作为返回类型可能比int更合适。 - B H

18
int result = colName.Select((c, i) =>
    ((c - 'A' + 1) * ((int)Math.Pow(26, colName.Length - i - 1)))).Sum();

13
int col = colName.ToCharArray().Select(c => c - 'A' + 1).
          Reverse().Select((v, i) => v * (int)Math.Pow(26, i)).Sum();

太好了。我花了一点时间才明白你为什么要反转(因为BB比AZ高)。而且你通过使用索引避免了其他人遇到的一个字符长度错误。 - Matt Mitchell

5
从后往前遍历每个字符。将每个字母的值(A=1,Z=26)乘以26的N次方,加到一个运行总数中。我的C#字符串操作技能很差,所以这里是一些混乱的伪代码:
sum=0;
len=length(letters);
for(i=0;i<len;i++)
  sum += ((letters[len-i-1])-'A'+1) * pow(26,i);

4
如果有人需要的话,这是我用JavaScript写的解决方案。
var letters = "abc".toUpperCase();
var sum = 0;
for(var i = 0; i < letters.length;i++)
{
    sum *= 26;
    sum += (letters.charCodeAt(i) - ("A".charCodeAt(0)-1));
}
alert(sum);

3
你可以将其视为26进制数,并将字母替换为26进制数字吗?
因此,实际上,您最右边的数字将始终是1到26之间的原始数字,“数字”的余数(左侧部分)是收集的26个数字的数量? 因此,A将表示26个一组,B将是2,依此类推。
例如:
B = 2 = 列2 AB = 26 * 1(A) + 2 = 列28 BB = 26 * 2(B) + 2 = 列54 DA = 26 * 4(D) + 1 = 列105
等等

你能否把它当作一个26进制数来处理呢?这本应该行不通,因为你提出的数字系统缺少零。但是看了你的例子,我有了一个想法,我会在我的答案中将其编码。 - B H
@BH - 在这个问题的背景下,这并不是必要的 - Excel 中没有零列(问题是“将Excel列字母转换为其数字的算法是什么?”)。话虽如此,上面仍有更好的答案 :) - Chris

1

以下是一个基本的C++答案,适用于对C++实现感兴趣的人。

int titleToNumber(string given) {
    int power=0;
    int res=0;
    for(int i=given.length()-1;i>=0;i--)
    {
        char c=given[i];
        res+=pow(26,power)*(c-'A'+1);
        power++;    
    }
    return res;     
    }

1
翻译:较短的版本:
int col = "Ab".Aggregate(0, (a, c) => a * 26 + c & 31);  // 28

忽略非 A-Za-z 字符:
int col = " !$Af$3 ".Aggregate(0, (a, c) => (uint)((c | 32) - 'a') > 25 ? a : a * 26 + (c & 31)); // 32

第二个例子忽略非A-Za-z字符,对于"AF"列及以上的列返回错误的列索引...例如对于单元格AF1应该返回32,但结果是0。 - JohannesGbg

0
在Excel VBA中,您可以使用.Range方法来获取数字,如下所示:
Dim rng as Range
Dim vSearchCol as variant 'your input column
Set rng.Thisworkbook.worksheets("mySheet").Range(vSearchCol & "1:" & vSearchCol & "1")

然后使用.column属性:

 debug.print rng.column

如果您需要完整的代码,请参见下面:

Function ColumnbyName(vInput As Variant, Optional bByName As Boolean = True) As Variant
    Dim Rng As Range
    If bByName Then
       If Not VBA.IsNumeric(vInput) Then
            Set Rng = ThisWorkbook.Worksheets("mytab").Range(vInput & "1:" & vInput & "1")
            ColumnbyName = Rng.Column
       Else
            MsgBox "Please enter valid non Numeric column or change paramter bByName to False!"
       End If

    Else
        If VBA.IsNumeric(vInput) Then
            ColumnbyName = VBA.Chr(64 + CInt(vInput))
        Else
            MsgBox "Please enter valid Numeric column or change paramter bByName to True!"
        End If

    End If
End Function

0

我猜这基本上与其他答案差不多,但可能更清楚地解释了数字字母的α等效物正在发生什么。它不完全是一个26进制系统,因为没有0占位符。也就是说,第26列将是“A0”或其他东西,而不是在26进制中的Z。它也不是27进制,因为“alpha-gits”不代表27的幂。天啊,这真让你欣赏巴比伦人发明零之前算术是多么混乱!

  UInt32 sum = 0, gitVal = 1;
  foreach (char alphagit in ColumnName.ToUpperInvariant().ToCharArray().Reverse())
  {
    sum += gitVal * (UInt32)(alphagit - 'A' + 1)
    gitVal *= 26;
  }

和其他一些人一样,我反转了字符数组,这样我就不需要知道指数的任何信息。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接