本问题已经有最佳答案,请猛点这里访问。
您如何确定Excel中第n列的列名(例如" AQ"或" BH")?
编辑:一种语言不可知的算法来确定这是这里的主要目标。
我曾经写过这个函数来执行确切的任务:
1 2 3 4 5 6 7 8 9 10
| 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());
} |
这是我能想到的最干净正确的解决方案(使用Java,但可以使用自己喜欢的语言):
1 2 3 4 5 6 7 8 9
| String getNthColumnName(int n) {
String name ="";
while (n > 0) {
n--;
name = (char)('A' + n%26) + name;
n /= 26;
}
return name;
} |
但是请让我知道如果您在此代码中发现错误,谢谢。
语言不可知算法将如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13
| 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个实例,以适应其他字母
谢谢,约瑟夫·斯特尔万特(Joseph Sturtevant)!您的代码运行完美-我在vbscript中需要它,所以想和我分享我的版本:
1 2 3 4 5 6 7 8 9 10 11 12 13
| 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 |
约瑟夫的代码不错,但是,如果您不需要或不需要使用VBA函数,请尝试一下。
假设n的值在单元格A2中
使用此功能:
1
| =MID(ADDRESS(1,A2),2,LEN(ADDRESS(1,A2))-3) |
从wcm:
如果您不想使用VBA,可以使用此
用您想要的号码替换colnr
1
| =MID(ADDRESS(1,colnr),2,LEN(ADDRESS(1,colnr))-3) |
请注意,由于使用了ADDRESS函数,此公式易变。易失函数是每次更改后excel都会重新计算的函数。
通常,excel仅在其依赖引用发生更改时才重新计算公式。
使用此公式可能会导致性能下降。
1
| IF(COLUMN()>=26,CHAR(ROUND(COLUMN()/26,1)+64)&CHAR(MOD(COLUMN(),26)+64),CHAR(COLUMN()+64)) |
这适用于2个字母列(直到列ZZ)。您必须为3个字母列嵌套另一个if语句。
上面的公式在列AY,AZ以及以下每个nY和nZ列上均无效。校正后的公式为:
1
| =IF(COLUMN()>26,CHAR(ROUNDDOWN((COLUMN()-1)/26,0)+64)&CHAR(MOD((COLUMN()-1),26)+65),CHAR(COLUMN()+64) |
Ruby一线:
1 2 3
| 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。最后,将他们重新团结在一起。无除法,模数或递归。
乐趣。
这是从VBScript版本到SQL Server 2000+的转换。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| 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 |
在MS Excel 2003-2010中可以正常工作。适用于支持Cells(...)。Address函数的早期版本:
对于第28列-采用columnNumber=28; Cells(1, columnNumber).Address返回"$AB$1"。
在$符号上进行拆分将返回数组:["","AB","1"]
因此,Split(Cells(1, columnNumber).Address,"$")(1)为您提供列名称"AB"。
更新:
摘自如何将Excel列号转换为字母字符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| ' 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 / 2002SE / 2000SE / 97SE
这似乎在vb.net中起作用
1 2 3 4 5 6 7 8 9 10 11
| 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喂食,看起来不错。
在VBA中,假设lCol是列号:
1 2 3
| function ColNum2Letter(lCol as long) as string
ColNum2Letter = Split(Cells(1, lCol).Address,"$")(0)
end function |
我想您需要VBA代码:
1 2 3 4 5 6 7 8
| Public Function GetColumnAddress(nCol As Integer) As String
Dim r As Range
Set r = Range("A1").Columns(nCol)
GetColumnAddress = r.Address
End Function |
这就是您在VBA中想要的
1 2 3 4 5
| 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 |
这些好人发布的所有这些代码示例看起来都不错。
有一件事情要注意。从Office 2007开始,Excel实际上最多有16,384列。转换为XFD(原来的256列最大值为IV)。您将不得不对这些方法进行一些修改,以使它们适用于三个字符。
不应该那么难...
这是Gary Waters解决方案
1 2 3 4 5 6 7 8 9
| 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/
考虑到wcm的注释(最高值= xfd),可以这样计算:
1 2 3 4 5 6 7 8 9 10
| 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)。
FYI T-SQL以单个语句为Excel列名指定序数(从零开始)。
小于0或大于16,383(Excel2010中的最大列)的任何值都将返回NULL。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| ; 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 |
我目前正在使用它,但是我感觉可以对其进行优化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| 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;
} |
= CHAR(64 + COLUMN())