· Workpaper Management · 12 min read

Data Validation Copier: Set Up Validation Once, Propagate to Every Entity Sheet

Select a template range with dropdowns and input restrictions, then copy those rules to the same cells on other sheets — all in one pass.

Share:

TL;DR: You spent 20 minutes setting up dropdown lists, date restrictions, and numeric limits on Entity-A’s schedule. Now Entity-B through Entity-L need the exact same validation in the exact same cells. This macro copies every rule from a template range to any sheets you choose. Two clicks, zero mistakes.

The Problem

It’s March 10th and the Henderson multi-entity consolidation is due Friday. You have 12 entities, each with a separate sheet — same columns, same rows, same structure. You carefully set up data validation on Entity-A: dropdowns for the tax treatment column, date restrictions for placed-in-service dates, whole-number limits for account codes. It took 18 minutes to get every rule right, including the input messages and error alerts.

Now you face the other 11 sheets. Same 50 rows of the same 3 columns of the same rules, set up 11 more times. You could copy-paste Entity-A’s cells (which copies validation), but then you’d overwrite the data. You could manually re-create every rule sheet by sheet — Format Cells → Data Validation → Settings → set Type → set Source → OK, 50 times per sheet. That’s over 500 clicks for your 11 sheets. The deadline is Friday.

This macro copies the validation rules and nothing else. Your data stays put. The dropdowns just appear.

#Prerequisites & Setup

What you’ll need:

  • Excel 2016+ (desktop)
  • A template sheet with data validation rules already set up on the range you want to copy
  • Destination sheets with the same structure — data in the same rows and columns as the template

Limitations:

  • The macro copies rules to the exact same cell positions on destination sheets. If Entity-B has headers in row 2 instead of row 1, the cell references will be off by one row.
  • Skips protected sheets automatically — unprotect them first if you want validation applied there
  • Input messages and error alerts are copied, but the macro can’t replicate custom validation formulas that reference sheet-specific ranges (e.g., =INDIRECT("Entity-A!Rates")). Formulas referencing the template sheet are adjusted to reference the destination sheet.
  • Only copies validation rules, not cell formatting, conditional formatting, or comments

#The Macro

Option Explicit

Sub CopyDataValidation()
    ' ── Data Validation Copier ──────────────────────────
    ' Copies data validation rules from a template range
    ' to the exact same cell positions on any number of
    ' destination sheets — without touching data.
    '
    ' Supports: dropdown lists, whole/decimal number
    ' limits, date restrictions, text-length limits, and
    ' custom formulas. Input messages, error alerts, and
    ' dropdown arrow preferences are preserved.
    ' ────────────────────────────────────────────────────

    ' ── State management ───────────────────────────────
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual

    ' ── Variables ──────────────────────────────────────
    Dim srcRng As Range, cell As Range
    Dim dstWs As Worksheet
    Dim dstSheets As String
    Dim sheetNames() As String
    Dim i As Long, s As Long
    Dim sheetCount As Long, cellTotal As Long
    Dim skipped As Long, valCount As Long

    ' ── Error handling ─────────────────────────────────
    On Error GoTo CleanUp

    ' ── Step 1: Select the template range ──────────────────
    On Error Resume Next
    Set srcRng = Application.InputBox( _
        "Select the range that HAS the validation rules " & _
        "you want to copy (mouse-drag to select).", _
        "Template Range", Type:=8)
    On Error GoTo CleanUp

    If srcRng Is Nothing Then
        MsgBox "No range selected. Cancelled.", vbExclamation
        GoTo CleanUp
    End If

    ' ── Step 2: Count cells with validation ────────────────
    valCount = 0
    For Each cell In srcRng
        On Error Resume Next
        If cell.Validation.Type >= 0 Then valCount = valCount + 1
        On Error GoTo CleanUp
    Next cell

    If valCount = 0 Then
        MsgBox "No data validation rules found in the " & _
               "selected range.", vbExclamation
        GoTo CleanUp
    End If

    ' ── Step 3: Choose destination sheets ──────────────────
    Dim wsList As String, ws As Worksheet
    wsList = "Available destination sheets:" & vbCrLf & vbCrLf
    For Each ws In ThisWorkbook.Worksheets
        If ws.Name <> srcRng.Worksheet.Name Then
            wsList = wsList & "  • " & ws.Name & vbCrLf
        End If
    Next ws

    dstSheets = InputBox(wsList & vbCrLf & _
        "Enter sheet names, separated by commas:" & vbCrLf & _
        "  Example: Entity-B, Entity-C, Entity-D" & vbCrLf & _
        "  Or type ALL for every sheet except the template.", _
        "Destination Sheets")

    If dstSheets = "" Then
        MsgBox "No sheets specified. Cancelled.", vbExclamation
        GoTo CleanUp
    End If

    If UCase(Trim(dstSheets)) = "ALL" Then
        s = -1 ' Flag: process all non-template sheets
    Else
        sheetNames = Split(dstSheets, ",")
    End If

    ' ── Step 4: Confirm before acting ──────────────────────
    Dim destCount As Long
    If s = -1 Then
        destCount = ThisWorkbook.Worksheets.Count - 1
    Else
        destCount = UBound(sheetNames) - LBound(sheetNames) + 1
    End If

    If MsgBox("Copy " & valCount & " validation rule(s) from '" & _
              srcRng.Worksheet.Name & "' to " & destCount & _
              " sheet(s)?", vbYesNo + vbQuestion, _
              "Confirm Copy") = vbNo Then GoTo CleanUp

    ' ── Step 5: Copy validation to each destination ────────
    Dim rowOff As Long, colOff As Long
    Dim dstCell As Range
    Dim found As Boolean
    Dim valType As Long

    sheetCount = 0: cellTotal = 0: skipped = 0

    For Each ws In ThisWorkbook.Worksheets
        ' Skip the template sheet
        If ws.Name = srcRng.Worksheet.Name Then GoTo NextSheet

        ' If not ALL, check if this sheet was requested
        If s <> -1 Then
            found = False
            For i = LBound(sheetNames) To UBound(sheetNames)
                If Trim(sheetNames(i)) = ws.Name Then
                    found = True
                    Exit For
                End If
            Next i
            If Not found Then GoTo NextSheet
        End If

        ' Skip protected sheets
        If ws.ProtectContents Then
            skipped = skipped + 1
            GoTo NextSheet
        End If

        ' Copy each validation rule
        Dim cellDone As Long
        cellDone = 0

        For Each cell In srcRng
            On Error Resume Next
            valType = cell.Validation.Type
            On Error GoTo CleanUp

            If valType >= 0 Then
                rowOff = cell.Row - srcRng.Row
                colOff = cell.Column - srcRng.Column
                Set dstCell = ws.Cells( _
                    srcRng.Row + rowOff, _
                    srcRng.Column + colOff)

                ' Clear existing validation on destination
                On Error Resume Next
                dstCell.Validation.Delete
                On Error GoTo CleanUp

                ' Copy based on validation type
                Select Case valType
                    Case 3 ' xlValidateList
                        dstCell.Validation.Add Type:=3, _
                            Formula1:=cell.Validation.Formula1
                    Case 1, 2, 4, 6, 7 ' Numeric, Date, Time, TextLength
                        dstCell.Validation.Add _
                            Type:=valType, _
                            AlertStyle:=cell.Validation.AlertStyle, _
                            Operator:=cell.Validation.Operator, _
                            Formula1:=cell.Validation.Formula1, _
                            Formula2:=cell.Validation.Formula2
                    Case Else ' Custom formula
                        dstCell.Validation.Add Type:=valType, _
                            Formula1:=cell.Validation.Formula1
                End Select

                ' Copy messaging properties
                With dstCell.Validation
                    .IgnoreBlank = cell.Validation.IgnoreBlank
                    .InCellDropdown = cell.Validation.InCellDropdown
                    .InputTitle = cell.Validation.InputTitle
                    .InputMessage = cell.Validation.InputMessage
                    .ErrorTitle = cell.Validation.ErrorTitle
                    .ErrorMessage = cell.Validation.ErrorMessage
                    .ShowInput = cell.Validation.ShowInput
                    .ShowError = cell.Validation.ShowError
                End With

                cellDone = cellDone + 1
            End If
        Next cell

        If cellDone > 0 Then
            sheetCount = sheetCount + 1
            cellTotal = cellTotal + cellDone
        End If

NextSheet:
    Next ws

    ' ── Step 6: Summary ────────────────────────────────────
    Dim msg As String
    If sheetCount = 0 Then
        msg = "No validation was copied." & vbCrLf & vbCrLf & _
              "All non-template sheets are either protected " & _
              "or were not selected."
    Else
        msg = "Copied " & cellTotal & " validation rule(s) to " & _
              sheetCount & " sheet(s)."
        If skipped > 0 Then
            msg = msg & vbCrLf & vbCrLf & skipped & _
                  " sheet(s) skipped (protected). Unprotect " & _
                  "and run again to include them."
        End If
    End If

    MsgBox msg, vbInformation, "Done"

CleanUp:
    Application.ScreenUpdating = True
    Application.Calculation = xlCalculationAutomatic

    If Err.Number <> 0 Then
        MsgBox "Error " & Err.Number & ": " & Err.Description, _
               vbCritical, "Macro Error"
    End If
End Sub

#How It Works

#User selects the template range with the mouse

Set srcRng = Application.InputBox( _
    "Select the range that HAS the validation rules...", Type:=8)

The Type:=8 argument turns the InputBox into a range selector. The user drags to highlight cells directly on the worksheet instead of typing cell references. No guessing column letters, no typos — just click and drag.

The range is captured as a Range object so the macro knows exactly which cells to scan for rules and where those cells sit on the sheet. The row/column offsets computed later (cell.Row - srcRng.Row) let it map each rule to the same position on destination sheets.

#Sheet names are typed, not selected from a dialog

VBA doesn’t have a built-in multi-select sheet picker without building a UserForm. To keep the macro short and pasteable, we show the user a list of every sheet (except the template) and ask them to type names separated by commas. Typing ALL processes every non-template sheet at once.

wsList = "Available destination sheets:" & vbCrLf & vbCrLf
For Each ws In ThisWorkbook.Worksheets
    If ws.Name <> srcRng.Worksheet.Name Then
        wsList = wsList & "  • " & ws.Name & vbCrLf
    End If
Next ws

The list is built into the InputBox text so the user doesn’t need to guess or remember tab names. If a sheet name has a comma in it (rare in tax workpapers but possible), we note this as a known limitation.

#Validation type determines which properties to copy

Select Case valType
    Case 3 ' xlValidateList
        dstCell.Validation.Add Type:=3, _
            Formula1:=cell.Validation.Formula1
    Case 1, 2, 4, 6, 7 ' Numeric, Date, Time, TextLength
        dstCell.Validation.Add Type:=valType, _
            AlertStyle:=cell.Validation.AlertStyle, _
            Operator:=cell.Validation.Operator, _
            Formula1:=cell.Validation.Formula1, _
            Formula2:=cell.Validation.Formula2

Not all validation types use all parameters. Dropdown lists (xlValidateList, type 3) only need a source — no operator, no Formula2. Numeric and date validations need the operator (between, greater than, equal to, etc.) and both Formula1 and Formula2 for “between” ranges. Trying to pass an operator to a list validation throws a runtime error, so the Select Case routes each type to the correct .Add call.

The messaging properties (InputTitle, InputMessage, ErrorTitle, ErrorMessage) are independent of the validation type and always copied. So are the display preferences (ShowInput, ShowError, InCellDropdown, IgnoreBlank).

#Protected sheets are skipped with a message

If ws.ProtectContents Then
    skipped = skipped + 1
    GoTo NextSheet
End If

Protected sheets block programmatic changes to their validation rules. Rather than failing mid-operation, the macro skips them and reports how many were skipped at the end. The user can unprotect and run again to include them.

#The confirmation message box shows what will happen before acting

If MsgBox("Copy " & valCount & " validation rule(s) from '" & _
          srcRng.Worksheet.Name & "' to " & destCount & _
          " sheet(s)?", vbYesNo + vbQuestion, _
          "Confirm Copy") = vbNo Then GoTo CleanUp

The macro counts validation rules in the template range before doing anything destructive and shows the user exactly what it found. If the count looks wrong — say, the user expected 50 rules but the macro found only 2 — they can cancel and check the template sheet before committing.

#Why you should never copy-paste validation by copying cells

The instinct is to copy the Entity-A range, go to Entity-B, and Paste Special → Validation. This works for a single sheet but has two fatal flaws:

  1. It also pastes data. If Entity-B has different numbers than Entity-A (different account balances, dates, text), Paste Special → Validation still copies the cell values unless you are very careful about selecting only Validation in the Paste Special dialog. One misclick and you’ve overwritten client data.

  2. It doesn’t scale. 12 sheets × 50 cells × 3 Paste Special dialogs = 1,800 manual operations. The macro replaces all of them with two InputBox responses.

The macro reads validation properties from the template and writes only validation to the destination — it never touches cell values.

#Adapt It

Get the next macro in your inbox

One copy-paste-ready macro recipe every two weeks. No spam, no VBA theory — just automation that saves you time.

One macro recipe every two weeks. Unsubscribe anytime.

E

Excel Macro Guy

Excel enthusiast · married to an accountant

I love Excel. My wife is an accountant. Every busy season, I watch her wrestle with workpapers and think "a macro could do that in half a second." So I build them. She tests them on real client data. What survives gets published here.

More about me →