【PHP】列Index値からExcelの列名を取得する方法
こんにちは、スズキです。
先日、検索結果をExcelファイルに出力してダウンロードする処理を開発していたのですが、
その際に、「列Index値からExcelの列名を取得できないかな?」と試行錯誤したので、
今回はそのときに行った対応方法を紹介しようと思います。
「0〜25」の数字を「A〜Z」の文字列に置き換える方法を紹介します。
まず、結論から言ってしまうと、「0〜25」の値を「A〜Z」の文字列に置き換える方法については、以下の式により実現できます。
では解説です。
まず、chrメソッド、ordメソッドですが、それぞれ以下の機能を持ったメソッドです。
なお、ここで$alphabetIndexは「目的の文字がAから何個分離れているか」を指した変数値です。(例:"C"の場合は$alphabetIndexが2になります。)
(1) 文字"A"のアスキーコード値
= ord("A")
(2) 文字「A〜Z」のアスキーコード値
= 文字"A"のアスキーコード値 + 「対象文字が"A"から何個分離れているか」
= ord("A") + $alphabetIndex
(3) 文字「A〜Z」
= chr(『文字「A〜Z」のアスキーコード値』)
= chr(ord("A") + $alphabetIndex)
皆さんもご存知の通り、Excelの列は「A、B、…、Z、AA、AB、…、AZ、BA、…」という形で列名が設定されています。
「0〜25」の列Index値をExcelの列名に置き換えるだけであれば、先ほど紹介したように
しかし、26以降の数字をExcelの列名("AA"などの値)に置き換えるには工夫が必要になります。
といっても、処理が若干複雑なだけでわざわざ解説するほどでも無いので変換メソッドを紹介するのみにとどめておこうと思います。
というわけで、列Index値をExcelの列名に置き換えるメソッドは以下になります。
これで、
「0、1、…、25、26、27、…」
という数値を
「A、B、…、Z、AA、AB、…」
という文字列に置き換えることができるようになりました。
ちなみに、Excel関係のプログラム処理を開発したことのある方であれば、
「Excelの列番号って0始まりではなく、1始まりの間違いでは?」
と疑問に思った方がいるかもしれないので補足をしておきます。
今回紹介したメソッドは以下のように、
「配列に出力するデータを格納→foreachで取り出してセル出力」
という使い方を想定して作成しています。
そのため、列Index値を「1始まり」で処理するよりも「0始まり」で処理した方が処理が自然になるため、今回紹介した方法は「0始まり」で解説しています。
(気に入らない方は適当にメソッドを修正してご利用ください)
先日、検索結果をExcelファイルに出力してダウンロードする処理を開発していたのですが、
その際に、「列Index値からExcelの列名を取得できないかな?」と試行錯誤したので、
今回はそのときに行った対応方法を紹介しようと思います。
「0〜25」の数字を「A〜Z」の文字列に置き換える方法
「0〜25」の数字を「A〜Z」の文字列に置き換える方法を紹介します。
まず、結論から言ってしまうと、「0〜25」の値を「A〜Z」の文字列に置き換える方法については、以下の式により実現できます。
$alphabet = chr(ord("A") + $alphabetIndex);
では解説です。
まず、chrメソッド、ordメソッドですが、それぞれ以下の機能を持ったメソッドです。
- chrメソッド:アスキーコード値から、対応する文字列を取得する。
- ordメソッド:「対象文字列の最初の文字」に対応したアスキーコード値を取得する。
なお、ここで$alphabetIndexは「目的の文字がAから何個分離れているか」を指した変数値です。(例:"C"の場合は$alphabetIndexが2になります。)
(1) 文字"A"のアスキーコード値
= ord("A")
(2) 文字「A〜Z」のアスキーコード値
= 文字"A"のアスキーコード値 + 「対象文字が"A"から何個分離れているか」
= ord("A") + $alphabetIndex
(3) 文字「A〜Z」
= chr(『文字「A〜Z」のアスキーコード値』)
= chr(ord("A") + $alphabetIndex)
任意の列Index値からExcelの列名を取得する方法
皆さんもご存知の通り、Excelの列は「A、B、…、Z、AA、AB、…、AZ、BA、…」という形で列名が設定されています。
「0〜25」の列Index値をExcelの列名に置き換えるだけであれば、先ほど紹介したように
$alphabet = chr(ord("A") + $alphabetIndex);
の式により取得することができます。しかし、26以降の数字をExcelの列名("AA"などの値)に置き換えるには工夫が必要になります。
といっても、処理が若干複雑なだけでわざわざ解説するほどでも無いので変換メソッドを紹介するのみにとどめておこうと思います。
というわけで、列Index値をExcelの列名に置き換えるメソッドは以下になります。
/**
* Excelの列名を取得します。
* @param $colIndex
* @return string
*/
public static function excelColName($colIndex)
{
if (!is_numeric($colIndex)) {
return "";
}
$retString = "";
$alphabetNum = 26;
$currentColIndex = $colIndex;
while (true) {
$alphabetIndex = $currentColIndex % $alphabetNum;
$alphabet = chr(ord("A") + $alphabetIndex);
$retString = $alphabet . $retString;
if ($currentColIndex < $alphabetNum) {
break;
}
$currentColIndex = intval(floor(($currentColIndex - $alphabetNum) / $alphabetNum));
};
return $retString;
}
これで、
「0、1、…、25、26、27、…」
という数値を
「A、B、…、Z、AA、AB、…」
という文字列に置き換えることができるようになりました。
余談
ちなみに、Excel関係のプログラム処理を開発したことのある方であれば、
「Excelの列番号って0始まりではなく、1始まりの間違いでは?」
と疑問に思った方がいるかもしれないので補足をしておきます。
今回紹介したメソッドは以下のように、
「配列に出力するデータを格納→foreachで取り出してセル出力」
という使い方を想定して作成しています。
// 出力情報加工
$detailInfoList = [];
$detailInfoList[] = [
"氏名",
"年齢",
"出身地",
];
foreach ($result->details as $detail) {
$detailInfoList[] = [
$detail->name,
$detail->age,
$detail->from,
];
}
// Excelに出力
$currentRowIndex = 1;
foreach ($detailInfoList as $detailInfo) {
foreach ($detailInfo as $colIndex => $colValue) {
$cellId = Str::excelColName($colIndex) . $currentRowIndex;
$sheet->setCellValue($cellId, $colValue);
}
$currentRowIndex++;
}
そのため、列Index値を「1始まり」で処理するよりも「0始まり」で処理した方が処理が自然になるため、今回紹介した方法は「0始まり」で解説しています。
(気に入らない方は適当にメソッドを修正してご利用ください)