Je travaille sur un script qui génère des documents Excel et je dois convertir un nombre en son nom de colonne équivalent. Par exemple:
1 => A
2 => B
27 => AA
28 => AB
14558 => UMX
J'ai déjà écrit un algorithme pour le faire, mais j'aimerais savoir s'il existe des moyens plus simples ou plus rapides de le faire:
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;
}
Connaissez-vous une meilleure façon de le faire? Peut-être quelque chose pour le garder plus simple? ou une amélioration de la performance?
l'implémentation d'ircmaxell fonctionne plutôt bien. Mais, je vais ajouter ce joli court:
function num2alpha($n)
{
for($r = ""; $n >= 0; $n = intval($n / 26) - 1)
$r = chr($n%26 + 0x41) . $r;
return $r;
}
Voici une belle fonction récursive simple (Basée sur zéro nombre indexé, ce qui signifie 0 == A, 1 == B, etc.) ...
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;
}
}
Et si vous le voulez indexé (1 == A, etc):
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;
}
}
Testé avec des nombres de 0 à 10000 ...
Utilisation de PhpSpreadsheet (PHPExcel est obsolète)
// result = 'A'
\PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex(1);
Note index 0 résultats dans 'Z'
https://phpspreadsheet.readthedocs.io/en/develop/
La réponse correcte (si vous utilisez la bibliothèque PHPExcel) est:
// result = 'A'
$columnLetter = PHPExcel_Cell::stringFromColumnIndex(0); // ZERO-based!
et à l'envers:
// result = 1
$colIndex = PHPExcel_Cell::columnIndexFromString('A');
Indexé pour 1 -> A, 2 -> B, etc.
function numToExcelAlpha($n) {
$r = 'A';
while ($n-- > 1) {
$r++;
}
return $r;
}
Indexé pour 0 -> A, 1 -> B, etc.
function numToExcelAlpha($n) {
$r = 'A';
while ($n-- >= 1) {
$r++;
}
return $r;
}
Profite du fait que PHP suit la convention de Perl lorsqu'il traite des opérations arithmétiques sur les variables de caractère et non sur les C. Notez que les variables de caractère peuvent être incrémentées mais pas décrémentées.
Cela va faire la conversion (en supposant l'arithmétique entière), mais je suis d'accord avec les autres affiches; utilisez simplement 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;
}
Nombre converti en lettres de colonnes Excel:
/**
* 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
Les lettres des colonnes Excel sont converties en nombre:
/**
* 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
Réponse tardive, mais voici ce que j'ai fait (pour 1 == indexé):
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);
}
Ensuite, si vous voulez convertir dans l'autre sens:
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;
}
<?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";
?>
En combinant la réponse récursive d'ircmaxell, j'ai celle-ci:
fonction getNameFromNumber ($ num, $ index = 0) { $ index = abs ($ index * 1); // vérifie que index est un entier positif $ numeric = ($ num - $ index)% 26; $ lettre = chr (65 + $ numérique); $ num2 = intval (($ num - $ index)/26); si ($ num2> 0) { retourne getNameFromNumber ($ num2 - 1 + $ index). $ lettre; } autre { return $ letter; } }
J'utilise l'indexation par défaut comme étant basée sur 0, mais il peut s'agir d'un entier positif pour jongler avec des tableaux en PHP.
Je n'utiliserais jamais cela en production car ce n'est pas lisible, mais pour le plaisir ......... Ne fait que jusqu'à ZZ.
<?php
$col = 55;
print (($n = (int)(($col - 1) / 26)) ? chr($n + 64) : '') . chr((($col - 1) % 26) + 65);
?>