Сведения о вопросе

Математик

12:57, 8th August, 2020

Теги

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

Просмотров: 606   Ответов: 20

Как бы вы определили имя столбца (например, "AQ" или "BH") n-го столбца в Excel?

Edit: языковой агностический алгоритм для определения этого является здесь главной целью.



  Сведения об ответе

park

14:56, 27th August, 2020

Однажды я написал эту функцию для выполнения именно этой задачи:

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());
}


  Сведения об ответе

DINO

12:54, 18th August, 2020

Вот самое чистое правильное решение, которое я мог бы придумать (в Java, но не стесняйтесь использовать свой любимый язык):

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

Но, пожалуйста, дайте мне знать, если вы найдете ошибку в этом коде, спасибо.


  Сведения об ответе

9090

10:04, 28th August, 2020

Языковой агностический алгоритм будет выглядеть следующим образом:

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 другим числом, чтобы разместить альтернативные алфавиты


  Сведения об ответе

PAGE

09:43, 27th August, 2020

Спасибо, Джозеф Стертевант! Ваш код работает отлично - мне он был нужен в 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


  Сведения об ответе

fo_I_K

01:54, 28th August, 2020

Код Джозефа хорош, но если вы не хотите или не хотите использовать функцию VBA, попробуйте сделать это.

Предполагая, что значение n находится в ячейке A2 , используйте эту функцию:

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


  Сведения об ответе

KOMP

18:58, 13th August, 2020

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)


  Сведения об ответе

9090

09:47, 26th August, 2020

От wcm:

Если вы не хотите использовать VBA, вы можете использовать это замените colnr на нужный вам номер

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

Обратите внимание, что эта формула является изменчивой из-за использования функции ADDRESS. Волатильные функции - это функции, которые пересчитываются по excel после изменения EVERY. Обычно excel пересчитывает Формулы только при изменении их зависимых ссылок.

Это может быть убийцей производительности, если использовать эту формулу.


  Сведения об ответе

JUST___

19:13, 11th August, 2020

А вот и конвертация из версии 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


  Сведения об ответе

davran

21:54, 17th August, 2020

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

Веселье.


  Сведения об ответе

appple

23:05, 16th August, 2020

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


  Сведения об ответе

прога

19:11, 14th August, 2020

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

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


  Сведения об ответе

KOMP

18:06, 22nd August, 2020

Это, кажется, работает в 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, и он выглядел хорошо.


  Сведения об ответе

crush

16:23, 1st August, 2020

Я полагаю, вам нужен код VBA:

Public Function GetColumnAddress(nCol As Integer) As String

Dim r As Range

Set r = Range("A1").Columns(nCol)
GetColumnAddress = r.Address

End Function


  Сведения об ответе

SKY

20:50, 17th August, 2020

Это делает то, что вы хотите в 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


  Сведения об ответе

P_S_S

16:43, 10th August, 2020

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

Есть одна вещь, которую нужно осознавать. Начиная с Office 2007, Excel фактически содержит до 16 384 столбцов. Это означает XFD (старый максимум 256 столбцов был IV). Вам придется несколько изменить эти методы, чтобы они работали для трех символов.

Это не должно быть так сложно...


  Сведения об ответе

ASSembler

06:19, 14th August, 2020

Вот решение Гэри Уотерса

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/


  Сведения об ответе

LIZA

08:04, 24th August, 2020

Учитывая комментарий 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 символов, и у нас есть система счисления, такая же, как hex или двоичная, только с необычным набором символов (A..Z), представляющим позиционно степени 26: (26^2)(26^1)(26^0).


  Сведения об ответе

JUST___

13:23, 17th August, 2020

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


  Сведения об ответе

SSESION

15:29, 23rd August, 2020

В настоящее время я использую его, но у меня есть ощущение, что его можно оптимизировать.

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;
}


  Сведения об ответе

appple

02:45, 25th August, 2020

=CHAR(64+COLUMN())


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться