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

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


当前回答

虽然我在这方面姗姗来迟,但格雷厄姆的答案远非最佳。特别是,你不需要使用模数,调用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;
}

其他回答

抱歉,这是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))

f#版本的各种方式

let rec getExcelColumnName x  = if x<26 then int 'A'+x|>char|>string else (x/26-1|>c)+ c(x%26)

对不起,最小化,正在开发一个更好的https://stackoverflow.com/a/4500043/57883版本

相反的方向:

// return values start at 0
let getIndexFromExcelColumnName (x:string) =
    let a = int 'A'
    let fPow len i =
        Math.Pow(26., len - 1 - i |> float)
        |> int

    let getValue len i c = 
        int c - a + 1 * fPow len i
    let f i = getValue x.Length i x.[i]
    [0 .. x.Length - 1]
    |> Seq.map f
    |> Seq.sum
    |> fun x -> x - 1

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;

似乎很多答案都比必要的要复杂得多。下面是一个基于上面描述的递归的通用Ruby答案:

这个答案的一个好处是,它不局限于26个英文字母。你可以在COLUMNS常量中定义任何你喜欢的范围,它会做正确的事情。

  # vim: ft=ruby
  class Numeric
    COLUMNS = ('A'..'Z').to_a

    def to_excel_column(n = self)
      n < 1 ?  '' : begin
        base = COLUMNS.size
        to_excel_column((n - 1) / base) + COLUMNS[(n - 1) % base]
      end
    end
  end

  # verify:
  (1..52).each { |i| printf "%4d => %4s\n", i, i.to_excel_column }

这将打印以下内容,例如:

   1 =>    A
   2 =>    B
   3 =>    C
  ....
  33 =>   AG
  34 =>   AH
  35 =>   AI
  36 =>   AJ
  37 =>   AK
  38 =>   AL
  39 =>   AM
  40 =>   AN
  41 =>   AO
  42 =>   AP
  43 =>   AQ
  44 =>   AR
  45 =>   AS
  46 =>   AT
  47 =>   AU
  48 =>   AV
  49 =>   AW
  50 =>   AX
  51 =>   AY
  52 =>   AZ

另一种VBA方式

Public Function GetColumnName(TargetCell As Range) As String
    GetColumnName = Split(CStr(TargetCell.Cells(1, 1).Address), "$")(1)
End Function