Excel 欄位命名採用 26 進制字母系統:A~Z、AA~AZ、BA~BZ... 當導出數據超過 26 列(Z 列)時,如何將數字索引正確轉換為字母列名(如 26→AA,27→AB)成為常見需求。PHPExcel 內置提供了高效的轉換方法,本文詳細解析其實現原理與使用技巧。
PHPExcel_Cell 類中的靜態方法,採用靜態緩存優化性能:
public static function stringFromColumnIndex($pColumnIndex = 0) {
static $_indexCache = array();
if (!isset($_indexCache[$pColumnIndex])) {
if ($pColumnIndex < 26) {
// 0-25: A-Z
$_indexCache[$pColumnIndex] = chr(65 + $pColumnIndex);
} elseif ($pColumnIndex < 702) {
// 26-701: AA-ZZ (26*26=676)
$_indexCache[$pColumnIndex] = chr(64 + ($pColumnIndex / 26)) . chr(65 + $pColumnIndex % 26);
} else {
// 702+: AAA-ZZZ...
$_indexCache[$pColumnIndex] = chr(64 + (($pColumnIndex - 26) / 676))
. chr(65 + ((($pColumnIndex - 26) % 676) / 26))
. chr(65 + $pColumnIndex % 26);
}
}
return $_indexCache[$pColumnIndex];
}
| 索引範圍 | 列名範圍 | 位數 | 計算公式 |
|---|---|---|---|
| 0 ~ 25 | A ~ Z | 1 位 | chr(65 + index) |
| 26 ~ 701 | AA ~ ZZ | 2 位 | chr(64 + index/26) . chr(65 + index%26) |
| 702 ~ 18277 | AAA ~ ZZZ | 3 位 | chr(64 + (index-26)/676) . chr(65 + ((index-26)%676)/26) . chr(65 + index%26) |
反向轉換,支援任意長度列名:
// 使用示例
$index = PHPExcel_Cell::columnIndexFromString('AA'); // 返回 26
$index = PHPExcel_Cell::columnIndexFromString('ZZ'); // 返回 701
$index = PHPExcel_Cell::columnIndexFromString('AAA'); // 返回 702
<?php
require_once 'PHPExcel.php';
$objPHPExcel = new PHPExcel();
$sheet = $objPHPExcel->getActiveSheet();
// 假設有 50 個欄位需要導出
$headers = array('ID', '姓名', '部門', '職位', '入職日期', /* ...共50個*/ );
foreach ($headers as $index => $header) {
$col = PHPExcel_Cell::stringFromColumnIndex($index);
$sheet->setCellValue($col . '1', $header);
}
// 設置樣式
$sheet->getStyle('A1:' . PHPExcel_Cell::stringFromColumnIndex(count($headers)-1) . '1')
->getFont()->setBold(true);
$writer = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
$writer->save('export.xlsx');
?>
<?php
// 使用 fromArray 批量寫入,自動處理列名
$data = [
['ID', '姓名', '部門', /* ... */],
[1, '張三', '技術部', /* ... */],
[2, '李四', '市場部', /* ... */],
// ... 萬條數據
];
$sheet->fromArray($data, null, 'A1');
// 或指定起始列
$startCol = 'D'; // 從 D 列開始
$startIndex = PHPExcel_Cell::columnIndexFromString($startCol);
$sheet->fromArray($data, null, PHPExcel_Cell::stringFromColumnIndex($startIndex) . '1');
?>
<?php
class ExcelColumnHelper {
/**
* 數字索引轉字母列名 (0-based)
*/
public static function indexToColumn($index) {
$column = '';
do {
$column = chr(65 + ($index % 26)) . $column;
$index = floor($index / 26) - 1;
} while ($index >= 0);
return $column;
}
/**
* 字母列名轉數字索引 (0-based)
*/
public static function columnToIndex($column) {
$index = 0;
$len = strlen($column);
for ($i = 0; $i < $len; $i++) {
$index = $index * 26 + (ord($column[$i]) - 64);
}
return $index - 1; // 轉為 0-based
}
/**
* 獲取區域字符串 (如 A1:Z100)
*/
public static function getRange($startCol, $startRow, $endCol, $endRow) {
return $startCol . $startRow . ':' . $endCol . $endRow;
}
}
// 使用示例
echo ExcelColumnHelper::indexToColumn(0); // A
echo ExcelColumnHelper::indexToColumn(25); // Z
echo ExcelColumnHelper::indexToColumn(26); // AA
echo ExcelColumnHelper::indexToColumn(701); // ZZ
echo ExcelColumnHelper::indexToColumn(702); // AAA
echo ExcelColumnHelper::columnToIndex('A'); // 0
echo ExcelColumnHelper::columnToIndex('Z'); // 25
echo ExcelColumnHelper::columnToIndex('AA'); // 26
echo ExcelColumnHelper::columnToIndex('ZZ'); // 701
fromArray() 而非逐單元格 setCellValue()PHPExcel_CachedObjectStorageFactory 啟用磁盤緩存| 問題 | 原因 | 解決方案 |
|---|---|---|
| 列名超過 Z 後錯誤 | 手動拼接字母邏輯錯誤 | 使用內置 stringFromColumnIndex() |
| 大數據導出內存溢出 | PHPExcel 將所有數據載入內存 | 啟用 caching 或改用 PhpSpreadsheet + chunk 讀寫 |
| 列名轉換不一致 | 0-based vs 1-based 混淆 | 統一規範:PHPExcel 方法均為 0-based |
掌握 Excel 列名的 26 進制轉換規律,善用 PHPExcel 內置的 stringFromColumnIndex() 和 columnIndexFromString() 方法,能輕松解決超 26 列的導出難題。對於新項目,強烈建議遷移至 PhpSpreadsheet,其 API 兼容 PHPExcel 且性能大幅提升,同時支援更多格式(ODS、HTML、PDF 等)。