C# 如何将列号(如127)转换为Excel列(如AA)

C# 如何将列号(如127)转换为Excel列(如AA),c#,excel,C#,Excel,如何将数字转换为C#中的Excel列名,而不使用直接从Excel获取值的自动化 Excel 2007的可能范围为1到16384,这是它支持的列数。结果值应采用excel列名的形式,例如A、AA、AAA等 int nCol = 127; string sChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; string sCol = ""; while (nCol >= 26) { int nChar = nCol % 26; nCol = (nCol

如何将数字转换为C#中的Excel列名,而不使用直接从Excel获取值的自动化

Excel 2007的可能范围为1到16384,这是它支持的列数。结果值应采用excel列名的形式,例如A、AA、AAA等

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:正确-上面的代码将返回27的AB。如果是实数基数26,AA等于A,Z后的下一个数字是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;
更新::的评论是正确的。这就是我在浏览器中编写代码的结果。:-)我的解决方案不是编译,它缺少最左边的字母,而是以相反的顺序构建字符串——所有这些都已修复

撇开错误不谈,该算法基本上是将一个数字从基数10转换为基数26

更新2:正确-上面的代码将返回27的AB。如果是实数基数26,AA等于A,Z后的下一个数字是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;

使用递归很容易。

public static string GetStandardExcelColumnName(int columnNumberOneBased)
{
  int baseValue = Convert.ToInt32('A');
  int columnNumberZeroBased = columnNumberOneBased - 1;

  string ret = "";

  if (columnNumberOneBased > 26)
  {
    ret = GetStandardExcelColumnName(columnNumberZeroBased / 26) ;
  }

  return ret + Convert.ToChar(baseValue + (columnNumberZeroBased % 26) );
}

使用递归很容易。

public static string GetStandardExcelColumnName(int columnNumberOneBased)
{
  int baseValue = Convert.ToInt32('A');
  int columnNumberZeroBased = columnNumberOneBased - 1;

  string ret = "";

  if (columnNumberOneBased > 26)
  {
    ret = GetStandardExcelColumnName(columnNumberZeroBased / 26) ;
  }

  return ret + Convert.ToChar(baseValue + (columnNumberZeroBased % 26) );
}

抱歉,这是Python而不是C#,但至少结果是正确的:

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))
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))
def ColIdxToXlName(idx):
如果idx<1:
提升值错误(“索引太小”)
result=“”
尽管如此:
如果idx>26:
idx,r=divmod(idx-1,26)
结果=chr(r+ord('A'))+结果
其他:
返回chr(idx+ord('A')-1)+结果
对于x范围内的i(1024):
打印“%4d:%s”%(i,ColIdxToXlName(i))

对不起,这是Python而不是C#,但至少结果是正确的:

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))
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))
def ColIdxToXlName(idx):
如果idx<1:
提升值错误(“索引太小”)
result=“”
尽管如此:
如果idx>26:
idx,r=divmod(idx-1,26)
结果=chr(r+ord('A'))+结果
其他:
返回chr(idx+ord('A')-1)+结果
对于x范围内的i(1024):
打印“%4d:%s”%(i,ColIdxToXlName(i))
我是这样做的:

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;
}
我是这样做的:

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;
}
不完全是基数26,系统中没有0。如果有,“Z”后面跟着“BA”,而不是“AA”


不完全是基数26,系统中没有0。如果有,“Z”后面跟着“BA”,而不是“AA”。

如果有人需要在没有VBA的Excel中执行此操作,下面是一种方法:

=SUBSTITUTE(ADDRESS(1;colNum;4);"1";"")
其中colNum是列号

在VBA中:

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

如果任何人需要在没有VBA的Excel中执行此操作,以下是一种方法:

=SUBSTITUTE(ADDRESS(1;colNum;4);"1";"")
其中colNum是列号

在VBA中:

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

精炼原始溶液(以C#表示):

公共静态类ExcelHelper
{
私有静态字典l_DictionaryOfColumns;
公共静态辅助程序(){
l_DictionaryOfColumns=新字典(256);
}
公共静态字符串GetExcelColumnName(UInt16 l_列)
{
UInt16 l_ColumnCopy=l_Column;
字符串l_Chars=“0abcdefghijklmnopqrstuvxyz”;
字符串l_rVal=“”;
UInt16 l_Char;
if(l_DictionaryOfColumns.ContainsKey(l_Column)==true)
{
l_rVal=l_字典的f列[l_列];
}
其他的
{
而(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;
}
如果(l_ColumnCopy!=0)
l_rVal=l_Chars[l_ColumnCopy]+l_rVal;
l_DictionaryOfColumns.ContainsKey(l_Column)=l_rVal;
}
返回l_rVal;
}
}

精炼原始溶液(C#):

公共静态类ExcelHelper
{
私有静态字典l_DictionaryOfColumns;
公共静态辅助程序(){
l_DictionaryOfColumns=新字典(256);
}
公共静态字符串GetExcelColumnName(UInt16 l_列)
{
UInt16 l_ColumnCopy=l_Column;
字符串l_Chars=“0abcdefghijklmnopqrstuvxyz”;
字符串l_rVal=“”;
UInt16 l_Char;
if(l_DictionaryOfColumns.ContainsKey(l_Column)==true)
{
l_rVal=l_字典的f列[l_列];
}
其他的
{
而(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;
}
如果(l_ColumnCopy!=0)
l_rVal=l_Chars[l_ColumnCopy]+l_rVal;
l_DictionaryOfColumns.ContainsKey(l_Column)=l_rVal;
}
返回l_rVal;
}
}

。并转换为php:

function GetExcelColumnName($columnNumber) {
    $columnName = '';
    while ($columnNumber > 0) {
        $modulo = ($columnNumber - 1) % 26;
        $columnName = chr(65 + $modulo) . $columnName;
        $columnNumber = (int)(($columnNumber - $modulo) / 26);
    }
    return $columnName;
}

…并转换为php:

function GetExcelColumnName($columnNumber) {
    $columnName = '';
    while ($columnNumber > 0) {
        $modulo = ($columnNumber - 1) % 26;
        $columnName = chr(65 + $modulo) . $columnName;
        $columnNumber = (int)(($columnNumber - $modulo) / 26);
    }
    return $columnName;
}

以下是Actionscript版本:

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

以下是Actionscript版本:

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

您可能需要以两种方式进行转换,例如从Excel列地址(如AAZ)转换为整数,以及从任意整数转换为Excel。下面的两种方法就可以做到这一点。假设基于1的索引,“数组”中的第一个元素是元素编号1。 这里没有大小限制,所以您可以使用诸如ERROR之类的地址,这将是列号2613824

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;
}
公共静态字符串列地址(int-col)
{
如果(列=0;--pos)
{
res+=数字[pos]*mul;
mul*=26;
}
返回res;
}

您可能需要以两种方式进行转换,例如从Excel列地址(如AAZ)转换为整数,从任意整数转换为Excel。下面的两种方法就可以做到这一点。
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;
}
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);
    }
}
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;
}
public function GetColumn($intNumber, $strCol = null) {

    if ($intNumber > 0) {
        $intRem = ($intNumber - 1) % 26;
        $strCol = $this->GetColumn(intval(($intNumber - $intRem) / 26), sprintf('%s%s', chr(65 + $intRem), $strCol));
    }

    return $strCol;
}
/**
 * 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;
};
Public Function GetColumnName(TargetCell As Range) As String
    GetColumnName = Split(CStr(TargetCell.Cells(1, 1).Address), "$")(1)
End Function
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;
    }
}
30.ColumnLabel(); // "AD"
"AD".ColumnIndex(); // 30
    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;
    }
    [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));
    }
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
/// <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);
}
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);
}
(char)('A' + index)
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))