Как вы определяете имя столбца (например, "AQ" или "BH" ) n-го столбца в Excel?
Редактировать. Алгоритм языка-агностика для определения этого является главной целью здесь.
Как вы определяете имя столбца (например, "AQ" или "BH" ) n-го столбца в Excel?
Редактировать. Алгоритм языка-агностика для определения этого является главной целью здесь.
Я однажды написал эту функцию для выполнения этой точной задачи:
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, но не стесняйтесь использовать свой любимый язык):
String getNthColumnName(int n) {
String name = "";
while (n > 0) {
n--;
name = (char)('A' + n%26) + name;
n /= 26;
}
return name;
}
Но, пожалуйста, дайте мне знать о том, нашли ли вы ошибку в этом коде, спасибо.
Агностический алгоритм языка был бы следующим:
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 снова обновляется для обработки столбцов более 16 тыс. Если вы действительно хотели зайти за борт, вы можете передать дополнительное значение и заменить экземпляры 26 другим номером, чтобы разместить альтернативные алфавиты
Спасибо, Джозеф Стертевант! Ваш код работает отлично - мне он нужен в 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
Код Джозефа хорош, но если вы не хотите или не хотите использовать функцию VBA, попробуйте это.
Предполагая, что значение n находится в ячейке A2
Используйте эту функцию:
=MID(ADDRESS(1,A2),2,LEN(ADDRESS(1,A2))-3)
IF(COLUMN()>=26,CHAR(ROUND(COLUMN()/26,1)+64)&CHAR(MOD(COLUMN(),26)+64),CHAR(COLUMN()+64))
Это работает 2 столбца (до столбца ZZ
). Вам нужно было бы вложить другой оператор if для трехбуквенных столбцов.
Вышеуказанная формула терпит неудачу в столбцах AY
, AZ
и каждой из следующих столбцов nY
и nZ
. Исправленная формула:
=IF(COLUMN()>26,CHAR(ROUNDDOWN((COLUMN()-1)/26,0)+64)&CHAR(MOD((COLUMN()-1),26)+65),CHAR(COLUMN()+64)
FROM wcm:
Если вы не хотите использовать VBA, вы можете использовать это замените colnr на нужное число
=MID(ADDRESS(1,colnr),2,LEN(ADDRESS(1,colnr))-3)
Обратите внимание на то, что эта формула является изменчивой из-за использования функции ADDRESS. Неустойчивые функции - это функции, которые пересчитываются через excel после КАЖДОГО изменения. Обычно excel пересчитывает формулу только тогда, когда изменяется их зависимые ссылки.
Это может быть убийца производительности, чтобы использовать эту формулу.
И вот переход от версии 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
Ruby one-liner:
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. Наконец присоединяется к ним все вместе. Нет деления, модуля или рекурсии.
Fun.
Это отлично работает в MS Excel 2003-2010. Должен работать для предыдущих версий, поддерживающих Cells (...). Адрес:
columnNumber=28
; Cells(1, columnNumber).Address
возвращает "$AB$1"
.$
возвращает массив: ["","AB","1"]
Split(Cells(1, columnNumber).Address, "$")(1)
дает имя столбца "AB"
.UPDATE:
Взято из Как конвертировать номера столбцов Excel в алфавитном порядке
' 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
Я полагаю, вам нужен код VBA:
Public Function GetColumnAddress(nCol As Integer) As String
Dim r As Range
Set r = Range("A1").Columns(nCol)
GetColumnAddress = r.Address
End Function
Это делает то, что вы хотите в 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
Это похоже на 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
Я взял Джозефа и проверил его на BH, а затем накормил его 980-1000, и он выглядел хорошо.
В VBA, если lCol - это номер столбца:
function ColNum2Letter(lCol as long) as string
ColNum2Letter = Split(Cells(1, lCol).Address, "$")(0)
end function
Все эти образцы кода, которые эти хорошие люди разместили, выглядят отлично.
Есть одна вещь, о которой нужно знать. Начиная с Office 2007, на самом деле Excel имеет до 16384 столбцов. Это переводит на XFD (старый максимум 256 колонок был IV). Вам придется немного изменить эти методы, чтобы заставить их работать на три символа.
Не должно быть так сложно...
Здесь решение Гэри Уотерса
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 (верхнее 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).
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
В настоящее время я использую это, но у меня есть ощущение, что его можно оптимизировать.
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())