2022年4月 プログラムの話 その2 | 初めての犬飼い日記

初めての犬飼い日記

シゲという名前の保護犬を飼うことになったアラフォーオッサンの記録です

 

誰も待っていないでしょうが、未来の自分の為に(最近、色々と忘れっぽくて困るのよ笑い泣き

昨日の記事の続きを書いていきたいと思います。

 

 

前回は元号の情報を設定したテーブルを準備したところまで終わってましたので、早速ですが変換用のプログラムコードをささっと列挙してしまいます。

 

まずは、年・月・日をパラメータとして渡すと、和暦文字列に変換するプログラムです。

 

年月日→元号年月日の文字列に変換する
      
Public Function YMD2ERA(ByVal y As Integer, ByVal m As Integer, ByVal d As Integer, ByRef rng As Range) As Variant

    ' 引数を日付型へ変換する
    Dim dt As Date
    dt = DateSerial(y, m, d)
    
    ' 該当する元号を探す
    Dim r As Long
    For r = 1 To rng.Rows.Count
        ' 開始年月日の取得
        Dim sy As Integer, sm As Integer, sd As Integer
        sy = CInt(rng(r, 2))
        sm = CInt(rng(r, 3))
        sd = CInt(rng(r, 4))
        Dim sdt As Date
        sdt = DateSerial(sy, sm, sd)
        
        ' 終了年月日の取得
        Dim ey As Integer, em As Integer, ed As Integer
        ey = CInt(rng(r, 5))
        em = CInt(rng(r, 6))
        ed = CInt(rng(r, 7))
        Dim edt As Date
        edt = DateSerial(ey, em, ed)
        
        ' 引数が開始年月日と終了年月日の間にあるか?
        If sdt <= dt And dt <= edt Then
            Dim era As String
            era = CStr(rng(r, 1))
            Dim ry As Integer
            ry = y - sy + 1
            YMD2ERA = era & CStr(ry) & "年" & CStr(m) & "月" & CStr(d) & "日"
            Exit Function
        End If
    Next
    
    ' エラー値を返す。
    YMD2ERA = CVErr(xlErrNA)

End Function
    
  

 

次に日付をパラメータとして渡すと、和暦文字列に変換するプログラムです。

1900/1/1 よりも前の日付でも文字列として渡してやれば、IsDate 関数で日付だと認識してくれますので、パラメータの型は Variant としてあります。

IsDate 関数によるチェックを通った場合は、晴れて日付であるということで、そこから年月日の情報を取り出して、先述の YMD2ERA 関数で和暦文字列に変換しております。

 

日付→元号年月日の文字列に変換する
      
Public Function AD2ERA(ByVal dt As Variant, ByRef rng As Range) As Variant

    ' 日付型ではない場合はエラーを返す
    If Not IsDate(dt) Then
        AD2ERA = CVErr(xlErrNA)
        Exit Function
    End If

    ' 年月日を取得して和暦に変換する
    Dim y As Integer, m As Integer, d As Integer
    y = Year(dt)
    m = Month(dt)
    d = Day(dt)
    AD2ERA = YMD2ERA(y, m, d, rng)

End Function
    
  

 

 

最後に和暦から西暦への変換ですが、元号年を取り出す為に文字列の最初の数字の位置を求める必要があります。文字列の中にある最初の数字の位置を返す処理がこの FindFirstNumber 関数となります。

この関数を利用して、和暦から西暦へ変換する関数が ERA2AD 関数となります。

 

最初の数字の位置を1から始まる数値で返す
      
Public Function FindFirstNumber(ByVal str As String) As Long

    ' パラメータの文字列の文字数 + 1 を初期位置とする
    Dim max As Long, ret As Long
    max = Len(str) + 1
    ret = max
    
On Error GoTo ERROR_CONTINUE:
    
    ' 0 ~ 9 を順番に検索する
    Dim i As Long
    For i = 0 To 9
        ' WorksheetFunction.Search 関数で数字の位置を探す。
        ' 見つからなかった場合はエラーが発生する。
        Dim id As Long
        id = CLng(WorksheetFunction.Search(CStr(i), str))
        
        ' 検出位置の最小値を保持する
        ret = IIf(id < ret, id, ret)
        GoTo LOOP_CONTINUE
        
ERROR_CONTINUE:
        ' この処理がないと、2回目以降のエラー時にキャッチできなくなる
        Resume LOOP_CONTINUE

LOOP_CONTINUE:
    Next
    
    ' 見つからなかった場合は 0 を、そうでない場合は検出位置を返す
    FindFirstNumber = IIf(ret = max, 0, ret)

End Function
    
  

 

和暦年月日の文字列を、西暦年月日の文字列に変換する
      
Public Function ERA2AD(ByVal src As Variant, ByRef rng As Range) As Variant

    ' 日付型に変換可能?
    If IsDate(src) Then
        src = AD2ERA(src, rng)
    End If

    ' 最初の数字の位置を検出する。
    Dim id As Long
    id = FindFirstNumber(src)
    If id = 0 Then
        ' 数字がみつからない場合はエラーを返す。
        GoTo ERROR_EXIT
    End If
    
On Error GoTo ERROR_EXIT
    
    ' 元号文字列を取得する。
    Dim era As String
    era = Left(src, id - 1)

    ' WorksheetFunction.VLookup 関数を使って開始年を取得する。
    ' 見つからなかった場合はエラーが発生する。
    Dim sy
    sy = WorksheetFunction.VLookup(era, rng, 2, False)

    ' "年" で文字列を分割して、元号年が格納されている側から元号を削除する。
    Dim arr As Variant
    arr = Split(src, "年")
    src = Replace(arr(0), era, "")

    ' 西暦年を取得する。
    Dim y As Integer
    y = sy + CLng(src) - 1
    
    ' 月、日を取得して、西暦年と結合して戻り値とする。
    Dim m As Integer, d As Integer
    arr = Split(arr(1), "月")
    m = CLng(arr(0))
    d = CLng(Val(arr(1)))
    ERA2AD = CStr(y) & "/" & CStr(m) & "/" & CStr(d)
    Exit Function
    
    
ERROR_EXIT:
    ' エラー値を返す。
    ERA2AD = CVErr(xlErrNA)
    
End Function
    
  

 

これらの関数を Module に実装することでワークシート上で変換処理を行うことが出来るようになります。

 

例えば、ワークシートのA1セルに変換元の日付が入力されているとします。

そういう場合はA1以外のセルに…

 

=AD2ERA(A1,T_元号設定)

 

と記述してやることで、和暦に変換された文字列が表示されると思います。

他の関数に関しても同じで…

 

=ERA2AD(A1,T_元号設定)

 

こんな感じでOKです。

元号が変わったら、元号テーブルへ新しい元号を追加することで対応できます。

 

マイクロソフト社も迅速に対応はしてくれますが、それでも少し古めな製品への新元号対応は数カ月掛かりましたし、サポートの終わっている製品だといつまで待っても 平成 のままで 令和永久にやってきません(笑)

 

ましてや、インターネット接続のない環境だとアップデートできません。

そういう場合には今回のように VBA を使って自作することで乗り越えることが出来ることもあったりします。

 

最初は取っつきにくいかもしれませんが、慣れてくると楽しいですよ!ニヤニヤ

 

 

最後に今回のプログラムを実装済みのサンプルファイルをしばらくの間だけダウンロードできるようにしておきます。

 

不具合とかあっても宇宙よりも広い心で許してくれる人でしたら、ご自由にお使いください笑い泣き

 

Googleドライブからダウンロードすると、拡張子が xlsx に勝手に変換されるようですので、xlsm に変更してから EXCEL で起動してください。