🔄 Smart Excel Macro for Merging Records into a Master File
Managing multiple Excel files can be a daunting task—especially when you're dealing with bank statements, vendor records, or invoice details. To simplify this process, I’ve developed a custom Excel VBA macro that intelligently merges records into a master file while handling duplicates and allowing column-level customization.
⚙️ Key Features
- Duplicate Detection: Prevents redundant entries based on unique identifiers.
- Custom Column Selection: Choose which columns to import.
- Flexible Use Cases: Works for bank statements, vendor data, invoices, and more.
- Timestamped Saving: Optional versioning with timestamps for traceability.
🛠️ How It Works
- Select the source Excel file.
- Define which columns to copy.
- Macro checks for duplicates in the master file.
- Clean data is appended and saved.
💡 Why This Macro Matters
Manual data consolidation is time-consuming and error-prone. This macro automates the process while giving you full control over what gets imported—perfect for professionals who value data integrity.
🚀 Want to Try It?
Below full code and a step-by-step tutorial soon. Stay tuned—and feel free to leave a comment if you’d like a custom version for your workflow!
📜 Sample VBA Code
Option Explicit
Sub ImportBankData()
Dim keyWb As Workbook, bankWb As Workbook, targetWb As Workbook
Dim keyWs As Worksheet, bankWs As Worksheet, targetWs As Worksheet
Dim bankFile As String, targetFile As String
Dim headerMap As Object
Dim lastRow As Long, lastCol As Long, i As Long
Dim targetHeader As Variant, bankHeader As String
Dim dictExisting As Object
Dim newRow As Long
Dim bankHeaders As Object, targetHeaderCols As Object
Dim rowKey As String
Dim openingBalCol As Long, closingBalCol As Long
Dim debitCol As Long, creditCol As Long
Dim openingBal As Double, debitVal As Double, creditVal As Double
Dim sNo As Long
Dim duplicateCount As Long, uniqueCount As Long
' Set reference to Key workbook and Input sheet
Set keyWb = ThisWorkbook
Set keyWs = keyWb.Sheets("Input")
' Build header mapping dictionary: key = Target Header, value = Bank Header
Set headerMap = CreateObject("Scripting.Dictionary")
For i = 1 To 20
If UCase(Trim(keyWs.Cells(i, 4).Value)) = "Y" Then
bankHeader = Trim(keyWs.Cells(i, 2).Value)
targetHeader = Trim(keyWs.Cells(i, 3).Value)
If targetHeader <> "" And bankHeader <> "" Then
headerMap(targetHeader) = bankHeader
End If
End If
Next i
If headerMap.Count = 0 Then
MsgBox "No headers marked 'Y' in Input sheet.", vbExclamation
Exit Sub
End If
' Browse and open Bank Statement workbook
bankFile = fl_browse()
If bankFile = "" Then Exit Sub
Set bankWb = Workbooks.Open(bankFile)
Set bankWs = bankWb.Sheets(1)
' Browse and open Target workbook
targetFile = fl_browse()
If targetFile = "" Then Exit Sub
Set targetWb = Workbooks.Open(targetFile)
Set targetWs = targetWb.Sheets("JPMC")
' Map target headers to their column numbers
Set targetHeaderCols = CreateObject("Scripting.Dictionary")
lastCol = targetWs.Cells(1, targetWs.Columns.Count).End(xlToLeft).Column
For i = 1 To lastCol
targetHeaderCols(targetWs.Cells(1, i).Value) = i
Next i
' Validate required headers
If Not targetHeaderCols.exists("Opening Balance") Then
MsgBox "'Opening Balance' column not found in target sheet.", vbCritical
Exit Sub
End If
If Not targetHeaderCols.exists("Closing Balance") Then
MsgBox "'Closing Balance' column not found in target sheet.", vbCritical
Exit Sub
End If
openingBalCol = targetHeaderCols("Opening Balance")
closingBalCol = targetHeaderCols("Closing Balance")
If targetHeaderCols.exists("Debit") Then debitCol = targetHeaderCols("Debit")
If targetHeaderCols.exists("Credit") Then creditCol = targetHeaderCols("Credit")
' Map bank headers to their column numbers
Set bankHeaders = CreateObject("Scripting.Dictionary")
lastCol = bankWs.Cells(1, bankWs.Columns.Count).End(xlToLeft).Column
For i = 1 To lastCol
bankHeaders(bankWs.Cells(1, i).Value) = i
Next i
' Create dictionary of existing rows to avoid duplicates
Set dictExisting = CreateObject("Scripting.Dictionary")
lastRow = targetWs.Cells(targetWs.Rows.Count, 1).End(xlUp).Row
For i = 2 To lastRow
rowKey = ""
For Each targetHeader In headerMap.Keys
If targetHeaderCols.exists(targetHeader) Then
rowKey = rowKey & "|" & NormalizeValue(targetWs.Cells(i, targetHeaderCols(targetHeader)).Value)
End If
Next
If rowKey <> "" Then dictExisting(rowKey) = True
Next i
' Determine starting row and opening balance
newRow = lastRow + 1
If lastRow < 2 Then
openingBal = 0
sNo = 1
Else
openingBal = val(targetWs.Cells(lastRow, closingBalCol).Value)
sNo = val(targetWs.Cells(lastRow, 1).Value) + 1
End If
' Loop through Bank Statement rows
lastRow = bankWs.Cells(bankWs.Rows.Count, 1).End(xlUp).Row
For i = 2 To lastRow
rowKey = ""
For Each targetHeader In headerMap.Keys
bankHeader = headerMap(targetHeader)
If bankHeaders.exists(bankHeader) Then
rowKey = rowKey & "|" & NormalizeValue(bankWs.Cells(i, bankHeaders(bankHeader)).Value)
End If
Next
If Not dictExisting.exists(rowKey) Then
targetWs.Cells(newRow, 1).Value = sNo
' Insert mapped values
For Each targetHeader In headerMap.Keys
bankHeader = headerMap(targetHeader)
If bankHeaders.exists(bankHeader) And targetHeaderCols.exists(targetHeader) Then
targetWs.Cells(newRow, targetHeaderCols(targetHeader)).Value = bankWs.Cells(i, bankHeaders(bankHeader)).Value
End If
Next
' Get debit/credit values
debitVal = 0: creditVal = 0
If debitCol > 0 Then debitVal = val(targetWs.Cells(newRow, debitCol).Value)
If creditCol > 0 Then creditVal = val(targetWs.Cells(newRow, creditCol).Value)
' Calculate and format balances
With targetWs.Cells(newRow, openingBalCol)
.Value = openingBal
.NumberFormat = "#,##0.00"
End With
With targetWs.Cells(newRow, closingBalCol)
.Value = openingBal + creditVal - debitVal
.NumberFormat = "#,##0.00"
End With
openingBal = openingBal + creditVal - debitVal
dictExisting(rowKey) = True
newRow = newRow + 1
sNo = sNo + 1
uniqueCount = uniqueCount + 1
Else
duplicateCount = duplicateCount + 1
End If
Next i
MsgBox "? Data import complete!" & vbCrLf & _
"? Unique rows added: " & uniqueCount & vbCrLf & _
"?? Duplicate rows skipped: " & duplicateCount, vbInformation
targetWb.SaveAs targetWb.Path & "\" & targetWb.Name & Format(Now, "yyyy-mm-dd_HHmm") & ".xlsx"
targetWb.Close savechanges:=False
bankWb.Close savechanges:=False
End Sub
Private Function NormalizeValue(val As Variant) As String
If IsNumeric(val) Then
NormalizeValue = Format(val, "0.00")
ElseIf IsDate(val) Then
NormalizeValue = Format(val, "yyyy-mm-dd")
Else
NormalizeValue = Trim(CStr(val))
End If
End Function
Below code input in other modules
Option Explicit
Public Function fl_browse() As String
Dim fd As FileDialog
Dim selectedFile As String
' Initialize the FileDialog object
Set fd = Application.FileDialog(msoFileDialogFilePicker)
With fd
.Title = "Select a File"
.AllowMultiSelect = False
.Filters.Clear
.Filters.Add "Excel Files", "*.xls; *.xlsx; *.xlsm"
.Filters.Add "All Files", "*.*"
.InitialFileName = ThisWorkbook.Path & "\"
' Show the dialog box
If .Show = -1 Then ' -1 means user clicked "Open"
selectedFile = .SelectedItems(1)
Else
selectedFile = "" ' User cancelled
End If
End With
' Return the selected file path
fl_browse = selectedFile
End Function
🎨 Want to Customize this Template?
This project is fully customizable. You can:
- Add HTML formatting to the email body
- Attach files dynamically
- Include CC/BCC recipients
- Pull data from multiple sheets or sources
📞 Need a Custom Email Automation Tool?
If you'd like to customize this template for your business—whether it's branding, attachments, or advanced logic—feel free to connect with us. We’d love to help you streamline your workflow and save time.
👉 Contact us today to get started with your personalized Excel email automation solution!

1 Comments
Very Good Project
ReplyDelete