Подтвердить что ты не робот

Перевести индекс столбца в имя столбца Excel

Учитывая индекс столбцов, как вы можете получить имя столбца Excel?

Проблема сложнее, чем кажется, потому что она не только base-26. Столбцы не обертываются, как обычные цифры. Даже Пример поддержки Microsoft не масштабируется за пределами ZZZ.

Отказ от ответственности: это какой-то код, который я сделал некоторое время назад, и сегодня он столкнулся с моим рабочим столом. Я думал, что это достойно публикации здесь как вопрос до ответа.

4b9b3361

Ответ 1

Ответ, который я придумал, - это немного рекурсивный. Этот код находится в VB.Net:

Function ColumnName(ByVal index As Integer) As String
        Static chars() As Char = {"A"c, "B"c, "C"c, "D"c, "E"c, "F"c, "G"c, "H"c, "I"c, "J"c, "K"c, "L"c, "M"c, "N"c, "O"c, "P"c, "Q"c, "R"c, "S"c, "T"c, "U"c, "V"c, "W"c, "X"c, "Y"c, "Z"c}

        index -= 1 ''//adjust so it matches 0-indexed array rather than 1-indexed column

        Dim quotient As Integer = index \ 26 ''//normal / operator rounds. \ does integer division, which truncates
        If quotient > 0 Then
               ColumnName = ColumnName(quotient) & chars(index Mod 26)
        Else
               ColumnName = chars(index Mod 26)
        End If
End Function

И в С#:

string ColumnName(int index)
{
    index -= 1; //adjust so it matches 0-indexed array rather than 1-indexed column

    int quotient = index / 26;
    if (quotient > 0)
        return ColumnName(quotient) + chars[index % 26].ToString();
    else
        return chars[index % 26].ToString();
}
private char[] chars = new char[] {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};

Единственным недостатком является то, что он использует столбцы с 1 индексом, а не 0-индексированные.

Ответ 2

Здесь замечательный код Joel, модифицированный для работы с нулевыми индексами столбцов и без массива char.

 Public Shared Function GetExcelColumn(ByVal index As Integer) As String

        Dim quotient As Integer = index \ 26 ''//Truncate 
        If quotient > 0 Then
            Return GetExcelColumn(quotient - 1) & Chr((index Mod 26) + 64).ToString

        Else
            Return Chr(index + 64).ToString

        End If

    End Function

Ответ 3

Именно по этой причине я избегаю имен столбцов в запрограммированном интерфейсе для Excel. Использование столбца числа отлично работает в ссылках Cell (r, c) и адресации R1C1.

EDIT: функция Range также принимает ссылки на ячейки, как в Range (Cell (r1, c1), Cell (r2, c2)). Кроме того, вы можете использовать функцию Address, чтобы получить адрес ячейки A1 или диапазон.

EDIT2: Здесь функция VBA, которая использует функцию Address() для извлечения имени столбца:

Function colname(colindex)
    x = Cells(1, colindex).Address(False, False) ' get the range name (e.g. AB1)
    colname = Mid(x, 1, Len(x) - 1)              ' return all but last character
End Function

Ответ 4

# Python 2.x, no recursive function calls

def colname_from_colx(colx):
    assert colx >= 0
    colname = ''
    r = colx
    while 1:
        r, d = divmod(r, 26)
        colname = chr(d + ord('A')) + colname
        if not r:
            return colname
        r -= 1

Ответ 5

public static String translateColumnIndexToName(int index) {
        //assert (index >= 0);

        int quotient = (index)/ 26;

        if (quotient > 0) {
            return translateColumnIndexToName(quotient-1) + (char) ((index % 26) + 65);
        } else {
            return "" + (char) ((index % 26) + 65);
        }


    }

и тест:

for (int i = 0; i < 100; i++) {
            System.out.println(i + ": " + translateColumnIndexToName(i));
}

вот результат:

0: A
1: B
2: C
3: D
4: E
5: F
6: G
7: H
8: I
9: J
10: K
11: L
12: M
13: N
14: O
15: P
16: Q
17: R
18: S
19: T
20: U
21: V
22: W
23: X
24: Y
25: Z
26: AA
27: AB
28: AC

Мне понадобилось 0 для POI

и перевод из индекса в имена:

public static int translateComunNameToIndex0(String columnName) {
        if (columnName == null) {
            return -1;
        }
        columnName = columnName.toUpperCase().trim();

        int colNo = -1;

        switch (columnName.length()) {
            case 1:
                colNo = (int) columnName.charAt(0) - 64;
                break;
            case 2:
                colNo = ((int) columnName.charAt(0) - 64) * 26 + ((int) columnName.charAt(1) - 64);
                break;
            default:
                //illegal argument exception
                throw new IllegalArgumentException(columnName);
        }

        return colNo;
    }

Ответ 6

Это старый пост, но, увидев некоторые из решений, я придумал свой собственный вариант С#. 0-Based, без рекурсии:

public static String GetExcelColumnName(int columnIndex)
{
    if (columnIndex < 0)
    {
        throw new ArgumentOutOfRangeException("columnIndex: " + columnIndex);
    }
    Stack<char> stack = new Stack<char>();
    while (columnIndex >= 0)
    {
        stack.Push((char)('A' + (columnIndex % 26)));
        columnIndex = (columnIndex / 26) - 1;
    }
    return new String(stack.ToArray());
}

Вот некоторые результаты теста в ключевых точках перехода:

0: A
1: B
2: C
...
24: Y
25: Z
26: AA
27: AB
...
50: AY
51: AZ
52: BA
53: BB
...
700: ZY
701: ZZ
702: AAA
703: AAB

Ответ 7

Версия php, спасибо этому сообщению, чтобы помочь мне разобраться! ^^

/**
 * Get excel column name
 * @param index : a column index we want to get the value in excel column format
 * @return (string) : excel column format
 */
function getexcelcolumnname($index) {
    //Get the quotient : if the index superior to base 26 max ?
    $quotient = $index / 26;
    if ($quotient >= 1) {
        //If yes, get top level column + the current column code
        return getexcelcolumnname($quotient-1). chr(($index % 26)+65);
    } else {
        //If no just return the current column code
        return chr(65 + $index);
    }
}

Ответ 8

Решение для JavaScript

/**
 * Calculate the column letter abbreviation from a 0 based index
 * @param {Number} value
 * @returns {string}
 */
getColumnFromIndex = function (value) {
    var base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
    value++;
    var remainder, result = "";
    do {
        remainder = value % 26;
        result = base[(remainder || 26) - 1] + result;
         value = Math.floor(value / 26);
    } while (value > 0);
    return result;
};

Ответ 9

в python с рекурсией. переведено из Joey answer. до сих пор он тестировался для работы с GetExcelByColumn (35) = 'AI'

def GetExcelColumn(index):

    quotient = int(index / 26)

    if quotient > 0:
        return GetExcelColumn(quotient) + str(chr((index % 26) + 64))

    else:
        return str(chr(index + 64))

Ответ 10

Мне нравится писать рекурсивные функции, но я не думаю, что это необходимо здесь. Это мое решение в VB. Он работает до столбца ZZ. Если кто-то скажет мне, работает ли это на AAA на ZZZ, что было бы хорошо знать.

Public Function TranslateColumnIndexToName(index As Integer) As String
'
Dim remainder As Integer
Dim remainder2 As Integer
Dim quotient As Integer
Dim quotient2 As Integer
'
quotient2 = ((index) / (26 * 26)) - 2
remainder2 = (index Mod (26 * 26)) - 1
quotient = ((remainder2) / 26) - 2
remainder = (index Mod 26) - 1
'
If quotient2 > 0 Then
    TranslateColumnIndexToName = ChrW(quotient2 + 65) & ChrW(quotient + 65) & ChrW(remainder + 65)
ElseIf quotient > 0 Then
    TranslateColumnIndexToName = ChrW(quotient + 65) & ChrW(remainder + 65)
Else
    TranslateColumnIndexToName = ChrW(remainder + 65)
End If 

Конечная функция

Ответ 11

Вот мое решение в С#

// test
void Main()
{

    for( var i = 0; i< 1000; i++ )
    {   var byte_array = code( i );
        Console.WriteLine("{0} | {1} | {2}", i, byte_array, offset(byte_array));
    }
}

// Converts an offset to AAA code
public string code( int offset )
{
    List<byte> byte_array = new List<byte>();
    while( offset >= 0 )
    {
        byte_array.Add( Convert.ToByte(65 + offset % 26) );
        offset = offset / 26 - 1;
    }
    return ASCIIEncoding.ASCII.GetString( byte_array.ToArray().Reverse().ToArray());
}

// Converts AAA code to an offset
public int offset( string code)
{
    var offset = 0;
    var byte_array = Encoding.ASCII.GetBytes( code ).Reverse().ToArray();
    for( var i = 0; i < byte_array.Length; i++ )
    {
        offset += (byte_array[i] - 65 + 1) * Convert.ToInt32(Math.Pow(26.0, Convert.ToDouble(i)));
    }
    return offset - 1;
}

Ответ 12

Вот мой ответ в С#, для перевода обоих способов между индексом столбца и именем столбца.

/// <summary>
/// Gets the name of a column given the index, as it would appear in Excel.
/// </summary>
/// <param name="columnIndex">The zero-based column index number.</param>
/// <returns>The name of the column.</returns>
/// <example>Column 0 = A, 26 = AA.</example>
public static string GetColumnName(int columnIndex)
{
    if (columnIndex < 0) throw new ArgumentOutOfRangeException("columnIndex", "Column index cannot be negative.");

    var dividend = columnIndex + 1;
    var columnName = string.Empty;

    while (dividend > 0)
    {
        var modulo = (dividend - 1) % 26;
        columnName = Convert.ToChar(65 + modulo) + columnName;
        dividend = (dividend - modulo) / 26;
    }

    return columnName;
}

/// <summary>
/// Gets the zero-based column index given a column name.
/// </summary>
/// <param name="columnName">The column name.</param>
/// <returns>The index of the column.</returns>
public static int GetColumnIndex(string columnName)
{
    var index = 0;
    var total = 0;
    for (var i = columnName.Length - 1; i >= 0; i--)
        total += (columnName.ToUpperInvariant()[i] - 64) * (int)Math.Pow(26, index++);

    return total - 1;
}

Ответ 13

В Ruby:

class Fixnum
  def col_name
    quot = self/26
    (quot>0 ? (quot-1).col_name : "") + (self%26+65).chr
  end
end

puts 0.col_name # => "A"
puts 51.col_name # => "AZ"

Ответ 14

Эта версия JavaScript показывает, что в ее основе это преобразование в базу 26:

function colName(x)
{
    x = (parseInt("ooooooop0", 26) + x).toString(26);
    return x.slice(x.indexOf('p') + 1).replace(/./g, function(c)
    {
        c = c.charCodeAt(0);
        return String.fromCharCode(c < 64 ? c + 17 : c - 22);
    });
}

Бит .toString(26) показывает, что Joel Coehoorn ошибочен: это простое базовое преобразование.

(Примечание: у меня есть более прямолинейная реализация, основанная на ответе Даны на производстве. Она менее тяжелая, работает для больших чисел, хотя это не повлияет на меня, но также не показывает математический принцип так ясно).

P.S. Здесь функция, вычисляемая в важных точках:

0 A
1 B
9 J
10 K
24 Y
25 Z
26 AA
27 AB
700 ZY
701 ZZ
702 AAA
703 AAB
18276 ZZY
18277 ZZZ
18278 AAAA
18279 AAAB
475252 ZZZY
475253 ZZZZ
475254 AAAAA
475255 AAAAB
12356628 ZZZZY
12356629 ZZZZZ
12356630 AAAAAA
12356631 AAAAAB
321272404 ZZZZZY
321272405 ZZZZZZ
321272406 AAAAAAA
321272407 AAAAAAB
8353082580 ZZZZZZY
8353082581 ZZZZZZZ
8353082582 AAAAAAAA
8353082583 AAAAAAAB

Ответ 15

это с Swift 4:

@IBAction func printlaction(_ sender: Any) {
    let textN : Int = Int (number_textfield.text!)!
    reslut.text = String (printEXCL_Letter(index: textN))
}


func printEXCL_Letter(index : Int) -> String {

    let letters = ["a", "b", "c","d", "e", "f","g", "h", "i","j", "k", "l","m", "n", "o","p", "q", "r","s", "t", "u","v","w" ,"x", "y","z"]

    var index = index;
    index -= 1
    let index_div = index / 26

    if (index_div > 0){
        return printEXCL_Letter(index: index_div) + letters[index % 26];
    }
    else {
        return letters[index % 26]
    }
}