it-swarm.com.de

Algorithmus zum Abrufen des Excel-ähnlichen Spaltennamens einer Zahl

Ich arbeite an einem Skript, das einige Excel-Dokumente generiert, und ich muss eine Zahl in das entsprechende Spaltennamen umwandeln. Zum Beispiel:

1 => A
2 => B
27 => AA
28 => AB
14558 => UMX

Ich habe bereits einen Algorithmus dafür geschrieben, aber ich würde gerne wissen, ob es einfachere oder schnellere Möglichkeiten gibt, dies zu tun:

function numberToColumnName($number){
    $abc = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    $abc_len = strlen($abc);

    $result_len = 1; // how much characters the column's name will have
    $pow = 0;
    while( ( $pow += pow($abc_len, $result_len) ) < $number ){
        $result_len++;
    }

    $result = "";
    $next = false;
    // add each character to the result...
    for($i = 1; $i<=$result_len; $i++){
        $index = ($number % $abc_len) - 1; // calculate the module

        // sometimes the index should be decreased by 1
        if( $next || $next = false ){
            $index--;
        }

        // this is the point that will be calculated in the next iteration
        $number = floor($number / strlen($abc));

        // if the index is negative, convert it to positive
        if( $next = ($index < 0) ) {
            $index = $abc_len + $index;
        }

        $result = $abc[$index].$result; // concatenate the letter
    }
    return $result;
}

Kennen Sie einen besseren Weg, um es zu tun? Vielleicht etwas einfacher zu halten? oder eine Leistungssteigerung?

Bearbeiten

die Implementierung von ircmaxell funktioniert ziemlich gut. Aber ich werde diese schöne kurze hinzufügen:

function num2alpha($n)
{
    for($r = ""; $n >= 0; $n = intval($n / 26) - 1)
        $r = chr($n%26 + 0x41) . $r;
    return $r;
}
75
Cristian

Hier ist eine einfache rekursive Funktion von Nice (basierend auf null indizierten Zahlen, dh 0 == A, 1 == B usw.) ...

function getNameFromNumber($num) {
    $numeric = $num % 26;
    $letter = chr(65 + $numeric);
    $num2 = intval($num / 26);
    if ($num2 > 0) {
        return getNameFromNumber($num2 - 1) . $letter;
    } else {
        return $letter;
    }
}

Und wenn Sie es indiziert haben wollen (1 == A usw.):

function getNameFromNumber($num) {
    $numeric = ($num - 1) % 26;
    $letter = chr(65 + $numeric);
    $num2 = intval(($num - 1) / 26);
    if ($num2 > 0) {
        return getNameFromNumber($num2) . $letter;
    } else {
        return $letter;
    }
}

Getestet mit Zahlen von 0 bis 10000 ...

129
ircmaxell

Verwenden von PhpSpreadsheet (PHPExcel ist veraltet)

// result = 'A'
\PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex(1);

Notizindex 0 führt zu 'Z'

https://phpspreadsheet.readthedocs.io/de/develop/


Die richtige Antwort (wenn Sie PHPExcel Library verwenden) lautet:

// result = 'A'
$columnLetter = PHPExcel_Cell::stringFromColumnIndex(0); // ZERO-based! 

und rückwärts:

// result = 1
$colIndex = PHPExcel_Cell::columnIndexFromString('A');
75
ksn135

Indiziert für 1 -> A, 2 -> B usw

function numToExcelAlpha($n) {
    $r = 'A';
    while ($n-- > 1) {
        $r++;
    }
    return $r;
}

Indiziert für 0 -> A, 1 -> B usw

function numToExcelAlpha($n) {
    $r = 'A';
    while ($n-- >= 1) {
        $r++;
    }
    return $r;
}

Nutzt die Tatsache, dass PHP der Perl-Konvention folgt, wenn es um arithmetische Operationen für Zeichenvariablen und nicht um C geht. Beachten Sie, dass Zeichenvariablen erhöht, aber nicht dekrementiert werden können.

12
Mark Baker

Dies gilt für die Konvertierung (vorausgesetzt, die Ganzzahlarithmetik), aber ich stimme den anderen Postern zu. benutze einfach base_convert

function numberToColumnName($number)
{
    $abc = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    $len = strlen($abc);

    $result = "";
    while ($number > 0) {
       $index  = $number % $len;
       $result = $abc[$index] . $result;
       $number = floor($number / $len);
    }

    return $result;
}
4
Lucas

Zahl in Excel-Spaltenbuchstaben konvertieren:

/**
 * Number convert to Excel column letters
 * 
 * 1 = A
 * 2 = B
 * 3 = C
 * 27 = AA
 * 1234567789 = CYWOQRM
 * 
 * @link https://vector.cool/php-number-convert-to-Excel-column-letters-2
 * 
 * @param int  $num       欄數
 * @param bool $uppercase 大小寫
 * @return void
 */
function num_to_letters($n)
{
    $n -= 1;
    for ($r = ""; $n >= 0; $n = intval($n / 26) - 1)
        $r = chr($n % 26 + 0x41) . $r;
    return $r;
}

ex:

echo num_to_letters(1);          // A
echo num_to_letters(2);          // B
echo num_to_letters(3);          // C
echo num_to_letters(27);         // AA
echo num_to_letters(1234567789); // CYWOQRM

Excel-Spaltenbuchstaben in Zahl konvertieren:

/**
 * Excel column letters convert to Number
 *
 * A = 1
 * B = 2
 * C = 3
 * AA = 27
 * CYWOQRM = 1234567789
 * 
 * @link https://vector.cool/php-number-convert-to-Excel-column-letters-2
 * 
 * @param string $letters
 * @return mixed
 */
function letters_to_num($a)
{
    $l = strlen($a);
    $n = 0;
    for ($i = 0; $i < $l; $i++)
        $n = $n * 26 + ord($a[$i]) - 0x40;
    return $n;
}

ex:

echo letters_to_num('A');       // 1
echo letters_to_num('B');       // 2
echo letters_to_num('C');       // 3
echo letters_to_num('AA');      // 27
echo letters_to_num('CYWOQRM'); // 1234567789
2
Ann

Späte Antwort, aber hier ist was ich getan habe (für 1 == A indexiert):

function num_to_letters($num, $uppercase = true) {
    $letters = '';
    while ($num > 0) {
        $code = ($num % 26 == 0) ? 26 : $num % 26;
        $letters .= chr($code + 64);
        $num = ($num - $code) / 26;
    }
    return ($uppercase) ? strtoupper(strrev($letters)) : strrev($letters);
}

Dann, wenn Sie in die andere Richtung konvertieren möchten:

function letters_to_num($letters) {
    $num = 0;
    $arr = array_reverse(str_split($letters));

    for ($i = 0; $i < count($arr); $i++) {
        $num += (ord(strtolower($arr[$i])) - 96) * (pow(26,$i));
    }
    return $num;
}
2
Mike
<?php
function numberToColumnName($number){
    $abc = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    $abc_len = strlen($abc);

    $result = "";
    $tmp = $number;

    while($number > $abc_len) {
        $remainder = $number % $abc_len;
        $result = $abc[$remainder-1].$result;
        $number = floor($number / $abc_len);
    }
    return $abc[$number-1].$result;
}

echo numberToColumnName(1)."\n";
echo numberToColumnName(25)."\n";
echo numberToColumnName(26)."\n";
echo numberToColumnName(27)."\n";
echo numberToColumnName(28)."\n";
echo numberToColumnName(14558)."\n";
?>
1
corsiKa

Die rekursive Antwort von ircmaxell kombiniert, habe ich folgende:

 Funktion getNameFromNumber ($ num, $ index = 0) {
 $ index = abs ($ index * 1); // Stellen Sie sicher, dass der Index eine positive ganze Zahl ist 
 $ numerisch = ($ num - $ index)% 26; 
 $ letter = chr (65 + $ numerisch); 
 $ num2 = intval (($ num - $ index)/26); 
 if ($ num2> 0) {
 return getNameFromNumber ($ num2 - 1 + $ index). $ letter; 
 } else {
 Rückgabe von $ letter; 
 } 
 } 

Ich verwende die Standard-Indizierung als 0-basiert, aber es kann eine beliebige positive Ganzzahl sein, wenn Sie mit Arrays in PHP jonglieren.

1

Ich würde das nie in der Produktion verwenden, weil es nicht lesbar ist, aber aus Spaß ... nur für ZZ.

<?php
    $col = 55;
    print (($n = (int)(($col - 1) / 26)) ? chr($n + 64) : '') . chr((($col - 1) % 26) + 65);
?>
0
simesy