Преобразовать десятичную дробь в алфавитный идентификатор столбца? - PullRequest
1 голос
/ 27 марта 2009

Работая с некоторыми элементами электронных таблиц, внутренне столбцы обозначаются простым десятичным числом (0 проиндексировано), но для вывода мне нужно, чтобы он был в стандартном удобочитаемом формате:

A, B, C, .. Z, AA, AB, AC, .. AZ, BA ..

Сначала я подумал: «Легко! Я просто переключусь на базу 26 и использую [AZ] вместо [0-9A-P]», за исключением того, что при использовании этой техники получается A => 0. B => 1. Поэтому последовательность на самом деле выглядит так:

A, B, .. Y, Z, BA, BB

Как преобразовать десятичные дроби в имя столбца в стиле Excel?

Ответы [ 6 ]

2 голосов
/ 27 марта 2009
0 голосов
/ 12 мая 2010

Не было бы полным без версии Java ...

protected static String columnLetter( int columnNumber ) {
 if( columnNumber < 0 ) return "Err";
 if( columnNumber < 26 )
  return Character.toString((char) (columnNumber+ 65));
 return columnLetter( (columnNumber / 26) - 1) + 
  columnLetter ( columnNumber % 26 );
}

(на основе рекурсивного примера VB .NET)

0 голосов
/ 27 марта 2009

Вот решение в PHP, взятое в значительной степени непосредственно из этого ответа от Грэма :

function rowCol2Cell($row, $col) {
    $dividend = $col + 1;
    $columnName = '';

    while ($dividend > 0) {
        $modulo = ($dividend - 1) % 26;
        $columnName = chr(65 + $modulo) . $columnName;
        $dividend = (int)(($dividend - $modulo) / 26);
    }

    return $columnName . ($row + 1);
}

// rowCol2Cell(0, 0) = "A1"
// rowCol2Cell(0, 1) = "B1"
// rowCol2Cell(0,26) = "AA1"

Редактировать

Если вы используете модуль PHP PEAR Spreadsheet Excel Writer, эта функция имеет встроенную функцию:

Spreadsheet_Excel_Writer::rowcolToCell

Я, наверное, должен был просто RTFM, эй ...

0 голосов
/ 27 марта 2009

В коде VB .NET и использовании рекурсии для выразительности

  Function Decimal2ExcelAZ(ByVal number As Integer) As String
    If number < 0 Then
      Throw New Exception("Number cannot be negative")
    ElseIf number < 26 Then
      Rem 65 is the ASCII of "A"
      Return New String(Chr(65 + number) + "")        
    Else
      Return Decimal2ExcelAZ(number \ 26 - 1) + Decimal2ExcelAZ(number Mod 26)
    End If
  End Function
0 голосов
/ 27 марта 2009

Вот функция VB. Используя модуль и логарифм, он тривиален и не требует рекурсии:

Function ColumnLetter(ByVal colNum As Long) As String
    Dim i As Long, x As Long
    For i = Int(Log(CDbl(25 * (CDbl(colNum) + 1))) / Log(26)) - 1 To 0 Step -1
        x = (26 ^ (i + 1) - 1) / 25 - 1
        If colNum > x Then
           ColumnLetter = ColumnLetter & Chr(((colNum - x - 1) \ 26 ^ i) Mod 26 + 65)
        End If
    Next i
End Function  

Soure

0 голосов
/ 27 марта 2009

Это, вероятно, не самый эффективный способ, но он довольно лаконичен и работает. Вероятно, стоит поставить проверку диапазона, чтобы он не превышал ZZ в рабочем коде, так как я подозреваю, что тогда могут произойти плохие вещи. И, конечно, вы можете расширить условный оператор до if/else, если он вам не нравится.

static string ColumnPrefix(int column)
{
    Debug.Assert(column >= 0, "Column would be below 'A'.");
    Debug.Assert(column <= 26 * 27, "Column would be above 'ZZ'.");

    Func<int, string> itoa = i => new string((char)('A' + i), 1);
    return column < 26 ? 
               itoa(column) : 
               itoa((column - 26) / 26) + itoa(column % 26);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...