¿Usas Excel 2016, 2019 o cualquier versión sin acceso a VSTACK y HSTACK? En este artículo te compartimos dos funciones VBA personalizadas — ApilarV y ApilarH — que replican exactamente ese comportamiento en cualquier versión de Excel con macros habilitadas. El código está optimizado para rendimiento, comentado para que entiendas cada línea y listo para copiar.
¿Qué son VSTACK y HSTACK y por qué no están en tu Excel?
Microsoft introdujo VSTACK (APILARV) y HSTACK (APILARH) en Excel 365 como parte de las nuevas funciones de matrices dinámicas. Su función es simple: combinar varios rangos apilándolos verticalmente o en horizontal, devolviendo una sola matriz de resultado.
El problema es que estas funciones no existen en Excel 2010, 2013, 2016, 2019 ni 2021. Si trabajas con alguna de esas versiones — muy comunes todavía en entornos empresariales e instituciones de ingeniería — tendrás que recrearlas con VBA.
Ahí es donde entran ApilarV y ApilarH.
¿Qué hacen estas funciones VBA?
- ApilarV(rng1, rng2, …) — apila rangos o matrices uno debajo del otro (equivalente a VSTACK). Todos los argumentos deben tener el mismo número de columnas.
- ApilarH(rng1, rng2, …) — apila rangos o matrices uno al lado del otro (equivalente a HSTACK). Todos los argumentos deben tener el mismo número de filas.
Ambas funciones aceptan rangos de celda y también matrices devueltas por otras fórmulas, por lo que se pueden anidar sin problema.
Requisitos
- Excel 2010 o superior en Windows
- Macros habilitadas
- Guardar el archivo en formato .xlsm (libro habilitado para macros)
- No requiere Internet ni complementos externos
Instalación paso a paso
- Abre tu archivo Excel y presiona Alt + F11 para abrir el Editor de Visual Basic.
- En el panel izquierdo, haz clic derecho sobre tu libro → Insertar → Módulo.
- Copia y pega el código completo que aparece más abajo en el módulo vacío.
- Cierra el editor y vuelve a Excel.
- Guarda el archivo como .xlsm (libro habilitado para macros).
Código VBA — ApilarV y ApilarH optimizadas
Copia el siguiente código completo y pégalo en el módulo VBA:
Option Explicit '=============================================================== ' APILARV – Apila rangos/matrices verticalmente (como VSTACK) ' ' USO: =ApilarV(rng1, rng2, ...) ' - Acepta rangos de hoja o matrices devueltas por otras fórmulas ' - Todos los argumentos deben tener el MISMO número de columnas ' - Ejemplo: =ApilarV(A1:C5, A10:C20, MiOtraFuncion(...)) '=============================================================== Function ApilarV(ParamArray rngs() As Variant) As Variant Dim totalFilas As Long, nCols As Long Dim arr() As Variant Dim tmp As Variant Dim i As Long, j As Long, k As Long, fila As Long ' --- Determinar número de columnas desde el primer argumento --- If TypeName(rngs(0)) = "Range" Then nCols = rngs(0).Columns.Count Else tmp = rngs(0) nCols = UBound(tmp, 2) End If ' --- Contar filas totales --- For i = LBound(rngs) To UBound(rngs) If TypeName(rngs(i)) = "Range" Then totalFilas = totalFilas + rngs(i).Rows.Count Else tmp = rngs(i) totalFilas = totalFilas + UBound(tmp, 1) End If Next i ReDim arr(1 To totalFilas, 1 To nCols) ' --- Volcar datos en el array de salida --- fila = 1 For i = LBound(rngs) To UBound(rngs) If TypeName(rngs(i)) = "Range" Then ' Leer bloque de rango en una sola operación (mucho más rápido que celda a celda) tmp = rngs(i).Value For j = 1 To UBound(tmp, 1) For k = 1 To nCols arr(fila, k) = tmp(j, k) Next k fila = fila + 1 Next j Else tmp = rngs(i) For j = 1 To UBound(tmp, 1) For k = 1 To nCols arr(fila, k) = tmp(j, k) Next k fila = fila + 1 Next j End If Next i ApilarV = arr End Function '=============================================================== ' APILARH – Apila rangos/matrices horizontalmente (como HSTACK) ' ' USO: =ApilarH(rng1, rng2, ...) ' - Acepta rangos de hoja o matrices devueltas por otras fórmulas ' - Todos los argumentos deben tener el MISMO número de filas ' - Ejemplo: =ApilarH(A1:A10, C1:D10, MiOtraFuncion(...)) '=============================================================== Function ApilarH(ParamArray rngs() As Variant) As Variant Dim nFilas As Long, totalCols As Long Dim arr() As Variant Dim tmp As Variant Dim i As Long, j As Long, k As Long, col As Long ' --- Determinar número de filas desde el primer argumento --- If TypeName(rngs(0)) = "Range" Then nFilas = rngs(0).Rows.Count Else tmp = rngs(0) nFilas = UBound(tmp, 1) End If ' --- Contar columnas totales --- For i = LBound(rngs) To UBound(rngs) If TypeName(rngs(i)) = "Range" Then totalCols = totalCols + rngs(i).Columns.Count Else tmp = rngs(i) totalCols = totalCols + UBound(tmp, 2) End If Next i ReDim arr(1 To nFilas, 1 To totalCols) ' --- Volcar datos en el array de salida --- col = 1 For i = LBound(rngs) To UBound(rngs) Dim nC As Long If TypeName(rngs(i)) = "Range" Then ' Leer bloque de rango en una sola operación (mucho más rápido que celda a celda) nC = rngs(i).Columns.Count tmp = rngs(i).Value Else tmp = rngs(i) nC = UBound(tmp, 2) End If For j = 1 To nFilas For k = 1 To nC arr(j, col + k - 1) = tmp(j, k) Next k Next j col = col + nC Next i ApilarH = arr End Function
¿Cómo se usan? — Ejemplos prácticos
ApilarV — apilar tablas verticalmente
Imagina que tienes el registro de obras de enero en A2:D20 y el de febrero en F2:I15. Para combinarlos en una sola lista:
=ApilarV(A2:D20, F2:I15)
El resultado se derrama hacia abajo automáticamente, igual que haría VSTACK en Excel 365.
ApilarH — combinar columnas de distintas tablas
Si tienes nombres de personal en A1:A30 y sus métricas en C1:E30, y quieres unirlos en una sola matriz para graficar o reportar:
=ApilarH(A1:A30, C1:E30)
Anidado con otras funciones
También puedes pasar como argumento el resultado de otras UDF o funciones matriciales:
=ApilarV(A1:C10, ApilarH(E1:E10, G1:H10))
Compatibilidad
| Versión de Excel | ApilarV / ApilarH | VSTACK / HSTACK nativa |
|---|---|---|
| Excel 2010 | ✅ Compatible | ❌ No disponible |
| Excel 2013 | ✅ Compatible | ❌ No disponible |
| Excel 2016 | ✅ Compatible | ❌ No disponible |
| Excel 2019 | ✅ Compatible | ❌ No disponible |
| Excel 2021 | ✅ Compatible | ❌ No disponible |
| Microsoft 365 | ✅ Compatible | ✅ Disponible de forma nativa |
| Excel para Mac | ✅ Compatible | Depende de versión |
| Excel Online | ❌ Sin soporte VBA | ✅ Disponible de forma nativa |
Notas importantes
- Mismo número de columnas (ApilarV) — todos los rangos que pases como argumento deben tener exactamente el mismo ancho. Si no, la función leerá solo las columnas del primero.
- Mismo número de filas (ApilarH) — todos los rangos deben tener la misma altura.
- Guardar como .xlsm — si guardas el archivo como .xlsx perderás las macros y las funciones devolverán
#NAME?. - Macros habilitadas — ve a Archivo → Opciones → Centro de confianza → Configuración de macros y habilita las macros.
- Rendimiento optimizado — el código usa
rango.Valuepara leer el bloque completo de una sola vez en memoria, evitando el acceso celda a celda que es notoriamente lento en VBA.
¿Por qué este código es más rápido que otras versiones?
La diferencia clave frente a implementaciones similares es la lectura del rango. Acceder a Cells(i, j).Value dentro de un bucle implica un cruce constante entre VBA y el motor de Excel (llamada COM), que se vuelve lento con rangos grandes. Esta versión ejecuta una sola operación para volcar todo el rango a una variable Variant en memoria, y luego trabaja puramente en RAM. En tablas de miles de filas, la diferencia es notable.
Si te interesa profundizar en otras herramientas VBA para Excel, puedes revisar también nuestra función para generar códigos QR directamente en Excel o explorar el índice completo de planillas Excel disponibles en Civil Excel.
Esperamos que estas funciones sean de utilidad en tus proyectos. Son herramientas gratuitas, sin dependencias externas y compatibles con el entorno de Excel que ya usas cada día. Saludos a toda la comunidad de Civil Excel.
0 Post a Comment:
Publicar un comentario