Buscar..


Referencias de calificación

Cuando se hace referencia a una worksheet , un range o cells individuales, es importante calificar completamente la referencia.

Por ejemplo:

ThisWorkbook.Worksheets("Sheet1").Range(Cells(1, 2), Cells(2, 3)).Copy

No está completamente calificado: las referencias de Cells no tienen un libro de trabajo y una hoja de cálculo asociados. Sin una referencia explícita, las celdas se refieren a ActiveSheet por defecto. Por lo tanto, este código fallará (producirá resultados incorrectos) si una hoja de cálculo que no sea Sheet1 es el ActiveSheet actual.

La forma más fácil de corregir esto es usar una instrucción With siguiente manera:

With ThisWorkbook.Worksheets("Sheet1")
    .Range(.Cells(1, 2), .Cells(2, 3)).Copy
End With

Alternativamente, puede usar una variable de la hoja de trabajo. (Probablemente este sea el método preferido si su código necesita hacer referencia a varias Hojas de trabajo, como copiar datos de una hoja a otra).

Dim ws1 As Worksheet
Set ws1 = ThisWorkbook.Worksheets("Sheet1")
ws1.Range(ws1.Cells(1, 2), ws1.Cells(2, 3)).Copy

Otro problema frecuente es hacer referencia a la colección de hojas de trabajo sin calificar el libro de trabajo. Por ejemplo:

Worksheets("Sheet1").Copy

La hoja de trabajo Sheet1 no está completamente calificada y carece de un libro de trabajo. Esto podría fallar si se hace referencia a varios libros en el código. En su lugar, utilice uno de los siguientes:

ThisWorkbook.Worksheets("Sheet1")       '<--ThisWorkbook refers to the workbook containing 
                                        'the running VBA code
Workbooks("Book1").Worksheets("Sheet1") '<--Where Book1 is the workbook containing Sheet1

Sin embargo, evite usar lo siguiente:

ActiveWorkbook.Worksheets("Sheet1")     '<--Valid, but if another workbook is activated
                                        'the reference will be changed

De manera similar, para los objetos de range , si no están calificados explícitamente, el range se referirá a la hoja actualmente activa:

Range("a1")

Es lo mismo que:

ActiveSheet.Range("a1")

Eliminar filas o columnas en un bucle

Si desea eliminar filas (o columnas) en un bucle, siempre debe hacerlo desde el final del rango y retroceder en cada paso. En caso de utilizar el código:

Dim i As Long
With Workbooks("Book1").Worksheets("Sheet1")
    For i = 1 To 4
        If IsEmpty(.Cells(i, 1)) Then .Rows(i).Delete
    Next i
End With

Te perderás algunas filas. Por ejemplo, si el código elimina la fila 3, entonces la fila 4 se convierte en la fila 3. Sin embargo, la variable i cambiará a 4. Entonces, en este caso, el código perderá una fila y marcará otra, que no estaba en el rango anterior.

El código correcto sería

Dim i As Long
With Workbooks("Book1").Worksheets("Sheet1")
    For i = 4 To 1 Step -1
        If IsEmpty(.Cells(i, 1)) Then .Rows(i).Delete
    Next i
End With

ActiveWorkbook vs. ThisWorkbook

ActiveWorkbook y ThisWorkbook veces se usan indistintamente por los nuevos usuarios de VBA sin entender completamente a qué se refiere cada objeto, esto puede causar un comportamiento no deseado en tiempo de ejecución. Ambos objetos pertenecen al objeto de aplicación.


El objeto ActiveWorkbook refiere al libro de trabajo que se encuentra actualmente en la vista superior del objeto de aplicación de Excel en el momento de la ejecución. (por ejemplo, el libro de trabajo que puede ver e interactuar en el momento en que se hace referencia a este objeto)

Sub ActiveWorkbookExample()

'// Let's assume that 'Other Workbook.xlsx' has "Bar" written in A1.

    ActiveWorkbook.ActiveSheet.Range("A1").Value = "Foo"
    Debug.Print ActiveWorkbook.ActiveSheet.Range("A1").Value '// Prints "Foo"

    Workbooks.Open("C:\Users\BloggsJ\Other Workbook.xlsx")
    Debug.Print ActiveWorkbook.ActiveSheet.Range("A1").Value '// Prints "Bar"

    Workbooks.Add 1
    Debug.Print ActiveWorkbook.ActiveSheet.Range("A1").Value '// Prints nothing

End Sub

El objeto ThisWorkbook refiere al libro de trabajo al que pertenece el código en el momento en que se está ejecutando.

Sub ThisWorkbookExample()

'// Let's assume to begin that this code is in the same workbook that is currently active

    ActiveWorkbook.Sheet1.Range("A1").Value = "Foo"
    Workbooks.Add 1
    ActiveWorkbook.ActiveSheet.Range("A1").Value = "Bar"

    Debug.Print ActiveWorkbook.ActiveSheet.Range("A1").Value '// Prints "Bar"
    Debug.Print ThisWorkbook.Sheet1.Range("A1").Value '// Prints "Foo"

End Sub

Interfaz de documento único frente a interfaces de documento múltiples

Tenga en cuenta que Microsoft Excel 2013 (y superior) utiliza la Interfaz de documento único (SDI) y que Excel 2010 (y más abajo) utiliza Interfaces de documentos múltiples (MDI).

Esto implica que para Excel 2013 (SDI), cada libro en una sola instancia de Excel contiene su propia interfaz de usuario de cinta:

introduzca la descripción de la imagen aquí

A la inversa, para Excel 2010, cada libro en una sola instancia de Excel utilizó una IU de cinta común (MDI): introduzca la descripción de la imagen aquí

Esto plantea algunos problemas importantes si desea migrar un código VBA (2010 <-> 2013) que interactúa con la cinta de opciones.

Se debe crear un procedimiento para actualizar los controles de la IU de la cinta en el mismo estado en todos los libros de trabajo para Excel 2013 y superior.

Tenga en cuenta que :

  1. Todos los métodos, eventos y propiedades de la ventana de nivel de aplicación de Excel no se verán afectados. ( Application.ActiveWindow , Application.Windows ...)
  2. En Excel 2013 y superior (SDI), todos los métodos, eventos y propiedades de la ventana de nivel de libro de trabajo ahora operan en la ventana de nivel superior. Es posible recuperar el identificador de esta ventana de nivel superior con Application.Hwnd

Para obtener más detalles, consulte la fuente de este ejemplo: MSDN .

Esto también causa algunos problemas con las formas de usuario sin modelo. Vea aquí para una solución.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow