経緯
職場で山のようなエクセルファイル同士の突き合わせチェックが必要でしたが、
比較ソフトのDL・インストールができない堅い環境だったので、
これまでしかなたくEXCEL内蔵のInquire機能か数式を使って泥臭く作業をしていました。
しかし、エクセルVBAの使用は可能であるため、
今回VBAを利用して自動的にファイルを比較する簡単なコードを組んでみました。
機能
業務で必要な下記の機能を実装します。
- 2つのファイル(excel,
csv)をエクスプローラーから開く。 - それらのを比較し共通点が多い行を自動で判別して横に並べる。
- 各行の全セルの差分を出す。
コード
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Option Explicit | |
'========================================================================================= | |
'メインプロシージャ その1 (差分確認シート新規作成) | |
'========================================================================================= | |
Sub MakeDataComparesion() | |
Dim columnsCount As Long: columnsCount = 10 '★データ幅(マジックナンバー) | |
Dim file1 As Variant, file2 As Variant | |
Dim wsNew1 As Worksheet, wsNew2 As Worksheet, wsNew3 As Worksheet | |
'■1.初期化(古いシートの削除) | |
Call InitializeSheets | |
Application.ScreenUpdating = False '画面更新OFF (古いシートの削除後) | |
'■2. エクスプローラーからデータ読み込み | |
file1 = SelectFile() 'まずは選択 | |
file2 = SelectFile() 'まずは選択 | |
Set wsNew1 = LoadData("Data1", file1) '新シート(Data1)を作り、入力データ(file1)を貼付け | |
Set wsNew2 = LoadData("Data2", file2) '新シート(Data2)を作り、入力データ(file2)を貼付け | |
'■3. 比較用シート作成 | |
Set wsNew3 = CompareSheet("比較", wsNew1, wsNew2, columnsCount) '新シート(比較)を作り、幅columnsCountの2個のデータ(wsNew1,wsNew2)を並べる。 | |
Call adjustCompareSheet(wsNew1, wsNew2, wsNew3, columnsCount, 7, 8, 9) 'wsNew1,wsNew2の7,8,9列で差分を見て、比較シート(wsNew3)を調整する。 | |
Call PutDifFormula(wsNew3.Range("W5:AF200")) '指定範囲に差分判定の数式を配置する。 | |
Application.ScreenUpdating = True '画面更新OFFを解除 | |
End Sub | |
'========================================================================================= | |
'メインプロシージャ その2 (数式のみ再配置) | |
'========================================================================================= | |
'差分数式を再配置 (手でセル挿入などすると差分数式の参照セルがズレるので、そのときの修正用) | |
Sub RefreshDifFormula() | |
Application.ScreenUpdating = False '画面更新OFF | |
Dim rng As Range | |
Set rng = ThisWorkbook.Sheets("比較").Range("W5:AF200") '※将来的には自動で範囲を取得したい | |
Call PutDifFormula(rng) | |
Application.ScreenUpdating = True '画面更新ON | |
End Sub | |
'========================================================================================= | |
'↓↓↓↓以下、メインプロシージャーからの呼び出し用↓↓↓↓ | |
'========================================================================================= | |
'------------------------------------------------------ | |
'①.シート初期化処理 ([引数]なし [戻り値]なし) | |
Sub InitializeSheets() | |
'初期化確認メッセージを表示 | |
Dim rc As Long | |
rc = MsgBox("読み込み済みデータが初期化されます。" & vbCrLf & "続けますか?", vbYesNo + vbQuestion) | |
If rc = 7 Then End ' キャンセルが押された場合、処理を終了 | |
'削除対象シートを取得する | |
Dim wsOLD1 As Worksheet, wsOLD2 As Worksheet, wsOLD3 As Worksheet | |
On Error Resume Next 'エラーハンドリングを有効にする | |
Set wsOLD1 = ThisWorkbook.Sheets("data1") | |
Set wsOLD2 = ThisWorkbook.Sheets("data2") | |
Set wsOLD3 = ThisWorkbook.Sheets("比較") | |
On Error GoTo 0 'エラーハンドリングを元に戻す | |
'削除対象シートが存在する場合は削除する | |
Application.DisplayAlerts = False 'シート削除確認ダイアログ無効 | |
If Not wsOLD1 Is Nothing Then wsOLD1.Delete | |
If Not wsOLD2 Is Nothing Then wsOLD2.Delete | |
If Not wsOLD3 Is Nothing Then wsOLD3.Delete | |
Application.DisplayAlerts = True 'シート削除確認ダイアログ無効を解除 | |
End Sub | |
'------------------------------------------------------ | |
'②入力ファイル選択 ([引数]なし [戻り値]選択したファイル) | |
Function SelectFile() As Variant | |
SelectFile = Application.GetOpenFilename("Excel ファイル (*.xls; *.xlsx; *.xlsm),*.xls; *.xlsx; *.xlsm") | |
If SelectFile = "False" Then End ' キャンセルが押された場合、処理を終了 | |
End Function | |
'------------------------------------------------------ | |
'③入力ファイル読み込み ([引数]作成シート名 [戻り値]入力データシート) | |
Function LoadData(sheetname As String, inputFile As Variant) As Worksheet | |
Dim wb As Workbook | |
Set wb = Workbooks.Open(inputFile, ReadOnly:=True) | |
With ThisWorkbook | |
Set LoadData = .Sheets.Add(After:=.Worksheets(.Worksheets.Count)) | |
LoadData.Name = sheetname | |
End With | |
wb.Sheets(1).UsedRange.Copy LoadData.Cells(2, 1) | |
wb.Close SaveChanges:=False | |
'書式設定 | |
With LoadData | |
.Cells.HorizontalAlignment = xlLeft | |
.UsedRange.EntireColumn.NumberFormatLocal = "@" | |
.UsedRange.EntireColumn.AutoFit | |
End With | |
'読み込みファイル名を記入(長いので書式設定(セル幅設定)より後に記入) | |
LoadData.Cells(1, 1) = inputFile | |
End Function | |
'------------------------------------------------------ | |
'④比較シート作成 ([引数]作成シート名, 入力データ1, 入力データ2, データの列数 [戻り値]比較シート) | |
Function CompareSheet(sheetname As String, ws1 As Worksheet, ws2 As Worksheet, columnsCount As Long) As Worksheet | |
Dim rng1 As Range, rng2 As Range | |
'比較用シートを挿入 | |
With ThisWorkbook | |
Set CompareSheet = .Sheets.Add(After:=.Worksheets(.Worksheets.Count)) | |
CompareSheet.Name = sheetname | |
End With | |
'特定の列範囲をコピー | |
Set rng1 = ws1.UsedRange ' 例としてA列からJ列までの範囲 | |
Set rng2 = ws2.UsedRange ' 例としてC列からJ列までの範囲 | |
rng1.Copy CompareSheet.Cells(1, 1) | |
rng2.Copy CompareSheet.Cells(1, columnsCount + 2) ' 左右に並べるため、列数を考慮 | |
'書式設定 | |
With CompareSheet | |
.Cells.HorizontalAlignment = xlLeft '全セル左寄せ | |
.Range(Columns(1), Columns(2 * columnsCount + 2)).NumberFormatLocal = "@" 'データを並べるセルの表示形式 | |
'.Range("A1:U1").EntireColumn.AutoFit '1行目に長い文字が入るので幅自動調整は行わない | |
.Columns(columnsCount + 1).ColumnWidth = 1 '区切りセルその1 幅 | |
.Columns(columnsCount + 1).Interior.Color = RGB(0, 0, 0) '区切りセルその1 色 | |
.Columns(2 * columnsCount + 2).ColumnWidth = 1 '区切りセルその2 幅 | |
.Columns(2 * columnsCount + 2).Interior.Color = RGB(0, 0, 0) '区切りセルその2 色 | |
End With | |
End Function | |
'------------------------------------------------------ | |
'⑤比較シート調整 ([引数]入力データ1, 入力データ2, 比較シート, データの列数) | |
Sub adjustCompareSheet(ws1 As Worksheet, ws2 As Worksheet, ws3 As Worksheet, columnsCount As Long, c1 As Long, c2 As Long, c3 As Long) | |
Dim rowsCount1, rowsCount2 As Long | |
Dim roopN As Long | |
Dim CONTENT1_1 As String, CONTENT2_1 As String, CONTENT3_1 As String | |
Dim CONTENT1_2 As String, CONTENT2_2 As String, CONTENT3_2 As String | |
Dim difFlg1 As Boolean, findFlg1 As Boolean, findFlg2 As Boolean | |
Dim i As Long, j As Long | |
rowsCount1 = ws1.UsedRange.Rows.Count | |
rowsCount2 = ws2.UsedRange.Rows.Count | |
roopN = ws3.UsedRange.Rows.Count | |
For i = 5 To roopN | |
CONTENT1_1 = ws3.Cells(i, c1) | |
CONTENT2_1 = ws3.Cells(i, c2) | |
CONTENT3_1 = ws3.Cells(i, c3) | |
CONTENT1_2 = ws3.Cells(i, c1 + columnsCount + 1) | |
CONTENT2_2 = ws3.Cells(i, c2 + columnsCount + 1) | |
CONTENT3_2 = ws3.Cells(i, c3 + columnsCount + 1) | |
'比較シートの左右比較 | |
difFlg1 = False | |
If CONTENT1_1 <> CONTENT1_2 Then difFlg1 = True | |
If CONTENT2_1 <> CONTENT2_2 Then difFlg1 = True | |
If CONTENT3_1 <> CONTENT3_2 Then difFlg1 = True | |
'比較シートの左右に差分があるとき、必要に応じ行挿入する処理に入る | |
If difFlg1 Then | |
'「今の行(比較シートDATA1側)」が「DATA2のいずれか」にある?→あったらfindFlg1=Ture | |
findFlg1 = 0 | |
For j = 5 To rowsCount2 | |
If CONTENT1_1 = ws2.Cells(j, c1) Then | |
If CONTENT2_1 = ws2.Cells(j, c2) Then | |
If CONTENT3_1 = ws2.Cells(j, c3) Then | |
findFlg1 = True | |
End If | |
End If | |
End If | |
Next j | |
'「今の行(比較シートDATA2側)」が「DATA1のいずれか」にある?→あったらfindFlg2=Ture | |
findFlg2 = False | |
For j = 5 To rowsCount1 | |
If CONTENT1_2 = ws1.Cells(j, c1) Then | |
If CONTENT2_2 = ws1.Cells(j, c2) Then | |
If CONTENT3_2 = ws1.Cells(j, c3) Then | |
findFlg2 = True | |
End If | |
End If | |
End If | |
Next j | |
'findFlg1,find2のどちらかがTureのとき、行挿入し左右を揃える | |
If findFlg1 Then | |
If Not findFlg2 Then | |
ws3.Range(ws3.Cells(i, 1), ws3.Cells(i, columnsCount)).Insert Shift:=xlShiftDown | |
ws3.Range(ws3.Cells(i, 1), ws3.Cells(i, columnsCount)).Interior.Color = RGB(200, 220, 220) | |
roopN = roopN + 1 'とりあえずループ数を増やす(増加不要のときもあるが、場合分けが面倒なため) | |
End If | |
Else | |
If findFlg2 Then | |
Range(ws3.Cells(i, columnsCount + 2), ws3.Cells(i, 2 * columnsCount + 1)).Insert Shift:=xlShiftDown | |
Range(ws3.Cells(i, columnsCount + 2), ws3.Cells(i, 2 * columnsCount + 1)).Interior.Color = RGB(200, 220, 220) | |
roopN = roopN + 1 'とりあえずループ数を増やす(増加不要のときもあるが、場合分けが面倒なため) | |
End If | |
End If | |
End If | |
Next i | |
End Sub | |
'------------------------------------------------------ | |
'⑥差分抽出数式配置 ([引数]対象セル範囲) | |
Sub PutDifFormula(rng As Range) | |
With rng | |
.Formula = "=IF(A5=L5, ""〇"", ""×"")" | |
.ColumnWidth = 2 | |
End With | |
Dim frmSetting As FormatCondition | |
Set frmSetting = rng.FormatConditions.Add(Type:=xlCellValue, Operator:=xlEqual, Formula1:="×") | |
frmSetting.Interior.Color = RGB(255, 70, 0) | |
End Sub | |
'------------------------------------------------------ |
コメント