【问题标题】:How do I find the Excel column name that corresponds to a given integer? [duplicate]如何找到与给定整数对应的 Excel 列名? [复制]
【发布时间】:2010-09-06 13:36:59
【问题描述】:

您将如何确定 Excel 中第 n 列的列名(例如“AQ”或“BH”)?

编辑:确定这一点的与语言无关的算法是这里的主要目标。

【问题讨论】:

  • 不要删除这个。 A)它需要作为存根来增加搜索找到规范的机会。 B) 它有很好的答案。
  • 这里要解决的一般问题是双射计数的转换,特别是bijective base-26

标签: algorithm excel language-agnostic


【解决方案1】:

我曾经写过这个函数来执行那个确切的任务:

public static string Column(int column)
{
    column--;
    if (column >= 0 && column < 26)
        return ((char)('A' + column)).ToString();
    else if (column > 25)
        return Column(column / 26) + Column(column % 26 + 1);
    else
        throw new Exception("Invalid Column #" + (column + 1).ToString());
}

【讨论】:

  • 我错过了什么吗?条件“(column >= 0 && column 25)”是否重叠? “else if”测试是错字吗?
  • @Onorio Catenacci:“column > 25”是“column >= 26”的另一种说法。我发现后者更清楚,但两者都是正确的。
  • 惊人的解决方案。太好了,我希望我能给 +10
  • Excel 2007 允许您拥有 3 个字符的列。所以你需要另一种情况(或用模式替换)。
  • @Michael - 此算法是递归的,适用于任何大小的列。我已经在 Excel 2007 3 字符列上对其进行了测试,它们工作正常(例如 Column(703) = "AAA"Column(704) = "AAB"
【解决方案2】:

我目前在用这个,但是感觉可以优化一下。

private String GetNthExcelColName(int n)
{
    String firstLetter = "";  
    //if number is under 26, it has a single letter name
    // otherwise, it is 'A' for 27-52, 'B' for 53-78, etc
    if(n > 26)
    {
        //the Converts to double and back to int are just so Floor() can be used
        Double value = Convert.ToDouble((n-1) / 26);
        int firstLetterVal = Convert.ToInt32(Math.Floor(value))-1;
        firstLetter = Convert.ToChar(firstLetterValue + 65).ToString();
    }    

    //second letter repeats
    int secondLetterValue = (n-1) % 26;
    String secondLetter = Convert.ToChar(secondLetterValue+65).ToString();

    return firstLetter + secondLetter;
}

【讨论】:

    【解决方案3】:

    Joseph 的代码不错,但如果您不想或不需要使用 VBA 函数,请试试这个。

    假设n的值在单元格A2中 使用这个功能:

    =MID(ADDRESS(1,A2),2,LEN(ADDRESS(1,A2))-3)
    

    【讨论】:

      【解决方案4】:

      我想你需要 VBA 代码:

      Public Function GetColumnAddress(nCol As Integer) As String
      
      Dim r As Range
      
      Set r = Range("A1").Columns(nCol)
      GetColumnAddress = r.Address
      
      End Function
      

      【讨论】:

        【解决方案5】:

        这些好人发布的所有这些代码示例看起来都很好。

        有一点需要注意。从 Office 2007 开始,Excel 实际上有多达 16,384 列。这转化为 XFD(256 列的旧最大值是 IV)。您将不得不稍微修改这些方法以使它们适用于三个字符。

        应该没那么难……

        【讨论】:

          【解决方案6】:

          与语言无关的算法如下:

          function getNthColumnName(int n) {
             let curPower = 1
             while curPower < n {
                set curPower = curPower * 26
             }
             let result = ""
             while n > 0 {
                let temp = n / curPower
                let result = result + char(temp)
                set n = n - (curPower * temp)
                set curPower = curPower / 26
             }
             return result
          

          此算法还会考虑 Excel 是否再次升级以处理超过 16k 列。如果你真的想太过分,你可以传入一个额外的值并将 26 的实例替换为另一个数字以适应替代字母

          【讨论】:

          • 不错。我假设temp 是一个整数,let temp = n / curPower 除法是如何四舍五入的,还有/ 26
          【解决方案7】:

          这可以满足您在 VBA 中的要求

          Function GetNthExcelColName(n As Integer) As String
              Dim s As String
              s = Cells(1, n).Address
              GetNthExcelColName = Mid(s, 2, InStr(2, s, "$") - 2)
          End Function
          

          【讨论】:

            【解决方案8】:

            这是 Gary Waters 的解决方案

            Function ConvertNumberToColumnLetter2(ByVal colNum As Long) As String
                Dim i As Long, x As Long
                For i = 6 To 0 Step -1
                    x = (1 - 26 ^ (i + 1)) / (-25) - 1 ‘ Geometric Series formula
                    If colNum > x Then
                        ConvertNumberToColumnLetter2 = ConvertNumberToColumnLetter2 & Chr(((colNum - x - 1)\ 26 ^ i) Mod 26 + 65)
                    End If
                Next i
            End Function
            

            通过http://www.dailydoseofexcel.com/archives/2004/05/21/column-numbers-to-letters/

            【讨论】:

              【解决方案9】:

              考虑到wcm(top value = xfd)的注释,可以这样计算;

              function IntToExcel(n: Integer); string;
              begin
                 Result := '';
                 for i := 2 down to 0 do 
                 begin
                    if ((n div 26^i)) > 0) or (i = 0) then
                       Result := Result + Char(Ord('A')+(n div (26^i)) - IIF(i>0;1;0));
                    n := n mod (26^i);
                 end;
              end;
              

              字母表中有 26 个字符,我们有一个数字系统,就像十六进制或二进制一样,只是有一个不寻常的字符集 (A..Z),在位置上表示 26 的幂:(26^2)(26^ 1)(26^0)。

              【讨论】:

              • 这里没有定义 IIF,所以这个实现比看起来要大。
              【解决方案10】:

              这似乎在 vb.net 中工作

              Public Function Column(ByVal pColumn As Integer) As String
                  pColumn -= 1
                  If pColumn >= 0 AndAlso pColumn < 26 Then
                      Return ChrW(Asc("A"c) + pColumn).ToString
                  ElseIf (pColumn > 25) Then
                      Return Column(CInt(math.Floor(pColumn / 26))) + Column((pColumn Mod 26) + 1)
                  Else
                  stop
                      Throw New ArgumentException("Invalid column #" + (pColumn + 1).ToString)
                  End If
              End Function
              

              我把 Joseph's 拿去给 BH 测试,然后喂它 980-1000,它看起来不错。

              【讨论】:

                【解决方案11】:

                =CHAR(64+COLUMN())

                【讨论】:

                • 这仅适用于 A 到 Z 列。其他 220 列呢?
                【解决方案12】:

                在VBA中,假设lCol是列号:

                function ColNum2Letter(lCol as long) as string
                    ColNum2Letter = Split(Cells(1, lCol).Address, "$")(0)
                end function
                

                【讨论】:

                  【解决方案13】:
                  IF(COLUMN()>=26,CHAR(ROUND(COLUMN()/26,1)+64)&CHAR(MOD(COLUMN(),26)+64),CHAR(COLUMN()+64))
                  

                  这适用于 2 个字母列(直到列 ZZ)。您必须为 3 个字母列嵌套另一个 if 语句。

                  上面的公式在AYAZ 列以及以下nYnZ 列中均失败。修正后的公式为:

                  =IF(COLUMN()>26,CHAR(ROUNDDOWN((COLUMN()-1)/26,0)+64)&CHAR(MOD((COLUMN()-1),26)+65),CHAR(COLUMN()+64)
                  

                  【讨论】:

                    【解决方案14】:

                    这是我能想到的最简洁的正确解决方案(在 Java 中,但请随意使用您最喜欢的语言):

                    String getNthColumnName(int n) {
                        String name = "";
                        while (n > 0) {
                            n--;
                            name = (char)('A' + n%26) + name;
                            n /= 26;
                        }
                        return name;
                    }
                    

                    但是,如果您发现此代码中有错误,请务必告诉我,谢谢。

                    【讨论】:

                    • 一段很棒的代码。相当简洁。你能解释一下n-- 背后的基本原理吗?
                    • @KodeSeeker 让我看看我能不能简单地解释一下……每个数字有 26 个符号,但这不是以 26 为底。它有点像以 27 为底,但没有 0。n--是一种将 0 从基数 27 移出的方法,剩下的 [1, 26] 范围映射到 [A, Z]。有意义吗?
                    • 只是给所有试图使用这个例子的人的注释——没有激活他的大脑(比如我):n 是列 NUMBER(以 1 开头)而不是 INDEX(以 0 开头)!跨度>
                    • @eventhorizo​​n 完全正确!
                    【解决方案15】:

                    谢谢,约瑟夫·斯图尔特万特!您的代码完美运行 - 我需要它在 vbscript 中,所以我想分享我的版本:

                    Function ColumnLetter(ByVal intColumnNumber)
                        Dim sResult
                        intColumnNumber = intColumnNumber - 1
                        If (intColumnNumber >= 0 And intColumnNumber < 26) Then
                            sResult = Chr(65 + intColumnNumber)
                        ElseIf (intColumnNumber >= 26) Then
                            sResult = ColumnLetter(CLng(intColumnNumber \ 26)) _
                                    & ColumnLetter(CLng(intColumnNumber Mod 26 + 1))
                        Else
                            err.Raise 8, "Column()", "Invalid Column #" & CStr(intColumnNumber + 1)
                        End If
                        ColumnLetter = sResult
                    End Function
                    

                    【讨论】:

                      【解决方案16】:

                      这是从 VBScript 版本到 SQL Server 2000+ 的转换。

                      CREATE FUNCTION [dbo].[GetExcelColRef] 
                      (
                          @col_seq_no int
                      )
                      RETURNS varchar(5)
                      AS
                      BEGIN
                      
                      declare @Result varchar(5)
                      set @Result = ''
                      set @col_seq_no = @col_seq_no - 1
                      If (@col_seq_no >= 0 And @col_seq_no < 26) 
                      BEGIN
                          set @Result = char(65 + @col_seq_no)
                      END
                      ELSE
                      BEGIN
                          set @Result = [dbo].[GetExcelColRef] (@col_seq_no / 26) + '' + [dbo].[GetExcelColRef]  ((@col_seq_no % 26) + 1)
                      END
                      Return @Result
                      
                      END
                      GO
                      

                      【讨论】:

                        【解决方案17】:

                        FYI T-SQL 给 Excel 列名称提供一个序数(从零开始),作为单个语句。

                        任何低于 0 或高于 16,383(Excel2010 中的最大列数)的值都返回 NULL。

                        ; WITH TestData AS ( -- Major change points
                            SELECT -1 AS FieldOrdinal
                            UNION ALL
                            SELECT 0
                            UNION ALL
                            SELECT 25
                            UNION ALL
                            SELECT 26
                            UNION ALL
                            SELECT 701
                            UNION ALL
                            SELECT 702
                            UNION ALL
                            SELECT 703
                            UNION ALL
                            SELECT 16383
                            UNION ALL
                            SELECT 16384
                        )
                        SELECT
                              FieldOrdinal
                            , CASE
                               WHEN FieldOrdinal < 0     THEN NULL
                               WHEN FieldOrdinal < 26    THEN ''
                               WHEN FieldOrdinal < 702   THEN CHAR (65 + FieldOrdinal / 26 - 1)
                               WHEN FieldOrdinal < 16384 THEN CHAR (65 + FieldOrdinal / 676 - 1)
                                                            + CHAR (65 + (FieldOrdinal / 26) - (FieldOrdinal / 676) * 26 - 1)
                               ELSE NULL
                              END
                              + CHAR (65 + FieldOrdinal % 26)
                         FROM TestData
                         ORDER BY FieldOrdinal
                        

                        【讨论】:

                          【解决方案18】:

                          来自 wcm:

                          如果你不想使用 VBA,你可以使用这个 用你想要的数字替换 colnr

                          =MID(ADDRESS(1,colnr),2,LEN(ADDRESS(1,colnr))-3)
                          

                          请注意,由于使用了 ADDRESS 函数,这个公式是不稳定的。易失函数是在每次更改后由 excel 重新计算的函数。 通常,只有在依赖引用发生变化时,excel 才会重新计算公式。

                          使用这个公式可能会成为性能杀手。

                          【讨论】:

                            【解决方案19】:

                            Ruby 单线:

                            def column_name_for(some_int)
                                some_int.to_s(26).split('').map {|c| (c.to_i(26) + 64).chr }.join # 703 => "AAA"
                            end
                            

                            它将整数转换为 base26,然后将其拆分并进行一些数学运算以将每个字符从 ascii 转换。终于把他们都重新聚在一起。没有除法、模数或递归。

                            有趣。

                            【讨论】:

                            • 错误:column_name_for(26) => 'A@'
                            【解决方案20】:

                            这在 MS Excel 2003-2010 中运行良好。应该适用于支持 Cells(...).Address 功能的早期版本:

                            1. 第 28 列 - 取columnNumber=28Cells(1, columnNumber).Address 返回"$AB$1"
                            2. $ 符号进行拆分会返回数组:["","AB","1"]
                            3. 所以Split(Cells(1, columnNumber).Address, "$")(1) 给你列名"AB"

                            更新:

                            取自How to convert Excel column numbers into alphabetical characters

                            ' The following VBA function is just one way to convert column number 
                            ' values into their equivalent alphabetical characters:
                            
                            Function ConvertToLetter(iCol As Integer) As String
                               Dim iAlpha As Integer
                               Dim iRemainder As Integer
                               iAlpha = Int(iCol / 27)
                               iRemainder = iCol - (iAlpha * 26)
                               If iAlpha > 0 Then
                                  ConvertToLetter = Chr(iAlpha + 64)
                               End If
                               If iRemainder > 0 Then
                                  ConvertToLetter = ConvertToLetter & Chr(iRemainder + 64)
                               End If
                            End Function
                            

                            适用于:Microsoft Office Excel 2007 SE / 2002 SE / 2000 SE / 97 SE

                            【讨论】:

                              猜你喜欢
                              • 1970-01-01
                              • 1970-01-01
                              • 2012-06-28
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 2012-02-03
                              相关资源
                              最近更新 更多