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

558

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

Excel 2007的可能范围是1到16384,这是它支持的列数。转换后的值应该是Excel列名的形式,例如A、AA、AAA等。


2
不要忘记可用列数的限制。例如:* Excel 2003(v11)最多到IV,2^8或256列。* Excel 2007(v12)最多到XFD,2^14或16384列。 - Unsliced
1
可能是重复的问题:如何找到对应于给定整数的Excel列名? - Daniel Trebbien
这个问题被标记为C#和Excel。我将此问题标记为过时,因为我们生活在2016年,有EPPLUS。这是一个常用的C#库,可以在服务器上创建高级Excel电子表格。它是根据GNU图书馆通用公共许可证(LGPL)提供的。使用EPPlus,您可以轻松地获取列字符串。 - Tony_KiloPapaMikeGolf
请注意,行和列的限制更多取决于文件格式而不是 Excel 版本,并且对于每个工作簿可能会有所不同。如果将其保存为旧版或新版格式,即使是同一工作簿,它们也可能会发生变化。 - Slai
@Tony_KiloPapaMikeGolf 我认为这并不过时。事实上,EPPLUS已经更改了许可证,这可能不适合各种原因。另外,如果你所需的只是如此简单的东西,为什么要引入一个库呢?我正在使用OpenXML以Excel格式导出数据,只需要一些像这里提问的算法。为什么要混合使用库呢?需求因人而异。该问题并不过时,对于简单的用例仍然很相关。话虽如此,EPPLUS是一个非常酷的库。 ;) - MetalMikester
如果您需要用于Aspose Cells,它们有内置的帮助程序。请参考:https://docs.aspose.com/cells/net/names-and-indices/。 - Uwe Keim
60个回答

0

以下是我在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后对其调用相同的函数。

0

我今天刚好要做这项工作,我的实现使用递归:

private static string GetColumnLetter(string colNumber)
{
    if (string.IsNullOrEmpty(colNumber))
    {
        throw new ArgumentNullException(colNumber);
    }

    string colName = String.Empty;

    try
    {
        var colNum = Convert.ToInt32(colNumber);
        var mod = colNum % 26;
        var div = Math.Floor((double)(colNum)/26);
        colName = ((div > 0) ? GetColumnLetter((div - 1).ToString()) : String.Empty) + Convert.ToChar(mod + 65);
    }
    finally
    {
        colName = colName == String.Empty ? "A" : colName;
    }

    return colName;
}

这个方法考虑到以字符串形式传入的数字和以"0"(A = 0)开头的数字。


0

Objective-C 实现:

-(NSString*)getColumnName:(int)n {
     NSString *name = @"";
     while (n>0) {
     n--;
     char c = (char)('A' + n%26);
     name = [NSString stringWithFormat:@"%c%@",c,name];
     n = n/26;
  }    
     return name;

}

SWIFT 实现:

func getColumnName(n:Int)->String{
 var columnName = ""
 var index = n
 while index>0 {
     index--
     let char = Character(UnicodeScalar(65 + index%26))
     columnName = "\(char)\(columnName)"
     index = index / 26
 }
 return columnName

}

答案基于: https://dev59.com/w3VD5IYBdhLWcg3wTZxm#4532562


0
 static string[] ExcelColumnAlphabetIdentifiers = new string[] { "", "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" };
 public static string ExcelColumnAlphabetIdentifier( int ColumnNumber)
    {
        StringBuilder sb = new StringBuilder();
        int remainder = ColumnNumber;
        do
        {
            sb.Append(ExcelColumnAlphabetIdentifiers[remainder % 26]);
            remainder = remainder / 26;
        }
        while (remainder > 0);
       return sb.ToString();
    }

0

T-SQL (SQL SERVER 18)

第一页的解决方案副本

CREATE FUNCTION dbo.getExcelColumnNameByOrdinal(@RowNum int)  
RETURNS varchar(5)   
AS   
BEGIN  
    DECLARE @dividend int = @RowNum;
    DECLARE @columnName varchar(max) = '';
    DECLARE @modulo int;

    WHILE (@dividend > 0)
    BEGIN  
        SELECT @modulo = ((@dividend - 1) % 26);
        SELECT @columnName = CHAR((65 + @modulo)) + @columnName;
        SELECT @dividend = CAST(((@dividend - @modulo) / 26) as int);
    END
    RETURN 
       @columnName;

END;

0
public static string ConvertToAlphaColumnReferenceFromInteger(int columnReference)
    {
        int baseValue = ((int)('A')) - 1 ;
        string lsReturn = String.Empty; 

        if (columnReference > 26) 
        {
            lsReturn = ConvertToAlphaColumnReferenceFromInteger(Convert.ToInt32(Convert.ToDouble(columnReference / 26).ToString().Split('.')[0]));
        } 

        return lsReturn + Convert.ToChar(baseValue + (columnReference % 26));            
    }

请您能否添加一些解释? - jeremy

0
看到另一个VBA答案 - 这可以在中使用一行UDF完成:
Function GetColLetter(ByVal colID As Integer) As String
    If colID > Columns.Count Then
        Err.Raise 9, , "Column index out of bounds"
    Else
        GetColLetter = Split(Cells(1, colID).Address, "$")(1)
    End If
End Function

太棒了。这是@paulma的一个变体。 - Jalal

0
如果您想以编程方式引用单元格,那么使用工作表的Cells方法而不是传统的单元格引用会使代码更易读。它采用行和列索引而不是传统的单元格引用。它与Offset方法非常相似。

Cells 可能是在 Excel 中引用范围的最差方式。它的性能令人震惊。使用 Offset 或只使用 Worksheet.Range 更好。 - Anonymous Type

0

在VB.Net 2005中使用:

Private Function ColumnName(ByVal ColumnIndex As Integer) As String

   Dim Name As String = ""

   Name = (New Microsoft.Office.Interop.Owc11.Spreadsheet).Columns.Item(ColumnIndex).Address(False, False, Microsoft.Office.Interop.Owc11.XlReferenceStyle.xlA1)
   Name = Split(Name, ":")(0)

   Return Name

End Function

1
好主意,但性能方面很糟糕。隐式地新建一个对象,然后使用另外四个点来调用最终的Address方法,这将导致一些可怕的Interop marshalling。肯定需要重新编写。 - Anonymous Type

0

我在VB.NET 2003中使用它,它运行良好...

Private Function GetExcelColumnName(ByVal aiColNumber As Integer) As String
    Dim BaseValue As Integer = Convert.ToInt32(("A").Chars(0)) - 1
    Dim lsReturn As String = String.Empty

    If (aiColNumber > 26) Then
        lsReturn = GetExcelColumnName(Convert.ToInt32((Format(aiColNumber / 26, "0.0").Split("."))(0)))
    End If

    GetExcelColumnName = lsReturn + Convert.ToChar(BaseValue + (aiColNumber Mod 26))
End Function

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