LoginSignup
0
0

More than 1 year has passed since last update.

VBA データを最新に更新したい(転記)

Posted at

初めに

今回の記事はVBA勉強会にて、お題に沿って自分なりにVBAを書いたものになります。
私自身VBA歴はまだまだ浅く、勉強中の身ですのでベストプラクティスとは言えないコードになっていることと思います。そのためあまり参考にならない可能性がありますのでご了承ください。

お題の内容

「社員情報の更新」
社員情報をエクセルで管理し、新入社員や中途社員といった新規社員の追加や、所属支店、氏名の変更が発生したケースについてです。
手動での変更はミスの温床となってしまいます。
そこで、VBAを使用して自動での情報更新を行なってみましょう!
今回も、記述方法、トリガー条件は自由です。
配布ファイルは
「旧社員マスタ」
「変更社員情報」
の2つです。
「変更社員情報」には変更のある社員情報が記載されています。これを元に「旧社員マスタ」の情報を更新してください。
「変更社員情報」は全ての項目が変更されているわけではありません。所属のみ変更されている場合や、氏名のみの変更もあります。

ファイルの内容

下記画像の2つのファイルを使用します。
image.png
image.png

コードと実行結果

Option Explicit
Sub 実行()
Application.ScreenUpdating = False

Dim FilePath As String: FilePath = ThisWorkbook.Path
Workbooks.Open FilePath & "\" & "変更社員情報.xlsx", ReadOnly:=True
Dim wb As Workbook: Set wb = ActiveWorkbook
Dim ws As Worksheet: Set ws = wb.Sheets("社員マスタ")
Dim i, j As Long '※←ミスコード! i がVariant型になる。
Dim target As Range '検索で使用
Dim Arr As Variant: Arr = ws.Range("A1").CurrentRegion   '更新データを配列に格納
wb.Close

'新しいデータの数だけ繰り返し
For i = 2 To UBound(Arr, 1)
    Set target = Cells.Find(what:=Arr(i, 1))           '変更する社員IDをターゲットに格納
    If target Is Nothing Then                          '変更するセルが見つからなかったら、最終行をターゲットにセット
        Set target = Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)
    End If
    '更新する列の数だけ繰り返し
    For j = 1 To UBound(Arr, 2)
        target.Offset(0, j - 1) = Arr(i, j)
    Next
Next
'罫線を引く
Range("A1").CurrentRegion.Borders.LineStyle = xlContinuous
Application.ScreenUpdating = True

End Sub

Findメソッドで社員番号が見つかった場合

image.png
下記のコードで旧社員番号を検索します。

Set target = Cells.Find(what:=Arr(i, 1))           '変更する社員IDをターゲットに格納

見つかった場合、見つかった場所を起点に転記処理を行っていきます。
(変更点以外の転記は無駄ですが、いったんそのままスルーしてください)

'更新する列の数だけ繰り返し
For j = 1 To UBound(Arr, 2)
    target.Offset(0, j - 1) = Arr(i, j)
Next

見つからなかった場合

image.png

検索して見つからなかった場合(RangeオブジェクトのtargetがNothingだったら)
下記のコードで、1列目の最終行から一つ下の行をターゲットとして処理を行っていきます。

先ほど変更点以外上書きしても無駄だといいましたが、こうすることで追加の場合と上書きの場合で処理を共通化できて、コードがすっきりするかなと思った次第です。

'見つからない場合、最終行をターゲットにセット
If target Is Nothing Then
    Set target = Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)
End If

'更新する列の数だけ繰り返し
For j = 1 To UBound(Arr, 2)
    target.Offset(0, j - 1) = Arr(i, j)
Next

実行結果

変更情報の値に更新され、項目も追加されていることがわかるかと思います。
社員情報変更.gif

感想

今回、とにかくコードが短くできないかなと考えて、更新情報の上書きと追加の処理を共通化してみたという感じです。(成果の発表の際長い間しゃべりたくないので、できるだけコードを短くして説明をできるだけ短くしたいという魂胆w)
今回学びもあり実りのある勉強会だったと思います。
あと初めてgif作ってみたけど楽しい。。。(笑)

学んだこと

変数はまとめて宣言できる認識だったが、今回型を明示的に指定しておらず想定とは違う型になっていた。※勉強会にてご指摘いただきました。

Dim i, j As Long '※←ミスコード! i がVariant型になる。

Arrの宣言時、Arr()としていないのでRangeオブジェクトが配列に格納されており、そのため配列のインデックス番号が1から始まっていた。配列は配列でも格納する情報が異なると、0から始まらないこともあるということが分かった。

Dim Arr As Variant: Arr = ws.Range("A1").CurrentRegion   '更新データを配列に格納

ローカルウィンドウ
image.png

if文の省略形があることを知ることができた。
分岐しない場合は、一行に収めることで、End If を省略できるらしい。ビビりまくった。

If target Is Nothing Then
    Set target = Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)
End If
If target Is Nothing Then Set target = Cells(Rows.Count, 1).End(xlUp).Offset(1, 0)

以上です。

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