システム開発の現場では、Excelで定義書を作って、定義書からソースコードを生成することがよくあります。
この中で、user_profile_id(スネークケース)とuserProfileId(キャメルケース)を行き来する変換がよくあり、この地味な変換作業は、VBAマクロでやってました。
(以前、関数でやろうとしたこともありましたが、SUBSTITUTE のネストが深くなって可読性が大変悪かったのでやめました)
Excelの LET関数、LAMBDA関数 が登場したことで、VBAマクロを書かなくても、 Excel関数 だけで書けるようになったので、試してみました。
1. スネークケース → キャメルケース (TOCAMEL)
user_profile_id を userProfileId に変換します。
数式(名前の定義に貼り付けて使用)
=LAMBDA(_セル範囲,
MAP(_セル範囲, LAMBDA(_セル,
IF(OR(ISERROR(_セル), _セル=""), _セル,
LET(
_文字, IF(ISNUMBER(_セル), TEXT(_セル, "@"), _セル),
_先頭文字, LEFT(_文字, 1),
IFS(
ISERROR(VALUE(_先頭文字))=FALSE, _文字 & "_ERROR_NUM_START",
ISNUMBER(FIND(" ", _文字)), _文字 & "_ERROR_CONTAIN_SPACE",
TRUE, LET(
_分割, TEXTSPLIT(_文字, "_"),
_先頭単語, LOWER(INDEX(_分割, 1)),
_以降の単語, PROPER(DROP(_分割, , 1)),
CONCAT(_先頭単語, _以降の単語)
)
)
)
)
))
)
ポイント:あえて「汚い変数名」を生成する
1user_2user のような「数字始まり」のスネークケースは、多くのプログラミング言語で変数名として不正です。
それっぽく 1user2User に変換してしまうこともできるのですが、後でコンパイルエラーになってメンドクサイです。
この関数では間にスペースが入ったり、数字始まりの場合、接尾辞を付与してます。
#N/Aとかのエラー値はそのままの値を返してます。こうすることで、おかしな変換に気づきやすくしてます。
-
1user2User// エラー箇所が埋もれる -
1user_2user_ERROR_NUM_START// 「ここがおかしい!」と気づきやすくする -
user profile_id_ERROR_CONTAIN_SPACE// 「ここがおかしい!」と気づきやすくする
「Fail Loudly:エラーが発生したら、即座に、かつ目立つ形で警告を出し、プログラムを止めるか、異常であることを知らせる」考え方で、設計書や定義書のバグを見つけやすくしています。
2. キャメルケース → スネークケース (TOSNAKE)
userProfileId を user_profile_id(または大文字の USER_PROFILE_ID)に変換します。
数式(名前の定義に貼り付けて使用)
=LAMBDA(_セル範囲, [_出力形式upper],
MAP(_セル範囲, LAMBDA(_セル,
IF(OR(ISERROR(_セル), _セル=""), _セル,
LET(
_文字, IF(ISNUMBER(_セル), TEXT(_セル, "@"), _セル),
_先頭文字, LEFT(_文字, 1),
IFS(
ISERROR(VALUE(_先頭文字))=FALSE, _文字 & "_ERROR_NUM_START",
ISNUMBER(FIND(" ", _文字)), _文字 & "_ERROR_CONTAIN_SPACE",
TRUE, LET(
_文字配列, MID(_文字, SEQUENCE(LEN(_文字)), 1),
_変換処理, MAP(_文字配列, LAMBDA(_char,
IF(AND(EXACT(_char, UPPER(_char)), ISERROR(VALUE(_char))),
"_" & LOWER(_char),
_char
)
)),
_結合結果, TEXTJOIN("", TRUE, _変換処理),
_頭抜き, IF(LEFT(_結合結果, 1)="_", RIGHT(_結合結果, LEN(_結合結果)-1), _結合結果),
IF(UPPER(_出力形式upper)="UPPER", UPPER(_頭抜き), LOWER(_頭抜き))
)
)
)
)
))
)
ポイント
-
数字とアルファベットの区別:
user1User2を変換する際、1も大文字判定されてUSER_1_USER_2になるのを防いでいます。VALUE関数で数値判定を行うことで、数字を単語の一部として扱い、期待値通りのuser1_user2を出力します。 -
PascalCase対応: クラス名など先頭が大文字(
UserProfile)の場合、単純変換すると_user_profileと頭にアンダースコアがついてしまいます。これを_頭抜き処理で除去しています。 -
間にスペースや数字はじまりはエラー: 変換元の文字列の末尾に
_ERROR_NUM_STARTや_ERROR_CONTAIN_SPACEを付与して即座に知らせます。
使い方イメージ
| A列 (元データ) | B列 (変換後) | 使用した関数 | 備考 |
|---|---|---|---|
user_profile_id |
userProfileId |
=TOCAMEL(A2) |
通常変換 |
user profile_id |
user profile_id_ERROR_CONTAIN_SPACE |
=TOCAMEL(A2) |
スペース混入警告 |
user1_user2 |
user1User2 |
=TOCAMEL(A2) |
数字混じりもOK |
1user_2user |
1user_2user_ERROR_NUM_START |
=TOCAMEL(A2) |
数字始まり警告 |
userProfileId |
user_profile_id |
=TOSNAKE(A2) |
通常変換 |
UserProfileId |
user_profile_id |
=TOSNAKE(A2) |
PascalCase対応 |
userProfileId |
USER_PROFILE_ID |
=TOSNAKE(A2, "UPPER") |
定数用大文字 |
1stUser |
1stUser_ERROR_NUM_START |
=TOSNAKE(A2) |
数字始まり警告 |
User Name |
User Name_ERROR_CONTAIN_SPACE |
=TOSNAKE(A2) |
スペース混入警告 |
導入方法
- Excelの [数式] タブ > [名前の定義] をクリック。
-
名前 に
TOCAMEL(またはTOSNAKE)と入力。 - 参照範囲 に上記のコードをコピペして保存。
一度名前定義すれば、そのブック内では標準関数と同じように呼び出せます。
思ったこと
Excelの LAMBDA関数 は、「手続き型プログラミング脳」を「関数型プログラミング脳」に鍛える訓練になるなぁと。
(LAMBDA と6文字使うのが残念なところだが...)