開発の現場では、Excelに定義したクラスやテーブル等の設計内容に基づいて、VBAで自動的にソースコードやSQL文等の成果物を生成したい場合があります。この処理を実装する場合、Excel上の項目名を、成果物の項目で使用されている命名規則に合わせて変換する機能が必要となります。
ここでは、命名規則に合わせて項目名を変換するためのサンプルを説明します。
概要
- ケバブケースから、スネークケース、パスカルケース、キャメルケース間で識別名を変換するサンプルです。
- 例えば、スネークケースからケバブケースに変換する場合は、Snake2Kebab関数を使用します。
- 各変換関数は「命名規則に基づいて文字列を複数の単語に分割する関数」(XXX2Words関数)、「分割された単語を命名規則に基づいて変換する関数」(Words2XXX関数)という2つの関数を組み合わせて変換しています。
- どちらの関数も、単語分割の区切り文字として半角空白を使用しています。例えば、”snakeToKebab”をケバブに変換する場合、Snake2Kebab関数では、Snake2Words関数とWords2Kebab関数を実行しています。
Snake2Words関数で単語の区切りに空白を挿入して”snake To Kebab”を生成します。Words2Kebabでは、半角空白を”-“に置換(かつ小文字化)して”snake-to-kebab”を生成します。 - 拡張性を持たせるために、このような作りになっています。もっと特定用途のために単純に実現することもできると思います。例えば、ケバブケースからスネークケースに変換するような場合、
Replace(kebab, "-", "_")等で変換できます。 - 元々は、”getHTTPClient”を”GetHttpClient”のように、大文字が連続する略語を含むキャメルケースをパスカルケースに変換するのが単純にできなくて作ったサンプルです。
サンプルコード
Option Explicit
Sub Main()
Debug.Print "========"
Debug.Print "---2Kebab"
Debug.Print Snake2Kebab("here_we_are") 'here-we-are
Debug.Print Pascal2Kebab("HereWeAre") 'here-we-are
Debug.Print Camel2Kebab("hereWeAre") 'here-we-are
Debug.Print "---2Snake"
Debug.Print Kebab2Snake("here-we-are") 'here_we_are
Debug.Print Pascal2Snake("HereWeAre") 'here_we_are
Debug.Print Camel2Snake("hereWeAre") 'here_we_are
Debug.Print "---2Pascal"
Debug.Print Kebab2Pascal("here-we-are") 'HereWeAre
Debug.Print Snake2Pascal("here_we_are") 'HereWeAre
Debug.Print Camel2Pascal("hereWeAre") 'HereWeAre
Debug.Print "---2Camel"
Debug.Print Kebab2Camel("here-we-are") 'hereWeAre
Debug.Print Snake2Camel("here_we_are") 'hereWeAre
Debug.Print Pascal2Camel("HereWeAre") 'hereWeAre
Debug.Print "---CamelVariation"
Debug.Print Camel2Kebab("update") 'update
Debug.Print Camel2Kebab("getHttp") 'get-http
Debug.Print Camel2Kebab("getHTTPClient") 'get-http-client
Debug.Print Camel2Kebab("setOpt1TextBox") 'set-opt1-text-box
Debug.Print Camel2Kebab("setURI") 'set-uri
Debug.Print Camel2Kebab("readEMail") 'read-e-mail
Debug.Print Camel2Kebab("readEmail") 'read-email
End Sub
'変換関数 ==================================================
'ケバブケースから変換する関数群
Public Function Kebab2Snake(kebab As String)
Kebab2Snake = Words2Snake(Kebab2Words(kebab))
End Function
Public Function Kebab2Pascal(kebab As String)
Kebab2Pascal = Words2Pascal(Kebab2Words(kebab))
End Function
Public Function Kebab2Camel(kebab As String)
Kebab2Camel = Words2Camel(Kebab2Words(kebab))
End Function
'スネークケースから変換する関数群
Public Function Snake2Kebab(snake As String)
Snake2Kebab = Words2Kebab(Snake2Words(snake))
End Function
Public Function Snake2Pascal(snake As String)
Snake2Pascal = Words2Pascal(Snake2Words(snake))
End Function
Public Function Snake2Camel(snake As String)
Snake2Camel = Words2Camel(Snake2Words(snake))
End Function
'パスカルケースから変換する関数群
Public Function Pascal2Kebab(pascal As String)
Pascal2Kebab = Words2Kebab(Pascal2Words(pascal))
End Function
Public Function Pascal2Snake(pascal As String)
Pascal2Snake = Words2Snake(Pascal2Words(pascal))
End Function
Public Function Pascal2Camel(pascal As String)
Pascal2Camel = Words2Camel(Pascal2Words(pascal))
End Function
'キャメルケースから変換する関数群
Public Function Camel2Kebab(camel As String)
Camel2Kebab = Words2Kebab(Camel2Words(camel))
End Function
Public Function Camel2Snake(camel As String)
Camel2Snake = Words2Snake(Camel2Words(camel))
End Function
Public Function Camel2Pascal(camel As String)
Camel2Pascal = Words2Pascal(Camel2Words(camel))
End Function
'内部関数 ==================================================
'各ケースから単語群に変換する関数群-------------------------
Private Function Kebab2Words(kebab As String)
Kebab2Words = Replace(kebab, "-", " ")
End Function
Private Function Snake2Words(snake As String)
Snake2Words = Replace(snake, "_", " ")
End Function
Private Function Pascal2Words(pascal As String)
Pascal2Words = Camel2Words(pascal)
End Function
Private Function Camel2Words(camel As String)
Dim ucs As Boolean 'スキャンモード(Upper Case Scan)
Dim i As Integer
Dim ch As String
Dim nch As String
Dim s As String
For i = 1 To Len(camel)
'HTTP等の略語で大文字が連続する場合は、大文字+小文字の直前で区切る
'それ以外は、小文字orその他文字が大文字に切り替わる直前で区切る
ch = Mid(camel, i, 1)
nch = Mid(camel, i + 1, 1)
If Not ucs And IsUCase(ch) And IsUCase(nch) Then
'大文字が連続する場合はスキャンモード有効
s = ch: ucs = True
ElseIf ucs And IsUCase(ch) And IsLCase(nch) Then
'スキャンモードの場合、大文字+小文字の前で区切る
s = " " & ch: ucs = False
ElseIf (IsLCase(ch) Or IsOther(ch)) And IsUCase(nch) Then
'通常、小文字(+その他文字)が大文字に変わった場合に区切る
s = ch & " "
Else
s = ch
End If
Camel2Words = Camel2Words & s
Next
End Function
'単語群から各ケースに変換する関数群-------------------------
Private Function Words2Kebab(words As String)
Words2Kebab = Join(Split(LCase(words)), "-")
End Function
Private Function Words2Snake(words As String)
Words2Snake = Join(Split(LCase(words)), "_")
End Function
Private Function Words2Pascal(words As String)
Dim w As Variant
For Each w In Split(words)
'各単語の先頭を大文字、それ以降を小文字に変更
Words2Pascal = Words2Pascal & UCase(Mid(w, 1, 1)) & LCase(Mid(w, 2))
Next
End Function
Private Function Words2Camel(words As String)
'パスカルケースの先頭を小文字に変更
Dim pascal As String: pascal = Words2Pascal(words)
Words2Camel = LCase(Mid(pascal, 1, 1)) & Mid(pascal, 2)
End Function
'その他の関数群---------------------------------------------
Private Function IsUCase(ch As String)
IsUCase = False
If ch = "" Then Exit Function
Dim c As Integer: c = Asc(ch)
IsUCase = (&H41 <= c And c <= &H5A)
End Function
Private Function IsLCase(ch As String)
IsLCase = False
If ch = "" Then Exit Function
Dim c As Integer: c = Asc(ch)
IsLCase = (&H61 <= c And c <= &H7A)
End Function
Function IsOther(ch As String)
IsOther = (InStr("0123456789", ch) > 0)
End Function