函数将列号转换为字母?


143

是否有人拥有可以从数字中返回列字母的Excel VBA函数?

例如,输入100应该返回CV



@FrancisDean是该问题的反面,它正在从号码中查找地址
brettdj

2
@brettdj链接的答案同时显示数字对字母和字母对数字。
弗朗西斯·迪安

2
@FrancisDean公平的观点,我看了链接中的问题标题,而不是公认的答案
brettdj 2015年

Answers:


211

此函数返回给定列号的列字母。

Function Col_Letter(lngCol As Long) As String
    Dim vArr
    vArr = Split(Cells(1, lngCol).Address(True, False), "$")
    Col_Letter = vArr(0)
End Function

列100的测试代码

Sub Test()
    MsgBox Col_Letter(100)
End Sub

9
(0)如果要保存变量声明和额外的代码行,可以在Split命令的末尾添加。例如Col_letter = Split(Cells(1, lngCol).Address(True, False), "$")(0)
Caltor

3
这是完全正确的,但是我认为使用几行代码更具可读性。
brettdj

6
在这种情况下为什么要麻烦布尔参数。你可以这样做:............................................. ......v = Split(Cells(1, lngCol).Address, "$")(1)
Excel Hero

1
虽然这很老了,但我还有一点点补充-首先检查数字是否为正,否则会遇到错误。如果lngcol <= 0,则
Selkie

1
使用VBS时,请记住这.Cells是Excel的属性,这意味着您需要使用<excel_object>.Cells()。否则,您将收到类型不匹配错误。
Stevoisiak

88

如果您不想使用范围对象:

Function ColumnLetter(ColumnNumber As Long) As String
    Dim n As Long
    Dim c As Byte
    Dim s As String

    n = ColumnNumber
    Do
        c = ((n - 1) Mod 26)
        s = Chr(c + 65) & s
        n = (n - c) \ 26
    Loop While n > 0
    ColumnLetter = s
End Function

1
不清楚为什么您要发布一个更长的基于循环的方法,如果您不想使用范围对象:
brettdj 2014年

29
@brettdj我可以想象几个原因:1)通过我的测试,此方法快6倍左右2)不需要访问Excel API 3)大概具有较小的内存占用。编辑:另外,我不确定为什么我对一个多年前的答案发表评论了:S
Blackhawk

6
但是,提高速度有一个缺点。如果传递无效的列号,则使用范围对象将引发错误。即使有人仍在使用Excel 2003,它也可以工作。如果需要这种例外,请使用range方法。否则,对robartsd表示敬意。
Engineer Toast

6
IF ColumnNumber <= Columns.Count最好避免围绕版本进行假设。
brettdj

1
使用此代码的另一个原因是,如果您不在VBA中,而是在VB,.net等中
Maury Markowitz


33

我很惊讶没有人建议:** <code> </ code> <code> Columns(</ code> *** <code> Column Index </ code> *** <code>)。Address </ code> <code> </ code> **

  • 例如: MsgBox Columns( 9347 ).Address return ** <code> $ MUM:$ MUM </ code> **

返回列字母Split((Columns(Column Index).Address(,0)),":")(0)

  • 例如: MsgBox Split((Columns( 2734 ).Address(,0)),":")(0) return ** <code> DAD </ code> **

  更多例子



这在Office 365中对我有用:string col = Worksheet.Columns [column] .Address; 返回col.Substring(col.IndexOf(“:”)+ 2); 由于某些原因,其他表达式(例如Range = Worksheet.Cells [1,column])抛出错误(无论是在Cells调用中还是当我尝试获取地址时,都不记得了-对不起-哪些行在其中
萨姆·阿泽

19

只是执行此操作的另一种方法。Brettdj的回答让我想到了这一点,但是如果您使用此方法,则不必使用变体数组,则可以直接使用字符串。

ColLtr = Cells(1, ColNum).Address(True, False)
ColLtr = Replace(ColLtr, "$1", "")

或者可以使它更紧凑

ColLtr = Replace(Cells(1, ColNum).Address(True, False), "$1", "")

注意,这确实取决于您引用cell对象中的第1行。


18

以及使用递归的解决方案:

Function ColumnNumberToLetter(iCol As Long) As String

    Dim lAlpha As Long
    Dim lRemainder As Long

    If iCol <= 26 Then
        ColumnNumberToLetter = Chr(iCol + 64)
    Else
        lRemainder = iCol Mod 26
        lAlpha = Int(iCol / 26)
        If lRemainder = 0 Then
            lRemainder = 26
            lAlpha = lAlpha - 1
        End If
        ColumnNumberToLetter = ColumnNumberToLetter(lAlpha) & Chr(lRemainder + 64)
    End If

End Function

剪切和粘贴非常适合转换大于676的数字。谢谢!
David Krider 2014年

1
余数永远不能超过26,那么为什么不整数而不是long呢?
卡托

10
@Caltor除非您有使用Integer的特殊用途,例如调用需要一个API的API,否则永远不要在Long上选择Integer。VBA针对Longs进行了优化。VBA处理Longs的速度比Integers更快。
Excel英雄

1
@ExcelHero我不知道。Long不会比Integer占用更多的内存吗?
卡托2015年

6
@Caltor实际上,Long是32位,而Integer是16位。但这在现代计算中并不重要。25年前...这很重要。但是今天(甚至是15年前),这种差异完全没有意义。
Excel英雄

9

这可以通过使用公式来获得:

=SUBSTITUTE(ADDRESS(1,COLUMN(),4),"1","")

因此也可以根据要求编写为VBA函数:

Function ColName(colNum As Integer) As String
    ColName = Split(Worksheets(1).Cells(1, colNum).Address, "$")(1)
End Function

8

这是robartsd的答案的版本(具有Jan Wijninckx的单行解决方案的风格),使用递归而不是循环。

Public Function ColumnLetter(Column As Integer) As String
    If Column < 1 Then Exit Function
    ColumnLetter = ColumnLetter(Int((Column - 1) / 26)) & Chr(((Column - 1) Mod 26) + Asc("A"))
End Function

我已经使用以下输入进行了测试:

1   => "A"
26  => "Z"
27  => "AA"
51  => "AY"
702 => "ZZ"
703 => "AAA" 
-1  => ""
-234=> ""

2
我刚刚注意到,这本质上与Nikolay Ivanov的解决方案相同,这使我的解决方案不那么新颖。我将其保留,因为对于某些细节,它显示出略有不同的方法
亚历山大

好的解决方案有两个原因:不使用任何对象(例如范围,单元格等);非常紧凑的定义。
love.by.Jesus,

8

罗伯茨的代码很优雅,但为了使其适应未来发展,请将n的声明更改为long类型

如果您想让公式避免使用宏,则可以使用以下内容(包括第702列)

=IF(A1>26,CHAR(INT((A1-1)/26)+64),"")&CHAR(MOD(A1-1,26)+65)

其中A1是包含要转换为字母的列号的单元格。


7

最新更新:请忽略下面的功能,@SurasinTancharoen设法提醒我它在处已损坏n = 53
对于那些感兴趣的人,下面是其他一些破碎的值n = 200

的某些值

请使用@brettdj函数满足您的所有需求。它甚至适用于Microsoft Excel最新的最大列数限制:16384应该给出XFD

在此处输入图片说明

更新结束


下面的功能由Microsoft提供:

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

资源: 如何将Excel列号转换为字母字符

适用于

  • 微软办公软件 Excel 2007
  • Microsoft Excel 2002标准版
  • Microsoft Excel 2000标准版
  • Microsoft Excel 97标准版

2
作为参考,此列具有较大的列集,因为Chr()不能很好地处理大量数字。
Azuvector 2014年

2
这有一个错误。尝试将ConvertToLetter(53)设为“ BA”,但会失败。
Surasin Tancharoen

@SurasinTancharoen非常感谢您注意到此缺陷。我从没想过Microsoft会提供一个损坏的功能,因为他们是自己创建Microsoft Excel的人。从现在开始,我将放弃此功能,并将使用@brettdj函数,甚至可以更正最新的Microsoft Excel最大列数限制Col_Letter(16384) = "XFD"
mtbink.com 2015年

4
这个“ 27分频”来自哪里?最后我检查了26个字母。这就是这段代码中断的原因。
ib11

5

这是一个基于@DamienFennelly上面的答案的函数。如果您给我竖起大拇指,也给他竖起大拇指!:P

Function outColLetterFromNumber(iCol as Integer) as String
    sAddr = Cells(1, iCol).Address
    aSplit = Split(sAddr, "$")
    outColLetterFromNumber = aSplit(1)
End Function

2
好人,但与接受的答案有何不同?
Ioannis

@loannis我基于DamianFennelly的回答,而不是被接受的回答。但是,是的,我的看起来很像被接受的答案,只是一行被分成两行以使其更具可读性。
BrettFromLA 2014年

3

使用Excel功能有一种非常简单的方法:Use Range.Cells.Address属性,这种方式:

strCol = Cells(1, lngRow).Address(xlRowRelative, xlColRelative)

这将返回上一行所需列的地址1.把它的1

strCol = Left(strCol, len(strCol) - 1)

请注意,它是如此快速且强大,您可以返回甚至存在的列地址!

lngRow使用Selection.Column属性替换所需的列号!


2

这是一个可以使用的简单衬管。

ColumnLetter = Mid(Cells(Row, LastColA).Address, 2, 1)

它仅适用于1个字母的列指定,但对简单的情况很好。如果您需要它专门用于2个字母的指定,则可以使用以下代码:

ColumnLetter = Mid(Cells(Row, LastColA).Address, 2, 2)

2

无论您的代码行中位于X行,Y列中的单元格中的哪一列,这都将起作用:

Mid(Cells(X,Y).Address, 2, instr(2,Cells(X,Y).Address,"$")-2)

如果您的单元格具有唯一定义的名称“ Cellname”:

Mid(Cells(1,val(range("Cellname").Column)).Address, 2, instr(2,Cells(1,val(range("Cellname").Column)).Address,"$")-2)

1

brettdj的解决方案效果极佳,但是如果出于与我相同的原因而将其作为潜在的解决方案,我想我会提供我的替代解决方案。

我遇到的问题是根据MATCH()函数的输出滚动到特定的列。我选择将参考样式从A1临时切换为R1C1,而不是将列号转换为平行的列字母。这样,我可以滚动到列号,而不必使用VBA函数。要在两种参考样式之间轻松切换,可以使用以下VBA代码:

Sub toggle_reference_style()

If Application.ReferenceStyle = xlR1C1 Then
  Application.ReferenceStyle = xlA1
Else
  Application.ReferenceStyle = xlR1C1
End If

End Sub

1

为了进一步回答brettdj,这里使列号的输入为可选。如果省略了列号输入,则该函数将返回调用该函数的单元格的列字母。我知道这也可以仅使用来实现ColumnLetter(COLUMN()),但我认为,如果它能很好地理解,那将是很好的。

Public Function ColumnLetter(Optional ColumnNumber As Long = 0) As String
    If ColumnNumber = 0 Then
        ColumnLetter = Split(Application.Caller.Address(True, False, xlA1), "$")(0)
    Else
        ColumnLetter = Split(Cells(1, ColumnNumber).Address(True, False, xlA1), "$")(0)
    End If
End Function

此功能的折衷之处在于,由于IF测试,它会比brettdj的回答慢很多。但是,如果该功能重复使用了很多次,就会感觉到。


1

这是一个迟到的回答,只是用简单的方法Int(),并If在1-3个字符列的情况下:

Function outColLetterFromNumber(i As Integer) As String

    If i < 27 Then       'one-letter
        col = Chr(64 + i)
    ElseIf i < 677 Then  'two-letter
        col = Chr(64 + Int(i / 26)) & Chr(64 + i - (Int(i / 26) * 26))
    Else                 'three-letter
        col = Chr(64 + Int(i / 676)) & Chr(64 + Int(i - Int(i / 676) * 676) / 26)) & Chr(64 + i - (Int(i - Int(i / 676) * 676) / 26) * 26))
    End If

    outColLetterFromNumber = col

End Function

1
Function fColLetter(iCol As Integer) As String
  On Error GoTo errLabel
  fColLetter = Split(Columns(lngCol).Address(, False), ":")(1)
  Exit Function
errLabel:
  fColLetter = "%ERR%"
End Function

1

这里,是Pascal(Delphi)中的一个简单函数。

function GetColLetterFromNum(Sheet : Variant; Col : Integer) : String;
begin
  Result := Sheet.Columns[Col].Address;  // from Col=100 --> '$CV:$CV'
  Result := Copy(Result, 2, Pos(':', Result) - 2);
end;

1

该公式将基于范围(即A1)给出列,其中range是单个单元格。如果给出了一个多单元格范围,它将返回左上角的单元格。注意,两个单元格引用必须相同:

MID(CELL(“ address”,A1),2,SEARCH(“ $”,CELL(“ address”,A1),2)-2)

这个怎么运作:

CELL(“ property”,“ range”)根据所使用的属性返回范围的特定值。在这种情况下,单元地址。地址属性返回值$ [col] $ [row],即A1-> $ A $ 1。MID函数解析$符号之间的列值。


0

获取列名的简单方法

Sub column()

cell=cells(1,1)
column = Replace(cell.Address(False, False), cell.Row, "")
msgbox column

End Sub

我希望它可以帮助=)


0
Sub GiveAddress()
    Dim Chara As String
    Chara = ""
    Dim Num As Integer
    Dim ColNum As Long
    ColNum = InputBox("Input the column number")

    Do
        If ColNum < 27 Then
            Chara = Chr(ColNum + 64) & Chara
            Exit Do
        Else
            Num = ColNum / 26
            If (Num * 26) > ColNum Then Num = Num - 1
            If (Num * 26) = ColNum Then Num = ((ColNum - 1) / 26) - 1
            Chara = Chr((ColNum - (26 * Num)) + 64) & Chara
            ColNum = Num
        End If
    Loop

    MsgBox "Address is '" & Chara & "'."
End Sub

0

所以我在这里参加聚会很晚,但是我想提出另一个答案,这个答案没有人解决,但还不涉及数组。您可以通过简单的字符串操作来实现。

Function ColLetter(Col_Index As Long) As String

    Dim ColumnLetter As String

    'Prevent errors; if you get back a number when expecting a letter, 
    '    you know you did something wrong.
    If Col_Index <= 0 Or Col_Index >= 16384 Then
        ColLetter = 0
        Exit Function
    End If

    ColumnLetter = ThisWorkbook.Sheets(1).Cells(1, Col_Index).Address     'Address in $A$1 format
    ColumnLetter = Mid(ColumnLetter, 2, InStr(2, ColumnLetter, "$") - 2)  'Extracts just the letter

    ColLetter = ColumnLetter
End Sub

输入格式后$A$1,使用Mid函数,从第2个位置开始计算第一个位置$,然后使用找出第二个$在字符串中出现的位置InStr,然后减去2以说明该起始位置。

这使您具有适应所有可能的列范围的优势。因此,ColLetter(1)返回“ A”,并 ColLetter(16384)返回“ XFD”,这是我的Excel版本的最后一个可能的列。


-1

可以通过以下步骤使用公式从列号中提取 列字母 : 1.
使用ADDRESS公式计算列地址
2.使用MID和FIND函数提取列字母

示例:
1. ADDRESS(1000,1000,1)
结果$ ALL $ 1000
2 = MID(F15,2,FIND(“ $”,F15,2)-2)
结果所有假定F15包含步骤1的结果。

我们可以一次性编写
MID(ADDRESS(1000,1000,1),2,FIND (“ $”,ADDRESS(1000,1000,1),2)-2)


-1

这仅用于REFEDIT ...通常在不久后使用此处的代码版本...易于阅读和理解/它使用$的poz

Private Sub RefEdit1_Change()

    Me.Label1.Caption = NOtoLETTER(RefEdit1.Value) ' you may assign to a variable  var=....'

End Sub

Function NOtoLETTER(REFedit)

    Dim First As Long, Second As Long

    First = InStr(REFedit, "$")                 'first poz of $
    Second = InStr(First + 1, REFedit, "$")     'second poz of $

    NOtoLETTER = Mid(REFedit, First + 1, Second - First - 1)   'extract COLUMN LETTER

End Function


-2

仅转换为ascii数字并使用Chr()转换回字母怎么办?

col_letter = Chr(选择栏+ 96)


-6

这是另一种方式:

{

      Sub find_test2()

            alpha_col = "A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,W,Z" 
            MsgBox Split(alpha_col, ",")(ActiveCell.Column - 1) 

      End Sub

}

1
无需创建列出字母的字符串。ASCII本质上为我们做到了。
卡托
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.