Как мне найти имя столбца Excel, соответствующее заданному целому числу?[дубликат]

StackOverflow https://stackoverflow.com/questions/22708

Вопрос

Как бы вы определили имя столбца (например"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 в столбцы из 3 букв.

Приведенная выше формула не работает для столбцов AY, AZ и каждый из следующих nY и nZ колонны.Исправленная формула выглядит следующим образом:

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

ИЗ 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

Рубиновый однострочник:

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.Наконец-то объединяет их всех вместе.Никакого деления, модуля или рекурсии.

Весело.

Это прекрасно работает в MS Excel 2003-2010.Должно работать для предыдущих версий, поддерживающих Клетки (...).Адрес функция:

  1. Для 28 - й колонки - взятие columnNumber=28; Cells(1, columnNumber).Address ВОЗВРАТ "$AB$1".
  2. Делаю раскол на $ sign возвращает массив: ["","AB","1"]
  3. Итак Split(Cells(1, columnNumber).Address, "$")(1) дает вам имя столбца "AB".

Обновить:

Взято из Как преобразовать номера столбцов 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

Я взял Joseph и протестировал его на BH, затем ввел 980-1000, и он выглядел хорошо.

В VBA предполагается, что lCol - это номер столбца:

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

Все эти примеры кода, которые опубликовали эти хорошие люди, выглядят прекрасно.

Есть одна вещь, о которой следует помнить.Начиная с Office 2007, Excel фактически содержит до 16 384 столбцов.Это переводится в 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 (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).

К вашему сведению, 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;
}

=СИМВОЛ (64+СТОЛБЕЦ())

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top