How to convert a column number (e.g. 127) into an Excel column (e.g. AA)

前端 未结 30 2123
鱼传尺愫
鱼传尺愫 2020-11-22 00:35

How do you convert a numerical number to an Excel column name in C# without using automation getting the value directly from Excel.

Excel 2007 has a possible range o

相关标签:
30条回答
  • 2020-11-22 00:52
    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;
    

    Update: Peter's comment is right. That's what I get for writing code in the browser. :-) My solution was not compiling, it was missing the left-most letter and it was building the string in reverse order - all now fixed.

    Bugs aside, the algorithm is basically converting a number from base 10 to base 26.

    Update 2: Joel Coehoorn is right - the code above will return AB for 27. If it was real base 26 number, AA would be equal to A and the next number after Z would be BA.

    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;
    
    0 讨论(0)
  • 2020-11-22 00:52

    In Delphi (Pascal):

    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;
    
    0 讨论(0)
  • 2020-11-22 00:56

    JavaScript Solution

    /**
     * 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;
    };
    
    0 讨论(0)
  • 2020-11-22 00:57

    I wanted to throw in my static class I use, for interoping between col index and col Label. I use a modified accepted answer for my ColumnLabel Method

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

    Use this like...

    30.ColumnLabel(); // "AD"
    "AD".ColumnIndex(); // 30
    
    0 讨论(0)
  • 2020-11-22 00:58

    In perl, for an input of 1 (A), 27 (AA), etc.

    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;
    }
    
    0 讨论(0)
  • 2020-11-22 00:59

    I'm surprised all of the solutions so far contain either iteration or recursion.

    Here's my solution that runs in constant time (no loops). This solution works for all possible Excel columns and checks that the input can be turned into an Excel column. Possible columns are in the range [A, XFD] or [1, 16384]. (This is dependent on your version of Excel)

    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);
        }
    }
    
    0 讨论(0)
提交回复
热议问题