Over time I've developed this highly enforced workbook where end users can paste data and then SQL code is generated for me to input the data into our dB. The only worksheet in question here is the "data" worksheet, as well as some VBA code contained in the "ThisWorkbook" area.
Currently the workbook is doing everything I want it to - it is correctly enforcing that the data being pasted or entered matches the Data Validation settings (and not overwriting data validation settings by changing any Paste function to a data-only paste function), and prompting the user to correct the data if it doesn't meet the criteria.
Beyond just pasted data, I needed to implement code to also validate the data if the end user manually typed in a cell; I did that by setting up VBA to execute on any workbook change, which calls the postPasteValidation Sub and confirms that data entered matches.
Private Sub Worksheet_Change(ByVal target As Range)
Application.EnableEvents = False
Application.ScreenUpdating = False
' LINE BELOW DUE TO PW PROMPT EVEN ON UNLOCKED DATA CELLS, WHEN WORKSHEET IS PROTECTED
ActiveSheet.Unprotect "PW"
Dim vCopyValue As Variant
Dim vCopyFormula As Variant
Dim CellAddr As String
CellAddr = ActiveCell.Address
On Error GoTo ExitClean
vCopyValue = target.Value
vCopyFormula = target.Formula
Application.Undo
target.Value = vCopyValue
target.Formula = vCopyFormula
On Error GoTo 0
ExitClean:
Application.CalculateFull
Range(CellAddr).Select
Call postPasteValidation
' LINE BELOW RE-PROTECTS SHEET AS VBA FINISHES AND RETURNS TO THE USER
ActiveSheet.Protect "PW"
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
Sub postPasteValidation()
Call ConvertCase
Dim validationCells As Range
Dim oneCell As Range
Dim userInput As Variant, promptStr As String
On Error Resume Next
Set validationCells = ActiveSheet.Cells.SpecialCells(xlCellTypeSameValidation)
On Error GoTo 0
If Not (validationCells Is Nothing) Then
For Each oneCell In validationCells
If Not (oneCell.Validation.Value) Then
promptStr = oneCell.Address & " has a bad value in it." & vbCrLf _
& "Please enter the correct data per" & vbCrLf _
& oneCell.Validation.InputMessage
userInput = Application.InputBox(prompt:=promptStr, Default:=oneCell.Value)
If userInput <> False And oneCell.Value <> vbNullString Then oneCell.Value = userInput
End If
Next oneCell
End If
Call ConvertCase
End Sub
The issue comes up when an end user edits a single cell - such as typing a note entry in Column N "W_Notes"; when they do this, it rechecks validation on EVERY cell in the worksheet (up to my defined range of 1001 rows). That takes approximately 45 seconds, which is not really an efficient use of time to write in a note in a single cell.
I've tried changing the setting in postPasteValidation from xlCellTypeALLValidation to xlCellTypeSameValidation, but that didn't seem to even decrease the amount of time for processing.
Set validationCells = ActiveSheet.Cells.SpecialCells(xlCellTypeSameValidation)
I'm OK with the "postPasteValidation" Sub running only 1 time before they close the workbook, and at that time checking all cells in the target range (and removing it from being called within the Paste and Workbook_Change Subs); but when I tried to move this code out to a Before_Close or Before_Save area, it wouldn't run.
I've attached a blank of the workbook here; the password to unlock the "data" tab is PW . I'm open to any and all suggestions, the end users love this workbook, but not the 45 second wait any time they need to edit a cell!
David
Bookmarks