Как реализовать самоименование столбца из его индекса? - PullRequest
0 голосов
/ 01 марта 2011

Я хотел бы иметь возможность создания экземпляра моего класса Cell, называя экземпляр ячейки такими именами, как "A", "B", "C" и т. Д., Как в электронной таблице Excel.

У меня есть Cell класс, например:

public class Cell {
    public Cell(Range nativeCell) {
        NativeCell = nativeCell;
    }

    public Range NativeCell { get; private set; }
}

И мой Sheet класс:

public class Sheet {
    private IDictionary<string, Cell> _cells;

    public Sheet(Worksheet nativeSheet) {
        NativeSheet = nativeSheet;

        _cells = new Dictionary<string, Cell>();

        for (int rowIndex = 1; rowIndex <= NativeSheet.Rows.Count; ++rowIndex)
            for (int colIndex = 1; colIndex <= NativeSheet.Columns.Count; ++colIndex) {
                ICell newCell = new Cell(NativeSheet.Cells(rowIndex, colIndex));
                newCell.Name = ?? // This name should look like "A1", "B1", "AA3", "CB20", etc.
                Cells.Add(newCell.Name, newCell);
            }
    }

    public IDictionary<string, Cell> Cells {
        get {
            return _cells;
        }
    }

    public Worksheet NativeSheet { get; private set; }
}

Мне нужно было бы сгенерировать имя на основе букв алфавита, удвоить и утроить их, как только я столкнусь с последней буквой алфавита 'Z'. Алгоритм должен был бы генерировать буквы, которые я бы конкатенировал со значением rowIndex, что привело бы к такой стратегии именования, как Excel.

Буквы будут:

A, B, C, D...Z, AA, AB, AC...AZ, BA, BB, BC...BZ, CA...XAA, XAB, XAC...

Хотя мы четко знаем, что colIndex значение 1 определенно будет обозначать столбец «A», значение 2 = «B», значение 3 = «C» и т. Д.

Моя проблема, особенно когда мы удваиваем буквы.

Есть ли у вас какие-либо идеи о том, как мне этого добиться в простейшей форме?

Спасибо! =) * * Тысяча двадцать пять

Ответы [ 2 ]

1 голос
/ 02 марта 2011

Эта функция сделает это за вас. Это в VB.NET, но я надеюсь, что вы сможете перенести его на C #, если это будет необходимо.
Я обновил ответ с помощью версии C # функции.

VB.NET

''' <summary>Returns the Excel-style name of the column from the column index.</summary>
''' <param name="colIndex">The column index.</param>
Function GetColumnName(ByVal colIndex As Integer) As String
    If colIndex < 1 Then Throw New ArgumentException("Column number must be greater or equal to 1.")

    Dim result As New List(Of String)

    'letter codes start at Chr(65)'
    Do While colIndex > 0
        'reduce the column number by 1 else the 26th column (Z) will become 0 (@) '
        'add 65 to the result and find the Chr() value.                           '
        'insert the character at position 0 of the character list                 '
        'integer divide by 26 to remove the column from the stack and repeat till '
        'there are no columns in the stack.                                       '
        result.Insert(0, Chr(65 + CInt((colIndex - 1) Mod 26)))
        colIndex = (colIndex - 1) \ 26
    Loop

    Return String.Join("", result.ToArray)
End Function

C #

/// <summary>Returns the Excel-style name of the column from the column index.</summary>
/// <param name="colIndex">The column index.</param>
static string GetColumnName(int colIndex)
{
    if (colIndex < 1)
        throw new ArgumentException("Column number must be greater or equal to 1.");

    var result = new List<char>();

    //letter codes start at Chr(65)'
    while (colIndex > 0)
    {
        //reduce the column number by 1 else the 26th column (Z) will become 0 (@) 
        //add 65 to the result and find the Chr() value.
        //insert the character at position 0 of the char list
        //integer divide the column index by 26 to remove the last calculated column 
        //from the stack and repeat till  there are no columns in the stack.                                       
        result.Insert(0, Microsoft.VisualBasic.Strings.Chr(65 + Convert.ToInt32((colIndex - 1) % 26)));
        colIndex = (int)((colIndex-1)/ 26);
    }

    return new string(result.ToArray());
}

Я проверял это до индекса столбца 1000, и он работал без сбоев.Я надеюсь, что вы найдете это полезным.

1 голос
/ 02 марта 2011

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

Не должно быть слишком сложно сделать его рекурсивным и дать вам именно то, что вам нужно. Надеюсь, это поможет.

...