Offset y Rangos, acceder a celdas desde Macros

Excel permite grabar acciones repetitivas y luego reproducirlas. El problema viene cuando la acción es repetitiva pero no exactamente la misma.

Por ejemplo, en el caso del ejercicio en el que había que trabajar con las tablas de pasajeros, para convertir la tabla de doble entrada en una tabla simple (poniendo la hora en una columna nueva o incluyendola en la fecha), hay que copiar todas las columnas una tras otra. Si copiamos y pegamos transpuesta la primera fila  y lo grabamos con excel, las referencias a las celdas aparecen de forma estática:

[code language=»vb»]
Range(«B2:Y2»).Select
Selection.Copy Sheets(«Hoja3»).Select
Range(«A1″).Select
Selection.PasteSpecial Paste:=xlAll, Operation:=xlNone, SkipBlanks:=False, Transpose:=True
[/code]

Para evitar tener que grabar el procedimiento se puede usar Offset(nFilas,nColumnas) que desplaza la selección nFilas hacia la derecha y nColumnas hacia abajo.

El siguiente código:
[code language=»vb»]
Range(«B2:Y2»).Select.Offset(0,1)
[/code]

Seleccionaría la siguiente columna

Guardar la selección en una variable tipo «Range» e ir desplazandola, hasta recorrer todas las columnas, sin embargo, resulta mucho más rápido seleccionar todos los datos que queremos copiar de una, y mediante un bucle, dejar que el excel haga el trabajo por nosotros.

[code language=»vb»]
‘En primer lugar definimos las variables que vamos a usar
Dim rangoDeDatos As Range
Dim escribirEn As Range
Dim celda As Range

‘A continuacion les asignamos valores
‘rangoDeDatos son las celdas con el numero de pasajeros por hora de todos los dias del año
‘escribirEn es donde vamos a empezar a pegarlas
Set rangoDeDatos = Worksheets(«Hoja1»).Range(«B2:Y366»)
Set escribirEn = Worksheets(«Hoja3»).Range(«A2:C2»)
‘Ahora para cada celda cojemos su fecha y su hora y las insertamos en columnas contiguas
For Each celda In rangoDeDatos

escribirEn(1).Value = Worksheets(«Hoja1»).Cells(celda.Row, 1)
escribirEn(2).Value = TimeSerial(Worksheets(«Hoja1»).Cells(1, celda.Column), 0, 0)
escribirEn(3).Value = celda.Value
‘Por ultimo transladamos el lugar donde escribiremos la proxima vez una fila más abajo
Set escribirEn = escribirEn.Offset(1, 0)

Next
[/code]

Si se quisisese, se podrían poner la fecha y la hora en una misma columna:

[code language=»vb»]
escribirEn(1).Value = CDate(Worksheets(«Hoja1»).Cells(celda.Row, 1).Value) + TimeSerial(Worksheets(«Hoja1»).Cells(1, celda.Column).Value, 0, 0)
[/code]