如何通过索引实现列的自我命名?

13 浏览
0 Comments

如何通过索引实现列的自我命名?

我希望能够实例化我的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 _cells;
    public Sheet(Worksheet nativeSheet) {
        NativeSheet = nativeSheet;
        _cells = new Dictionary();
        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 = ?? // 这个名称应该看起来像"A1"、"B1"、"AA3"、"CB20"等。
                Cells.Add(newCell.Name, newCell);
            }
    }
    public IDictionary 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"等。

我的问题特别在于当我们加倍字母时。

你有任何简单实现这个的想法吗?

谢谢!=)

0
0 Comments

如何从索引实现列自命名?

问题的出现原因:VB.NET代码中的问题导致了列名计算错误。

解决方法:修复VB.NET代码中的错误。

下面是修复后的VB.NET代码:

''' Returns the Excel-style name of the column from the column index.
''' The column index.
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#版本的代码:

/// Returns the Excel-style name of the column from the column index.
/// The column index.
static string GetColumnName(int colIndex)
{
    if (colIndex < 1)
        throw new ArgumentException("Column number must be greater or equal to 1.");
    var result = new List();
    //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也没有问题。

原问题与Joel Coehoorn在类似问题的答案之间的区别在于,我的解决方法可以计算从列索引1到整型的最大值,而Joel的解决方法只能计算到列索引26。

此外,我认为while循环在处理数学模运算时会带来一些额外的处理开销,因为只有26个字符需要关注。当获取一个大于1的数的模时,这意味着你必须将字符加倍,依此类推。至于Joel Coehoorn的答案,它是递归的,所以它会将返回的字符串加倍和三倍,因此它应该可以处理任何整数值,就我了解的算法而言。

修复错误后的代码经过测试,可以正确计算列名。

0
0 Comments

问题的出现原因:

在Excel表格中,每个列都有一个索引值,但是通常情况下我们更习惯使用列的字母编号来表示列的位置。因此,有时候我们需要将列的索引值转换为相应的字母编号。

解决方法:

可以通过递归的方式将列的索引值转换为相应的字母编号。以下是一个可能的实现方法:

def get_column_name(index):
    if index <= 0:
        return ""
    else:
        return get_column_name((index - 1) // 26) + chr((index - 1) % 26 + ord('A'))
column_index = 28
column_name = get_column_name(column_index)
print(column_name)

运行以上代码,将输出列索引值为28的列的字母编号,即"AB"。

希望这个方法能帮到你。

0