Como utilizar 2 macros que utilizan Worksheet_Change(ByVal Target As Range)

Tengo dos macros en la hoja 1 y ambas empiezan con Private Sub Worksheet_Change .Y a la hora de ejecutar las dos marcan error. ¿Qué debo modificar para que funcionen? Anexo las dos macros.

Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address(0, 0) = "A1" And Target = 1 Then
End If
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
    Dim chkbox As CheckBox
    Dim cell As Range
    If Not Intersect(Target, Range("A10:A1000")) Is Nothing Then
        For Each cell In Intersect(Target, Range("A10:A1000"))
            If Not IsEmpty(cell.Value) Then
                'If the cell is NOT empy, I should add a checkbox, to the right of the cell without text
                Set chkbox = ActiveSheet.CheckBoxes.Add(cell.Left, cell.Top, cell.Width, cell.Height)
                With chkbox
                    .Text = ""
                End With
            Else
                For Each chkbox In ActiveSheet.CheckBoxes
                    If Not Intersect(cell, chkbox.TopLeftCell) Is Nothing Then
                        chkbox.Delete
                    End If
                Next chkbox
            End If
        Next cell
    End If
    Call LinkCheckBoxes
End Sub
Respuesta
1

Pues si ambas macros no interfieren uno con la otra bastaría con copiar el código de una dentro de la otra... (solo el código no la línea Sub ni la línea End Sub)

Por ultimo veo una línea que llama a otra macro... que no se exactamente que hace... des cualquier manera quizás deberías adicionalmente aplicar esta sugerencia:

Un evento Change se genera cuando algo se modifica en la hoja de cálculo... pero si dentro del evento se modifica (la macro) algo más en la hoja, se termina llamando al mismo evento de manera recursiva... eso no es bueno.

Para evitarlo deberías desactivar los eventos mientras se están ejecturando las macros contenidas en sus código... colocando las siguientes instrucciones como primera y ultima líneas del código del evento

INICIO:              Application.EnableEvents=False

FINAL:               Application.EnableEvents=True

Muchas gracias por la aclaración. 

La idea es encontrar valores en la columna A y de ahí generar automáticamente un checkbox que me permita tildarlo y con ello pasarlo a otra hoja.

Lo que se me ocurrió es con la función contar verificar si la celda A tenia números y en caso afirmativo colocar un 1 en la columna J. La primer macro lo que debería hacer es recorrer la columna J y ver si hay un 1 o un cero para ejecutar otra macro.

Y esta sería la que agrega los checkbox.

Agradezco tu colaboración. Saludos. 

La primer macro tiene esta estructura 

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Range("A1:A100")) Is Nothing Then
        If Target.Count > 1 Then Exit Sub
        If Target.Value = 1 Then
            'MsgBox "macro1"
            Call Macro1
        End If
    End If
End Sub

Me confundi al inicio de la pregunta.

A ver... ordenemos un poco antes de que me confunda yo...

Me dices que ya no considere eso: (primera macro)

Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Address(0, 0) = "A1" And Target = 1 Then
End If
End Sub

y que considere en su lugar esto:

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Range("A1:A100")) Is Nothing Then
        If Target.Count > 1 Then Exit Sub
        If Target.Value = 1 Then
            'MsgBox "macro1"
            Call Macro1
        End If
    End If
End Sub

... lo que hace es reaccionar si la celda que se acaba de modificar esta en la columna A (rango A1:A100) y acaba de ser escrito un 1...  solo reacciona con el numero 1... no con cualquier número.  

Hasta allí... todo podría estar bien (aun si decías que era verificar número, pero el único que aceptas es el número 1) ... ¿Pero me parece que esta es la macro que debería recorrer más bien la columna J?

la otra macro...

Private Sub Worksheet_Change(ByVal Target As Range)
    Dim chkbox As CheckBox
    Dim cell As Range
    If Not Intersect(Target, Range("A10:A1000")) Is Nothing Then
        For Each cell In Intersect(Target, Range("A10:A1000"))
            If Not IsEmpty(cell.Value) Then
                'If the cell is NOT empy, I should add a checkbox, to the right of the cell without text
                Set chkbox = ActiveSheet.CheckBoxes.Add(cell.Left, cell.Top, cell.Width, cell.Height)
                With chkbox
                    .Text = ""
                End With
            Else
                For Each chkbox In ActiveSheet.CheckBoxes
                    If Not Intersect(cell, chkbox.TopLeftCell) Is Nothing Then
                        chkbox.Delete
                    End If
                Next chkbox
            End If
        Next cell
    End If
    Call LinkCheckBoxes
End Sub

reacciona solo si se ha modificado algo (celda o rango) dentro del rango A10:A1000 (es un rango diferente al primero)  y pone o borra los checkboxes existentes en la celda.  Estos checkbox no estan con link a ninguna celda... (indicabas que sería a la columna J)...

Pero al final de la macro veo que llamas a otra macro que por el nombre indudablemente se encarga de esa tarea y supongo que estos checkboxes son los que están con el link a la columna J... (sería bueno ver si ese código no tiene escondido algo que modifique alguna celda de la hoja... normalmente al agregar el link a un checkbox no se carga ningún valor en el mismo... ni en la celda con el link (solo después al hacer o quitar el check se modifica el valor de verdadero o falso en la celda)... pero... aun así no suena muy eficiente que hagas el link al final porque quiere decir que lo vas a hacer para todos los checkboxes (no veo tu código pero presumo que es así...) . Sería más lógico hacerlo en el instante que los agregas con

              .LinkedCell = Cells(cell.Row, "J").Address

Hasta allí todo bien... hasta que percaté de algo... asumiendo que tu primera macro, corregida, debiera realizar algo cada vez que haces clic en el checkbox.. tenemos un problema aparentemente infranqueable...

El evento Change reacciona cada vez que se modifica algo en una celda, que no es lo mismo cuando cambia el valor en una celda... porque si no piensa... en general... cualquiera cambio en una celda modifica muchos valores en todas las fórmulas asociadas a esa celda... y el evento no se va a "disparar" por cada una de esas celdas... sino solo por la que fue escrita o modficada originalmente...

El detalle es que para Excel una modificación de un LinkedCell no califica como si fuera una modificación de una celda... por lo que NO VA A REACCIONAR CON EL EVENTO CHANGE CUANDO HAGAS CLIC EN NINGÚN CHECKBOX... así están definidos los eventos... (o mejor dicho así NO están definidos).

Y hasta aquí iba originalmente mi respuesta... hasta que se me ocurrió una manera de "sacarle la vuelta a Excel"...

Te planteo:

Al crear el checkbox... asociale una macro... directamente... así si tenemos manera de darnos cuenta que el usuario hizo check... el problema es que la macro no tendrá idea de cual fue el checkbox involucrado...

Entonces pensé que podemos guardar "adicional" a la columna J, un espejo de los valores de esta columna J... así se puede recorrer toda la columna y fijarse cual ha cambiado para deducir que fue esta la columna implicada...

Con todo esto te propongo esto:

(Estoy suponiendo que los números irán en A10:A1000, los checkbox en esa misma columna, los valores asociados en la columna J, y el "espejo" en la columna K)

En el modulo de hoja pon el siguiente código (que ya incluye el linkcell adecuado)

Private Sub Worksheet_Change(ByVal Target As Range)
    Dim chkbox As CheckBox
    Dim cell As Range
    Application.EnableEvents = False
    If Not Intersect(Target, Range("A10:A1000")) Is Nothing Then
        For Each cell In Intersect(Target, Range("A10:A1000"))
            If Not IsEmpty(cell.Value) Then
                'If the cell is NOT empy, I should add a checkbox, to the right of the cell without text
                Set chkbox = ActiveSheet.CheckBoxes.Add(cell.Left, cell.Top, cell.Width, cell.Height)
                With chkbox
                    .Text = ""
                    .Value = xlOff
                    .LinkedCell = Cells(cell.Row, "J").Address
                    .Display3DShading = False
                    .OnAction = "Macro1"
                End With
            Else
                For Each chkbox In ActiveSheet.CheckBoxes
                    If Not Intersect(cell, chkbox.TopLeftCell) Is Nothing Then
                        Cells(chkbox.TopLeftCell.Row, "J") = Empty
                        chkbox.Delete
                    End If
                Next chkbox
            End If
        Next cell
    End If
    Application.EnableEvents = True
End Sub

y en un módulo:

Sub Macro1()
For i = 10 To 1000
    If Cells(i, "J") <> Cells(i, "K") And Cells(i, "J") = True Then
        ' *****************************************************
        ' *  REEMPLAZAR ESTO POR TU VERDADERA MACRO1  *
        ' *****************************************************
    End If
    Cells(i, "K") = Cells(i, "J")
Next i
End Sub

Asi... si veo que reacciona cuando haces clic en el checkbox y lo activas... y relaciona tu macro con el valor de i que tiene el número de fila en el cual se está haciendo click

Buena suerte.

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas