He escuchado mucho acerca de la aborrecible comprensión del uso .Select
en Excel VBA, pero no estoy seguro de cómo evitar usarlo. Estoy descubriendo que mi código sería más reutilizable si pudiera usar variables en lugar de Select
funciones. Sin embargo, no estoy seguro de cómo referirme a cosas (como el ActiveCell
etc.) si no las estoy usando Select
.
He encontrado este artículo sobre rangos y este ejemplo sobre los beneficios de no usar select pero no puedo encontrar nada sobre cómo .
Select
y / oActiveSheet
etc., etc. es completamente inevitable. Aquí hay un ejemplo que encontré: stackoverflow.com/questions/22796286/….Select / .Selection
ser necesario.Respuestas:
Algunos ejemplos de cómo evitar seleccionar
Use
Dim
'd variablesSet
la variable al rango requerido. Hay muchas formas de referirse a un rango de celda únicao un rango de celdas múltiples
Usted puede utilizar el acceso directo al
Evaluate
método, pero esto es menos eficiente y por lo general se debe evitar en el código de producción.Todos los ejemplos anteriores se refieren a celdas en la hoja activa . A menos que desee trabajar específicamente solo con la hoja activa, también es mejor atenuar una
Worksheet
variableSi no desea trabajar con el
ActiveSheet
, para mayor claridad lo mejor es ser explícita. Pero tenga cuidado, ya que algunosWorksheet
métodos cambian la hoja activa.Nuevamente, esto se refiere al libro de trabajo activo . A menos que desee trabajar específicamente solo con
ActiveWorkbook
oThisWorkbook
, es mejor atenuar unaWorkbook
variable también.Si no desea trabajar con el
ActiveWorkbook
, para mayor claridad lo mejor es ser explícita. Pero tenga cuidado, ya que muchosWorkBook
métodos cambian el libro activo.También puede usar el
ThisWorkbook
objeto para referirse al libro que contiene el código en ejecución.Un código común (malo) es abrir un libro, obtener algunos datos y luego cerrar de nuevo
Esto es malo:
Y sería mejor como:
Pase rangos a su
Sub
syFunction
s como variables de rangoTambién debe aplicar métodos (como
Find
yCopy
) a las variablesSi realiza un bucle en un rango de celdas, a menudo es mejor (más rápido) copiar primero los valores del rango en una matriz variante y hacer un bucle sobre ese
Esta es una pequeña muestra de lo que es posible.
fuente
rng1(12, 12)
, funcionará aunque rng1 esté configurado en[A1:A10]
solo.Range
así:ActiveSheet.[a1:a4]
ows.[b6]
.variant
variable no requiereSet
hasta que le asigne un objeto. Por ejemplo,Dim x: x = 1
está bien, peroDim x: x = Sheets("Sheet1")
generará un error 438. Sin embargo sólo para confundir / aclararDim x: x = Range("A1")
va a no crear un error. ¿Por qué? ... porque se le asigna el valor del objeto a la variable, no una referencia al objeto en sí (ya que es el equivalente deDim x: x = Range("A1").Value
)Dos razones principales por las que
.Select
/.Activate
/Selection
/Activecell
/Activesheet
/Activeworkbook
etc ... deben evitarse¿Cómo lo evitamos?
1) Trabajar directamente con los objetos relevantes.
Considera este código
Este código también se puede escribir como
2) Si es necesario, declare sus variables. El mismo código anterior se puede escribir como
fuente
Sheets(2).[C10:D12].Value = Sheets(1).[A1:B3].Value
.Activate
para moverse a la hoja original, solo useApplication.Goto
Agregaré un pequeño punto de énfasis a todas las excelentes respuestas dadas anteriormente:
Probablemente, lo más importante que puede hacer para evitar el uso de Seleccionar es usar, en la medida de lo posible, rangos con nombre (combinados con nombres de variables significativos) en su código VBA . Este punto fue mencionado anteriormente, pero pasó por alto un poco; Sin embargo, merece especial atención.
Aquí hay un par de razones adicionales para hacer un uso liberal de los rangos con nombre, aunque estoy seguro de que podría pensar en más.
Los rangos con nombre hacen que su código sea más fácil de leer y comprender.
Ejemplo:
Es bastante obvio lo que los rangos con nombre
Months
yMonthlySales
contiene, y lo que está haciendo el procedimiento.¿Porque es esto importante? Parcialmente porque es más fácil para otras personas entenderlo, pero incluso si usted es la única persona que alguna vez verá o usará su código, aún debe usar rangos con nombre y buenos nombres de variables porque OLVIDARÁ lo que quiso hacer con él un año después, y perderá 30 minutos solo para descubrir qué está haciendo su código.
Los rangos con nombre aseguran que sus macros no se rompan cuando (¡no si!) La configuración de la hoja de cálculo cambia.
Considere, si el ejemplo anterior se hubiera escrito así:
Al principio, este código funcionará bien, es decir, hasta que usted o un futuro usuario decida "caramba, creo que voy a agregar una nueva columna con el año en Columna
A
", o colocar una columna de gastos entre los meses y columnas de ventas, o agregue un encabezado a cada columna. Ahora, tu código está roto. Y debido a que usó nombres de variables terribles, le llevará mucho más tiempo descubrir cómo solucionarlo de lo que debería tomar.Si había utilizado rangos con nombre para comenzar, las columnas
Months
ySales
podrían moverse alrededor de todo lo que desee, y su código continuará funcionando bien.fuente
Voy a dar la respuesta corta ya que todos los demás dieron la respuesta larga.
Obtendrá .select y .activate cada vez que grabe macros y los reutilice. Cuando selecciona una celda u hoja, solo la activa. A partir de ese momento, siempre que use referencias no calificadas, como
Range.Value
ellos solo usan la celda y hoja activas. Esto también puede ser problemático si no mira dónde se coloca su código o si un usuario hace clic en el libro.Por lo tanto, puede eliminar estos problemas haciendo referencia directa a sus celdas. Que va:
O podrías
Existen varias combinaciones de estos métodos, pero esa sería la idea general expresada tan pronto como sea posible para personas impacientes como yo.
fuente
Si bien no puedo pensar en nada más que un puñado de situaciones aisladas en las
.Select
que sería una mejor opción que la referencia directa a las celdas, me levantaría en defensaSelection
y señalaría que no debe descartarse por las mismas razones que.Select
deberían evitarse.Hay momentos en los que tener subrutinas macro breves y que ahorran tiempo asignadas a combinaciones de teclas de acceso rápido disponibles con solo tocar un par de teclas ahorra mucho tiempo. Ser capaz de seleccionar un grupo de celdas para promulgar el código operativo en maravillas de obras cuando se trata de datos de bolsillo que no se ajustan a un formato de datos de toda la hoja de trabajo. De la misma manera que puede seleccionar un grupo de celdas y aplicar un cambio de formato, seleccionar un grupo de celdas para ejecutar un código macro especial puede ser un gran ahorro de tiempo.
Ejemplos de subestructura basada en selección:
El código real para procesar podría ser cualquier cosa, desde una sola línea hasta varios módulos. He usado este método para iniciar rutinas de larga ejecución en una selección irregular de celdas que contienen los nombres de archivo de libros externos.
En resumen, no descarte
Selection
debido a su estrecha asociación con.Select
yActiveCell
. Como una propiedad de hoja de trabajo tiene muchos otros propósitos.(Sí, sé que se trataba esta pregunta
.Select
,Selection
pero quería eliminar cualquier idea errónea que los codificadores principiantes de VBA pudieran inferir).fuente
Selection
puede ser cualquier cosa en la hoja de trabajo, así que también podría probar primero el tipo del objeto antes de asignarlo a una variable, ya que lo declaró explícitamente comoRange
.Tenga en cuenta que a continuación comparo el enfoque Seleccionar (el que el OP quiere evitar), con el enfoque Rango (y esta es la respuesta a la pregunta). Así que no dejes de leer cuando veas el primer Select.
Realmente depende de lo que intentes hacer. De todos modos, un simple ejemplo podría ser útil. Supongamos que desea establecer el valor de la celda activa en "foo". Usando ActiveCell escribirías algo como esto:
Si desea usarlo para una celda que no es la activa, por ejemplo, para "B2", debe seleccionarla primero, así:
Usando Rangos puede escribir una macro más genérica que se puede usar para establecer el valor de cualquier celda que desee a lo que quiera:
Entonces puedes reescribir Macro2 como:
Y Macro1 como:
Espero que esto ayude a aclarar un poco las cosas.
fuente
Evitar
Select
yActivate
es el movimiento que te hace un mejor desarrollador de VBA. En general,Select
yActivate
se usan cuando se graba una macro, por lo tanto, laParent
hoja de trabajo o el rango siempre se consideran activos.Así es como puede evitar
Select
yActivate
en los siguientes casos:Agregar una nueva hoja de trabajo y copiar una celda en ella:
De (código generado con la grabadora de macros):
A:
Cuando desee copiar el rango entre hojas de trabajo:
Desde:
A:
Usando elegantes rangos con nombre
Puede acceder a ellos con
[]
, lo cual es realmente hermoso, en comparación con la otra manera. Comprueba tu mismo:El ejemplo de arriba se vería así:
No copiando valores, sino tomándolos
Por lo general, si está dispuesto a hacerlo
select
, lo más probable es que esté copiando algo. Si solo está interesado en los valores, esta es una buena opción para evitar seleccionar:Range("B1:B6").Value = Range("A1:A6").Value
Intente siempre hacer referencia a la Hoja de trabajo también
Este es probablemente el error más común en vba. Siempre que copie rangos, a veces la hoja de trabajo no está referenciada y, por lo tanto, VBA considera que la hoja incorrecta es ActiveWorksheet.
¿Realmente nunca puedo usar
.Select
o.Activate
para nada?.Activate
y.Select
cuándo quiere asegurarse de que se seleccione una Hoja de trabajo específica por razones visuales. Por ejemplo, que su Excel siempre se abriría con la hoja de cálculo de portada seleccionada primero, sin tener en cuenta cuál era la ActiveSheet cuando se cerró el archivo.Por lo tanto, algo como el siguiente código está absolutamente bien:
Otro buen ejemplo es cuando necesita exportar todas las hojas a un archivo PDF, como se menciona en este caso: ¿Cómo evitar las declaraciones select / active en VBA en este ejemplo?
Cuando un comando sólo funciona con
ActiveWindow
igual ActiveWindow.Zoom o ActiveWindow.FreezePanesfuente
.Select
, así como mi trabajo, se puede encontrar en Cómo escribir información idéntica en todas las hojas - @Vityata :).FillAcrossSheets
, por lo que esto está en algún punto intermedio (al menos en mi idea sobre la taxonomía VBA)Indique siempre el libro de trabajo, la hoja de trabajo y la celda / rango.
Por ejemplo:
Debido a que los usuarios finales siempre harán clic en los botones y tan pronto como el foco se salga del libro de trabajo, el código quiere trabajar, entonces las cosas van completamente mal.
Y nunca use el índice de un libro de trabajo.
No sabe qué otros libros de trabajo estarán abiertos cuando el usuario ejecute su código.
fuente
Estos métodos son bastante estigmatizados, por lo que tomar el liderazgo de @Vityata y @Jeeped por el simple hecho de dibujar una línea en la arena:
¿Por qué no llamar
.Activate
,.Select
,Selection
,ActiveSomething
métodos / propiedadesBásicamente porque están llamados principalmente para manejar la entrada del usuario a través de la interfaz de usuario de la aplicación. Dado que son los métodos que se llaman cuando el usuario maneja objetos a través de la interfaz de usuario, son los que registra la macrograbadora, y por eso llamarlos es frágil o redundante para la mayoría de las situaciones: no tiene que seleccionar un objeto para realizar una acción
Selection
inmediatamente después.Sin embargo, esta definición resuelve situaciones en las que se requieren:
Cuando llamar
.Activate
,.Select
,.Selection
,.ActiveSomething
métodos / propiedadesBásicamente cuando espera que el usuario final desempeñe un papel en la ejecución.
Si está desarrollando y espera que el usuario elija las instancias de objeto para que su código las maneje, entonces
.Selection
o.ActiveObject
es apropiado.Por otro lado,
.Select
y.Activate
son útiles cuando puede inferir la siguiente acción del usuario y desea que su código guíe al usuario, posiblemente ahorrándole algo de tiempo y clics del mouse. Por ejemplo, si su código acaba de crear una nueva instancia de un gráfico o una actualizada, el usuario puede desear echarle un vistazo, y puede recurrir.Activate
a él o a su hoja para ahorrarle al usuario el tiempo que lo busca; o si sabe que el usuario necesitará actualizar algunos valores de rango, puede seleccionar ese rango mediante programación.fuente
En mi humilde opinión, el uso
.select
proviene de personas que, como yo, comenzaron a aprender VBA por necesidad a través de la grabación de macros y luego la modificación del código sin darse cuenta de eso,.select
y posteriormenteselection
es solo un intermediario innecesario..select
puede evitarse, como muchos ya se publicaron, trabajando directamente con los objetos ya existentes, lo que permite varias referencias indirectas como calcular i y j de una manera compleja y luego editar la celda (i, j), etc.De lo contrario, no hay nada implícitamente incorrecto en
.select
sí mismo y puede encontrar usos para esto fácilmente, por ejemplo, tengo una hoja de cálculo que relleno con la fecha, active la macro que hace algo de magia con ella y la exporta en un formato aceptable en una hoja separada, que , sin embargo, requiere algunas entradas manuales finales (impredecibles) en una celda adyacente. Así que aquí llega el momento en.select
que eso me ahorra ese movimiento y clic adicionales del mouse.fuente
Respuesta rápida:
Para evitar el uso del
.Select
método, puede establecer una variable igual a la propiedad que desee.► Por ejemplo, si desea el valor
Cell A1
, puede establecer una variable igual a la propiedad de valor de esa celda.valOne = Range("A1").Value
► Por ejemplo, si desea el nombre en clave de 'Sheet3', puede establecer una variable igual a la propiedad de nombre en clave de esa hoja de trabajo.
valTwo = Sheets("Sheet3").Codename
Espero que eso ayude. Hazme saber si tienes alguna pregunta.
fuente
Noté que ninguna de estas respuestas menciona la propiedad .Offset . Esto también se puede usar para evitar el uso de la
Select
acción al manipular ciertas celdas, particularmente en referencia a una celda seleccionada (como menciona el OPActiveCell
).Aqui hay un par de ejemplos.
También asumiré que el "ActiveCell" es J4 .
ActiveCell.Offset(2, 0).Value = 12
J6
a un valor de 12ActiveCell.Offset(0,1).Copy ActiveCell.Offset(,2)
k4
queL4
.i4
ActiveCell.Offset(, -1).EntireColumn.ClearContents
Esto no quiere decir que sean "mejores" que las opciones anteriores, sino simplemente enumerar alternativas.
fuente
Trabajando con .Parent característica. Este ejemplo muestra cómo configurar solo una referencia myRng permite el acceso dinámico a todo el entorno sin .Select, .Activate, .Activecell, .ActiveWorkbook, .ActiveSheet, etc. (No hay genereic. Característica infantil)
fuente
La razón principal por la que nunca debe usar Select o Activesheet es porque la mayoría de las personas tendrán al menos otro par de libros abiertos (a veces docenas) cuando ejecuten su macro, y si hacen clic fuera de su hoja mientras su macro se está ejecutando y hacen clic en otro libro que tienen abierto, luego cambia la "Hoja activa", y también cambia el libro de trabajo de destino para un comando "Seleccionar" no calificado.
En el mejor de los casos, su macro se bloqueará, en el peor de los casos, podría terminar escribiendo valores o cambiando celdas en el libro de trabajo incorrecto sin forma de "Deshacerlos".
Tengo una regla de oro simple que sigo: Agregar variables llamadas "wb" y "ws" para un objeto de libro de trabajo y un objeto de hoja de trabajo y siempre usarlas para referirme a mi macro libro. Si necesito referirme a más de un libro, o más de una hoja, agrego más variables.
por ejemplo
El comando "Establecer wb = ThisWorkbook" es absolutamente clave. "ThisWorkbook" es un valor especial en Excel, y significa el libro desde el cual se está ejecutando actualmente su código VBA . Un atajo muy útil para configurar la variable de su libro de trabajo.
Una vez que hayas hecho eso en la parte superior de tu Sub, usarlos no podría ser más simple, solo úsalos donde sea que uses "Selección":
Entonces, para cambiar el valor de la celda "A1" en "Salida" a "Hola", en lugar de:
Ahora podemos hacer esto:
Lo que no solo es mucho más confiable y es menos probable que se bloquee si el usuario está trabajando con varias hojas de cálculo, sino que también es mucho más corto, más rápido y más fácil de escribir.
Como beneficio adicional, si siempre nombra sus variables "wb" y "ws", puede copiar y pegar el código de un libro a otro y, por lo general, funcionará con los cambios mínimos necesarios, si corresponde.
fuente
ThisWorkbook
... No estoy seguro de que su comentario sea exacto.Este es un ejemplo que borrará el contenido de la celda "A1" (o más si el tipo de selección es xllastcell, etc.). Todo hecho sin tener que seleccionar las celdas.
Espero que esto ayude a alguien.
fuente
Workbook(WorkbookName).Worksheets(WorksheetName).Range("A1").ClearContents
una línea y no dos, y en realidad funciona sin seleccionar celdas.