Diferencia en el tipo entre usar y no usar Establecer palabra clave

Acabo de resolver un problema que estaba teniendo poner la palabra clave “Establecer” en una línea de definición, pero lo que me gustaría saber es “¿por qué?”

Básicamente, estoy haciendo esto:

Dim startCell, iCell as Range For Each iCell in Range(whatever) If iCell.value "" Then Set startCell = Cells(iCell.Row + 1, iCell.Column) End If Next iCell 

Si omito la palabra clave “Establecer”, el código aún se comstack bien, pero en la ventana de variables locales veo que su tipo cambia a “Cadena” en lugar de “Variante / Objeto / Rango”. ¿Por qué sucedería eso?

Esta es la razón por. Cuando dices esto:

 Dim startCell, iCell As Range 

crees que has hecho esto

 Dim startCell As Range, iCell As Range 

pero lo que realmente has hecho es esto:

 Dim startCell 'As Variant, by default Dim iCell As Range 

Este es un error clásico de VBA. La mayoría de los progtwigdores de VBA lo han logrado, y es por eso que la mayoría de los progtwigdores de VBA recurren a declarar solo una variable por statement Dim (es decir, una por línea). De lo contrario, es demasiado fácil cometer ese error y es difícil detectarlo después.

Entonces con Dim startCell has declarado implícitamente tu variable como tipo Variant (equivalente a Dim startCell As Variant ).

Cuando dices esto:

 Set startCell = Cells(iCell.Row + 1, iCell.Column) 

la Variante adquiere el tipo de cosa en el lado derecho de la asignación de referencia (Rango). Sin embargo, cuando dices esto:

 startCell = Cells(iCell.Row + 1, iCell.Column) 

sin la palabra clave Set , no está asignando una referencia, sino un valor a la variable startCell , que ahora adquiere el tipo del valor en el lado derecho. ¿Qué es ese tipo? Bueno, la propiedad predeterminada de un objeto Range es Value , por lo que obtendrá el tipo de Cells(iCell.Row + 1, iCell.Column).Value . Si esa celda contiene una cadena, obtendrás una cadena.

Set se usa para asignar una referencia a un objeto, Let (o simple assignment) para asignar el valor de un objeto (si lo hay)

  Dim a As Variant Set a = ActiveSheet.Cells(1) 'TypeName(a) = Range, a now contains reference to the cell's range a = ActiveSheet.Cells(1) 'TypeName(a) = Double or String, whatever is in the Cell, a contains the cell's value 

Debe usar la palabra clave Set al asignar un objeto a una variable. Cells(iCell.Row + 1, iCell.Column) devuelven un objeto Range , por lo que se debe usar Set ; de lo contrario, obtendrás el error de VBA favorito de todos: 91: Object variable or With block variable not set .

Editar:

Los objetos de rango también tienen una propiedad de retorno predeterminada, que es la propiedad ‘Valor’. Si tuviera que hacer referencia al rango (“A1”), tomaría los rangos ‘Valor’ como valor predeterminado para una variante. Es por eso que debe evitar el uso de variantes cuando el tipo de datos se conoce con anticipación.