74

I need an algorithm to convert an Excel Column letter to its proper number.

The language this will be written in is C#, but any would do or even pseudo code.

Please note I am going to put this in C# and I don't want to use the office dll.

For 'A' the expected result will be 1

For 'AH' = 34

For 'XFD' = 16384

Ian Nelson
  • 57,123
  • 20
  • 76
  • 103
David Basarab
  • 72,212
  • 42
  • 129
  • 156
  • 7
    For the reverse (from number to column-letter) see: http://stackoverflow.com/questions/181596/how-to-convert-a-column-number-eg-127-into-an-excel-column-eg-aa – surfmuggle Mar 05 '14 at 20:35

11 Answers11

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;
}
Ian Nelson
  • 57,123
  • 20
  • 76
  • 103
  • 7
    Using Math.Pow is actually not the best idea (floating-point issues,performance...) Use 'sum*=26;sum+=(characters[i] -'A'+1);' – ackb Mar 21 '09 at 00:27
  • I'm curious, what is the purpose of the characters array? It appears to work by indexing directly into string with: sum += (columnName[i] - 'A' + 1) – RyanW Jul 23 '13 at 22:05
  • 1
    To anyone who's having issues getting the above to work quite right, or who happens to need this in PHP: http://ideone.com/rE2xi4 – Seldom 'Where's Monica' Needy Oct 27 '15 at 23:28
  • I'm working with Open XML SDK 2.0 and I think UInt32 may be more appropriate as a return type than int. – B H Aug 22 '16 at 19:00
17
int result = colName.Select((c, i) =>
    ((c - 'A' + 1) * ((int)Math.Pow(26, colName.Length - i - 1)))).Sum();
mqp
  • 70,359
  • 14
  • 95
  • 123
11
int col = colName.ToCharArray().Select(c => c - 'A' + 1).
          Reverse().Select((v, i) => v * (int)Math.Pow(26, i)).Sum();
wethercotes
  • 646
  • 1
  • 7
  • 10
  • Perfect. Took me a moment to work why you were reversing (it's because BB is higher than AZ). And you avoid the off by one character length bug others have had by using the index. – Matt Mitchell Sep 22 '09 at 08:40
5

Here is a solution I wrote up in JavaScript if anyone is interested.

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);
Jesse Puente
  • 51
  • 1
  • 2
5

Loop through the characters from last to first. Multiply the value of each letter (A=1, Z=26) times 26**N, add to a running total. My string manipulation skill in C# is nonexistent, so here is some very mixed pseudo-code:

sum=0;
len=length(letters);
for(i=0;i<len;i++)
  sum += ((letters[len-i-1])-'A'+1) * pow(26,i);
Sparr
  • 7,489
  • 31
  • 48
3

Could you perhaps treat it like a base 26 number, and then substitute letters for a base 26 number?

So in effect, your right most digit will always be a raw number between 1 and 26, and the remainder of the "number" (the left part) is the number of 26's collected? So A would represent one lot of 26, B would be 2, etc.

As an example:

B = 2 = Column 2
AB = 26 * 1(A) + 2 = Column 28
BB = 26 * 2(B) + 2 = Column 54
DA = 26 * 4(D) + 1 = Column 105

etc

Chris
  • 3,487
  • 3
  • 25
  • 37
  • "Could you perhaps treat it like a base 26 number". This shouldn't work because your proposed number system lacks a zero. But looking at your example gives me an idea that I will put into code in my answer. – B H Aug 22 '16 at 18:57
  • @BH - in context of the question this is not necessary - there is no column zero in Excel (question is "What is the algorithm to convert an Excel Column Letter into its Number?"). Having said that, there are still better answers above :) – Chris Aug 22 '16 at 23:17
1

Shorter version:

int col = "Ab".Aggregate(0, (a, c) => a * 26 + c & 31);  // 28

To ignore non A-Za-z characters:

int col = " !$Af$3 ".Aggregate(0, (a, c) => (uint)((c | 32) - 'a') > 25 ? a : a * 26 + (c & 31)); // 32
Slai
  • 22,144
  • 5
  • 45
  • 53
  • The second example that ignores non A-Za-z characters, returns the wrong column index for "AF" columns and above...Eg for cell AF1 32 should be returned, but the result is 0. – JohannesGbg Dec 11 '20 at 07:02
1

Here is a basic c++ answer for those who are intrested in c++ implemention.

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;     
    }
0

in Excel VBA you could use the .Range Method to get the number, like so:

Dim rng as Range
Dim vSearchCol as variant 'your input column
Set rng.Thisworkbook.worksheets("mySheet").Range(vSearchCol & "1:" & vSearchCol & "1")

Then use .column property:

 debug.print rng.column

if you need full code see below:

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
V. Wolf
  • 123
  • 1
  • 8
0

I guess this essentially works out pretty much the same as some of the other answers, but it may make a little more clear what's going on with the alpha equivalent of a numeric digit. It's not quite a base 26 system because there is no 0 placeholder. That is, the 26th column would be 'A0' or something instead of Z in base 26. And it's not base 27 because the 'alpha-gits' don't represent powers of 27. Man, it really makes you appreciate what a mess arithmetic must have been before the Babylonians invented the zero!

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

Like some others, I reversed the character array so I don't need to know anything about exponents.

B H
  • 1,730
  • 18
  • 24
0

For this purpose I use only one line:

int ColumnNumber = Application.Range[MyColumnName + "1"].Column;