1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

レイアウト変更に強いVBAコード

Last updated at Posted at 2020-01-21

更新履歴

日付 内容
2020-01-25 Enum版を追加

概要

VBAメモ:シートのレイアウト変更に伴うVBAコード修正を減らしたい。 の記事を見て、自分のやり方を投下してみました。

本文

2パターン投下します

私の中で基本形だったものと、それを改良したものです。
2020-01-25追記: @jinoji さんにご紹介いただいたEnumのコードを追加しました。

サンプル題材

題材として、DBからエクスポートしてきた住所テーブルを、住所録っぽく書き換える処理を用います。
なお題材の処理自体にはあまり力を入れてませんので、そちらへのツッコミは容赦願いたいです。

入力
image.png

結果
image.png

パターン1、基本形

方針

とにかくコード内でマジックナンバーになるような箇所すべて定数にします。
全コードはこちら

' --- シート定義
Const INPUT_SHEET_NAME = "INPUT"
Const OUTPUT_SHEET_NAME = "OUTPUT"

' --- 入力列定義
Const COL_IN_INDEX = 1
Const COL_IN_FAMILY_NAME = 2
Const COL_IN_LAST_NAME = 3
Const COL_IN_SEX = 4
Const COL_IN_ZIP1 = 5
Const COL_IN_ZIP2 = 6
Const COL_IN_PREFECTURE = 7
Const COL_IN_CITY = 8
Const COL_IN_TOWN = 9
Const COL_IN_BUILDING = 10
Const COL_IN_ADDRESSLIST_PROHIBITED = 11

' --- 入力行定義
Const ROW_IN_DATA_START = 2

' --- 出力列定義
Const COL_OUT_NAME = 1
Const COL_OUT_ZIP = 2
Const COL_OUT_ADDRESS = 3

' --- 出力行定義
Const ROW_OUT_DATA_START = 3

弱点

  • 列が10個くらいならいいですが、Z列より先になると、列アルファベットを列番号に変換するのがひと手間です。
  • 途中の列に何かを追加することになった時(たとえば入力のD列あたりに名前カナを入れるとか)となったとき、列番号をまとめて直す必要があり、これはけっこうな手間です。

パターン2、改良版

方針

列番号を動的に設定します。

全コードはこちら

パターン1では定数だったところを、モジュール変数にします。
そして、COL_IN_ITEM_START という定数を設け、項目の開始列を指定します。

' --- 入力列定義
Const COL_IN_ITEM_START = 1
Dim COL_IN_INDEX As Long
Dim COL_IN_FAMILY_NAME As Long
Dim COL_IN_LAST_NAME As Long
Dim COL_IN_SEX As Long
Dim COL_IN_ZIP1 As Long
Dim COL_IN_ZIP2 As Long
Dim COL_IN_PREFECTURE As Long
Dim COL_IN_CITY As Long
Dim COL_IN_TOWN As Long
Dim COL_IN_BUILDING As Long
Dim COL_IN_ADDRESSLIST_PROHIBITED As Long

そして、列番号を増分しながら代入していきます。

    Dim i As Long: i = COL_IN_ITEM_START - 1
    i = i + 1: COL_IN_INDEX = i ' A列
    i = i + 1: COL_IN_FAMILY_NAME = i ' B列
    i = i + 1: COL_IN_LAST_NAME = i ' C列
    i = i + 1: COL_IN_SEX = i ' D列
    i = i + 1: COL_IN_ZIP1 = i ' E列
    i = i + 1: COL_IN_ZIP2 = i ' F列
    i = i + 1: COL_IN_PREFECTURE = i
    i = i + 1: COL_IN_CITY = i
    i = i + 1: COL_IN_TOWN = i
    i = i + 1: COL_IN_BUILDING = i
    i = i + 1: COL_IN_ADDRESSLIST_PROHIBITED = i

何が改善されるか

列の入れ替えや追加があったとき、列番号の代入箇所を編集するだけで済みます。
上から列順に並んでますので、実際の表を見ながら並び替えることができ、失敗もしにくいです。

ちょっともやもやする点

事実上定数なのに、文法的には変数にしてしまっていますので、その点ちょっともやつきます。

パターン3、Enum版

@jinoji さんにコメント頂いた、Enumを使ってみました。
全コードはこちら

こんな感じで定義すると、

' --- 入力列定義
Enum COL_IN
    Index = 1
    familyName ' 2 (値を指定しなければ、前の項目からインクリメントされた値になる)
    lastName ' 3
    sex ' 4
    zip1 ' (以下略)
    zip2
    prefecture
    city
    town
    building
    addresslistProhibited
End Enum

Enum名.項目名 な感じで使えます。

    ' 住所
    Dim prefecture As String: prefecture = wsIn.Cells(rowNoIn, COL_IN.prefecture).Value
    Dim city As String: city = wsIn.Cells(rowNoIn, COL_IN.city).Value
    Dim town As String: town = wsIn.Cells(rowNoIn, COL_IN.town).Value
    Dim building As String: building = wsIn.Cells(rowNoIn, COL_IN.building).Value

これは書きやすくていいですね。
ただ難点があるとすれば、項目名が短くなりすぎるために、

Enum COL_IN
    Index = 1

のように、他の変数と綴りが同じになったものは、大文字小文字がひきずられてしまいます。
贅沢な悩みのような気もしますが・・・。
命名をうまく回さないと、項目名の統一性がなくなってしまうので、注意が要りそうです。

参考資料

Enumステートメント(VBA) - Microsoft Dosc

1
2
2

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
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?