excel 如果输入了不正确的值,是否有方法退出单元格编辑会话而不进行任何更改?

brc7rcf0  于 2022-12-14  发布在  其他
关注(0)|答案(1)|浏览(108)

我在Excel工作表中使用两个不同的宏来执行以下操作:#1允许在同一单元格中输入多个日期(用逗号分隔)#2只允许以DD/MM/YYYY格式输入从01/01/2000到今天的日期。
当在单元格中输入不正确的值时会出现问题,我需要一种更好的方法来处理这些错误。
例如,如果单元格中已经有日期,并且添加了第二个无效值(例如,未来的日期,如01/01/2024),则会弹出一条错误消息,让用户单击“重试”以输入其他值,或单击“取消”退出单元格编辑。但是,有时(并非总是)当我单击“取消”时,所有单元格值都将被删除(甚至包括以前在其中的正确值)。
正如我提到的,有时会发生这种错误,有时不会。但这是一个主要问题,因为如果一个无效的值被意外输入到一个单元格,所有的单元格内容可能会被删除,Excel不允许我撤销这个操作。
因此,我正在寻找一种方法来退出单元格编辑,而不更改任何单元格值,如果一个无效的值输入到一个单元格。
以下是宏:#1

Option Explicit

Private Sub Worksheet_Change(ByVal Target As Range)

' Written by Philip Treacy
' https://www.myonlinetraininghub.com/select-multiple-items-from-drop-down-data-validation-list

    Dim OldVal As String
    Dim NewVal As String
    
    ' If more than 1 cell is being changed
    If Target.Count > 1 Then Exit Sub
    If Target.Value = "" Then Exit Sub
    
    If Not Intersect(Target, ActiveSheet.Range("Date_Entry")) Is Nothing Then
    
        ' Turn off events so our changes don't trigger this event again
        Application.EnableEvents = False
        
        NewVal = Target.Value
        
        ' If there's nothing to undo this will cause an error
        On Error Resume Next
        Application.Undo
        On Error GoTo 0
        
        OldVal = Target.Value
        
        ' If selection is already in the cell we want to remove it
        If InStr(OldVal, NewVal) Then
        
            'If there's a comma in the cell, there's more than one word in the cell
            If InStr(OldVal, ",") Then
            
                If InStr(OldVal, ", " & NewVal) Then
                
                    Target.Value = Replace(OldVal, ", " & NewVal, "")
                
                Else
                
                    Target.Value = Replace(OldVal, NewVal & ", ", "")
                
                End If
                
            Else
            
                ' If we get to here the selection was the only thing in the cell
                Target.Value = ""
            
            End If
        
        Else
        
            If OldVal = "" Then
        
                Target.Value = NewVal
            
            Else
            
                ' Delete cell contents
                If NewVal = "" Then
            
                    Target.Value = ""
                
                Else
            
                    ' This IF prevents the same value appearing in the cell multiple times
                    ' If you are happy to have the same value multiple times remove this IF
                    If InStr(Target.Value, NewVal) = 0 Then
                    
                        Target.Value = OldVal & ", " & NewVal
                
                    End If
                
                End If
            
            End If
            
        End If
        
        Application.EnableEvents = True
            
    Else
    
        Exit Sub
        
    End If

End Sub

2

Sub customised_validation_dates()

With ActiveSheet.Range("Date_Entry").Validation
    .Delete
    .Add Type:=xlValidateDate, AlertStyle:=xlValidAlertStop, _
     Operator:=xlBetween, Formula1:="01/01/2000", Formula2:="=TODAY()"
    .IgnoreBlank = True
    .ErrorTitle = "Invalid Date"
    .ErrorMessage = "Input must be date between 01/01/2000 and today. Date must also be entered in DD/MM/YYYY format."
    .ShowInput = True
    .ShowError = True
End With

End Sub
sy5wg1nm

sy5wg1nm1#

此代码允许使用Excel内置数据验证方法无法使用的几个功能:
1.一个单元格中可以添加多个日期值
1.只允许指定范围内的日期值
1.如果用户添加了不正确的值(例如:不是日期的值,或者日期福尔斯指定范围),则代码将退出单元格编辑,而不修改单元格中的原始值。
我创建了两个变量dtStartdtEnd,它们包含了我想用于日期验证的开始日期和结束日期。
我将这些变量添加到了工作表更改事件sub中。
dtEnd很特殊,因为它调用dtTodaydtToday检索今天的日期,我想在日期范围验证中使用它。
我的大部分代码来自this website,它最初是为了允许用户覆盖excel的数据验证方法,允许从数据验证列表中选择多个项,并删除重复项而编写的。我修改了这段代码,以便随后检查值是否为日期,然后检查该日期是否福尔斯指定的范围内。
下面是函数代码:

Option Explicit

Private Sub Worksheet_Change(ByVal Target As Range)

    Dim OldVal As String 'original cell value before edit
    Dim NewVal As String 'new value entered by user
    Dim dtStart As Date 'start value as date, for date range validation
    Dim dtEnd As Date 'end value as date, for date range validation
    dtStart = #1/1/2000# 'set a start date
    dtEnd = Date 'get today's date and set it as the end date
    
    
    
    ' If more than 1 cell is being changed
    If Target.Count > 1 Then Exit Sub
    If Target.Value = "" Then Exit Sub
    
    If Not Intersect(Target, ActiveSheet.Range("stack_vba_testing")) Is Nothing Then
    
        ' Turn off events so our changes don't trigger this event again
        Application.EnableEvents = False
        
        ' store the selected date into a value called "NewVal"
        NewVal = Target.Value
        
        ' If there's nothing to undo this will cause an error
        On Error Resume Next
        
        'we don't want the new value to take over the cell, so undo adding the new value
        Application.Undo
        On Error GoTo 0
        
        'because of application.undo, we can access the original cell value. store that as "OldVal"
        OldVal = Target.Value
        
        'Before starting, reformat NewVal to dd mm yyyy, because excel does weird things when / is used to seperate mm dd yyyy
        NewVal = Format(NewVal, "dd mm yyyy")

        'check if oldval contains newval
        If InStr(OldVal, NewVal) Then
        
            'Check if there is a comma in the cell, which would indicate that there is more than one value in the cell
            If InStr(OldVal, ",") Then
            
                'Then check if the oldval contains a comma *followed by* the new val
                If InStr(OldVal, ", " & NewVal) Then
                    
                    'then remove the comma and the value; replace with an empty space
                    Target.Value = Replace(OldVal, ", " & NewVal, "")
                   
                
                Else
                'Else, if old val contains new val but ends witha comma (instead of starting with a comma)
                
                    'then replace the value (which ends with a comma) with an empty space
                    Target.Value = Replace(OldVal, NewVal & ", ", "")
                    
                    
                
                End If
                
            Else
            
                'Else, old val was equal to new val without anything else in the cell, so make the cell = nothing
                Target.Value = ""
            
            End If
        
        Else
            'Check if old value = nothing/empty
            If OldVal = "" Then 'check if oldval is empty
                
                If IsDate(NewVal) Then 'if old val is empty, check if new val is a date
                    
                    If NewVal >= dtStart And NewVal <= dtEnd Then 'if newval is a date, check if it falls within date range
                        Target.Value = Format(NewVal, "dd mm yyyy") 'if new val is a date, make the cell = newval
                    
                    Else
                    
                    MsgBox ("Date is out of range (01/01/2000 and Today)")
                    
                    End If
                
                Else
                    MsgBox ("Not a date") 'otherwise, throw error message
                    Target.Value = OldVal 'and keep original cell contents
                    
                End If
                
                
            Else
            
                'If the new value = nothing, then make the cell = nothing
                If NewVal = "" Then
            
                    
                    Target.Value = ""
                    
                    
                
                Else
            
                    'Check if the old value (target) are different
                    If InStr(Target.Value, NewVal) = 0 Then
                        
                        If IsDate(NewVal) Then 'if they are different check if newval is a date value
                            
                            If NewVal >= dtStart And NewVal <= dtEnd Then 'if newval is a date, check if it falls within date range
                            Target.Value = OldVal & ", " & Format(NewVal, "dd mm yyyy") 'if date falls within specified range, concatenate newval and oldval using a comma
                            
                            Else
                                MsgBox ("Date out of range")
                                
                            End If
                            
                        Else
                            MsgBox ("Not a date") 'if new val is not a date, throw error message
                            Target.Value = OldVal 'and keep original cell value
                            
                        End If
                        
                
                    End If
                
                End If
            
            End If
            
        End If
        
        Application.EnableEvents = True
            
    Else
    
        Exit Sub
        
    End If
    

End Sub

相关问题