LoginSignup
0
0

More than 1 year has passed since last update.

【VBA】全角半角混在文字列からバイト単位で取り出したい

Last updated at Posted at 2021-05-04

はじめに

企業の総務部門や社労士事務所さんが使うシステムは、人事労務勤怠管理給与計算に大別されます。
同じシステムで纏めて処理することもあれば、ベンダーが異なるシステム同士をデータ連携させることもあります。
近年はソフトのクラウド化が進み、APIで連携できるようになったものの、まだCSVファイルでデータ受け渡しを行う現場が多勢です。

今回、人事労務システムの「SmartHR」から、給与計算システムの「給与奉行」に、連携(データ変換)するVBAマクロを組む機会があったので、少し解説してみます。所得控除の話も出てきます。
image.png
ちなみにHRとはHuman Resourceの略で、直訳すると人材という意味になりますが、人事部という意味もあります。人事系のシステムやイベントにはHRを冠したものが多いです。HRTechは人事とITを掛け合わせた造語で、FinTech(金融×IT)、EdTech(教育×IT)、AdTech(広告×IT)と並ぶ、X-Techの造語になります。

実現方式

このデータ変換は、勤怠を締めてから給与計算を回すまでに基本一度だけ行えば良いので、API連携ではなく簡易なVBAマクロで処理します。
オービックビジネスコンサルタント社(OBC)のERPパッケージである奉行シリーズには「OBC受入形式」という汎用フォーマットがあり、この形式に変換できれば、奉行にインポート可能なようです。このときの文字コードはShift-JISです。

例えば下表のように、SmartHRの項目名▶奉行の受入記号の変換表を作成しておき、これに準じてマクロを組めばOKです。

SmartHRの項目名 給与奉行の受入記号 給与奉行の項目名 変換方法
社員番号 EBAS001 社員番号 ゼロパディングで5桁
姓(ヨミガナ)
名(ヨミガナ) EBAS002 氏名(フリガナ) 姓と半角スペース区切りで結合
EBAS003 氏名 姓と半角スペース区切りで結合
部署名 ECHA003 所属コード 所属マスタからコードに変換
役職 ECHA005 役職コード 役職マスタからコードに変換
雇用形態 EBAS005 雇用区分コード 1:正社員 2:契約社員
3:派遣社員 4:アルバイト
5:パート 6:役員
性別 EBAS008 性別コード 0:男性 1:女性
生年月日 EBAS010 生年月日
雇い入れ年月日 EBAS011 入社年月日
ビジネスネーム 姓(ヨミガナ)
ビジネスネーム 名(ヨミガナ) EBAS026 職場氏名(フリガナ) 姓と半角スペース区切りで結合
ビジネスネーム 姓
ビジネスネーム 名 EBAS027 職場氏名 姓と半角スペース区切りで結合
住所(郵便番号) EADD004 郵便番号 ハイフンを含む
住所(都道府県) EADD005 都道府県 12文字まで
住所(市区町村) EADD006 市区町村 24文字まで
住所(丁目・番地) EADD007 番地 30文字まで
住所(建物名・部屋番号) EADD008 マンション/ビル等 50文字まで
住所(ヨミガナ) EADD009 住所カナ
電話番号 EADD010 電話番号 7桁-5桁-5桁
メールアドレス EWOR002 社用e-Mail1
社用メールアドレス EWOR004 社用e-Mail2
発令情報.職種 ECHA009 職種区分コード 職種区分マスタからコードに変換
発令情報.採用区分 ECHA011 採用区分コード 採用区分マスタからコードに変換
発令情報.等級 ECHA013 等級コード 等級マスタからコードに変換
発令情報.事業所情報 ECHA015 事業所コード 事業所マスタからコードに変換
発令情報.一般職管理職区分 EUNP002 給与体系コード 給与体系マスタからコードに変換
給与支給形態 EUNP003 給与区分コード 0:月給 1:日給 2:時給
税表区分.税表区分 ESAL003 課税区分コード 0:計算不要 1:甲欄
2:乙欄 3:丙欄
4:報酬 5:非居住者
6:課税不要
配偶者 姓(ヨミガナ)
配偶者 名(ヨミガナ) EFMM001 配偶者-フリガナ 姓と半角スペース区切りで結合
配偶者 姓
配偶者 名 EFMM002 配偶者-氏名 姓と半角スペース区切りで結合
配偶者 性別 EFMM003 配偶者-性別コード 0:男性 1:女性
配偶者 生年月日 EFMM004 配偶者-生年月日
配偶者 同居・別居の別 EFMM009 配偶者-同居区分コード 0:対象外 1:同居
配偶者 障害者区分 EFMM011 配偶者-障害者区分コード 0:対象外 1:一般障害者
2:特別障害者
配偶者 社会保険の扶養状況 EFMM012 配偶者-健保扶養区分コード 0:未加入 1:加入
配偶者 税法上の扶養状況 EFMM020 配偶者-扶養区分コード 0:控除対象外
1:源泉控除配偶
家族1 姓(ヨミガナ)
家族1 名(ヨミガナ) EFMD001 扶養親族1-フリガナ
家族1 姓
家族1 名 EFMD002 扶養親族1-氏名
家族1 性別 EFMD003 扶養親族1-性別コード
家族1 続柄 EFMD004 扶養親族1-続柄コード
家族1 生年月日 EFMD005 扶養親族1-生年月日
家族1 同居・別居の別 EFMD010 扶養親族1-同居区分コード
家族1 税法上の扶養状況 EFMD011 扶養親族1-扶養区分コード 0:控除対象外 1:一般扶養
2:特定扶養 3:老人扶養
4:老親等 9:年少扶養
家族1 障害者区分 EFMD012 扶養親族1-障害者区分コード 0:対象外 1:一般障害者
2:特別障害者
家族1 社会保険の扶養状況 EFMD013 扶養親族1-健保扶養区分コード 0:未加入 1:加入
寡婦・ひとり親 ESED001 寡婦/ひとり親区分コード 0:対象外 1:寡婦
2:ひとり親
障害者区分 ESED002 障害者区分コード 0:対象外 1:一般障害者
2:特別障害者
勤労学生フラグ ESED003 勤労学生区分コード 0:対象外 1:勤労学生
基礎年金番号 ESOC001 基礎年金番号
健康保険の被保険者整理番号 ESOC005 健保証番号
給与振込口座 銀行コード ESPY105 給与振込1-振込先銀行コード
給与振込口座 支店コード ESPY106 給与振込1-振込先支店コード
給与振込口座 預金種別 ESPY107 給与振込1-預金種目コード
給与振込口座 口座番号 ESPY108 給与振込1-口座番号
給与振込口座 名義(カタカナ) ESPY109 給与振込1-フリガナ

業務用語解説

先述の表には、所得控除に関する用語が沢山出てきました。
業務システム開発に関わるアプリケーションエンジニアにとってはクライアント業務の基礎的な勉強は避けられませんし、サラリーマンで年末調整する方も、フリーランスで確定申告する方も、所得控除は知らないと損する話です。
一緒に学んでいきましょう。

所得控除について

会社の利益に対してかかる法人税と違い、個人の所得に対してかかる所得税では、個人の事情が考慮され、扶養控除や医療費控除などの所得控除が設けられています。
所得税は、所得(収入-経費=利益)に税率を乗じて計算されますが、この所得から控除できる金額のことを所得控除というわけです。(個人事業主の場合は売上高から必要経費を差し引いた利益がそのまま自分の所得となり、これを事業所得といいます)
所得控除には、基礎控除、配偶者控除、扶養控除などの種類があります。

扶養控除とは

扶養とは親族から経済的援助を受けることをいいます。「妻が夫の扶養に入る」という使い方をしますよね。
一般に「親族」というと親戚すべての人が含まれますが、法律上の親族という場合には、配偶者、6親等内の血族(血が繋がっている人。養子縁組は法的な血縁関係が生じる)、3親等内の姻族(配偶者の血族)に限られます。
扶養を受けている者(被扶養者)は、収入が一定金額を超えると扶養から外れて、税金の負担が大きくなります。

扶養控除は、その年12月31日現況で、いくつかの要件を満たす扶養親族がいる場合に控除できます。
要件には、16歳以上とか、配偶者以外の親族とか、納税者と生計を一にしているとか、他にも色々あります。

扶養親族には、次の種類があります。

  • 特定扶養親族
    その年12月31日の年齢が19歳以上23歳未満の人です。
    つまり、2021年分なら、生年月日が1999年1月2日~2003年1月1日の人を指します。

  • 老人扶養親族
    その年12月31日の年齢が70歳以上の人です。
    つまり、2021年分なら、生年月日が1952年1月1日以前の人を指します。
    なお、日時などを定める際に法律で用いられる「以前」は、その基準時点を含んでそれより前という意味です。

  • 同居老親
    老人扶養親族のうち、納税者と同居している人です。

  • 年少扶養
    こども手当(現在は児童手当)に移行したため、年少扶養親族(16歳未満)に対する扶養控除は廃止されました。
    ただし、住民税については非課税限度額という制度があり、16歳未満の子供の有無が税額計算に関わってくるため、扶養控除等申告書の住民税に関する事項には記入が必要です。
    2021年分なら、生年月日が2006年1月2日以後の人を指します。

ということで、税法上の扶養では、生年月日と同居区分から、扶養区分(OBC受入形式のEFMD011)を求めることができます。

扶養区分を求める
' 生年月日が入力されているか?
If 生年月日 <> "" Then
    誕生日 = Format(生年月日, "yyyy/mm/dd")

    ' 年少扶養か?
    If 誕生日 >= "2006/01/02" Then
        扶養区分 = "年少扶養"
    Else
        ' 老人扶養親族か?
        If 誕生日 <= "1952/01/01" Then
            ' 同居しているか?
            If 同居フラグ = "同居" Then
                扶養区分 = "老親等"
            Else
                扶養区分 = "老人扶養"
            End If
        Else
            ' 特定扶養親族か?
            If 誕生日 >= "1999/01/02" And 誕生日 <= "2003/01/01" Then
                扶養区分 = "特定扶養"
            Else
                扶養区分 = "一般扶養"
            End If
        End If
    End If
End If

ところで、扶養控除には「税法上の扶養」と「社会保険上の扶養」があるのをご存知でしたか?
「税法上の扶養」は、家計を主に支える方が住民税や所得税の控除を受けて、納めるべき税金を低く抑えられるというものです。「給与所得者の扶養控除等(異動)申告書」に記載する「源泉控除対象配偶者」もこれと同じです。
「社会保険上の扶養」は、家計を主に支える方の勤務先の健康保険や厚生年金の被扶養者になることで、自分で社会保険料を納めなくても良いというものです。

配偶者控除とは

納税者に控除対象配偶者がいる場合に受けられる控除です。内縁関係は含まれません。
これにもいくつかの要件があります。
控除対象配偶者でありながら年間の合計所得金額が48万円を超えているために配偶者控除を受けられない場合、配偶者特別控除が受けられます。

なお、給与計算システムの配偶者の設定では、

  • 源泉控除対象配偶者かどうかのチェック。(チェックすると扶養親族にカウントされる)
  • 同一生計配偶者かどうかのチェック。(チェックしないと控除対象配偶者ということ)

が入れられるようになっていて、この設定を間違えると正しく年末調整できません。

同一生計配偶者は配偶者控除を使えませんが、その配偶者が障害者の場合、障害者控除が受けられます。

他に混同しがちな用語

寡婦(夫)とひとり親の違いは婚姻歴の有無です。寡婦(夫)は離婚や死別によるものでしたが、ひとり親は未婚です。子供の貧困を救済するため、令和2年から未婚のひとり親も控除を受けられるようになりました。

文字数制限問題

システムの話に戻ります。

テキスト型の項目では、最大文字数の制限が設けられているのが普通です。
この場合、単位が、文字数なのかバイト数なのかを仕様書から読み解くことになります。
日本語などの DBCS では、全角1文字を2バイトでカウントするため、文字種(全角/半角)の違いで最大文字数が変わるようならバイト数単位と考えて良いです。

給与奉行の「番地」は30文字までの制限がありました。文字種の言及は無いので、全角半角に関係なく30文字を超えてはならないようです。この場合、VBAのLeft関数で先頭から30文字を取り出せば良いです。31文字目以降はMid関数で取り出し、次項目の「マンション/ビル等」に突っ込みます。

全角半角混在文字列からバイト単位で取り出す場合は注意が必要です。全角文字は2バイトなので分割位置によっては文字化けが起こるからです。
image.png
そこで、バイト単位の文字列分割に利用できる汎用のサブプロシージャを作成しました。

Public Sub JustRightSplit(mixStr As String, cutPos As Integer, firstStr As String, secondStr As String)
    Dim s As String, n As Integer

    s = StrConv(mixStr, vbFromUnicode)
    If LenB(s) > cutPos Then
        n = (LenB(StrConv(LeftB(s, cutPos), vbUnicode)) = LenB(StrConv(LeftB(s, 1 + cutPos), vbUnicode)))
        firstStr = StrConv(LeftB(s, cutPos + n), vbUnicode)
        secondStr = StrConv(MidB(s, 1 + cutPos + n), vbUnicode)
    Else
        firstStr = mixStr
        secondStr = ""
    End If
End Sub

考え方としては、今どきのWindowsが内部で使っているUnicode(UTF-16)を既定のコードページ(つまりShift-JIS)に変換し、LenB関数とLeftB関数を使ってバイト単位で計算しています。

使い方は次の通りです。

  • 第一引数:分割したい文字列
  • 第二引数:取り出したいバイト数
  • 第三引数:分割後文字列の前半を格納する変数
  • 第四引数:分割後文字列の後半を格納する変数
Dim a As String, b As String

JustRightSplit "あいAうBCえお", 10, a, b

Debug.Print a
Debug.Print b
出力
あいAうBC
えお

半端なバイト数でも丁度良い位置で分割してくれます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0