数値を日付化型に変換し、和暦表示させる(VBA実践ケース1~その➀)
はじめに
プログラミング(Python)を学ぶ方の集まりに参加させていただています。
そこで、ある方から「こんな業務内容は自動化できないか?」というご相談がありました。
内容的に、VBAマクロの方が良いのではないかと思い。実現方式を考え、コードを書いてみました。
ある業務について、業務要件的なものが3つあり、それに対して3つコードを書きました。3回に分けて書いていきたいと思います。
そもそも、VBAって???方がいましたら、こちらをお読みください。
1. 数値を日付型にし、和暦表示させる
まず一つ目は、「業務システムからCSV出力される8桁の数値を、最終的に一覧上和暦表示できるようにしたいという内容」です。
2. インプットデータ
CSV出力される一覧が以下のようなものだった場合を想定しています。
3. VBAコード
実現のためのコードとしては、以下の通りです。
Sub 数値を日付型にして和暦表示()
Dim targetSheet As Worksheet
Dim periodColumn As Integer
Dim lastRow As Integer
Dim targetNum As Long
Dim targetStr As String
Dim dateVal As Date
Dim i As Integer
'操作するシートをオブジェクトセットし、アクティブ化する
Set targetSheet = ThisWorkbook.Worksheets("サンプル")
targetSheet.Activate
'最終行をlastRow変数に格納
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
'契約期間の列をperiodColumnに格納
periodColumn = Cells.Find("契約期間").Column
'値がある2行目から最終行までForループ処理
For i = 2 To lastRow
'i行目の契約期間(数値)を取得し、targetNum変数に格納
targetNum = Cells(i, periodColumn).Value
'targetNum変数を文字列に変換
targetStr = Str(targetNum)
'余分なスペースが入って8文字以上になってないか確認
If Len(targetStr) > 8 Then
'8文字以上の場合は、Replace関数でスペースを削除(置換)
targetStr = Replace(targetStr, " ", "")
End If
'Mid関数で4桁・2桁・2桁にし、スラッシュを間に入れて日付型に変換
dateVal = Mid(targetStr, 1, 4) & "/" & _
Mid(targetStr, 5, 2) & "/" & _
Mid(targetStr, 7, 2)
'Format関数で和暦変換する
Cells(i, periodColumn).Value = Format(dateVal, "ggge年m月d日")
Next i
End Sub
4. 複数行のデータを処理する準備
(1) 何行分処理すればいいかを確認する
まず数値を、日付型に変換しています。
複数行処理したいので、最終行を予め取得し、lastRow変数に格納します。
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
(2) 何列目が処理対象かを確認する
そして、契約期間の列数をperiodColumnという変数に数値型で格納しておきます。これはfind関数を使って行います。
periodColumn = Cells.Find("契約期間").Column
これで、何行分ループ処理を回して、どの列の値を修正していけばいいかが分かりました。
5. ループ処理を行う
何行(何回)処理を回せばいいか分かったので、forループ処理を使って処理を行います。
なお、数値型を日付型に変換し和暦にするために、以下の順番で行いました。
①文字列にする → ➁スラッシュ(/)を入れて、日付型にする→➂和暦にする
まずは、ループ処理を書きます。書き出しは・・・
for i = 2 to lastRow
となります。カウント変数であるiを2からスタートしているのは、1行目がヘッダーで、2行目から値が入力されているためです。
次にまずは、契約期間を取得します。
targetNum = Cells(i, periodColumn).Value
targetNumというLong型の変数を定義しておき、そこにi行目(初回ならi=2)のperiodColumn列目(これはずっと5)のセルの値を格納します。
なお、VBAには複数数値型があります。Integerという数値型だと、-32,767~32,767の範囲しか扱えないため、オーバーフロー(エラー)となります。
そのため、Longという数値型にしています。
これをStr関数で文字列に変換します。
targetStr = Str(targetNum)
なお、この時F8のデバッグモードで確認していただくと分かるのですが、なぜか先頭に半角スペースが入ります。この後、日付型にする時に邪魔なので、その場合スペースを消す処理を行います。
桁数を確認して、スペースを取り除くにはReplace関数を使います。
if Len(targetStr) > 8 Then
Replace(targetStr, " ", "")
if文で、Len関数という文字列の文字数を返す関数で、8文字超となっている場合は、Replace関数の引数に対象の文字列(targetStr)、置き替え対象の文字(” ” 半角スペース)、置き替え後の文字(”” 削除)、という引数を与えます。
次に、4桁(西暦年)、2桁(月)、2桁(日)に区切って間にスラッシュ(/)を入れることで、日付型として扱えるようにしています。
dateVal = Mid(targetStr, 1, 4) & "/" & _
Mid(targetStr, 5, 2) & "/" & _
Mid(targetStr, 7, 2)
dateValという、日付型の変数を定義しておき、そこにMid関数で対象の文字列(targetStr)の1文字目から4文字を取り出し、&(アンパサンド)で文字型"/"を結合、同様にMid関数で対象の文字列(targetStr)の5文字目から2文字を取り出し、また&でスラッシュと結合、最後に日にちとして7行目から2文字を取り出して結合すれば、”XXXX/XX/XX”という日付型が完成します。
最後に、日付型をFormat関数で和暦表示に変換します。
Cells(i, periodColumn).Value = Format(dateVal, "ggge年m月d日")
i行目のperiodColumn列目のセルの値に、Format関数でdateValという日付型の変数を"ggge年m月d日"という表示形式で与えてね、と書いてます。
Next i
でループ処理が最終行までされますと、以下のように和暦表示に変換されます。
ご自身で、今度は和暦から8桁の数値に戻すプログラムをModule2とかに作ってみると、理解が進むと思います。
6. さいごに
僕のnoteでVBAのマガジンを書いてますので、気になった方は他のも読んでみてください。できるだけ、これができてなんになるのだろう?
と勉強中の方が、余計混乱しないよう、「なんのためにこのコード」を書いているのか?を実践的に書けたらなーと工夫しておいます。