Evitar borrar Validación de datos en Excel al pegar datos copiados
martes, diciembre 22, 2009
Empiezo con una aclaración: por primera vez he eliminado una entrada luego de haberla publicado. Se trata de la entrada donde mostraba un código para evitar el problema de la destrucción de la validación de datos al pegar un valor copiado de otra celda. Había demasiadas circunstancias que provocaban que el código no funcionara. Mea culpa!
Volviendo sobre el tema, una de las debilidades de Validación de Datos es que si un usuario pega un valor en una celda del rango validado en lugar de ingresarlo manualmente, las definiciones de la validación quedan eliminadas.
La única forma de evitar estas situaciones es usar macros, más precisamente eventos.
Buscando en la Internet encontré, entre otras, una solución propuesta por John Walkenbach. El problema con esta solución es que si el usuario en lugar de pegar el valor usa la opción Pegado Especial-Valores (o Fórmulas), el evento no responde y el valor es aceptado.
El código que propongo usa una parte del código de Walkenbach, para el caso que el usuario use la opción de pegado común, y parte de mi código para el caso que use pegar-valores, pegar-fórmulas, Insertar o arrastre el valor a la celda.
En el módulo de Vba de la hoja pegamos estos códigos
Private Sub Worksheet_Change(ByVal Target As Range)
' rutina desarrollada por Jorge Dunkelman - JLD Excel Blog
' parte del codigo tomado de la nota de John Walkenbach http://www.j-walk.com/ss/excel/tips/tip98.htm
Dim rngValid As Range, cell As Range
Dim Msg As String
Dim codeValid As Variant
Set rngValid = Range("rngValidado")
On Error Resume Next
If Not HasValidation(rngValid) Then
Application.Undo
MsgBox "Valor no válido", vbCritical
Application.EnableEvents = False
Target.ClearContents
Application.EnableEvents = True
End If
For Each cell In Target
If Union(cell, rngValid).Address = rngValid.Address Then
codeValid = ActiveCell.Validation.Value
If codeValid = True Then
Exit Sub
Else
MsgBox "Valor no válido", vbCritical
Application.EnableEvents = False
cell.ClearContents
cell.Activate
Application.EnableEvents = True
End If
End If
Next cell
End Sub
Private Function HasValidation(r) As Boolean
Dim x
On Error Resume Next
x = r.Validation.Type
If Err.Number = 0 Then HasValidation = True Else HasValidation = False
End Function
Nótese que estamos usando un evento Worksheet_Change y una función UDF.
Al rango B3:B12 de la hoja hemos aplicado validación de datos con la opción Lista. Los valores permitidos son a1, a2, a3 y a4.
Este video muestra cómo funciona la macro
El archivo con el ejemplo y el código puede descargarse aquí.






19 comments:
Buenos días Jorge,
Esta macro aplica tanto a valores númericos como alfanúmericos?
Mil gracias por toda tu ayuda.
Jorge Alberto,
si. La macro de hecho comprueba primero si se ha quitado la validación de la celda que se está evaluando (cosa que sucede si se aplica copiar/pegar). Si se ha quitado la validación, la macro corre la orden UNDO y cancela la acción del usuario. Como ves, este no está ligado al tipo de valor o regla que hayamos puesto en la validación.
La segunda parte de la rutina evalúa si el valor en la celda coincide con alguno de los valores permitidos. Esto es necesario en caso que el usuario use Pegar Especial-Valores o Fórmulas. Tampoco en este caso importa si los valores de la validación son numéricos o alfa-numéricos.
Felicitaciones Julio por tu sapiencia. También por la nueva forma de descargar tus ejemplos, brinda mayor facilidad para las descargas. Feliz Navidad 2009.
Hola, Jorge.
La solución funciona bastante bien, aunque se echa en falta algo más genérico que no hubiera que programar para cada rango en que queramos tener una validación, porque si tenemos varios se complica mucho la cosa.
Haciéndole perrerías he encontrado un comportamiento anómalo, que te lo cuento sólo a modo de curiosidad, porque reconozco que es un tanto rebuscado: si se intenta cambiar algo de la validación de alguna de las celdas del rango parece que si el cambio no afecta a todas por igual se vuelve un poco loca la macro y ya no acepta ningún valor y se queda en bucle señalando el error.
Y por último, me gustaría saber con qué programa haces tus videos de demo. hace tiempo contestaste en otra nota que hacías unas demo en flash con Wink, pero estos videso quedan bastante mejor y se ven directamente, es mucho mejor.
Saludos y gracias por tu tiempo.
Gracias, pero...¿quien es Julio?
gracias maestro, es usted un genio en esto.
y sobre todo lo mas valioso que le he conocido.
la capacidad y humildad para compartir sus conocimientos.
Que tenga usted feliz navidad y un prospero año nuevo.
Gracias, pero lo de genio me queda un poco grande.
Que tengas un excelente año!
Javier,
tenés razón, habría que programar algomás general. En cuanto al "bug" que encontraste me olvidé de aclarar que la macro funciona bien sólo si todas las celdas del rango contienen validación de datos. Tasl vez más adelante publique algo más general.
Feliz año nuevo!
Ah, me olvidaba. Las capturas de pantalla en video las hago con el Windows Media Encoder de Microsoft (se puede descargar gratuitamente).
La ventaja del Wink es que podes editar y agregar comentarios.
Muchisimas gracias por su humildad y generosidad en compartir sus valiosisimos conocimientos don Jorge. Exitos y Bendiciones para este 2010. Que la pase bien. Saludos desde Guatemala.
Hola Jorge. Me han gustado mucho tus notas, gracias por tu esfuerzo, aunque no he tenido tiempo para probarlas todas. Tengo una consulta, me gustaría saber como valido datos según un orden asignado. Por ejemplo: Si en la celda A1 tengo "Documento A" y la celda B1 "Revisión 1", y en la celda A2 tengo el mismo texto "Documento A" entonces la celda B2 solo me deberia permitir digitar "Revisión 2", no me deberia dejar digitar "Revisión 3" o "Revisión 0" porque no es el consecutivo correspondiente. Te enviare un archivo adjunto a tu correo para que sea mas clara la pregunta.
Muchas gracias de antemano y sigue con el buen trabajo.
Se puede hacer, aunque la explicación es un poco larga para ponerla en un comentario.
No me queda claro por qué se necesita validación de datos. Si en las celdas de la columna B tiene que aparecer siempre el valor correspondiente al de la columna A, podrías usar una fóemula sencilla como ="Revisión "&A1
Buenos días, me ha venido genial tu código pero me surge un problema, tengo que validar los datos de toda la hoja y aquí solo me valida de la B3:B12, como podría cambiar esto? Gracias y un saludo.
Esimado,
supongo que habrás descargado el archivo del ejemplo. En este archivo el rango que contiene la validación de datos está incluido en un nombre, rngValidado. Tienes que adaptar el rango a tus necesidades.
Jorge, estoy probando este código en una planilla, pero como hago si necesito usar el código para otros rangos de celdas no adyacentes.
Habría que definir todos los rangos que contengan validación de datos. No veo otra manera-
Al respecto le comento Sr. Jorge que a 3 celdas no contiguas les nombre "rngValidado", pero la macro entra un bucle sin fin y me muestra la ventana de error "Valor no valido".
el codigo se ve chevere... soy nuevo en las macros pero me encantan un monton... ¿donde pego ese codigo? tengo algo en el siguiente libro: la "hoja3" celda "C10" y la "hoja4" celda "C10" tienen listas desplegables, ¿como hago para que el codigo funcione en esas celdas? gracias por su ayuda...
Angel,
como pongo en la nota, en el módulo de la hoja. Te sugiero que descargues el ejemplo y lo investigues. Para ver los códigos debes abrir el editor de Vb (Alt+F11).
Publicar un comentario