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

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


当前回答

下面是我在Python中如何做的。算法说明如下:

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可以用数字和一个空字符串来调用,比如:

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为基数的数字。

注:如果你想让数字从1开始,在输入数字减去1后调用相同的函数。

其他回答

精炼原始的解决方案(在c#中):

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

更新:Peter的评论是正确的。这就是我在浏览器中编写代码的结果。:-)我的解决方案是不编译,它是最左边的字母,它是在反向顺序构建字符串-现在都固定了。

除了bug之外,该算法基本上是将一个数字从10进制转换为26进制。

更新2:Joel Coehoorn是对的-上面的代码将返回AB为27。如果它是一个以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;

虽然我在这方面姗姗来迟,但格雷厄姆的答案远非最佳。特别是,你不需要使用模数,调用ToString()和apply (int)强制转换。考虑到在c#世界中的大多数情况下,您将从0开始编号,以下是我的修订:

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

另一个解决方案:

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博士

打印稿

function lengthToExcelColumn(len: number): string {

    let dividend: number = len;
    let columnName: string = '';
    let modulo: number = 0;

    while (dividend > 0) {
        modulo = (dividend - 1) % 26;
        columnName = String.fromCharCode(65 + modulo).toString() + columnName;
        dividend = Math.floor((dividend - modulo) / 26);
    }
    return columnName;
}