Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Página 1
VBA
#vba
https://translate.googleusercontent.com/translate_f 1/223
6/1/2021 Intitulado
Página 2
Tabla de contenido
Acerca de 1
Observaciones 2
Versiones 2
Ejemplos 2
Depuración 5
Ventana de relojes 5
Ventana inmediata 5
Introducción 7
Observaciones 7
Ejemplos 8
API de Mac 19
Capítulo 3: Matrices 25
Ejemplos 25
Acceso a elementos 25
Indexación de matrices 25
Índice específico 25
Declaración dinámica 25
Página 3
Matrices dinámicas 29
https://translate.googleusercontent.com/translate_f 2/223
6/1/2021 Intitulado
Agregar valores dinámicamente 29
Matrices multidimensionales 33
Matrices multidimensionales 33
Observaciones 40
Ejemplos 40
Utilice la función Cadena para asignar una cadena con n caracteres repetidos 40
Utilice las funciones String y Space para asignar una cadena de n caracteres 40
Capítulo 5: Atributos 41
Sintaxis 41
Ejemplos 41
VB_Name 41
VB_GlobalNameSpace 41
VB_Createable 41
VB_PredeclaredId 42
Declaración 42
Llamada 42
VB_Exposed 42
VB_Description 43
Página 4
Hacer una clase iterable con una construcción de bucle For Each 44
Introducción 46
Sintaxis 46
Observaciones 46
Ejemplos 46
Código 47
https://translate.googleusercontent.com/translate_f 3/223
6/1/2021 Intitulado
Objeto de sistema de archivos de secuencias de comandos 48
Objeto Diccionario de secuencias de comandos 48
Raspado web 49
Hacer clic 51
IE Principales problemas 52
Capítulo 7: Colecciones 53
Observaciones 53
Ejemplos 53
Llaves 58
Artículos 58
Capítulo 8: Comentarios 61
Página 5
Observaciones 61
Ejemplos 61
Comentarios REM 62
Observaciones 63
Ejemplos 63
Ejemplos 64
Uso de Declare Importaciones que funcionan en todas las versiones de Office sesenta y cinco
Observaciones 67
Ejemplos 67
https://translate.googleusercontent.com/translate_f 4/223
6/1/2021 Intitulado
Utilice CStr para convertir un tipo numérico en una cadena 67
Utilice Formato para convertir y formatear un tipo numérico como una cadena 67
Utilice StrConv para convertir una matriz de bytes de caracteres de un solo byte en una cadena 67
Convierta implícitamente una matriz de bytes de caracteres de varios bytes en una cadena 67
Ejemplos 69
Copiar matrices 69
Página 6
Observaciones 74
Ejemplos 74
Observaciones 76
Ejemplos 76
Ejemplos 80
Devolviendo un valor 80
Introducción 82
Ejemplos 82
Lista enlazada 82
Árbol binario 83
Ejemplos 85
Byte 85
https://translate.googleusercontent.com/translate_f 5/223
6/1/2021 Intitulado
Entero 86
Booleano 86
Largo 87
Soltero 87
Doble 87
Moneda 88
Fecha 88
Cuerda 88
Longitud variable 89
Longitud fija 89
Página 7
Largo largo 89
Variante 90
LongPtr 91
Decimal 91
Ejemplos 93
Calendario 93
Ejemplo 93
Funciones base 94
Función de temporizador 94
IsDate () 95
Funciones de extracción 95
Función DatePart () 96
Funciones de cálculo 97
DateDiff () 98
DateAdd () 98
Conversión y creación 99
CDate () 99
DateSerial () 100
Observaciones 102
Ejemplos 102
Asignar caracteres específicos dentro de una cadena usando la declaración Mid 103
https://translate.googleusercontent.com/translate_f 6/223
6/1/2021 Intitulado
Asignación hacia y desde una matriz de bytes 103
Ejemplos 104
Página 8
Variables 104
Alcance 104
Campos 106
Ejemplos 115
Sintaxis 122
Observaciones 122
Ejemplos 122
Manipuladores 122
https://translate.googleusercontent.com/translate_f 7/223
6/1/2021 Intitulado
Página 9
Fuentes 124
Ejemplos 127
Sintaxis 129
En bucle 130
Introducción 132
Ejemplos 132
Introducción 134
Ejemplos 134
Ejemplos 138
Observaciones 151
Ejemplos 151
Use la función Len para determinar el número de caracteres en una cadena 151
Utilice la función LenB para determinar el número de bytes en una cadena 151
Prefiera `If Len (myString) = 0 Then` sobre` If myString = "" Then` 151
Página 10
Ejemplos 152
https://translate.googleusercontent.com/translate_f 8/223
6/1/2021 Intitulado
Capítulo 29: Caracteres no latinos 157
Introducción 157
Ejemplos 157
Ejemplos 160
Abstracción 160
Los niveles de abstracción ayudan a determinar cuándo dividir las cosas. 160
Encapsulamiento 160
La encapsulación oculta los detalles de implementación del código del cliente. 160
Polimorfismo 164
El polimorfismo es la capacidad de presentar la misma interfaz para diferentes impleme subyacentes 164
Observaciones 167
Ejemplos 167
Notas 169
Introducción 175
Observaciones 175
Página 11
Ejemplos 175
ByRef 176
ByVal 178
Sintaxis 180
https://translate.googleusercontent.com/translate_f 9/223
6/1/2021 Intitulado
Parámetros 180
Observaciones 180
Ejemplos 180
Capítulo 34: Lectura de archivos de 2GB + en binario en VBA y File Hashes 184
Introducción 184
Observaciones 184
Ejemplos 185
Esto tiene que estar en un módulo de clase, los ejemplos más adelante se denominarán "aleatorios" 185
Calcular todos los archivos hash desde una carpeta raíz 191
Pagina 12
Código 191
Introducción 195
Observaciones 195
Ejemplos 195
Factoriales 195
Observaciones 197
Ejemplos 197
Ejemplos 203
https://translate.googleusercontent.com/translate_f 10/223
6/1/2021 Intitulado
Usando FSO.BuildPath para construir una ruta completa a partir de la ruta de la carpeta y el nombre del archivo 207
Observaciones 208
Ejemplos 208
Use InStr para determinar si una cadena contiene una subcadena 208
Use InStr para encontrar la posición de la primera instancia de una subcadena 208
Utilice InStrRev para encontrar la posición de la última instancia de una subcadena 208
Página 13
Introducción 209
Ejemplos 209
Capítulo 40: Literales de cadena: caracteres de escape, no imprimibles y continuaciones de línea 212
Observaciones 212
Ejemplos 212
Observaciones 215
Ejemplos 215
Use Left o Left $ para obtener los 3 caracteres más a la izquierda en una cadena 215
Use Right o Right $ para obtener los 3 caracteres más a la derecha en una cadena 215
Use Mid o Mid $ para obtener caracteres específicos dentro de una cadena 215
Utilice Recortar para obtener una copia de la cadena sin espacios iniciales o finales 215
Ejemplos 217
https://translate.googleusercontent.com/translate_f 11/223
6/1/2021 Intitulado
Sintaxis 222
Parámetros 222
Página 14
Observaciones 222
Ejemplos 223
Introducción 228
Ejemplos 228
https://translate.googleusercontent.com/translate_f 12/223
6/1/2021 Intitulado
código incorrecto 229
¿Por qué no funciona esto? 230
Página 15
Error en tiempo de ejecución '91': variable de objeto o con variable de bloque no establecida 231
Observaciones 234
Ejemplos 234
Capítulo 46: Trabajar con archivos y directorios sin usar FileSystemObject 239
Observaciones 239
Ejemplos 239
Créditos 242
https://translate.googleusercontent.com/translate_f 13/223
6/1/2021 Intitulado
Página 16
Acerca de
Puede compartir este PDF con cualquier persona que crea que podría beneficiarse de él, descargue la última versión
desde: vba
Es un libro electrónico de VBA no oficial y gratuito creado con fines educativos. Se extrae todo el contenido
desde Stack Overflow Documentation , que está escrita por muchas personas trabajadoras en Stack
Desbordamiento. No está afiliado a Stack Overflow ni a VBA oficial.
Utilice el contenido presentado en este libro bajo su propio riesgo; no se garantiza que sea correcto ni
precisa, envíe sus comentarios y correcciones a info@zzzprojects.com
https://riptutorial.com/ 1
Página 17
Esta sección proporciona una descripción general de qué es vba y por qué un desarrollador podría querer usarlo.
También debe mencionar cualquier tema importante dentro de vba y vincular a los temas relacionados. Desde el
La documentación para vba es nueva, es posible que deba crear versiones iniciales de esos temas relacionados.
Versiones
Ejemplos
Puede abrir el editor VB en cualquiera de las aplicaciones de Microsoft Office presionando Alt + F11 o yendo
a la pestaña Desarrollador y haciendo clic en el botón "Visual Basic". Si no ve la pestaña Desarrollador
en la cinta, compruebe si está habilitado.
De forma predeterminada, la pestaña Desarrollador está desactivada. Para habilitar la pestaña Desarrollador, vaya a Archivo -> Opciones, seleccione
Personalice la cinta en la lista de la izquierda. En la vista de árbol "Personalizar la cinta" de la derecha, busque
Elemento del árbol del desarrollador y marque la casilla de verificación de Desarrollador. Haga clic en Aceptar para cerrar
el cuadro de diálogo Opciones.
https://riptutorial.com/ 2
Página 18
https://translate.googleusercontent.com/translate_f 15/223
6/1/2021 Intitulado
La pestaña Desarrollador ahora está visible en la cinta en la que puede hacer clic en "Visual Basic" para abrir
el Editor de Visual Basic. Alternativamente, puede hacer clic en "Ver código" para ver directamente el panel de código
del elemento activo actualmente, por ejemplo, hoja de trabajo, gráfico, forma.
https://riptutorial.com/ 3
Página 19
https://translate.googleusercontent.com/translate_f 16/223
6/1/2021 Intitulado
https://riptutorial.com/ 4
Página 20
Depuración
La depuración es una forma muy poderosa de observar más de cerca y corregir el funcionamiento incorrecto (o no
código de trabajo).
• Breakpoint ( F9 , Debug - Toggle breakpoint): puede agregar un punto de interrupción a cualquier línea ejecutada
(por ejemplo, no a declaraciones), cuando la ejecución llega a ese punto, se detiene y da control a
usuario.
• También puede agregar la palabra clave Stop a una línea en blanco para que el código se detenga en esa ubicación en
tiempo de ejecución. Esto es útil si, por ejemplo, antes de las líneas de declaración a las que no puede agregar una
punto de interrupción con F9
• Step into ( F8 , Debug - Step into): ejecuta solo una línea de código, si es una llamada de un usuario
sub / función definida, entonces se ejecuta línea por línea.
• Pasar por encima ( Shift + F8 , Depurar - Pasar por encima): ejecuta una línea de código, no ingresa al usuario
subs / funciones definidas.
• Salir ( Ctrl + Shift + F8 , Depurar - Salir): Salir de la subfunción / función actual (ejecutar el código hasta
fin).
• Ejecutar al cursor ( Ctrl + F8 , Depurar - Ejecutar al cursor): ejecuta el código hasta llegar a la línea con el
cursor.
• Puede utilizar Debug.Print para imprimir líneas en la ventana Inmediato en tiempo de ejecución. También puede
utilizar Debug.? como un atajo para Debug.Print
https://translate.googleusercontent.com/translate_f 17/223
6/1/2021 Intitulado
Ventana de relojes
Ejecutar código línea por línea es solo el primer paso, necesitamos conocer más detalles y una herramienta para eso
es la ventana de observación (Ver - Ventana de observación), aquí puede ver los valores de las expresiones definidas. A
agregue una variable a la ventana de inspección, ya sea:
Cuando agrega una nueva expresión, puede elegir si solo desea ver su valor o también
romper la ejecución del código cuando es verdadero o cuando cambia su valor.
Ventana inmediata
https://riptutorial.com/ 5
Página 21
Algunos ejemplos:
• ? ActiveSheet.Name :
devuelve el nombre de la hoja activa
• Print ActiveSheet.Name :
devuelve el nombre de la hoja activa
• ? foo - devuelve el valor de foo *
• x = 10 conjuntos x a 10 *
* Obtener / configurar valores para variables a través de la ventana inmediata solo se puede realizar durante el tiempo de ejecución
Si eso no ayuda, comience a depurarlo; para procedimientos cortos, puede ser eficiente simplemente ejecutarlo
línea por línea, para los más largos probablemente necesite establecer puntos de interrupción o interrupciones en la visualización
expresiones, el objetivo aquí es encontrar la línea que no funciona como se esperaba.
Una vez que tenga la línea que da el resultado incorrecto, pero la razón aún no está clara, intente
simplificar expresiones, o reemplazar variables con constantes, que pueden ayudar a comprender si
el valor de las variables es incorrecto.
https://translate.googleusercontent.com/translate_f 18/223
6/1/2021 Intitulado
https://riptutorial.com/ 6
Página 22
Las API para VBA implican un conjunto de métodos que permiten la interacción directa con el sistema operativo
Las llamadas al sistema se pueden realizar ejecutando procedimientos definidos en archivos DLL
Observaciones
Archivos de biblioteca de entornos operativos comunes (DLL):
Enlace dinámico
Descripción
Biblioteca
Biblioteca de servicios avanzados para API que incluyen muchas funciones de seguridad y
Advapi32.dll
Llamadas de registro
Winspool.drv Interfaz de cola de impresión que contiene las llamadas a la API de cola de impresión
https://translate.googleusercontent.com/translate_f 19/223
6/1/2021 Intitulado
https://riptutorial.com/ 7
Página 23
Este es un tipo de datos de 8 bytes que solo está disponible en versiones de 64 bits
Tipo de datos Largo largo de Office 2010. Puede asignar valores numéricos pero no numéricos
tipos (para evitar el truncamiento)
Operador de conversión CLngPtr Convierte una expresión simple en un tipo de datos LongPtr
Operador de conversión CLngLng Convierte una expresión simple en un tipo de datos LongLong
• Win32api32.txt para Visual Basic 5.0 (declaraciones de API antiguas, última revisión en marzo de 2005, Microsoft)
Ejemplos
Opción explícita
Privado Declare PtrSafe Sub xLib "Kernel32" Alias "Sleep" (ByVal dwMilliseconds As Long)
Private Declare Sub apiSleep Lib "Kernel32" Alias "Sleep" (ByVal dwMilliseconds As Long)
https://riptutorial.com/ 8
Página 24
#Terminara si
La declaración anterior le dice a VBA cómo llamar a la función "Sleep" definida en el archivo Kernel32.dll
https://translate.googleusercontent.com/translate_f 20/223
6/1/2021 Intitulado
Win64 y Win32 son constantes predefinidas que se utilizan para compilación condicional
Constantes predefinidas
Algunas constantes de compilación ya están predefinidas. Cuales existen dependerán del bitness
de la versión de Office en la que está ejecutando VBA. Tenga en cuenta que Vba7 se introdujo junto con Office 2010
para admitir versiones de 64 bits de Office.
Estas constantes se refieren a la versión de Office, no a la versión de Windows. Por ejemplo Win32 = TRUE
en Office de 32 bits, incluso si el sistema operativo es una versión de Windows de 64 bits.
La principal diferencia al declarar API es entre las versiones de Office de 32 bits y 64 bits que
introdujo nuevos tipos de parámetros (consulte la sección Comentarios para obtener más detalles)
Notas:
• Las declaraciones se colocan en la parte superior del módulo y fuera de cualquier Subs o
Funciones
• Los procedimientos declarados en módulos estándar son públicos por defecto
• Para declarar un procedimiento privado a un módulo, preceda la declaración con el
Palabra clave privada
• Los procedimientos DLL declarados en cualquier otro tipo de módulo son privados para ese módulo
https://riptutorial.com/ 9
Página 25
start = temporizador
Debug.Print "Paused for" & Format (Timer - start, "#, ###. 000") & "seconds"
End Sub
Se recomienda crear un módulo API dedicado para proporcionar un fácil acceso al sistema.
funciones de envoltorios de VBA: subs o funciones de VBA normales que encapsulan los detalles
necesarios para la llamada al sistema real, como los parámetros utilizados en las bibliotecas y la inicialización de esos
https://translate.googleusercontent.com/translate_f 21/223
6/1/2021 Intitulado
parámetros
Para declarar un procedimiento de DLL, agregue una instrucción Declare a la sección Declaraciones del código
ventana.
Declarar función publicname Lib "libname" [Alias "alias"] [([[ByVal] variable [Como tipo]
[, [ByVal] variable [Como tipo]] ...])] Como tipo
Declare Sub publicname Lib "libname" [Alias "alias"] [([[ByVal] variable [As type] [, [ByVal]
variable [Como tipo]] ...])]
También es de destacar que la mayoría de las llamadas no válidas a las API bloquearán Excel y posiblemente
archivos de datos corruptos
Sistema privado Declare Function Lib "libc.dylib" (comando ByVal como cadena) As Long
Sub RunSafari ()
Resultado tenue tan largo
resultado = sistema ("abrir -a Safari --args http://www.google.com")
Debug.Print Str (resultado)
https://riptutorial.com/ 10
Página 26
End Sub
Los ejemplos siguientes (API de Windows - Módulo dedicado (1 y 2)) muestran un módulo API que
incluye declaraciones comunes para Win64 y Win32
Opción explícita
https://translate.googleusercontent.com/translate_f 22/223
6/1/2021 Intitulado
Función privada Declare PtrSafe apiDestroyWindow Lib "User32" Alias "DestroyWindow"
(ByVal hWnd tan largo) como booleano
Función privada Declare PtrSafe apiEndDialog Lib "User32" Alias "EndDialog" (ByVal hWnd
As Long, ByVal result As Long) As Boolean
Función privada Declare PtrSafe apiEnumChildWindows Lib "User32" Alias "EnumChildWindows"
(ByVal hWndParent tan largo, ByVal pEnumProc tan largo, ByVal lParam tan largo)
Función privada Declare PtrSafe apiSalirWindowsEx Lib "User32" Alias "ExitWindowsEx"
(ByVal uFlags tan largo, ByVal dwReserved tan largo)
Función privada Declare PtrSafe apiFindExecutable Lib "Shell32" Alias "FindExecutableA"
(ByVal lpFile como cadena, ByVallpDirectory como cadena, ByVal lpResult como cadena) Tan largo
Función privada Declare PtrSafe apiFindWindow Lib "User32" Alias "FindWindowA" (ByVal
lpClassName como cadena, ByVal lpWindowName como cadena) Tan largo
Función privada Declare PtrSafe apiFindWindowEx Lib "User32" Alias "FindWindowExA" (ByVal
hWnd1 tan largo, ByVal hWnd2 tan largo, ByVal lpsz1 como cadena, ByVal lpsz2 como cadena) Tan largo
Función privada Declare PtrSafe apiGetActiveWindow Lib "User32" Alias "GetActiveWindow"
() Siempre que
Función privada Declare PtrSafe apiGetClassNameA Lib "User32" Alias "GetClassNameA"
(ByVal hWnd tan largo, ByVal szClassName como cadena, ByVal lLength tan largo)
Función privada Declare PtrSafe apiGetCommandLine Lib "Kernel32" Alias "GetCommandLineW"
() Siempre que
Función privada Declare PtrSafe apiGetCommandLineParams Lib "Kernel32" Alias
"GetCommandLineA" () siempre que
Función privada Declare PtrSafe apiGetDiskFreeSpaceEx Lib "Kernel32" Alias
"GetDiskFreeSpaceExA" (ByVal lpDirectoryName como cadena, lpFreeBytesAvailableToCaller como
Moneda, lpTotalNumberOfBytes como moneda, lpTotalNumberOfFreeBytes como moneda) As Long
Función privada Declare PtrSafe apiGetDriveType Lib "Kernel32" Alias "GetDriveTypeA"
(ByVal nDrive como cadena) Tan largo
Función privada Declare PtrSafe apiGetSalirCodeProcess Lib "Kernel32" Alias
"GetSalirCodeProcess" (ByVal hProcess tan largo, lpSalirCode tan largo)
Función privada Declare PtrSafe apiGetForegroundWindow Lib "User32" Alias
"GetForegroundWindow" () tan largo
Función privada Declare PtrSafe apiGetFrequency Lib "Kernel32" Alias
"QueryPerformanceFrequency" (cyFrequency como moneda) siempre que
https://riptutorial.com/ 11
Página 27
Función privada Declare PtrSafe apiGetLastError Lib "Kernel32" Alias "GetLastError" () como
Entero
Función privada Declare PtrSafe apiGetParent Lib "User32" Alias "GetParent" (ByVal hWnd
Siempre que)
Función privada Declare PtrSafe apiGetSystemMetrics Lib "User32" Alias "GetSystemMetrics"
(ByVal nIndex As Long) As Long
Función privada Declare PtrSafe apiGetSystemMetrics32 Lib "User32" Alias
"GetSystemMetrics" (ByVal nIndex As Long) As Long
Función privada Declare PtrSafe apiGetTickCount Lib "Kernel32" Alias
"QueryPerformanceCounter" (cyTickCount como moneda) siempre que
Función privada Declare PtrSafe apiGetTickCountMs Lib "Kernel32" Alias "GetTickCount" ()
Tanto tiempo
Función privada Declare PtrSafe apiGetUserName Lib "AdvApi32" Alias "GetUserNameA" (ByVal
lpBuffer As String, nSize As Long) As Long
Función privada Declare PtrSafe apiGetWindow Lib "User32" Alias "GetWindow" (ByVal hWnd
Tan largo, ByVal wCmd Tan largo) Tan largo
Función privada Declare PtrSafe apiGetWindowRect Lib "User32" Alias "GetWindowRect"
(ByVal hWnd Tan largo, lpRect como winRect) Tan largo
Función privada Declare PtrSafe apiGetWindowText Lib "User32" Alias "GetWindowTextA"
(ByVal hWnd tan largo, ByVal szWindowText como cadena, ByVal lLength tan largo)
Función privada Declare PtrSafe apiGetWindowThreadProcessId Lib "User32" Alias
"GetWindowThreadProcessId" (ByVal hWnd tan largo, lpdwProcessId tan largo)
Función privada Declare PtrSafe apiIsCharAlphaNumericA Lib "User32" Alias
"IsCharAlphaNumericA" (ByVal byChar As Byte) Tan largo
Función privada Declare PtrSafe apiIsIconic Lib "User32" Alias "IsIconic" (ByVal hWnd As
Long) Tan largo
Función privada Declare PtrSafe apiIsWindowVisible Lib "User32" Alias "IsWindowVisible"
(ByVal hWnd As Long) Siempre que
Función privada Declare PtrSafe apiIsZoomed Lib "User32" Alias "IsZoomed" (ByVal hWnd As
Long) Tan largo
Función privada Declare PtrSafe apiLStrCpynA Lib "Kernel32" Alias "lstrcpynA" (ByVal
pDestination como cadena, ByVal pSource tan largo, ByVal iMaxLength como entero) Tan largo
Función privada Declare PtrSafe apiMessageBox Lib "User32" Alias "MessageBoxA" (ByVal
hWnd tan largo, ByVal lpText como cadena, ByVal lpCaption como cadena, ByVal wType tan largo)
Función privada Declare PtrSafe apiOpenIcon Lib "User32" Alias "OpenIcon" (ByVal hWnd As
Long) Tan largo
Función privada Declare PtrSafe apiOpenProcess Lib "Kernel32" Alias "OpenProcess" (ByVal
dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Función privada Declare PtrSafe apiPathAddBackslashByPointer Lib "ShlwApi" Alias
"PathAddBackslashW" (ByVal lpszPath As Long) As Long
https://translate.googleusercontent.com/translate_f 23/223
6/1/2021 Intitulado
Función privada Declare PtrSafe apiPathAddBackslashByString Lib "ShlwApi" Alias
"PathAddBackslashW" (ByVal lpszPath como cadena) As Long 'http://msdn.microsoft.com/en-
us / library / aa155716% 28office.10% 29.aspx
Función privada Declare PtrSafe apiPostMessage Lib "User32" Alias "PostMessageA" (ByVal
hWnd tan largo, ByVal wMsg tan largo, ByVal wParam tan largo, ByVal lParam tan largo)
Función privada Declare PtrSafe apiRegQueryValue Lib "AdvApi32" Alias "RegQueryValue"
(ByVal hKey tan largo, ByVal sValueName como cadena, ByVal dwReserved tan largo, ByRef lValueType como
Long, ByVal sValue As String, ByRef lResultLen As Long) As Long
Función privada Declare PtrSafe apiSendMessage Lib "User32" Alias "SendMessageA" (ByVal
hWnd As Long, ByVal wMsg As Long, ByVal wParam Tan Long, lParam As Any) As Long
Función privada Declare PtrSafe apiSetActiveWindow Lib "User32" Alias "SetActiveWindow"
(ByVal hWnd As Long) Siempre que
Función privada Declare PtrSafe apiSetCurrentDirectoryA Lib "Kernel32" Alias
"SetCurrentDirectoryA" (ByVal lpPathName como cadena) Tan largo
Función privada Declare PtrSafe apiSetFocus Lib "User32" Alias "SetFocus" (ByVal hWnd As
Long) Tan largo
Función privada Declare PtrSafe apiSetForegroundWindow Lib "User32" Alias
"SetForegroundWindow" (ByVal hWnd As Long) As Long
Función privada Declare PtrSafe apiSetLocalTime Lib "Kernel32" Alias "SetLocalTime"
(lpSystem como SystemTime) Siempre que
Función privada Declare PtrSafe apiSetWindowPlacement Lib "User32" Alias
https://riptutorial.com/ 12
Página 28
https://translate.googleusercontent.com/translate_f 24/223
6/1/2021 Intitulado
strTitle As String 'INPUT
hWnd tan largo 'SALIDA
Tipo final 'Encuentra una ventana específica con subtítulos dinámicos de un
lista de todas las ventanas abiertas: http://www.everythingaccess.com/tutorials.asp?ID=Bring-an-external-
ventana de la aplicación al primer plano
Función privada Declare PtrSafe apiEnumWindows Lib "User32" Alias "EnumWindows" (ByVal
lpEnumFunc As LongPtr, ByVal lParam As LongPtr) As Long
Private Type lastInputInfo 'utilizado por apiGetLastInputInfo, getLastInputTime
cbSize As Long
dwTime As Long
https://riptutorial.com/ 13
Página 29
Tipo final
Función privada Declare PtrSafe apiGetLastInputInfo Lib "User32" Alias "GetLastInputInfo"
(ByRef plii como lastInputInfo) Tan largo
'http://www.pgacon.com/visualbasic.htm#Take%20Advantage%20of%20Conditional%20Compilation
'Operadores lógicos y bit a bit en Visual Basic: http://msdn.microsoft.com/en-
us / library / wz3k228a (v = frente a 80) .aspx y http://stackoverflow.com/questions/1070863/hidden-
características-de-vba
Tipo privado SystemTime
wYear Como entero
wMonth Como entero
wDayOfWeek como entero
wDía Como entero
wHour Como entero
wMinuto Como entero
wSecond Como entero
wMilliseconds como entero
Tipo final
Privada Declare PtrSafe Sub apiGetLocalTime Lib "Kernel32" Alias "GetLocalTime" (lpSystem
Como SystemTime)
Private Type pointAPI 'utilizado por apiSetWindowPlacement
X tanto tiempo
Y siempre que
Tipo final
Private Type rectAPI 'utilizado por apiSetWindowPlacement
Left_Renamed As Long
Top_Renamed As Long
Right_Renamed As Long
Bottom_Renamed As Long
Tipo final
WinPlacement de tipo privado 'utilizado por apiSetWindowPlacement
longitud tan larga
banderas tan largas
showCmd tan largo
ptMinPosition como pointAPI
ptMaxPosition como pointAPI
rcNormalPosition como rectAPI
Tipo final
Función privada Declare PtrSafe apiGetWindowPlacement Lib "User32" Alias
"GetWindowPlacement" (ByVal hWnd As Long, ByRef lpwndpl As winPlacement) As Long
Tipo privado winRect 'utilizado por apiMoveWindow
Dejó tanto tiempo
Arriba siempre que
Tanto tiempo
Fondo tan largo
Tipo final
Función privada Declare PtrSafe apiMoveWindow Lib "User32" Alias "MoveWindow" (ByVal hWnd
Tan largo, xIzquierdo tan largo, ByVal yTop tan largo, wWidth tan largo, ByVal hHeight tan largo, ByVal
repintar siempre que)
https://translate.googleusercontent.com/translate_f 25/223
6/1/2021 Intitulado
https://riptutorial.com/ 14
Página 30
dwContext tan largo) como booleano 'Obtener un archivo', por ejemplo: blnRC = FtpGetFile (lngINetConn,
"dirmap.txt", "c: \ dirmap.txt", 0, 0, 1, 0)
Función privada Declare PtrSafe apiFtpPutFile Lib "WiniNet" Alias "FtpPutFileA" (ByVal
hFtpSession como larga, ByVal lpszLocalFile como cadena, ByVal lpszRemoteFile como cadena, ByVal
dwFlags As Long, ByVal dwContext As Long) Como booleano 'Enviar un archivo' ej: blnRC =
FtpPutFile (lngINetConn, "c: \ dirmap.txt", "dirmap.txt", 1, 0)
Función privada Declare PtrSafe apiFtpDeleteFile Lib "WiniNet" Alias "FtpDeleteFileA"
(ByVal hFtpSession tan largo, ByVal lpszFileName como cadena) Como booleano 'Eliminar un archivo' ex: blnRC
= FtpDeleteFile (lngINetConn, "test.txt")
Función privada Declare PtrSafe apiInternetCloseHandle Lib "WiniNet" (ByVal hInet As
Long) Como entero 'Cerrar el objeto de Internet' ex: InternetCloseHandle lngINetConn 'ex:
InternetCloseHandle lngINet
Función privada Declare PtrSafe apiFtpFindFirstFile Lib "WiniNet" Alias
"FtpFindFirstFileA" (ByVal hFtpSession tan largo, ByVal lpszSearchFile como cadena, lpFindFileData
Como WIN32_FIND_DATA, ByVal dwFlags tan largo, ByVal dwContent tan largo)
Tipo privado FILETIME
dwLowDateTime tan largo
dwHighDateTime tan largo
Tipo final
Tipo privado WIN32_FIND_DATA
dwFileAttributes tan largo
ftCreationTime como FILETIME
ftLastAccessTime como FILETIME
ftLastWriteTime como FILETIME
nFileSizeHigh tan largo
nFileSizeLow tanto tiempo
dwReserved0 siempre que
dwReserved1 siempre que
cFileName como cadena * 1 'MAX_FTP_PATH
cAlternate como cadena * 14
Tipo de finalización 'ex: lngHINet = FtpFindFirstFile (lngINetConn, "*. *", PData, 0, 0)
Función privada Declare PtrSafe apiInternetFindNextFile Lib "WiniNet" Alias
"InternetFindNextFileA" (ByVal hFind As Long, lpvFindData As WIN32_FIND_DATA) As Long 'ex:
blnRC = InternetFindNextFile (lngHINet, pData)
#ElseIf Win32 Then 'Win32 = True, Win16 = False
https://riptutorial.com/ 15
Página 31
https://translate.googleusercontent.com/translate_f 26/223
6/1/2021 Intitulado
lpApplicationName tan largo, ByVal lpCommandLine como cadena, lpProcessAttributes como cualquiera,
lpThreadAttributes As Any, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long,
lpEnvironment como cualquiera, ByVal lpCurrentDriectory como cadena, lpStartupInfo como STARTUPINFO,
lpProcessInformation como PROCESS_INFORMATION) Siempre que
Función de declaración privada apiDestroyWindow Lib "User32" Alias "DestroyWindow" (ByVal hWnd
Tan largo) como booleano
Función de declaración privada apiEndDialog Lib "User32" Alias "EndDialog" (ByVal hWnd As Long,
ByVal result As Long) As Boolean
Función de declaración privada apiEnumChildWindows Lib "User32" Alias "EnumChildWindows" (ByVal
hWndParent tan largo, ByVal pEnumProc tan largo, ByVal lParam tan largo)
Función de declaración privada apiSalirWindowsEx Lib "User32" Alias "ExitWindowsEx" (ByVal uFlags
Siempre que, ByVal dwReservado Siempre que)
Función de declaración privada apiFindExecutable Lib "Shell32" Alias "FindExecutableA" (ByVal
lpFile como cadena, ByVallpDirectory como cadena, ByVal lpResult como cadena) Tan largo
Función de declaración privada apiFindWindow Lib "User32" Alias "FindWindowA" (ByVal lpClassName
Como cadena, ByVal lpWindowName como cadena) tan largo
Función de declaración privada apiFindWindowEx Lib "User32" Alias "FindWindowExA" (ByVal hWnd1
Tan largo, ByVal hWnd2 tan largo, ByVal lpsz1 como cadena, ByVal lpsz2 como cadena) Tan largo
Función de declaración privada apiGetActiveWindow Lib "User32" Alias "GetActiveWindow" () como
Largo
Función de declaración privada apiGetClassNameA Lib "User32" Alias "GetClassNameA" (ByVal hWnd
As Long, ByVal szClassName As String, ByVal lLength As Long) As Long
Función de declaración privada apiGetCommandLine Lib "Kernel32" Alias "GetCommandLineW" () como
Largo
Función de declaración privada apiGetCommandLineParams Lib "Kernel32" Alias "GetCommandLineA" ()
Tanto tiempo
Función de declaración privada apiGetDiskFreeSpaceEx Lib "Kernel32" Alias "GetDiskFreeSpaceExA"
(ByVal lpDirectoryName como cadena, lpFreeBytesAvailableToCaller como moneda,
lpTotalNumberOfBytes como moneda, lpTotalNumberOfFreeBytes como moneda) siempre que
Función de declaración privada apiGetDriveType Lib "Kernel32" Alias "GetDriveTypeA" (ByVal
nDrive As String) Tan largo
Función de declaración privada apiGetSalirCodeProcess Lib "Kernel32" (ByVal hProcess As Long,
lpSalirCode tan largo)
Función de declaración privada apiGetFileSize Lib "Kernel32" (ByVal hFile As Long,
lpFileSizeHigh siempre que)
Función de declaración privada apiGetForegroundWindow Lib "User32" Alias "GetForegroundWindow"
() Siempre que
Función de declaración privada apiGetFrequency Lib "Kernel32" Alias "QueryPerformanceFrequency"
(Cifrecuencia como moneda) Siempre que
Función de declaración privada apiGetLastError Lib "Kernel32" Alias "GetLastError" () como entero
Función de declaración privada apiGetParent Lib "User32" Alias "GetParent" (ByVal hWnd As Long)
Tanto tiempo
Función de declaración privada apiGetSystemMetrics Lib "User32" Alias "GetSystemMetrics" (ByVal
nIndex As Long) Siempre que
Función de declaración privada apiGetTickCount Lib "Kernel32" Alias "QueryPerformanceCounter"
(cyTickCount como moneda) Siempre que
Función de declaración privada apiGetTickCountMs Lib "Kernel32" Alias "GetTickCount" () As Long
Función de declaración privada apiGetUserName Lib "AdvApi32" Alias "GetUserNameA" (ByVal
lpBuffer As String, nSize As Long) As Long
Función de declaración privada apiGetWindow Lib "User32" Alias "GetWindow" (ByVal hWnd As Long,
ByVal wCmd As Long) Siempre que
Función de declaración privada apiGetWindowRect Lib "User32" Alias "GetWindowRect" (ByVal hWnd
Siempre que, lpRect como winRect) Siempre que
Función de declaración privada apiGetWindowText Lib "User32" Alias "GetWindowTextA" (ByVal hWnd
As Long, ByVal szWindowText como cadena, ByVal lLength As Long) As Long
Función de declaración privada apiGetWindowThreadProcessId Lib "User32" Alias
"GetWindowThreadProcessId" (ByVal hWnd tan largo, lpdwProcessId tan largo)
https://riptutorial.com/ dieciséis
Página 32
https://translate.googleusercontent.com/translate_f 27/223
6/1/2021 Intitulado
Función de declaración privada apiPathAddBackslashByPointer Lib "ShlwApi" Alias
"PathAddBackslashW" (ByVal lpszPath As Long) As Long
Función de declaración privada apiPathAddBackslashByString Lib "ShlwApi" Alias
"PathAddBackslashW" (ByVal lpszPath como cadena) As Long 'http://msdn.microsoft.com/en-
us / library / aa155716% 28office.10% 29.aspx
Función de declaración privada apiPostMessage Lib "User32" Alias "PostMessageA" (ByVal hWnd As
Long, ByVal wMsg tan largo, ByVal wParam tan largo, ByVal lParam tan largo)
Función de declaración privada apiReadFile Lib "Kernel32" (ByVal hFile As Long, lpBuffer As Any,
ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, lpOverlapped As Any) As Long
Función de declaración privada apiRegQueryValue Lib "AdvApi32" Alias "RegQueryValue" (ByVal hKey
As Long, ByVal sValueName As String, ByVal dwReserved As Long, ByRef lValueType As Long, ByVal
sValue As String, ByRef lResultLen As Long) As Long
Función de declaración privada apiSendMessage Lib "User32" Alias "SendMessageA" (ByVal hWnd As
Long, ByVal wMsg Tan largo, ByVal wParam Tan largo, lParam Como cualquiera) Tan largo
Función de declaración privada apiSetActiveWindow Lib "User32" Alias "SetActiveWindow" (ByVal
hWnd As Long) Siempre que
Función de declaración privada apiSetCurrentDirectoryA Lib "Kernel32" Alias
"SetCurrentDirectoryA" (ByVal lpPathName como cadena) Tan largo
Función de declaración privada apiSetFocus Lib "User32" Alias "SetFocus" (ByVal hWnd As Long)
Largo
Función de declaración privada apiSetForegroundWindow Lib "User32" Alias "SetForegroundWindow"
(ByVal hWnd As Long) Siempre que
Función de declaración privada apiSetLocalTime Lib "Kernel32" Alias "SetLocalTime" (lpSystem As
SystemTime) siempre que
Función de declaración privada apiSetWindowPlacement Lib "User32" Alias "SetWindowPlacement"
(ByVal hWnd As Long, ByRef lpwndpl As winPlacement) As Long
Función de declaración privada apiSetWindowPos Lib "User32" Alias "SetWindowPos" (ByVal hWnd As
Long, ByVal hWndInsertAfter tan largo, ByVal X tan largo, ByVal Y tan largo, ByVal cx tan largo, ByVal
cy As Long, ByVal wFlags As Long) As Long
Función de declaración privada apiSetWindowText Lib "User32" Alias "SetWindowTextA" (ByVal hWnd
Tan largo, ByVal lpString como cadena) Tan largo
Función de declaración privada apiShellExecute Lib "Shell32" Alias "ShellExecuteA" (ByVal hWnd
As Long, ByVal lpOperation como cadena, ByVal lpFile como cadena, ByVal lpParameters como cadena,
ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
Función de declaración privada apiShowWindow Lib "User32" Alias "ShowWindow" (ByVal hWnd As
Long, ByVal nCmdShow As Long) As Long
Función de declaración privada apiShowWindowAsync Lib "User32" Alias "ShowWindowAsync" (ByVal
hWnd As Long, ByVal nCmdShow As Long) As Long
Función de declaración privada apiStrCpy Lib "Kernel32" Alias "lstrcpynA" (ByVal pDestination As
String, ByVal pSource como cadena, ByVal iMaxLength como entero) Tan largo
Función de declaración privada apiStringLen Lib "Kernel32" Alias "lstrlenW" (ByVal lpString As
Long) Tan largo
Función de declaración privada apiStrTrimW Lib "ShlwApi" Alias "StrTrimW" () como booleano
Función de declaración privada apiTerminateProcess Lib "Kernel32" Alias "TerminateProcess"
(ByVal hWnd tan largo, ByVal uSalirCode tan largo)
https://riptutorial.com/ 17
Página 33
https://translate.googleusercontent.com/translate_f 28/223
6/1/2021 Intitulado
lpTemplateName como cadena
Tipo final
Función de declaración privada apiChooseColor Lib "ComDlg32" Alias "ChooseColorA" (pChoosecolor
Como CHOOSECOLOR) siempre que
Estructura personalizada de FindWindowParameters de tipo privado para pasar los parámetros de entrada / salida
de la función de enumeración de ganchos; podría usar variables globales en su lugar, pero esto es mejor
strTitle As String 'INPUT
hWnd tan largo 'SALIDA
Tipo final 'Encuentra una ventana específica con subtítulos dinámicos de un
lista de todas las ventanas abiertas: http://www.everythingaccess.com/tutorials.asp?ID=Bring-an-external-
ventana de la aplicación al primer plano
Función de declaración privada apiEnumWindows Lib "User32" Alias "EnumWindows" (ByVal lpEnumFunc
As Long, ByVal lParam As Long) As Long
Private Type lastInputInfo 'utilizado por apiGetLastInputInfo, getLastInputTime
cbSize As Long
dwTime As Long
Tipo final
Función de declaración privada apiGetLastInputInfo Lib "User32" Alias "GetLastInputInfo" (ByRef
plii As lastInputInfo) Tan largo
Tipo privado SystemTime
wYear Como entero
wMonth Como entero
wDayOfWeek como entero
wDía Como entero
wHour Como entero
wMinuto Como entero
wSecond Como entero
wMilliseconds como entero
Tipo final
Private Declare Sub apiGetLocalTime Lib "Kernel32" Alias "GetLocalTime" (lpSystem As
Hora del sistema)
Punto de tipo privado API
X tanto tiempo
Y siempre que
https://riptutorial.com/ 18
Página 34
Tipo final
Tipo privado rectAPI
Left_Renamed As Long
Top_Renamed As Long
Right_Renamed As Long
Bottom_Renamed As Long
Tipo final
Tipo privado winPlacement
longitud tan larga
banderas tan largas
showCmd tan largo
ptMinPosition como pointAPI
ptMaxPosition como pointAPI
rcNormalPosition como rectAPI
Tipo final
Función de declaración privada apiGetWindowPlacement Lib "User32" Alias "GetWindowPlacement"
(ByVal hWnd As Long, ByRef lpwndpl As winPlacement) As Long
Tipo privado winRect
Dejó tanto tiempo
Arriba siempre que
Tanto tiempo
Fondo tan largo
Tipo final
Función de declaración privada apiMoveWindow Lib "User32" Alias "MoveWindow" (ByVal hWnd As
Long, xLeft tan largo, ByVal yTop tan largo, wWidth tan largo, ByVal hHeight tan largo, ByVal repintado
Siempre que)
#Else 'Win16 = Verdadero
#Terminara si
API de Mac
Microsoft no admite oficialmente las API, pero con un poco de investigación se pueden encontrar más declaraciones
en línea
https://translate.googleusercontent.com/translate_f 29/223
6/1/2021 Intitulado
A diferencia de otras versiones de las aplicaciones de Office que admiten VBA, las aplicaciones de Office 2016 para Mac son de espacio aislado.
La zona de pruebas impide que las aplicaciones accedan a recursos fuera del contenedor de aplicaciones. Esto afecta
cualquier complemento o macros que implique el acceso a archivos o la comunicación entre procesos. Usted puede
Minimice los efectos del sandboxing utilizando los nuevos comandos descritos en la siguiente sección.
Nuevos comandos de VBA para Office 2016 para Mac
Los siguientes comandos de VBA son nuevos y exclusivos de Office 2016 para Mac.
https://riptutorial.com/ 19
Página 35
Sistema privado Declare Function Lib "libc.dylib" (comando ByVal como cadena) As Long
Función de declaración privada popen Lib "libc.dylib" (comando ByVal como cadena, modo ByVal como
String) tan largo
Función de declaración privada pclose Lib "libc.dylib" (archivo ByVal siempre que sea largo)
Función de declaración privada fread Lib "libc.dylib" (ByVal outStr As String, ByVal size As Long,
Elementos ByVal As Long, ByVal stream As Long) As Long
Función de declaración privada feof Lib "libc.dylib" (archivo ByVal siempre que sea largo)
Función privada Declare PtrSafe popen Lib "libc.dylib" (comando ByVal como cadena, modo ByVal
Como cadena) Como LongPtr
Función privada Declare PtrSafe pclose Lib "libc.dylib" (archivo ByVal como LongPtr) As Long
Función privada Declare PtrSafe fread Lib "libc.dylib" (ByVal outStr As String, ByVal size As
Elementos LongPtr, ByVal As LongPtr, ByVal stream As LongPtr) As Long
Función privada Declare PtrSafe feof Lib "libc.dylib" (archivo ByVal como LongPtr) como LongPtr
Opción explícita
'Envoltorios de VBA:
Función pública dllGetMonitors () tan largo
Const SM_CMONITORS = 80
dllGetMonitors = GetSystemMetrics32 (SM_CMONITORS)
Función final
https://translate.googleusercontent.com/translate_f 30/223
6/1/2021 Intitulado
Función final
'Monitores totales: 1
'Resolución horizontal: 1920
'Resolución vertical: 1080
End Sub
https://riptutorial.com/ 20
Página 36
modFTP
Opción explícita
Opción Comparar texto
Opción Módulo Privado
'http://msdn.microsoft.com/en-us/library/aa384180(v=VS.85).aspx
'http://www.dailydoseofexcel.com/archives/2006/01/29/ftp-via-vba/
'http://www.15seconds.com/issue/981203.htm
'Conéctese a la red
Función de declaración privada InternetConnect Lib "wininet.dll" Alias "InternetConnectA" (_
ByVal hInternetSession siempre que, _
ByVal sServerName como cadena, _
ByVal nServerPort como entero, _
ByVal sUsername como cadena, _
ByVal sPassword como cadena, _
ByVal lService siempre que, _
ByVal lFlags As Long, _
ByVal lContext tan largo _
) Tanto tiempo
'ej: lngINetConn = InternetConnect (lngINet, "ftp.microsoft.com", 0, "anónimo",
"wally@wallyworld.com", 1, 0, 0)
'Obtener un archivo
Función de declaración privada FtpGetFile Lib "wininet.dll" Alias "FtpGetFileA" (_
ByVal hFtpSession siempre que, _
ByVal lpszRemoteFile como cadena, _
ByVal lpszNewFile como cadena, _
ByVal fFailIfExists como booleano, _
ByVal dwFlagsAndAttributes As Long, _
ByVal dwFlags As Long, _
ByVal dwContext siempre que _
) Como booleano
'ex: blnRC = FtpGetFile (lngINetConn, "dirmap.txt", "c: \ dirmap.txt", 0, 0, 1, 0)
'Enviar un archivo
Función de declaración privada FtpPutFile Lib "wininet.dll" Alias "FtpPutFileA" _
(_
ByVal hFtpSession siempre que, _
ByVal lpszLocalFile como cadena, _
ByVal lpszRemoteFile como cadena, _
ByVal dwFlags tan largo, ByVal dwContext tan largo _
) Como booleano
'ex: blnRC = FtpPutFile (lngINetConn, "c: \ dirmap.txt", "dirmap.txt", 1, 0)
'Eliminar un archivo
Función de declaración privada FtpDeleteFile Lib "wininet.dll" Alias "FtpDeleteFileA" _
https://translate.googleusercontent.com/translate_f 31/223
6/1/2021 Intitulado
https://riptutorial.com/ 21
Página 37
(_
ByVal hFtpSession siempre que, _
ByVal lpszFileName como cadena _
) Como booleano
'ex: blnRC = FtpDeleteFile (lngINetConn, "test.txt")
https://riptutorial.com/ 22
Página 38
Si lngINetConn> 0, entonces
FtpPutFile lngINetConn, "C: \ Tmp \ ftp.cls", "ftp.cls", FTP_TRANSFER_BINARY, 0
'lngFindFirst = FtpFindFirstFile (lngINetConn, "ExcelDiff.xlsm", pData, 0, 0)
https://translate.googleusercontent.com/translate_f 32/223
6/1/2021 Intitulado
Si lngINet = 0 entonces
msg = "Error de DLL:" & Err.LastDllError & ", Número de error:" & Err.Number & ",
Error Desc: "& Err.Description
Más
msg = left (pData.cFileName, InStr (1, pData.cFileName, String (1, 0),
vbBinaryCompare) - 1)
Terminara si
InternetCloseHandle lngINetConn
Terminara si
InternetCloseHandle lngINet
Terminara si
MsgBox msg
End Sub
modRegional:
Opción explícita
Función de declaración privada GetLocaleInfo Lib "Kernel32" Alias "GetLocaleInfoA" (ByVal Locale As
Long, ByVal LCType tan largo, ByVal lpLCData como cadena, ByVal cchData tan largo)
Función de declaración privada SetLocaleInfo Lib "Kernel32" Alias "SetLocaleInfoA" (ByVal Locale As
Long, ByVal LCType tan largo, ByVal lpLCData como cadena) como booleano
Función de declaración privada GetUserDefaultLCID% Lib "Kernel32" ()
Función privada SetLocalSetting (LC_CONST tan largo, configuración como cadena) como booleano
Llamar a SetLocaleInfo (GetUserDefaultLCID (), LC_CONST, Configuración)
https://riptutorial.com/ 23
Página 39
Función final
https://translate.googleusercontent.com/translate_f 33/223
6/1/2021 Intitulado
https://riptutorial.com/ 24
Página 40
Capítulo 3: Matrices
Ejemplos
Declarar una matriz es muy similar a declarar una variable, excepto que debe declarar la
dimensión de la matriz justo después de su nombre:
Dim myArray (9) As String 'Declarando una matriz que contendrá hasta 10 cadenas
De forma predeterminada, las matrices en VBA están indexadas desde CERO , por lo tanto, el número dentro del paréntesis
no se refiere al tamaño de la matriz, sino al índice del último elemento
Acceso a elementos
El acceso a un elemento de la matriz se realiza mediante el nombre de la matriz, seguido del índice
https://translate.googleusercontent.com/translate_f 34/223
6/1/2021 Intitulado
del elemento, entre paréntesis:
Indexación de matrices
Puede cambiar la indexación de matrices colocando esta línea en la parte superior de un módulo:
Opción Base 1
Con esta línea, todas las matrices declaradas en el módulo se indexarán desde ONE .
Índice específico
También puede declarar cada Array con su propio índice utilizando la palabra clave To , y la menor y
límite superior (= índice):
Declaración dinámica
Cuando no conoce el tamaño de su Array antes de su declaración, puede usar la dinámica
declaración y la palabra clave ReDim :
https://riptutorial.com/ 25
Página 41
Tenga en cuenta que el uso de la palabra clave ReDim eliminará cualquier contenido anterior de su matriz. Para prevenir esto,
puede usar la palabra clave Preserve después de ReDim :
Función dividida
devuelve una matriz unidimensional de base cero que contiene un número específico de subcadenas.
Sintaxis
Parte Descripción
Opcional. Carácter de cadena utilizado para identificar límites de subcadena. Si se omite, el espacio
https://translate.googleusercontent.com/translate_f 35/223
6/1/2021 Intitulado
Opcional. Número de subcadenas que se devolverán; -1 indica que todas las subcadenas
límite
se devuelven.
Opcional. Valor numérico que indica el tipo de comparación que se utilizará cuando
comparar
evaluar subcadenas. Consulte la sección Configuración para conocer los valores.
Configuraciones
https://riptutorial.com/ 26
Página 42
Ejemplo
En este ejemplo se demuestra cómo funciona Split mostrando varios estilos. Los comentarios
muestra el conjunto de resultados para cada una de las diferentes opciones de división realizadas. Finalmente se demuestra como
para recorrer la matriz de cadenas devuelta.
Subprueba
https://translate.googleusercontent.com/translate_f 36/223
6/1/2021 Intitulado
próximo
End Sub
https://riptutorial.com/ 27
Página 43
Un bucle For Each iterará todas las dimensiones de exterior a interior (el mismo orden en que se muestran los elementos
establecidos en la memoria), por lo que no hay necesidad de bucles anidados:
https://translate.googleusercontent.com/translate_f 37/223
6/1/2021 Intitulado
https://riptutorial.com/ 28
Página 44
Tenga en cuenta que los bucles For Each se utilizan mejor para iterar objetos de colección , si el rendimiento es importante.
0
1
2
3
Matrices dinámicas
Agregar y reducir variables en una matriz de forma dinámica es una gran ventaja para cuando
la información que está tratando no tiene un número determinado de variables.
En el siguiente ejemplo, creamos una matriz y la aumentamos en una variable más en cada iteración.
conservando los valores que ya están en la matriz.
Para n = 1 a 100
Más
ReDim Preserve Dynamic_array (0 a UBound (Dynamic_array) + 1)
'en la línea de arriba cambiamos el tamaño de la matriz de la variable 0 al UBound () = last
variable, más uno que aumenta efectivamente el tamaño de la matriz en uno
Matriz_dinámica (UBound (Matriz_dinámica)) = n
'atribuir un valor a la última variable de Dynamic_array
Terminara si
próximo
https://riptutorial.com/ 29
Página 45
eliminado de la matriz.
https://translate.googleusercontent.com/translate_f 38/223
6/1/2021 Intitulado
En el fragmento de abajo, construyo una matriz con los valores de 1 a 40, vacío la matriz y vuelvo a llenar el
matriz con valores de 40 a 100, todo esto realizado de forma dinámica.
Para n = 1 a 100
próximo
Aunque las matrices irregulares son bastante complicadas y difíciles de usar debido a sus niveles anidados y no
tienen mucha seguridad de tipos, pero son muy flexibles, le permiten manipular diferentes tipos de datos
https://riptutorial.com/ 30
Página 46
https://translate.googleusercontent.com/translate_f 39/223
6/1/2021 Intitulado
Construiremos dinámicamente una matriz de encabezado y una matriz de clientes, el encabezado contendrá el
los títulos de las columnas y la matriz Clientes contendrán la información de cada cliente / fila como matrices.
https://riptutorial.com/ 31
Página 47
Para r = 2 a 6
'iterar a través de los clientes / filas
Para c = 1 a 4
'iterar a través de los valores / columnas
https://translate.googleusercontent.com/translate_f 40/223
6/1/2021 Intitulado
Para comprender mejor la forma de construir dinámicamente una matriz unidimensional, consulte
Matrices dinámicas (cambio de tamaño de matriz y manejo dinámico) en la documentación de matrices.
El resultado del fragmento anterior es una matriz dentada con dos matrices, una de esas matrices con 4
elementos, 2 niveles de sangría, y el otro es en sí mismo otra matriz dentada que contiene 5 matrices de
4 elementos cada uno y 3 niveles de sangría, consulte la estructura a continuación:
Main_Array (0) - Encabezados - Matriz ("Nombre", "Teléfono", "Correo electrónico", "Número de cliente")
(1) - Clientes (0) - Matriz ("Persona1", 153486231, "1 @ STACK", 001)
Clientes (1) - Array ("Person2", 153486242, "2 @ STACK", 002)
...
Clientes (4) - Array ("Person5", 153486275, "5 @ STACK", 005)
Para acceder a la información tendrás que tener en cuenta la estructura del Jagged Array que creas,
En el ejemplo anterior, puede ver que la matriz principal contiene una matriz de encabezados y una matriz de
Matrices ( Clientes ) por lo tanto con diferentes formas de acceder a los elementos.
Ahora leeremos la información del Main Array e imprimiremos la información de cada uno de los Clientes.
como tipo de información: Info .
https://riptutorial.com/ 32
Página 48
Debug.Print Main_Array (0) (j) & ":" & Main_Array (1) (n) (j)
'print Main_Array (0) (j) que es el encabezado y Main_Array (0) (n) (j) que es el
elemento en la matriz de clientes
'podemos llamar al encabezado con j ya que la matriz de encabezado tiene la misma estructura que el
matriz de clientes
próximo
próximo
RECUERDE realizar un seguimiento de la estructura de su Jagged Array, en el ejemplo anterior para acceder
el Nombre de un cliente es accediendo a Main_Array -> Clientes -> CustomerNumber -> Name which
tiene tres niveles, para devolver "Person4" necesitará la ubicación de los clientes en Main_Array, luego
la Ubicación del cliente cuatro en la matriz de Clientes irregulares y, por último, la ubicación del
elemento que necesita, en este caso Main_Array (1) (3) (0) que es
Main_Array (Clientes) (CustomerNumber) (Nombre) .
Matrices multidimensionales
Matrices multidimensionales
Como su nombre lo indica, las matrices multidimensionales son matrices que contienen más de una dimensión,
generalmente dos o tres pero puede tener hasta 32 dimensiones.
https://translate.googleusercontent.com/translate_f 41/223
6/1/2021 Intitulado
Una matriz múltiple funciona como una matriz con varios niveles, tome en ejemplo una comparación entre uno,
dos y tres dimensiones.
* 1D: visualmente *
(0)
(1)
(2)
Dos dimensiones se verían como una cuadrícula de Sudoku o una hoja de Excel, al inicializar la matriz
definiría cuántas filas y columnas tendría la matriz.
* 2D: visualmente *
(0,0) (0,1) (0,2)
(1,0) (1,1) (1,2)
(2,0) (2,1) (2,2)
https://riptutorial.com/ 33
Página 49
* 3D: visualmente *
1ra capa Segunda capa Tercera capa
frente medio espalda
(0,0,0) (0,0,1) (0,0,2) ¦ (1,0,0) (1,0,1) (1,0,2) ¦ (2,0,0 ) (2,0,1) (2,0,2)
(0,1,0) (0,1,1) (0,1,2) ¦ (1,1,0) (1,1,1) (1,1,2) ¦ (2,1,0 ) (2,1,1) (2,1,2)
(0,2,0) (0,2,1) (0,2,2) ¦ (1,2,0) (1,2,1) (1,2,2) ¦ (2,2,0 ) (2,2,1) (2,2,2)
Otras dimensiones podrían pensarse como la multiplicación del 3D, por lo que un 4D (1,3,3,3) sería dos
matrices 3D en paralelo.
El siguiente ejemplo será una compilación de una lista de empleados, cada empleado tendrá un conjunto de
información de la lista (nombre, apellido, dirección, correo electrónico, teléfono ...), el ejemplo
esencialmente se almacenará en la matriz (empleado, información) siendo el (0,0) el primer empleado
primer nombre.
https://translate.googleusercontent.com/translate_f 42/223
6/1/2021 Intitulado
Para empleado = 0 a UBound (empleados, 1)
'para cada empleado / fila en la matriz, UBound para matrices 2D, que obtendrá el último elemento en
la matriz
'necesita dos parámetros, primero la matriz que verificar y segundo la dimensión, en este caso 1 =
empleado y 2 = información
Para información_e = 0 a UBound (empleados, 2)
'para cada elemento / columna de información de la matriz
https://riptutorial.com/ 34
Página 50
próximo
Cambiar el tamaño
Cambiar el tamaño o ReDim Preservar una matriz múltiple como la norma para una matriz de una dimensión obtendría un
error, en cambio, la información debe transferirse a una matriz temporal con el mismo tamaño
como el original más el número de filas / columnas para agregar. En el ejemplo siguiente veremos cómo
inicializar una matriz temporal, transferir la información desde la matriz original, llenar el resto
elementos vacíos y reemplace la matriz temporal por la matriz original.
'transferir
Para emp = LBound (empleados, 1) a UBound (empleados, 1)
Para información = LBound (Empleados, 2) A UBound (Empleados, 2)
'para transferir empleados a TempEmp iteramos ambas matrices y llenamos TempEmp con el
valor del elemento correspondiente en Empleados
TempEmp (emp, info) = Empleados (emp, info)
próximo
próximo
'llenar restante
'después de las transferencias, la matriz Temp todavía tiene elementos no utilizados al final, ya que fue
aumentado
'para llenar los elementos restantes, iterar desde la última "fila" con valores hasta la última fila en el
formación
'en este caso, la última fila en Temp será el tamaño de las filas de la matriz Empleados + 1, ya que
La última fila de la matriz de empleados ya está llena en TempArray
próximo
próximo
Para cambiar / alterar los valores en un determinado elemento se puede hacer simplemente llamando a la coordenada a
cambiar y darle un nuevo valor: Empleados (0, 0) = "NewValue"
https://translate.googleusercontent.com/translate_f 43/223
6/1/2021 Intitulado
Alternativamente, iterar a través de las condiciones de uso de coordenadas para hacer coincidir los valores correspondientes al
parámetros necesarios:
https://riptutorial.com/ 35
Página 51
Leyendo
El acceso a los elementos de la matriz se puede hacer con un bucle anidado (iterando cada elemento),
Loop and Coordinate (iterar filas y acceder a columnas directamente), o acceder directamente con
ambas coordenadas.
'bucle y coordina, iteración a través de todas las filas y en cada fila accediendo a todas las columnas
directamente
Para emp = LBound (empleados, 1) a UBound (empleados, 1)
Debug.Print empleados (emp, 0)
Debug.Print empleados (emp, 1)
Debug.Print empleados (emp, 2)
Debug.Print empleados (emp, 3)
Empleados de Debug.Print (emp, 4)
Debug.Print empleados (emp, 5)
próximo
Recuerde , siempre es útil mantener un mapa de matriz cuando se utilizan matrices multidimensionales, pueden
convertirse fácilmente en confusión.
La matriz 3D tendrá los Empleados (se puede considerar como Filas), la Información (Columnas),
y edificios que se pueden considerar como hojas diferentes en un documento de Excel, tienen el mismo
tamaño entre ellos, pero cada hoja tiene un conjunto diferente de información en sus celdas / elementos. El 3D
matriz contendrá n número de matrices 2D.
Creando
https://riptutorial.com/ 36
Página 52
https://translate.googleusercontent.com/translate_f 44/223
6/1/2021 Intitulado
Una matriz 3D necesita 3 coordenadas para ser inicializada Dim 3Darray (2,5,5) Como Variante la primera coordenada
en la matriz estará el número de Edificios / Hojas (diferentes conjuntos de filas y columnas), segundo
La coordenada definirá Filas y terceras Columnas. La atenuación anterior dará como resultado una matriz 3D con 108
elementos ( 3 * 6 * 6 ), que efectivamente tienen 3 conjuntos diferentes de matrices 2D.
Cambiar el tamaño
Cambiar el tamaño de una matriz 3D es similar a cambiar el tamaño de una 2D, primero cree una matriz temporal con el mismo tamaño de
el original agregando uno en la coordenada del parámetro a aumentar, la primera coordenada será
aumentar el número de conjuntos en la matriz, la segunda y tercera coordenadas aumentarán el
número de filas o columnas en cada conjunto.
El siguiente ejemplo aumenta el número de Filas en cada conjunto en uno y llena las que se encuentran recientemente.
elementos agregados con nueva información.
'transferir
Para construir = LBound (ThreeDArray, 1) To UBound (ThreeDArray, 1)
Para emp = LBound (ThreeDArray, 2) To UBound (ThreeDArray, 2)
Para información = LBound (ThreeDArray, 3) To UBound (ThreeDArray, 3)
'para transferir ThreeDArray a TempEmp iterando todos los conjuntos en la matriz 3D y
llene TempEmp con el valor del elemento correspondiente en cada conjunto de cada fila
TempEmp (edificio, emp, información) = ThreeDArray (edificio, emp, información)
próximo
próximo
https://riptutorial.com/ 37
Página 53
próximo
'llenar restante
'para llenar los elementos restantes, necesitamos iterar desde la última "fila" con valores hasta la última
fila en la matriz en cada conjunto, recuerde que el primer elemento vacío es la matriz original
Hacia arriba () más 1
Para la construcción = LBound (TempEmp, 1) To UBound (TempEmp, 1)
Para emp = UBound (ThreeDArray, 2) + 1 To UBound (TempEmp, 2)
Para información = LBound (TempEmp, 3) a UBound (TempEmp, 3)
https://translate.googleusercontent.com/translate_f 45/223
6/1/2021 Intitulado
próximo
próximo
próximo
Leer y cambiar los elementos en la matriz 3D se puede hacer de manera similar a como lo hacemos
Matriz 2D, solo ajuste el nivel extra en los bucles y coordenadas.
Hacer
'usando Do ... While para salida anticipada
Para la construcción = 0 a UBound (ThreeDArray, 1)
Para emp = 0 a UBound (ThreeDArray, 2)
Si ThreeDArray (edificio, emp, 0) = "Gloria" y ThreeDArray (edificio, emp, 1) =
"Stephan" Entonces
'si se encuentra el valor
ThreeDArray (building, emp, 1) = "Casado, cambio de apellido"
Salir Hacer
'no iterar a través de toda la matriz a menos que sea necesario
Terminara si
próximo
próximo
Bucle en falso
'bucle y coordenada, iterará a través de todo el conjunto de filas y pedirá la fila más el valor
elegimos para las columnas
Para construir = LBound (ThreeDArray, 1) To UBound (ThreeDArray, 1)
Para emp = LBound (ThreeDArray, 2) To UBound (ThreeDArray, 2)
Debug.Print ThreeDArray (edificio, emp, 0)
Debug.Print ThreeDArray (edificio, emp, 1)
Debug.Print ThreeDArray (edificio, emp, 2)
Debug.Print ThreeDArray (edificio, emp, 3)
Debug.Print ThreeDArray (edificio, emp, 4)
https://riptutorial.com/ 38
Página 54
https://translate.googleusercontent.com/translate_f 46/223
6/1/2021 Intitulado
https://riptutorial.com/ 39
Página 55
• Cadena / Cadena $
• Espacio / Espacio $ .
Ejemplos
Utilice la función Cadena para asignar una cadena con n caracteres repetidos
Utilice las funciones String y Space para asignar una cadena de n caracteres
https://translate.googleusercontent.com/translate_f 47/223
6/1/2021 Intitulado
stringOfSpaces = Espacio $ (255)
https://riptutorial.com/ 40
Página 56
Capítulo 5: Atributos
Sintaxis
• Atributo VB_Name = "ClassOrModuleName"
• Atributo VB_GlobalNameSpace = False 'Ignorado
• Atributo VB_Creatable = Falso 'Ignorado
• Atributo VB_PredeclaredId = {Verdadero | Falso}
• Atributo VB_Exposed = {Verdadero | Falso}
• Atributo variableName.VB_VarUserMemId = 0 'Cero indica que este es el valor predeterminado
miembro de la clase.
• Attribute variableName.VB_VarDescription = "alguna cadena" 'Agrega el texto al objeto
Información del navegador para esta variable.
• Atributo procName.VB_Description = "alguna cadena" 'Agrega el texto al buscador de objetos
información para el procedimiento.
• Atributo procName.VB_UserMemId = {0 | -4}
'0: Hace que la función sea el miembro predeterminado de la clase.
○
Ejemplos
VB_Name
VB_GlobalNameSpace
https://translate.googleusercontent.com/translate_f 48/223
6/1/2021 Intitulado
En VB6, crea una instancia global predeterminada de la clase (un "atajo") para que los miembros de la clase puedan
ser accedido sin usar el nombre de la clase. Por ejemplo, DateTime (como en DateTime.Now ) es en realidad
parte de la clase VBA.Conversion .
Debug.Print VBA.Conversion.DateTime.Now
Debug.Print DateTime.Now
VB_Createable
https://riptutorial.com/ 41
Página 57
En VB6, se utilizó en combinación con el atributo VB_Exposed para controlar la accesibilidad de las clases.
fuera del proyecto actual.
VB_Exposed = Verdadero
VB_Creatable = Verdadero
Daría como resultado una clase pública , a la que se podría acceder desde otros proyectos, pero esta funcionalidad
no existe en VBA.
VB_PredeclaredId
Crea una instancia predeterminada global de una clase. Se accede a la instancia predeterminada a través del nombre del
clase.
Declaración
Llamada
Debug.Print Class1.GiveMeATwo
De alguna manera, esto simula el comportamiento de clases estáticas en otros lenguajes, pero a diferencia de otros
idiomas, aún puede crear una instancia de la clase.
VB_Exposed
https://translate.googleusercontent.com/translate_f 49/223
6/1/2021 Intitulado
Controla las características de creación de instancias de una clase.
https://riptutorial.com/ 42
Página 58
Hace que la clase sea privada . No se puede acceder fuera del proyecto actual.
Expone la clase Pública Ly, fuera del proyecto. Sin embargo, dado que VB_Createable se ignora en VBA,
Las instancias de la clase no se pueden crear directamente. Esto es equivalente a la siguiente VB.Net
clase.
Para obtener una instancia desde fuera del proyecto, debe exponer una fábrica para crear instancias.
Una forma de hacerlo es con un módulo público normal .
Dado que los módulos públicos son accesibles desde otros proyectos, esto nos permite crear nuevas instancias de
nuestras clases públicas - no creables .
VB_Description
Agrega una descripción de texto a un miembro de clase o módulo que se vuelve visible en el Explorador de objetos.
Idealmente, todos los miembros públicos de una interfaz / API pública deberían tener una descripción.
Nota: todos los miembros de acceso de una propiedad ( Get , Let , Set ) usan la misma descripción.
https://riptutorial.com/ 43
Página 59
https://translate.googleusercontent.com/translate_f 50/223
6/1/2021 Intitulado
Pero con un atributo VB_UserMemId establecido en 0 en la propiedad Item , el código del cliente puede hacer esto:
Solo un miembro puede tener legalmente VB_UserMemId = 0 en una clase determinada. Para propiedades, especifique el
atributo en el descriptor de acceso Get :
Opción explícita
Privado interno como nueva colección
Objeto de obtención de propiedad pública (índice ByVal tan largo) como variante
Attribute Item.VB_Description = "Obtiene o establece el elemento en el índice especificado".
Elemento de atributo.VB_UserMemId = 0
'Obtiene el elemento en el índice especificado.
Elemento = interno (índice)
Propiedad final
Propiedad pública Let Item (ByVal index As Long, ByVal value As Variant)
'Establece el elemento en el índice especificado.
Con interno
Si index = .Count + 1 Entonces
.Añadir elemento: = valor
ElseIf index = .Count Then
.Eliminar índice
.Añadir elemento: = valor
ElseIf index <.Count Then
.Eliminar índice
.Añadir elemento: = valor, antes: = índice
Terminara si
Terminar con
Propiedad final
construir
Con el valor mágico -4 , el atributo VB_UserMemId le dice a VBA que este miembro produce un
enumerador, que permite que el código del cliente haga esto:
https://riptutorial.com/ 44
Página 60
La forma más sencilla de implementar este método es llamando al getter de propiedad oculto [_NewEnum] en un
interna / encapsulada ; el identificador debe incluirse entre corchetes porque
Colección
https://translate.googleusercontent.com/translate_f 51/223
6/1/2021 Intitulado
Attribute NewEnum.VB_Description = "Obtiene un enumerador que recorre la lista en iteración".
Atributo NewEnum.VB_UserMemId = -4
El atributo NewEnum.VB_MemberFlags = "40" 'ocultaría el miembro en VB6. no es compatible con VBA.
'Obtiene un enumerador que recorre la Lista.
Establecer NewEnum = internal. [_ NewEnum]
Propiedad final
https://riptutorial.com/ 45
Página 61
Sintaxis
• expression.CreateObject (ObjectName)
• expresión; Necesario. Una expresión que devuelve un objeto Aplicación.
https://translate.googleusercontent.com/translate_f 52/223
6/1/2021 Intitulado
• Nombre del objeto; Cadena requerida. El nombre de clase del objeto que se va a crear. Para obtener información sobre
nombres de clases válidos, consulte Identificadores de programación OLE.
Observaciones
• Automatización de comprensión de MSDN
Cuando una aplicación admite Automatización, los objetos que expone la aplicación pueden ser
accedido por Visual Basic. Utilice Visual Basic para manipular estos objetos invocando
métodos en el objeto o obteniendo y estableciendo las propiedades del objeto.
Si usa los objetos en otras aplicaciones como parte de su aplicación de Visual Basic,
es posible que desee establecer una referencia a las bibliotecas de objetos de esas aplicaciones. antes de
Puede hacerlo, primero debe asegurarse de que la aplicación proporcione una biblioteca de objetos.
Le permite seleccionar los objetos de otra aplicación que desea que estén disponibles en su código
estableciendo una referencia a la biblioteca de objetos de esa aplicación.
• Método MSDN-CreateObject
Ejemplos
https://riptutorial.com/ 46
Página 62
Código
Puede utilizar estas funciones para obtener resultados RegEx, concatenar todas las coincidencias (si hay más de 1) en 1
cadena y muestra el resultado en la celda de Excel.
https://translate.googleusercontent.com/translate_f 53/223
6/1/2021 Intitulado
Establecer RegExObject = createVBScriptRegExObject
Terminara si
Función final
Con RegExObj
.Global = isGlobalSearch
.IgnoreCase = Not (isCaseSensitive) 'es más fácil de usar usar un significado positivo
de argumento, como isCaseSensitive, que usar IgnoreCase negativo
.Patrón = RegExPattern
Establecer getRegExMatches = .Execute (SourceString)
Terminar con
Función final
Función privada concatObjectItems (ByRef Obj como objeto, ByVal DelimiterCustom opcional como
String = ";") como cadena
Atenuar objeto como variante
Para cada objeto en el objeto
concatObjectItems = concatObjectItems & DelimiterCustom & ObjElement.Value
https://riptutorial.com/ 47
Página 63
próximo
Función final
Función pública removeLeadingDelimiter (ByVal SourceString como cadena, ByVal Delimiter como
String) como cadena
If Left $ (SourceString, Len (Delimiter)) = Delimiter Then
removeLeadingDelimiter = Mid $ (SourceString, Len (Delimitador) + 1)
Terminara si
Función final
El modelo de objetos del sistema de archivos (FSO) proporciona una herramienta basada en objetos para trabajar con
carpetas y archivos. Le permite utilizar la sintaxis conocida de object.method con un rico conjunto de
propiedades, métodos y eventos para procesar carpetas y archivos. También puede emplear el
instrucciones y comandos tradicionales de Visual Basic.
https://translate.googleusercontent.com/translate_f 54/223
6/1/2021 Intitulado
Objeto de scripting.Dictionary
Objeto MSDN-Dictionary
https://riptutorial.com/ 48
Página 64
Objeto MSDN-InternetExplorer
Sub IEGetToKnow ()
Atenuar IE como referencia de InternetExplorer a los controles de Internet de Microsoft
Establecer IE = New InternetExplorer
Con IE
.Visible = True 'Establece u obtiene un valor que indica si el objeto es visible o
oculto.
'Navegación
.Navigate2 "http://www.example.com" 'Navega el navegador a una ubicación que
no puede expresarse como una URL, como un PIDL para una entidad en el espacio de nombres de Windows Shell.
Debug.Print .Busy 'Obtiene un valor que indica si el objeto está involucrado en un
operación de navegación o descarga.
Debug.Print .ReadyState 'Obtiene el estado listo del objeto.
.Navigate2 "http://www.example.com/2"
.GoBack 'Navega hacia atrás un elemento en la lista del historial
.GoForward 'Avanza un elemento en la lista del historial.
.GoHome 'Navega a la página de inicio o de inicio actual.
.Stop 'Cancela una navegación o descarga pendiente y detiene los elementos dinámicos de la página, como
como sonidos de fondo y animaciones.
.Refresh 'Vuelve a cargar el archivo que se muestra actualmente en el objeto.
Debug.Print .Top 'Establece u obtiene las coordenadas del borde superior del objeto.
Debug.Print .Left 'Establece u obtiene las coordenadas del borde izquierdo del objeto.
Debug.Print .Height 'Establece u obtiene la altura del objeto.
Debug.Print .Width 'Establece u obtiene el ancho del objeto.
Terminar con
https://translate.googleusercontent.com/translate_f 55/223
6/1/2021 Intitulado
Raspado web
https://riptutorial.com/ 49
Página 65
Lo más común que se puede hacer con IE es extraer información de un sitio web o completar un
formulario del sitio web y enviar información. Veremos cómo hacerlo.
<cuerpo>
<div>
<h1> Dominio de ejemplo </h1>
<p> Este dominio está establecido para ser utilizado para ejemplos ilustrativos en documentos.
Puedes usar esto
dominio en ejemplos sin coordinación previa o sin pedir permiso. </p>
<p> <a href="http://www.iana.org/domains/example"> Más información ... </a> </p>
</div>
</body>
</html>
Sub IEWebScrape1 ()
Atenuar IE como referencia de InternetExplorer a los controles de Internet de Microsoft
Establecer IE = New InternetExplorer
Con IE
.Visible = Verdadero
.Navigate2 "http://www.example.com"
'agregamos un bucle para asegurarnos de que el sitio web esté cargado y listo.
'No funciona de manera consistente. No se puede confiar en él.
Hacer mientras .Busy = True O .ReadyState <> READYSTATE_COMPLETE 'Equivalente = .ReadyState
<> 4
'DoEvents - vale la pena considerarlo. Conozca las implicaciones antes de usarlo.
Application.Wait (Now + TimeValue ("00:00:01")) 'Espere 1 segundo y vuelva a verificar.
Lazo
Podemos cambiar el sitio web que se muestra localmente. No se preocupe por romper el sitio.
.GetElementsByTagName ("título") (0) .innerHtml = "Psst, raspado ..."
.GetElementsByTagName ("h1") (0) .innerHtml = "Déjame probar algo sospechoso". 'Tienes
https://riptutorial.com/ 50
Página 66
https://translate.googleusercontent.com/translate_f 56/223
6/1/2021 Intitulado
End Sub
Que esta pasando? El jugador clave aquí es el .Document , que es el código fuente HTML. Podemos
aplicamos algunas consultas para obtener las Colecciones o el Objeto que queremos.
Por ejemplo, IE.Document.GetElementsByTagName ("título") (0) .innerHtml . GetElementsByTagName
devuelve una colección de elementos HTML, que tienen la etiqueta " título ". Solo hay una etiqueta de este tipo en el
código fuente. La colección está basada en 0. Entonces, para obtener el primer elemento agregamos (0) . Ahora, en nuestro caso,
solo queremos el innerHtml (una cadena), no el objeto elemento en sí. Entonces especificamos la propiedad que
desear.
Hacer clic
Para seguir un enlace en un sitio, podemos utilizar varios métodos:
Sub IEGoToPlaces ()
Atenuar IE como referencia de InternetExplorer a los controles de Internet de Microsoft
Establecer IE = New InternetExplorer
Con IE
.Visible = Verdadero
.Navigate2 "http://www.example.com"
Detener 'VBE Stop. Continúe línea por línea para ver qué sucede.
'Hacer clic
.Document.GetElementsByTagName ("a") (0) .Haga clic en
Detener 'VBE Stop.
'Devolver
.Regresa
Detener 'VBE Stop.
https://riptutorial.com/ 51
Página 67
IE Principales problemas
El problema principal con IE es verificar que la página haya terminado de cargarse y esté lista para interactuar con ella.
El bucle Do While ... ayuda, pero no es confiable.
Además, usar IE solo para raspar contenido HTML es OVERKILL. ¿Por qué? Porque el navegador está diseñado para
navegación, es decir, mostrar la página web con todos los CSS, JavaScripts, imágenes, ventanas emergentes, etc.
https://translate.googleusercontent.com/translate_f 57/223
6/1/2021 Intitulado
Solo necesita los datos brutos, considere un enfoque diferente. Por ejemplo, usandoXML HTTPRequest . Más sobre
esto en otro ejemplo.
https://riptutorial.com/ 52
Página 68
Capítulo 7: Colecciones
Observaciones
Una colección es un objeto contenedor que se incluye en el tiempo de ejecución de VBA. No hay referencias adicionales
necesario para poder utilizarlo. Una colección se puede utilizar para almacenar elementos de cualquier tipo de datos y permite
recuperación mediante el índice ordinal del elemento o mediante el uso de una clave única opcional.
Iterar todo
Cómo determinar si existe un artículo Iterar todos los elementos Iterar todos los elementos
artículos
Cómo determinar si existe una clave Controlador de errores N/A .Existe función
.Eliminar todo
Iterar y
Quitar todos los elementos Borrar , ReDim
.Eliminar función
1 Solo se puede cambiar el tamaño de las matrices dinámicas y solo la última dimensión de las matrices multidimensionales.
Ejemplos
https://riptutorial.com/ 53
Página 69
Sintaxis:
Descripción de parámetros
El artículo para almacenar en la Colección . Esto puede ser esencialmente cualquier valor que
articulo se puede asignar una variable, incluidos tipos primitivos, matrices, objetos y
Nada .
Opcional. Una cadena que sirve como identificador único para recuperar elementos del
Colección .
Si la clave especificada ya existe en la colección , resultará en una
llave
Error 457 en tiempo de ejecución: "Esta clave ya está asociada con un elemento de este
colección".
Opcional. Una clave existente ( valor de cadena ) o índice (valor numérico) para insertar el
artículo antes en la Colección . Si se da un valor, el parámetro after debe ser
vacío o un error en tiempo de ejecución 5: se producirá un "argumento o llamada de procedimiento no válida". Si un
antes de Se pasa una clave de cadena que no existe en la colección , un error de tiempo de ejecución 5:
Se producirá un "argumento o llamada de procedimiento no válida". Si se pasa un índice numérico que
no existe en la colección , un error en tiempo de ejecución 9: "Subíndice fuera de rango"
resultará.
https://translate.googleusercontent.com/translate_f 59/223
6/1/2021 Intitulado
Opcional. Una clave existente ( valor de cadena ) o índice (valor numérico) para insertar el
después artículo después en la colección . Si se da un valor, el parámetro before debe ser
vacío. Los errores generados son idénticos al parámetro anterior .
Notas:
• Las claves no distinguen entre mayúsculas y minúsculas. .Añadir "Bar", "Foo" y .Añadir "Baz", "foo" dará como resultado una clave
colisión.
• Si no se proporciona ninguno de los parámetros opcionales antes o después , el elemento se agregará después del
último elemento de la colección .
• Las inserciones realizadas especificando un parámetro antes o después alterarán los índices numéricos de
miembros existentes para que coincidan con su nueva posición. Esto significa que se debe tener cuidado cuando
haciendo inserciones en bucles utilizando índices numéricos.
Uso de muestra:
Subejemplo público ()
Dim foo como nueva colección
Con foo
.Agrega uno" 'No hay llave. Este elemento solo se puede recuperar por índice.
https://riptutorial.com/ 54
Página 70
.Añadir "Dos", "Segunda" 'Clave dada. Puede recuperarse por clave o índice.
.Añadir "Tres", 1 'Insertado al inicio de la colección.
.Añadir "Cuatro",,, 1 'Insertado en el índice 2.
Terminar con
Sintaxis:
.Remove (índice)
Descripción de parámetros
Notas:
• Eliminar un elemento de una colección cambiará los índices numéricos de todos los elementos posteriores
en la colección . Para los bucles que usan índices numéricos y eliminan elementos, deben ejecutarse
hacia atrás ( Paso -1 ) para evitar excepciones de subíndices y elementos omitidos.
• Los elementos generalmente no deben eliminarse de una colección desde el interior de un bucle For Each, ya que
https://translate.googleusercontent.com/translate_f 60/223
6/1/2021 Intitulado
puede dar resultados impredecibles.
Uso de muestra:
Subejemplo público ()
Dim foo como nueva colección
Con foo
.Agrega uno"
.Añadir "Dos", "Segundo"
.Añadir "Tres"
.Añadir "Cuatro"
Terminar con
https://riptutorial.com/ 55
Página 71
Sintaxis:
.Contar()
Uso de muestra:
Subejemplo público ()
Dim foo como nueva colección
Con foo
.Agrega uno"
.Añadir "Dos"
.Añadir "Tres"
.Añadir "Cuatro"
Terminar con
Sintaxis:
.Artículo (índice)
Descripción de parámetros
https://riptutorial.com/ 56
Página 72
Notas:
• .Item es
el miembro predeterminado de Collection . Esto permite flexibilidad en la sintaxis como se demuestra en
el uso de muestra a continuación.
• Los índices numéricos están basados en 1.
• Las claves no distinguen entre mayúsculas y minúsculas. .Item ("Foo") y .Item ("foo") se refieren a la misma clave.
• El parámetro de índice no se convierte implícitamente en un número de una cadena o viceversa. Es
Es totalmente posible que .Item (1) y .Item ("1") se refieran a diferentes elementos de la Colección .
Subejemplo público ()
Dim foo como nueva colección
Con foo
.Agrega uno"
.Añadir "Dos"
.Añadir "Tres"
.Añadir "Cuatro"
Terminar con
Subejemplo público ()
Dim keys () como cadena
keys = Split ("Foo, Bar, Baz", ",")
Dim valores () como cadena
valores = Dividir ("Uno, Dos, Tres", ",")
Subejemplo público ()
Dim foo como nueva colección
Con foo
.Añadir "Uno", "Foo".
.Añadir "Dos", "Barra"
.Añadir "Tres", "Baz"
https://riptutorial.com/ 57
https://translate.googleusercontent.com/translate_f 62/223
6/1/2021 Intitulado
Página 73
Terminar con
Tenga en cuenta que la sintaxis bang ( ! ) Está permitida porque .Item es el miembro predeterminado y puede tomar un solo
Argumento de cadena . La utilidad de esta sintaxis es cuestionable.
Llaves
A diferencia de un Scripting.Dictionary , una colección no tiene un método para determinar si una clave dada
existe o una forma de recuperar claves que están presentes en la Colección . El único método para determinar si
una clave está presente es usar el controlador de errores:
Si .Number = 0 Entonces
KeyExistsInCollection = True
ElseIf .Number <> 5 Entonces
.Raise .Number
Terminara si
Terminar con
Función final
Artículos
La única forma de determinar si un elemento está contenido en una colección es iterar sobre la colección
hasta que se localice el artículo. Tenga en cuenta que debido a que una colección puede contener primitivas u objetos,
se necesita un manejo adicional para evitar errores en tiempo de ejecución durante las comparaciones:
https://riptutorial.com/ 58
Página 74
encontrado = Falso
Caso otro
encontrado = (candidato = objetivo)
Finalizar Seleccionar
Si se encuentra entonces
ItemExistsInCollection = True
Función de salida
Terminara si
próximo
https://translate.googleusercontent.com/translate_f 63/223
6/1/2021 Intitulado
Función final
La forma más sencilla de eliminar todos los elementos de una colección es simplemente reemplazarla por una nueva.
Recolección y deje que el anterior salga de alcance:
Subejemplo público ()
Dim foo como nueva colección
Con foo
.Agrega uno"
.Añadir "Dos"
.Añadir "Tres"
Terminar con
Sin embargo, si hay varias referencias a la Colección que se tiene, este método solo le dará una
Colección vacía para la variable asignada .
Subejemplo público ()
Dim foo como nueva colección
Dim bar como colección
Con foo
.Agrega uno"
.Añadir "Dos"
.Añadir "Tres"
Terminar con
En este caso, la forma más fácil de borrar el contenido es recorrer el número de elementos en el
Recolectar y eliminar repetidamente el elemento más bajo:
https://riptutorial.com/ 59
Página 75
https://translate.googleusercontent.com/translate_f 64/223
6/1/2021 Intitulado
https://riptutorial.com/ 60
Página 76
Capítulo 8: Comentarios
Observaciones
Bloques de comentarios
Si necesita comentar o descomentar varias líneas a la vez, puede usar la barra de herramientas de edición del IDE
botones:
Bloque de comentarios : agrega un solo apóstrofe al comienzo de todas las líneas seleccionadas
Bloque de eliminación de comentarios : elimina el primer apóstrofo del inicio de todas las líneas seleccionadas
Comentarios de varias líneas Muchos otros idiomas admiten comentarios de bloques de varias líneas, pero solo VBA
permite comentarios de una sola línea.
Ejemplos
https://translate.googleusercontent.com/translate_f 65/223
6/1/2021 Intitulado
Comentarios del apóstrofe
Un comentario se marca con un apóstrofo ( ' ) y se ignora cuando se ejecuta el código. Ayuda de comentarios
Explique su código a futuros lectores, incluido usted mismo.
Dado que todas las líneas que comienzan con un comentario se ignoran, también se pueden usar para evitar que el código
ejecutando (mientras depura o refactoriza). Colocar un apóstrofe ' antes de que su código lo convierta en un
comentario. (Esto se llama comentar la línea).
'Se pueden colocar antes de una línea de código, lo que evita que la línea se ejecute
'Debug.Print "Hola mundo"
'' '' Los comentarios pueden contener varios apóstrofos '' ''
https://riptutorial.com/ 61
Página 77
'La sintaxis de instrucción continua (:) se trata como parte del comentario, por lo que
'no es posible colocar una declaración ejecutable después de un comentario
'Esto no se ejecutará: Debug.Print "Hello World"
End Sub
Comentarios REM
Sub RemComments ()
Los comentarios rem comienzan con "Rem" (VBA cambiará cualquier carcasa alternativa a "Rem")
Rem es una abreviatura de Remark y similar a la sintaxis de DOS
Rem es un enfoque heredado para agregar comentarios, y se deben preferir los apóstrofos
Los comentarios rem NO PUEDEN aparecer después de una declaración, use la sintaxis de apóstrofo en su lugar
Rem A menos que estén precedidos por el token separador de instrucciones
Debug.Print "Hello World": Rem imprime un mensaje de bienvenida
Debug.Print "Hello World" 'Imprime un mensaje de bienvenida
'Rem no puede ser seguido inmediatamente por los siguientes caracteres "!, @, #, $,%, &"
Mientras que la sintaxis del apóstrofo puede ir seguida de cualquier carácter imprimible.
End Sub
https://translate.googleusercontent.com/translate_f 66/223
6/1/2021 Intitulado
https://riptutorial.com/ 62
Página 78
Las matrices de cadenas también se pueden concatenar mediante la función Unir y proporcionar una cadena (que puede
ser de longitud cero) que se utilizará entre cada elemento de la matriz.
Ejemplos
'Concatenar con Join y separar cada elemento con una cadena de 3 caracteres
concatenatedString = VBA.Strings.Join (widgetNames, ">")
'concatenatedString = "foo> bar> fizz"
'Concatenar con Join y separar cada elemento con una cadena de ancho cero
concatenatedString = VBA.Strings.Join (widgetNames, vbNullString)
'concatenatedString = "foobarfizz"
https://translate.googleusercontent.com/translate_f 67/223
6/1/2021 Intitulado
https://riptutorial.com/ 63
Página 79
La directiva #Const se usa para definir una constante de preprocesador personalizada. Estos pueden ser utilizados posteriormente por
#Si controlar qué bloques de código se compilan y ejecutan.
#Const DEBUGMODE = 1
Esto da como resultado que el valor de la ruta de archivo se establezca en "C: \ Users \ UserName \ Path \ To \ File.txt" . Eliminando
la línea #Const , o cambiarla a #Const DEBUGMODE = 0 daría como resultado que la ruta del archivo se establezca en
"\\ servidor \ recurso compartido \ ruta \ a \ archivo.txt" .
#Const alcance
La directiva #Const solo es efectiva para un solo archivo de código (módulo o clase). Debe ser declarado para
todos y cada uno de los archivos en los que desea utilizar su constante personalizada. Alternativamente, puede declarar un
#Const globalmente
para su proyecto yendo a Herramientas >> [Nombre de su proyecto] Propiedades del proyecto. Esta
Aparecerá el cuadro de diálogo de propiedades del proyecto donde ingresaremos la declaración constante. En el
En el cuadro “Argumentos de compilación condicional”, escriba [constName] = [value] . Puede ingresar más de
1 constante separándolos con dos puntos, como [constName1] = [value1]: [constName2] = [value2]
.
https://riptutorial.com/ 64
https://translate.googleusercontent.com/translate_f 68/223
6/1/2021 Intitulado
Página 80
Constantes predefinidas
Algunas constantes de compilación ya están predefinidas. Cuales existen dependerán del bitness
de la versión de Office en la que está ejecutando VBA. Tenga en cuenta que Vba7 se introdujo junto con Office 2010
para admitir versiones de 64 bits de Office.
Tenga en cuenta que Win64 / Win32 se refiere a la versión de Office, no a la versión de Windows. Por ejemplo Win32 =
VERDADERO en Office de 32 bits, incluso si el sistema operativo es una versión de Windows de 64 bits.
Página 81
https://translate.googleusercontent.com/translate_f 69/223
6/1/2021 Intitulado
Esto se puede simplificar un poco según las versiones de Office que necesite admitir. por
Por ejemplo, todavía no hay mucha gente compatible con las versiones de Office de 16 bits. La última versión de 16 bi t
office fue la versión 4.3, lanzada en 1994 , por lo que la siguiente declaración es suficiente para casi todos
casos modernos (incluido Office 2007).
Si no tiene que admitir nada anterior a Office 2010, esta declaración funciona bien.
'Solo tenemos instalaciones de 2010, por lo que ya sabemos que tenemos Vba7.
https://riptutorial.com/ 66
Página 82
Ejemplos
https://translate.googleusercontent.com/translate_f 70/223
6/1/2021 Intitulado
Utilice CStr para convertir un tipo numérico en una cadena
Const zipCode As Long = 10012
Dim zipCodeText como cadena
'Convierta el número zipCode en una cadena de caracteres de dígitos
zipCodeText = CStr (código postal)
'zipCodeText = "10012"
Utilice Formato para convertir y formatear un tipo numérico como una cadena
Utilice StrConv para convertir una matriz de bytes de caracteres de un solo byte en una cadena
'Declare una matriz de bytes, asigne códigos de caracteres de un solo byte y convierta a una cadena
Dim singleByteChars (4) Como Byte
singleByteChars (0) = 72
singleByteChars (1) = 101
singleByteChars (2) = 108
singleByteChars (3) = 108
singleByteChars (4) = 111
Dim stringFromSingleByteChars como cadena
stringFromSingleByteChars = StrConv (singleByteChars, vbUnicode)
'stringFromSingleByteChars = "Hola"
Convierta implícitamente una matriz de bytes de caracteres de varios bytes en una cadena
'Declare una matriz de bytes, asigne códigos de caracteres multibyte y convierta a una cadena
Dim multiByteChars (9) como byte
multiByteChars (0) = 87
multiByteChars (1) = 0
multiByteChars (2) = 111
multiByteChars (3) = 0
https://riptutorial.com/ 67
Página 83
https://translate.googleusercontent.com/translate_f 71/223
6/1/2021 Intitulado
https://riptutorial.com/ 68
Página 84
Copiar matrices
Puede copiar una matriz VBA en una matriz del mismo tipo utilizando el operador = . Las matrices deben ser
del mismo tipo, de lo contrario, el código arrojará un error de compilación "No se puede asignar a la matriz".
La matriz de origen puede ser fija o dinámica, pero la matriz de destino debe ser dinámica. Tratando de
copiar a una matriz fija arrojará un error de compilación "No se puede asignar a la matriz". Cualquier dato preexistente en
la matriz receptora se pierde y sus límites y dimensiones se cambian a los mismos que los de la fuente
formación.
https://translate.googleusercontent.com/translate_f 72/223
6/1/2021 Intitulado
Una vez que se realiza la copia, las dos matrices se separan en la memoria, es decir, las dos variables no se
referencias a los mismos datos subyacentes, por lo que los cambios realizados en una matriz no aparecen en la otra.
fuente (0) = 3
fuente (1) = 1
fuente (2) = 4
destino = fuente
destino (0) = 2
https://riptutorial.com/ 69
Página 85
destino = fuente
Establecer destino (0) = La referencia de rango ("A4") 'cambió en el destino pero no en la fuente
var = fuente
destino = var
var = 5
destino = var 'arroja un error de tiempo de ejecución
https://translate.googleusercontent.com/translate_f 73/223
6/1/2021 Intitulado
Una función en un módulo normal (pero no un módulo de clase) puede devolver una matriz poniendo () después de la
tipo de datos.
outputArray (0) = 3
https://riptutorial.com/ 70
Página 86
outputArray (1) = 1
outputArray (2) = 4
arrayOfPiDigits = outputArray
Función final
El resultado de la función se puede colocar en una matriz dinámica del mismo tipo o variante. los
También se puede acceder directamente a los elementos utilizando un segundo conjunto de corchetes, sin embargo, esto llamará
la función cada vez, por lo que es mejor almacenar los resultados en una nueva matriz si planea usarlos más
de una vez
Sub arrayExample ()
destino = arrayOfPiDigits ()
var = arrayOfPiDigits
End Sub
Tenga en cuenta que lo que se devuelve es en realidad una copia de la matriz dentro de la función, no una referencia. Así que si
la función devuelve el contenido de una matriz estática, sus datos no pueden ser cambiados por la llamada
procedimiento.
Sub printPiDigits ()
Dim dígitos (0 a 2) tan largos
dígitos de threePiDigits
Debug.Print dígitos (0); dígitos (1); dígitos (2) 'salidas 3 1 4
End Sub
https://riptutorial.com/ 71
https://translate.googleusercontent.com/translate_f 74/223
6/1/2021 Intitulado
Página 87
destino (0) = 3
destino (1) = 1
destino (2) = 4
End Sub
mathConsts.threePiDigits dígitos
Debug.Print dígitos (0); dígitos (1); dígitos (2) 'salidas 3 1 4
End Sub
Las matrices se pueden pasar a los procedimientos poniendo () después del nombre de la variable de matriz.
Las matrices deben pasarse por referencia. Si no se especifica ningún mecanismo de paso, por ejemplo, myFunction (arr ()) ,
entonces VBA asumirá ByRef de forma predeterminada, sin embargo, es una buena práctica de codificación hacerlo explícito.
Intentar pasar una matriz por valor, por ejemplo, myFunction (ByVal arr ()) resultará en un "argumento de matriz
debe ser un error de compilación ByRef "(o un error de compilación" Error de sintaxis "si la comprobación automática de sintaxis no está
marcado en las opciones de VBE).
Pasar por referencia significa que cualquier cambio en la matriz se conservará en la llamada
proceder.
Sub testArrayPassing ()
Fuente de atenuación (0 a 1) siempre que
fuente (0) = 3
fuente (1) = 1
https://riptutorial.com/ 72
Página 88
Función final
Si desea evitar cambiar la matriz original, tenga cuidado de escribir la función para que
no cambia ningún elemento.
https://translate.googleusercontent.com/translate_f 75/223
6/1/2021 Intitulado
Función doubleAndSum (ByRef arr () As Long)
doubleAndSum = arr (0) * 2 + arr (1) * 2
Función final
https://riptutorial.com/ 73
Página 89
GetObject requiere que esté presente al menos uno de estos dos parámetros opcionales:
https://translate.googleusercontent.com/translate_f 76/223
6/1/2021 Intitulado
1. Pathname - Variant (String): La ruta completa, incluido el nombre de archivo, del archivo que contiene el
objeto. Este parámetro es opcional, pero se requiere Class si se omite Pathname .
2. Clase - Variante (Cadena): Una cadena que representa la definición formal (Aplicación y
ObjectType) del objeto. Se requiere la clase si se omite Pathname .
1. Clase - Variante (Cadena): Una cadena que representa la definición formal (Aplicación y
ObjectType) del objeto. La clase es un parámetro obligatorio.
2. Servername - Variant (String): El nombre de la computadora remota en la que se ubicará el objeto.
creado. Si se omite, el objeto se creará en la máquina local.
1. Word.Application
2. Hoja de Excel
3. Scripting.FileSystemObject
Ejemplos
Función MSDN-GetObject
Utilice la función GetObject cuando haya una instancia actual del objeto o si lo desea
https://riptutorial.com/ 74
Página 90
para crear el objeto con un archivo ya cargado. Si no hay una instancia actual y usted
no quiere que el objeto comience con un archivo cargado, use la función CreateObject.
Sub CreateVSGet ()
Dim ThisXLApp As Excel.Application 'Un ejemplo de enlace anticipado
Dim AnotherXLApp As Object 'Un ejemplo de enlace tardío
Atenuar ThisNewWB como libro de trabajo
Atenuar otroNuevoWB como libro de trabajo
Dim wb como libro de trabajo
https://translate.googleusercontent.com/translate_f 77/223
6/1/2021 Intitulado
Para cada wb en ThisXLApp.Workbooks
Debug.Print wb.Name
próximo
'Ahora la primera instancia tiene 2 libros de trabajo: Libro1 y Libro3
'Si cierra la primera instancia de Excel,
'Book1 y Book3 se cerrarán, pero book2 seguirá abierto
End Sub
https://riptutorial.com/ 75
Página 91
Ejemplos
Un procedimiento de propiedad es una serie de instrucciones que recupera o modifica una propiedad personalizada en un
módulo.
Los descriptores de acceso a las propiedades a menudo se definen en pares, utilizando tanto Get como Let / Set para cada propiedad. UN
la propiedad con solo un procedimiento Get sería de solo lectura, mientras que una propiedad con solo un Let / Set
El procedimiento sería de solo escritura.
En el siguiente ejemplo, se definen cuatro descriptores de acceso a la propiedad para la clase DateRange :
1. StartDate (
lectura / escritura ). Valor de fecha que representa la fecha anterior en un rango. Cada procedimiento
usa el valor de la variable del módulo, mStartDate .
2. EndDate (lectura / escritura ). Valor de fecha que representa la fecha posterior en un rango. Cada procedimiento utiliza
el valor de la variable del módulo, mEndDate .
https://translate.googleusercontent.com/translate_f 78/223
6/1/2021 Intitulado
3. DaysBetween (
solo lectura ). Valor entero calculado que representa el número de días entre
las dos fechas. Debido a que solo hay un procedimiento Get , esta propiedad no se puede modificar
directamente.
4. RangeToCopy ( solo escritura ). Un procedimiento Set utilizado para copiar los valores de un DateRange existente
objeto.
Privado mStartDate como fecha 'Variable del módulo para contener la fecha de inicio
Privado mEndDate como fecha 'Variable de módulo para contener la fecha de finalización
'Establezca el valor de la fecha de inicio. Tenga en cuenta que dos métodos tienen el nombre StartDate
Propiedad pública Let StartDate (ByVal NewValue As Date)
mStartDate = NewValue
Propiedad final
https://riptutorial.com/ 76
Página 92
'Propiedad de solo lectura que devuelve el número de días entre las dos fechas
Propiedad pública Obtener DaysBetween () como entero
DaysBetween = DateDiff ("d", mStartDate, mEndDate)
Función final
'Propiedad de solo escritura que pasa una referencia de objeto de un rango para clonar
Conjunto de propiedades públicas RangeToCopy (ByRef ExistingRange como DateRange)
Me.StartDate = ExistingRange.StartDate
Me.EndDate = ExistingRange.EndDate
Propiedad final
Cualquier sub , función o propiedad pública dentro de un módulo de clase se puede llamar antes de la llamada con
una referencia de objeto:
Objeto.Procedimiento
En una clase DateRange , un Sub podría usarse para agregar un número de días a la fecha de finalización:
Una función podría devolver el último día del próximo fin de mes (tenga en cuenta que GetFirstDayOfMonth no
ser visible fuera de la clase porque es privado):
https://translate.googleusercontent.com/translate_f 79/223
6/1/2021 Intitulado
Los procedimientos pueden aceptar argumentos de cualquier tipo, incluidas referencias a objetos de la clase que se
definido.
El siguiente ejemplo prueba si el objeto DateRange actual tiene una fecha de inicio y una finalización
fecha que incluye la fecha de inicio y finalización de otro objeto DateRange .
https://riptutorial.com/ 77
Página 93
Tenga en cuenta el uso de la notación Me como una forma de acceder al valor del objeto que ejecuta el código.
De forma predeterminada, un nuevo módulo de clase es una clase privada, por lo que solo está disponible para instanciar y usar
dentro del VBProject en el que está definido. Puede declarar, instanciar y usar la clase
en cualquier lugar del mismo proyecto:
Pero a menudo escribirás clases que te gustaría usar en otros proyectos sin copiar el módulo
entre proyectos. Si define una clase llamada Lista en ProjectA y desea usar esa clase en
ProjectB , entonces deberá realizar 4 acciones:
2. Cree una función de "fábrica" pública en ProjectA que cree y devuelva una instancia de una lista
clase. Normalmente, la función de fábrica incluiría argumentos para la inicialización de la clase
ejemplo. La función de fábrica es necesaria porque ProjectB puede utilizar la clase, pero
ProjectB no puede crear directamente una instancia de la clase de ProjectA .
4. En ProjectB , declare una variable y asígnele una instancia de List usando la función de fábrica
de ProjectA
https://translate.googleusercontent.com/translate_f 80/223
6/1/2021 Intitulado
https://riptutorial.com/ 78
Página 94
https://riptutorial.com/ 79
Página 95
https://translate.googleusercontent.com/translate_f 81/223
6/1/2021 Intitulado
Ejemplos
Introducción a los procedimientos
Un Sub es un procedimiento que realiza una tarea específica pero no devuelve un valor específico.
Una función es un procedimiento que recibe datos y devuelve un valor, idealmente sin global o módulo
efectos secundarios del alcance.
Una propiedad es un procedimiento que encapsula los datos del módulo. Una propiedad puede tener hasta 3 accesos:
Obtener para devolver un valor o referencia de objeto, Dejar para asignar un valor y / o Establecer para asignar un objeto
referencia.
Las propiedades se usan generalmente en módulos de clase (aunque están permitidas en módulos estándar como
bien), exponiendo al autor de acceso a datos que de otro modo serían inaccesibles para el código de llamada. Una propiedad que
solo expone que un descriptor de acceso Get es "de solo lectura"; una propiedad que solo expondría un Let y / o Set
El descriptor de acceso es de "solo escritura". Las propiedades de solo escritura no se consideran una buena práctica de programación, si
el código del cliente puede escribir un valor, debería poder leerlo . Considere implementar un Sub
procedimiento en lugar de hacer una propiedad de solo escritura.
Devolviendo un valor
Un procedimiento de obtención de función o propiedad puede (¡y debería!) Devolver un valor a su llamador. Esto es hecho por
asignando el identificador del trámite:
https://riptutorial.com/ 80
Página 96
Como se indicó anteriormente, las funciones son procedimientos más pequeños que contienen pequeños fragmentos de código que pueden
repetitivo dentro de un procedimiento.
Similar a un procedimiento, una función puede declararse con o sin una lista de argumentos.
La función se declara como un tipo de retorno, ya que todas las funciones devuelven un valor. El nombre y el regreso
Las variables de una función son iguales.
https://translate.googleusercontent.com/translate_f 82/223
6/1/2021 Intitulado
La función se puede llamar de varias formas dentro de una función. Dado que una función declarada con un
el tipo de retorno es básicamente una variable. se usa de manera similar a una variable.
Llamadas funcionales:
call greet () 'Similar a una llamada de procedimiento solo permite que el procedimiento use el
saludo variable
string_1 = greet () 'El valor de retorno de la función se usa para la variable
'asignación
Además, la función también se puede utilizar como condiciones para if y otras declaraciones condicionales.
para i = 1 a 10
si check_even (i) entonces
msgbox i & "es par"
más
msgbox i & "es impar"
terminara si
siguiente yo
Además, más funciones pueden tener modificadores como By ref y By val para sus argumentos.
https://riptutorial.com/ 81
Página 97
Ejemplos
Lista enlazada
Este ejemplo de lista enlazada implementa Establecer operaciones de tipo de datos abstractos .
Clase SinglyLinkedNode
Opción explícita
https://translate.googleusercontent.com/translate_f 83/223
6/1/2021 Intitulado
NextNode privado como SinglyLinkedNode '"Siguiente" es una palabra clave en VBA y, por lo tanto, no es válida
nombre de la variable
Clase LinkedList
Opción explícita
https://riptutorial.com/ 82
Página 98
Más
Establezca prev.nextNode = node.nextNode
Terminara si
Salir de Sub
Terminara si
Establecer prev = nodo
Establecer nodo = nodo.nextNode
Encaminarse a
End Sub
Función final
Árbol binario
https://translate.googleusercontent.com/translate_f 84/223
6/1/2021 Intitulado
Este es un ejemplo de un desequilibrio árbol de búsqueda binaria . Un árbol binario está estructurado conceptualmente
como una jerarquía de nodos que descienden de una raíz común, donde cada nodo tiene dos
niños: izquierda y derecha. Por ejemplo, suponga que los números 7, 5, 9, 3, 11, 6, 12, 14 y 15 son
insertado en un BinaryTree. La estructura sería la siguiente. Tenga en cuenta que este árbol binario no es
equilibrado , que puede ser una característica deseable para garantizar el rendimiento de las búsquedas -
ver Árboles AVL para un ejemplo de árbol de búsqueda binaria autoequilibrado.
7
/\
59
/\\
3 6 11
\
12
\
14
\
15
https://riptutorial.com/ 83
Página 99
Clase BinaryTreeNode
Opción explícita
Clase BinaryTree
[QUE HACER]
https://translate.googleusercontent.com/translate_f 85/223
6/1/2021 Intitulado
https://riptutorial.com/ 84
Página 100
Byte
Un byte es un tipo de datos de 8 bits sin firmar. Puede representar números enteros entre 0 y 255 y
intentar almacenar un valor fuera de ese rango resultará en error de tiempo de ejecución 6: desbordamiento . Byte es el
único tipo intrínseco sin firmar disponible en VBA.
La función de conversión para convertir a un Byte es CByte (). Para las conversiones de tipos de punto flotante, el resultado es
redondeado al valor entero más cercano con .5 redondeando hacia arriba.
Las cadenas y las matrices de bytes se pueden sustituir entre sí mediante una asignación simple (no
funciones de conversión necesarias).
Por ejemplo:
Sub ByteToStringAndBack ()
End Sub
Para poder codificar Caracteres Unicode , cada carácter de la cadena ocupa dos bytes
en la matriz, con el byte menos significativo primero. Por ejemplo:
Sub UnicodeExample ()
Debug.Print byt (0), byt (1), byt (2), byt (3) 'Imprime: 35,33,46,0
https://translate.googleusercontent.com/translate_f 86/223
6/1/2021 Intitulado
https://riptutorial.com/ 85
Página 101
End Sub
Entero
Un entero es un tipo de datos de 16 bits con signo. Puede almacenar números enteros en el rango de -32,768 a
32,767 e intentar almacenar un valor fuera de ese rango resultará en un error de tiempo de ejecución 6: desbordamiento.
Los enteros se almacenan en la memoria como valores little-endian con negativos representados como undos' s
complemento .
Tenga en cuenta que, en general, es una mejor práctica utilizar un Largo en lugar de un entero a menos que el más pequeño
type es un miembro de un Type o es requerido (ya sea por una convención de llamada a la API o alguna otra
razón) para ser 2 bytes. En la mayoría de los casos, VBA trata a los enteros como de 32 bits internamente, por lo que generalmente no hay
ventaja de utilizar el tipo más pequeño. Además, existe una penalización de desempeño incurrida cada
vez que se usa un tipo Integer, ya que se convierte silenciosamente como Long.
La función de conversión para convertir a un entero es CInt () . Para moldes de tipos de punto flotante, el
el resultado se redondea al valor entero más cercano con 0,5 redondeando hacia arriba.
Booleano
Un booleano se usa para almacenar valores que se pueden representar como Verdadero o Falso. Internamente, el
El tipo de datos se almacena como un valor de 16 bits, donde 0 representa Falso y cualquier otro valor representa
Cierto.
Cabe señalar que cuando un booleano se convierte en un tipo numérico, todos los bits se establecen en 1. Este
da como resultado una representación interna de -1 para tipos firmados y el valor máximo para un sin firmar
tipo (Byte).
La función de conversión para convertir a booleano es CBool () . Aunque se representa internamente como
un número de 16 bits, la conversión a un booleano desde valores fuera de ese rango está a salvo del desbordamiento,
aunque establece los 16 bits en 1:
https://riptutorial.com/ 86
Página 102
Largo
https://translate.googleusercontent.com/translate_f 87/223
6/1/2021 Intitulado
Un Long es un tipo de datos de 32 bits con signo. Puede almacenar números enteros en el rango de -2,147,483,648 a
2,147,483,647 e intentar almacenar un valor fuera de ese rango resultará en un error de tiempo de ejecución 6:
Desbordamiento.
Los largos se almacenan en la memoria como valores little-endian con negativos representados como undos' s
complemento .
Tenga en cuenta que dado que Long coincide con el ancho de un puntero en un sistema operativo de 32 bits, Longs son
de uso común para almacenar y pasar punteros hacia y desde funciones API.
La función de conversión para convertir a Long es CLng () . Para las conversiones de tipos de punto flotante, el resultado es
redondeado al valor entero más cercano con .5 redondeando hacia arriba.
Soltero
Un Single es un tipo de datos de coma flotante de 32 bits con signo. Se almacena internamente mediante unIEEE little-endian
754 diseño de memoria. Como tal, no existe un rango fijo de valores que pueda ser representado por el
tipo de datos: lo que está limitado es la precisión del valor almacenado. Un solo puede almacenar un valor entero
valores en el rango de -16.777.216 a 16.777.216 sin pérdida de precisión. La precisión de
los números de coma flotante dependen del exponente.
Al igual que con todos los números de coma flotante, se debe tener cuidado al hacer comparaciones de igualdad. Mejor
La práctica consiste en incluir un valor delta apropiado para la precisión requerida.
Doble
Un Double es un tipo de datos de coma flotante de 64 bits con signo. Como elÚnico , se almacena internamente mediante un
diseño de memoria Little-Endian IEEE 754 y se deben tomar las mismas precauciones con respecto a la precisión.
tomado. Un Double puede almacenar valores enteros en el rango de -9,007,199,254,740,992 a
9,007,199,254,740,992 sin pérdida de precisión. La precisión de los números de coma flotante
depende del exponente.
https://riptutorial.com/ 87
Página 103
exponentes negativos, aunque la precisión utilizable será cuestionable antes de que el límite superior sea
alcanzado.
Moneda
Una moneda es un tipo de datos de coma flotante de 64 bits con signo similar a un Doble , pero escalado de 10,000 a
dar mayor precisión a los 4 dígitos a la derecha del punto decimal. Una variable de moneda puede almacenar
valores de -922,337,203,685,477.5808 a 922,337,203,685,477.5807, lo que le da el mayor
https://translate.googleusercontent.com/translate_f 88/223
6/1/2021 Intitulado
capacidad de cualquier tipo intrínseco en una aplicación de 32 bits. Como implica el nombre del tipo de datos, es
consideró la mejor práctica para utilizar este tipo de datos al representar cálculos monetarios como el
el escalado ayuda a evitar errores de redondeo.
Fecha
Un tipo de fecha se representa internamente como un tipo de datos de coma flotante de 64 bits firmado con el valor
la izquierda del punto decimal que representa el número de días desde la fecha época diciembre de 30 º ,
1899 (aunque vea la nota a continuación). El valor a la derecha del decimal representa el tiempo como un
día fraccionario. Por lo tanto, una fecha entera tendría un componente de hora de 12:00:00 AM y x.5
tener un componente de tiempo de 12:00:00 PM.
Los valores válidos para fechas son entre enero 1 st 100 y 31 de diciembre st 9999. Desde una doble tiene
un rango más grande, es posible desbordar una fecha asignando valores fuera de ese rango.
Como tal, se puede usar indistintamente con un Doble para cálculos de fecha:
La función de conversión para convertir a una fecha es CDate () , que acepta cualquier cadena de tipo numérico
representación de fecha / hora. Es importante tener en cuenta que las representaciones de cadenas de fechas
convertido en base a la configuración regional actual en uso, por lo que se deben evitar las conversiones directas si el código
está destinado a ser portátil.
Cuerda
https://riptutorial.com/ 88
Página 104
Longitud variable
Una cadena de longitud variable permite anexar y truncamiento y se almacena en la memoria como COM
BSTR . Consiste en un entero sin signo de 4 bytes que almacena la longitud de la cadena en bytes
seguido por los datos de la cadena en sí como caracteres anchos (2 bytes por carácter) y terminados con 2
bytes nulos. Por lo tanto, la longitud máxima de la cadena que puede manejar VBA es 2,147,483,647
caracteres.
Debido a que la longitud puede cambiar, VBA reasigna memoria para una Cadena cada vez que la variable es
asignados , lo que puede imponer sanciones de desempeño por procedimientos que los modifiquen repetidamente.
Longitud fija
https://translate.googleusercontent.com/translate_f 89/223
6/1/2021 Intitulado
Dim Value As String * 1024 'Declara una cadena de longitud fija de 1024 caracteres.
A las cadenas de longitud fija se les asignan 2 bytes para cada carácter y se almacenan en la memoria como un simple
matriz de bytes. Una vez asignada, la longitud de la Cadena es inmutable. Están no terminada en nulo en
memoria, por lo que una cadena que llena la memoria asignada con caracteres no nulos no es adecuada para
pasando a funciones de API esperando una cadena terminada en nulo.
Las cadenas de longitud fija tienen una limitación de índice de 16 bits heredada, por lo que solo pueden tener hasta 65.535
caracteres de longitud. Intentar asignar un valor mayor que el espacio de memoria disponible no
dará como resultado un error de tiempo de ejecución; en su lugar, el valor resultante simplemente se truncará:
Largo largo
Un LongLong es un tipo de datos firmado de 64 bits y solo está disponible en aplicaciones de 64 bits. Es no
disponible en aplicaciones de 32 bits que se ejecutan en sistemas operativos de 64 bits. Puede almacenar valores enteros en
el rango de -9,223,372,036,854,775,808 a 9,223,372,036,854,775,807 e intentar almacenar un
el valor fuera de ese rango dará como resultado un error de tiempo de ejecución 6: desbordamiento.
LongLongs se almacenan en la memoria como valores little-endian con negativos representados como undos' s
https://riptutorial.com/ 89
Página 105
complemento .
El tipo de datos LongLong se introdujo como parte del soporte del sistema operativo de 64 bits de VBA. En 64
aplicaciones de bits, este valor se puede utilizar para almacenar y pasar punteros a API de 64 bits.
La función de conversión para convertir a LongLong es CLngLng () . Para moldes de tipos de punto flotante, el
el resultado se redondea al valor entero más cercano con 0,5 redondeando hacia arriba.
Variante
Una variante es un tipo de datos COM que se utiliza para almacenar e intercambiar valores de tipos arbitrarios, y
cualquier otro tipo en VBA se puede asignar a una variante. Variables declaradas sin un tipo explícito
especificado por Como [Tipo] predeterminado en Variante.
Las variantes se almacenan en la memoria como Estructura VARIANT que consta de un descriptor de tipo de byte (
VARTYPE ) seguido de 6 bytes reservados y luego un área de datos de 8 bytes. Para tipos numéricos (incluidos
Date y booleano), el valor subyacente se almacena en la propia Variant. Para todos los demás tipos, los datos
El área contiene un puntero al valor subyacente.
El tipo subyacente de una variante se puede determinar con la función VarType () que devuelve
el valor numérico almacenado en el descriptor de tipo, o la función TypeName () que devuelve la cadena
representación:
https://translate.googleusercontent.com/translate_f 90/223
6/1/2021 Intitulado
Ejemplo = 42
Debug.Print VarType (Ejemplo) 'Imprime 2 (VT_I2)
Debug.Print TypeName (Ejemplo) 'Imprime "Entero"
Example = "Algún texto"
Debug.Print VarType (Ejemplo) 'Imprime 8 (VT_BSTR)
Debug.Print TypeName (Ejemplo) 'Imprime "Cadena"
Dado que las variantes pueden almacenar valores de cualquier tipo, las asignaciones de literales sin las sugerencias de tipo serán
conversión implícita a una variante del tipo apropiado de acuerdo con la tabla siguiente. Literales con tipo
las sugerencias se convertirán en una variante del tipo insinuado.
https://riptutorial.com/ 90
Página 106
Nota: A menos que haya una razón específica para usar una variante (es decir, un iterador en un bucle For Each o un
Requisito de API), el tipo generalmente debe evitarse para tareas de rutina por las siguientes razones:
• No son seguros para los tipos, lo que aumenta la posibilidad de errores en tiempo de ejecución. Por ejemplo, una variante
mantener un valor Integer se convertirá silenciosamente en un Long en lugar de desbordarse.
• Introducen una sobrecarga de procesamiento al requerir al menos una desreferencia de puntero adicional.
• El requisito de memoria para una variante es siempre al menos 8 bytes más alto de lo necesario para almacenar
el tipo subyacente.
LongPtr
Su uso principal es proporcionar una forma portátil de almacenar y pasar punteros en ambas arquitecturas.
(Ver Cambiar el comportamiento del código en tiempo de compilación .
Aunque el sistema operativo lo trata como una dirección de memoria cuando se usa en llamadas a la API,
Debe tenerse en cuenta que VBA lo trata como un tipo firmado (y, por lo tanto, sujeto a unsigned to firmado
Desbordamiento). Por esta razón, cualquier aritmética de puntero realizada con LongPtrs no debe usar > o <
comparaciones. Esta "peculiaridad" también hace posible que la adición de compensaciones simples que apunten a
direcciones en la memoria pueden causar errores de desbordamiento, por lo que se debe tener cuidado al trabajar con
punteros en VBA.
La función de conversión para convertir a LongPtr es CLngPtr () . Para moldes de tipos de punto flotante, el
El resultado se redondea al valor entero más cercano con .5 redondeando hacia arriba (aunque como suele ser un
dirección de memoria, usarlo como destino de asignación para un cálculo de punto flotante es peligroso en
mejor).
Decimal
https://translate.googleusercontent.com/translate_f 91/223
6/1/2021 Intitulado
Valor de atenuación como variante
Valor = CDec (1.234)
El tipo de datos Decimal solo está disponible como un subtipo de Variant , por lo que debe declarar cualquier variable
que debe contener un decimal como variante y luego asignar un valor decimal usando el CDec
función. La palabra clave Decimal es una palabra reservada (lo que sugiere que VBA finalmente se
https://riptutorial.com/ 91
Página 107
para agregar soporte de primera clase para el tipo), por lo que Decimal no se puede usar como una variable o procedimiento
nombre.
El tipo decimal requiere 14 bytes de memoria (además de los bytes requeridos por el padre
Variant) y puede almacenar números con hasta 28 decimales. Para números sin decimal
lugares, el rango de valores permitidos es -79,228,162,514,264,337,593,543,950,335 a
+79,228,162,514,264,337,593,543,950,335 inclusive. Para números con un máximo de 28 decimal
lugares, el rango de valores permitidos es -7,9228162514264337593543950335 a
+7.9228162514264337593543950335 inclusive.
https://translate.googleusercontent.com/translate_f 92/223
6/1/2021 Intitulado
https://riptutorial.com/ 92
Página 108
Calendario
Ejemplo
Sub CalendarExample ()
'Almacene en caché la configuración actual.
Dim en caché como entero
Cached = Calendario
Calendario actual: 0
SampleDate = 2016-07-28
Calendario actual: 1
SampleDate = 1437-10-23
https://riptutorial.com/ 93
Página 109
Funciones base
https://translate.googleusercontent.com/translate_f 93/223
6/1/2021 Intitulado
Sub DateTimeExample ()
'------------------------------------------------- ----
'Nota: sistema de la UE con formato de fecha predeterminado DD / MM / AAAA
'------------------------------------------------- ----
Debug.Print Now 'imprime 28/07/2016 10:16:01 (el resultado a continuación asume esta fecha y hora)
Debug.Print Date 'imprime 28/07/2016
Debug.Print Time 'imprime 10:16:01
End Sub
Función de temporizador
La función Timer devuelve un Single que representa el número de segundos transcurridos desde la medianoche.
La precisión es una centésima de segundo.
Sub TimerExample ()
End Sub
Debido a que las funciones Ahora y Hora solo son precisas en segundos, el temporizador ofrece una manera conveniente de
aumentar la precisión de la medición del tiempo:
Sub GetBenchmark ()
https://riptutorial.com/ 94
Página 110
End Sub
https://translate.googleusercontent.com/translate_f 94/223
6/1/2021 Intitulado
IsDate ()
IsDate () prueba si una expresión es una fecha válida o no. Devuelve un booleano .
Sub IsDateExamples ()
End Sub
Funciones de extracción
Estas funciones toman una variante que se puede convertir a una fecha como parámetro y devuelven un entero
que representa una parte de una fecha u hora. Si el parámetro no se puede convertir a una fecha , resultará en una
Error 13 en tiempo de ejecución: no coinciden los tipos.
Devuelto
Función Descripción
valor
Entero (100 a
Año() Devuelve la parte del año del argumento de fecha.
9999)
https://riptutorial.com/ 95
Página 111
Devuelto
Función Descripción
valor
12)
Entero (1 a
Día() Devuelve la parte del día del argumento de fecha.
31)
Entero (0 a
Hora() Devuelve la parte de la hora del argumento de fecha.
23)
Entero (0 a
Minuto() Devuelve la parte de los minutos del argumento de fecha.
59)
Entero (0 a
Segundo() Devuelve la segunda parte del argumento de fecha.
59)
Ejemplos:
https://translate.googleusercontent.com/translate_f 95/223
6/1/2021 Intitulado
Debug.Print Format $ (MyDate, "aaaa-mm-dd hh: nn: ss") 'imprime 2016-07-28 12:34:56
End Sub
Función DatePart ()
DatePart () también
es una función que devuelve una parte de una fecha, pero funciona de manera diferente y permite más
posibilidades que las funciones anteriores. Por ejemplo, puede devolver el trimestre del año o el
Semana del año.
Sintaxis:
https://riptutorial.com/ 96
Página 112
DatePart (intervalo, fecha [, primer día de la semana] [, primera semana del año])
"q" Cuarto (1 a 4)
firstdayofweek es opcional. es una constante que especifica el primer día de la semana. Si no se especifica,
Se asume vbSunday .
firstweekofyear es opcional. es una constante que especifica la primera semana del año. Si no se especifica,
https://translate.googleusercontent.com/translate_f 96/223
6/1/2021 Intitulado
se supone que la primera semana es la semana en la que ocurre el 1 de enero.
Ejemplos:
Sub DatePartExample ()
Debug.Print Format $ (MyDate, "aaaa-mm-dd hh: nn: ss") 'imprime 2016-07-28 12:34:56
End Sub
Funciones de cálculo
https://riptutorial.com/ 97
Página 113
DateDiff ()
DateDiff () devuelve un Long que representa el número de intervalos de tiempo entre dos fechas especificadas.
Sintaxis
DateDiff (intervalo, fecha1, fecha2 [, primer día de la semana] [, primera semana del año])
Ejemplos
Sub DateDiffExamples ()
End Sub
DateAdd ()
DateAdd () devuelve una fecha a la que se ha agregado una fecha o intervalo de tiempo específico.
Sintaxis
https://translate.googleusercontent.com/translate_f 97/223
6/1/2021 Intitulado
Ejemplos:
Sub DateAddExamples ()
https://riptutorial.com/ 98
Página 114
End Sub
Conversión y creación
CDate ()
CDate () convierte algo de cualquier tipo de datos a un tipo de datos de fecha
Sub CDateExamples ()
'Convierte una cadena que representa una fecha y hora en una fecha
sample = CDate ("11 de septiembre de 2001 12:34")
Debug.Print Format $ (sample, "aaaa-mm-dd hh: nn: ss") 'imprime 2001-09-11 12:34:00
End Sub
Tenga en cuenta que VBA también tiene un CVDate () escrito libremente que funciona de la misma manera que CDate ()
función que no sea devolver una Variante de fecha escrita en lugar de una Fecha fuertemente escrita . El CDate ()
la versión debe ser preferida cuando se pasa a un parámetro de fecha o se asigna a una variable de fecha , y
la versión CVDate () debe ser preferida cuando se pasa a un parámetro Variant o se asigna
https://translate.googleusercontent.com/translate_f 98/223
6/1/2021 Intitulado
a una variable Variant . Esto evita la conversión de tipos implícita.
https://riptutorial.com/ 99
Página 115
DateSerial ()
La función DateSerial () se utiliza para crear una fecha. Devuelve una fecha para un año, mes y
día.
Sintaxis:
Con argumentos de año, mes y día válidos. Enteros (año de 100 a 9999, mes de 1 a
12, Día del 1 al 31).
Ejemplos
Sub DateSerialExamples ()
End Sub
Tenga en cuenta que DateSerial () aceptará fechas "no válidas" y calculará una fecha válida a partir de ellas. Esto puede ser
utilizado creativamente para siempre:
Ejemplo positivo
Sub GoodDateSerialExample ()
End Sub
Sin embargo, es más probable que cause molestias al intentar crear una fecha de un usuario no validado.
entrada:
Ejemplo negativo
Sub BadDateSerialExample ()
https://riptutorial.com/ 100
Página 116
https://translate.googleusercontent.com/translate_f 99/223
6/1/2021 Intitulado
Atenuar mi año tan largo
myYear = InputBox ("Ingresar año")
'Suponga que el usuario ingresa a 2009
Dim myMonth tan largo
myMonth = InputBox ("Ingresar mes")
'Suponga que el usuario ingresa 2
Dim myDay As Long
myDay = InputBox ("Ingresar día")
'Suponga que el usuario ingresa 31
Debug.Print Format $ (DateSerial (myYear, myMonth, myDay), "aaaa-mm-dd")
'impresiones 2009-03-03
End Sub
https://riptutorial.com/ 101
Página 117
https://translate.googleusercontent.com/translate_f 100/223
6/1/2021 Intitulado
Ejemplos
https://riptutorial.com/ 102
Página 118
VBA ofrece una función Mid para devolver subcadenas dentro de una cadena, pero también ofrece Mid
Declaración que se puede utilizar para asignar subcadenas o caracteres individuales dentro de una cadena.
'Salida:
'Smyth
https://translate.googleusercontent.com/translate_f 101/223
6/1/2021 Intitulado
Nota: Si necesita asignar bytes individuales en una cadena en lugar de caracteres individuales dentro de una
cadena (consulte las observaciones a continuación sobre el conjunto de caracteres de varios bytes), la declaración MidB se puede
usado. En este caso, el segundo argumento para la declaración MidB es la posición basada en 1 del
byte donde comenzará el reemplazo, por lo que la línea equivalente al ejemplo anterior sería
MidB (apellido, 5, 2) = "y" .
Las cadenas se pueden asignar directamente a matrices de bytes y viceversa. Recuerda que las cadenas se almacenan
en un conjunto de caracteres de varios bytes (consulte las observaciones a continuación), por lo que solo cada otro índice de la matriz resultante
será la parte del carácter que se encuentre dentro del rango ASCII.
ejemplo = "Prueba".
bytes = ejemplo 'Asignación directa.
https://riptutorial.com/ 103
Página 119
Si un módulo de código no contiene Option Explicit en la parte superior del módulo, el compilador
automáticamente (es decir, "implícitamente") crea variables para usted cuando las usa. Ellos predeterminarán
tipo de variable Variant .
someVariable = 10 '
someOtherVariable = "Hola mundo"
'Ambas variables son del tipo Variant.
End Sub
Opción explícita
https://translate.googleusercontent.com/translate_f 102/223
6/1/2021 Intitulado
someOtherVariable = "Hola mundo"
End Sub
Se considera una buena práctica utilizar Option Explicit en los módulos de código, para asegurarse de declarar todos
variables.
Ver VBA Best Practices cómo configurar esta opción de forma predeterminada.
Variables
Alcance
Se puede declarar una variable (en aumento del nivel de visibilidad):
• A nivel de procedimiento, usar la palabra clave Dim en cualquier procedimiento; una variable local .
• A nivel de módulo, utilizando la palabra clave Private en cualquier tipo de módulo; un campo privado .
• A nivel de instancia, usando la palabra clave Friend en cualquier tipo de módulo de clase; un campo amigo .
• A nivel de instancia, usando la palabra clave Public en cualquier tipo de módulo de clase; un campo público .
• Globalmente, usando la palabra clave Public en un módulo estándar ; una variable global .
https://riptutorial.com/ 104
Página 120
Las variables siempre deben declararse con el menor alcance posible: prefiera pasar parámetros
a los procedimientos, en lugar de declarar variables globales.
Variables locales
La parte [As Type] de la sintaxis de declaración es opcional. Cuando se especifica, establece los datos de la variable
type, que determina cuánta memoria se asignará a esa variable. Esto declara una cadena
variable:
La sintaxis de VBA también admite la declaración de múltiples variables en una sola declaración:
Tenga en cuenta que se debe especificar [Como tipo] para cada variable (excepto las de 'Variante'). Esto es un
trampa relativamente común:
Variables estáticas
Las variables locales también pueden ser estáticas . En VBA, la palabra clave estática se usa para hacer una variable
"recordar" el valor que tenía la última vez que se llamó a un procedimiento:
https://translate.googleusercontent.com/translate_f 103/223
6/1/2021 Intitulado
Aquí la colección de valores se declara como local estático ; porque es una variable de objeto , es
inicializado en Nothing . La condición que sigue a la declaración verifica si la referencia del objeto fue
https://riptutorial.com/ 105
Página 121
Establecer antes:
si es la primera vez que se ejecuta el procedimiento, la colección se inicializa. Hacer algo más
podría estar agregando o quitando elementos, y todavía estarán en la colección la próxima vez que DoSomething sea
llamado.
Alternativa
La palabra clave estática de VBA puede malinterpretarse fácilmente, especialmente por expertos
programadores que suelen trabajar en otros lenguajes. En muchos idiomas, se usa estática
hacer que un miembro de la clase (campo, propiedad, método, ...) pertenezca al tipo en lugar de
la instancia . El código en contexto estático no puede hacer referencia al código en contexto de instancia . los
La palabra clave estática de VBA significa algo tremendamente diferente.
A menudo, un local estático también podría implementarse como una variable privada de nivel de módulo (campo):
Sin embargo, esto desafía el principio por el cual una variable debe declararse con el mínimo
posible alcance; confíe en sus instintos, use el que prefiera, ambos funcionarán ... pero usando Static
sin entender lo que hace, podría dar lugar a errores interesantes.
La palabra clave Dim es legal a nivel de módulo y procedimiento; su uso a nivel de módulo es equivalente a
usando la palabra clave privada :
Opción explícita
Dim privateField1 As Long 'igual que Private privateField2 as Long
Private privateField2 As Long 'igual que Dim privateField2 as Long
La palabra clave Privada solo es legal a nivel de módulo; esto invita a reservar Dim para variables locales y
declarar variables de módulo con Private , especialmente con la palabra clave Public contrastante que
debe utilizarse de todos modos para declarar un miembro público. Alternativamente, use Dim en todas partes : ¿qué
lo que importa es la coherencia :
"Campos privados"
Campos
https://translate.googleusercontent.com/translate_f 104/223
6/1/2021 Intitulado
Una variable declarada a nivel de módulo, en la sección de declaraciones en la parte superior del cuerpo del módulo, es una
https://riptutorial.com/ 106
Página 122
Se puede acceder a una variable con un alcance global desde cualquier lugar, incluidos otros proyectos de VBA que
haría referencia al proyecto en el que está declarado.
Para hacer que una variable sea global / pública, pero solo visible desde dentro del proyecto, use el modificador Friend :
Esto es especialmente útil en complementos, donde la intención es que otros proyectos de VBA hagan referencia al complemento.
proyecto y puede consumir la API pública.
FriendField As Long 'público dentro del proyecto, también conocido como código de "amigo"
Public PublicField As Long 'público dentro y fuera del proyecto
Campos de instancia
Una variable declarada a nivel de módulo, en la sección de declaraciones en la parte superior del cuerpo de una clase
módulo (incluyendo ThisWorkbook , ThisDocument , Worksheet , UserForm y módulos de clase ), es un
campo de instancia : solo existe mientras haya una instancia de la clase alrededor.
'> Clase1
Opción explícita
Public PublicField siempre que
'> Módulo1
Opción explícita
Sub público DoSomething ()
'Class1.PublicField no significa nada aquí
Con New Class1
.PublicField = 42
Terminar con
'Class1.PublicField no significa nada aquí
End Sub
Encapsular campos
Los datos de instancia a menudo se mantienen privados y se denominan encapsulados . Un campo privado puede quedar expuesto
utilizando un procedimiento de propiedad . Para exponer una variable privada públicamente sin dar acceso de escritura a la
llamador, un módulo de clase (o un módulo estándar) implementa un miembro Property Get :
Opción explícita
Privado encapsulado siempre que
https://riptutorial.com/ 107
Página 123
https://translate.googleusercontent.com/translate_f 105/223
6/1/2021 Intitulado
Propiedad pública Get SomeValue () mientras
SomeValue = encapsulado
Propiedad final
La clase en sí puede modificar el valor encapsulado, pero el código de llamada solo puede acceder al Public
miembros (y miembros amigos , si la persona que llama está en el mismo proyecto).
Constantes (Const)
Si tiene un valor que nunca cambia en su aplicación, puede definir una constante con nombre y
utilícelo en lugar de un valor literal.
Puede usar Const solo a nivel de módulo o procedimiento. Esto significa el contexto de declaración para un
la variable debe ser una clase, estructura, módulo, procedimiento o bloque, y no puede ser un archivo fuente,
espacio de nombres o interfaz.
End Sub
Si bien se puede considerar una buena práctica especificar tipos de constantes, no es estrictamente necesario. No
especificar el tipo aún resultará en el tipo correcto:
Public Const GLOBAL_CONSTANT = "Versión del proyecto # 1.000.000.001" 'Sigue siendo una cadena
Declaración de subejemplo público ()
End Sub
Tenga en cuenta que esto es específico de las constantes y en contraste con las variables donde no se especifica el tipo
https://riptutorial.com/ 108
Página 124
Si bien es posible declarar explícitamente una constante como una cadena, no es posible declarar una
constante como una cadena usando sintaxis de cadena de ancho fijo
https://translate.googleusercontent.com/translate_f 106/223
6/1/2021 Intitulado
Modificadores de acceso
La instrucción Dim debe reservarse para variables locales. A nivel de módulo, prefiera el acceso explícito
modificadores:
• Privado para campos privados, a los que solo se puede acceder dentro del módulo en el que están declarados.
• Público para campos públicos y variables globales, a las que se puede acceder mediante cualquier código de llamada.
• Amigo delas variables públicas dentro del proyecto, pero inaccesible a otros VBA de referencia
proyectos (relevante para complementos)
• Global tambiénse puede usar para campos públicos en módulos estándar, pero es ilegal en módulos de clase
y es obsoleto de todos modos - prefiera el modificador Público en su lugar. Este modificador no es legal para
procedimientos tampoco.
End Sub
GlobalVariable = "Esto se puede hacer desde cualquier módulo dentro de este proyecto"
End Sub
Por el contrario, los procedimientos de función pública en módulos estándar se exponen como definidos por el usuario
funciones (UDF) en la aplicación host.
Especificar Option Private Module en la parte superior de un módulo estándar evita que sus miembros sean
https://riptutorial.com/ 109
Página 125
Sugerencias de tipo
Las sugerencias de tipo están muy desaconsejadas. Existen y están documentados aquí para fines históricos y
razones de compatibilidad con versiones anteriores. En su lugar, debería utilizar la sintaxis As [DataType] .
Las sugerencias de tipo disminuyen significativamente la legibilidad del código y fomentan un legado Notación húngara
https://translate.googleusercontent.com/translate_f 107/223
6/1/2021 Intitulado
que también dificulta la legibilidad:
Dim strFile $
Dim iFile%
En su lugar, declare las variables más cercanas a su uso y nombre las cosas por lo que se usan, no después
su tipo:
Las sugerencias de tipo también se pueden usar en literales para imponer un tipo específico. Por defecto, un literal numérico
menor que 32,768 se interpretará como un literal entero , pero con una sugerencia de tipo que puede controlar
ese:
Las sugerencias de tipo generalmente no son necesarias en literales, porque se asignarían a una variable
declarado con un tipo explícito, o convertido implícitamente al tipo apropiado cuando se pasa como
parámetros. Las conversiones implícitas se pueden evitar utilizando una de las conversiones de tipo explícitas
funciones:
'Llama al procedimiento DoSomething y pasa un literal 42 como Long usando una sugerencia de tipo
Hacer algo 42 y
https://riptutorial.com/ 110
Página 126
https://translate.googleusercontent.com/translate_f 108/223
6/1/2021 Intitulado
• VBA.Strings.LCase -> VBA.Strings.LCase $
• VBA.Strings.Left -> VBA.Strings.Left $
• VBA.Strings.LeftB -> VBA.Strings.LeftB $
• VBA.Strings.LTtrim -> VBA.Strings.LTrim $
• VBA.Strings.Mid -> VBA.Strings.Mid $
• VBA.Strings.MidB -> VBA.Strings.MidB $
• VBA.Strings.Right -> VBA.Strings.Right $
• VBA.Strings.RightB -> VBA.Strings.RightB $
• VBA.Strings.RTrim -> VBA.Strings.RTrim $
• VBA.Strings.Space -> VBA.Strings.Space $
• VBA.Strings.Str -> VBA.Strings.Str $
• VBA.Strings.String -> VBA.Strings.String $
• VBA.Strings.Trim -> VBA.Strings.Trim $
• VBA.Strings.UCase -> VBA.Strings.UCase $
Tenga en cuenta que estos son alias de funciones , no sugerencias de tipo . La función Izquierda corresponde a la
función oculta B_Var_Left , mientras que la versión Left $ corresponde a la función oculta B_Str_Left .
En versiones muy tempranas de VBA, el signo $ no es un carácter permitido y el nombre de la función tenía que ser
entre corchetes. En Word Basic, hubo muchas, muchas más funciones que devolvieron
cadenas que terminan en $.
https://riptutorial.com/ 111
Página 127
En VBA, las cadenas se pueden declarar con una longitud específica; se rellenan o truncan automáticamente
para mantener esa longitud declarada.
End Sub
Una variable estática declarada localmente no se destruye y no pierde su valor cuando el Sub
se sale del procedimiento. Las llamadas posteriores al procedimiento no requieren reinicialización o
asignación aunque es posible que desee "poner a cero" los valores recordados.
Estos son particularmente útiles cuando se vincula tarde un objeto en un sub 'auxiliar' que se llama repetidamente.
Opción explícita
Sub principal()
Dim w tan largo
https://translate.googleusercontent.com/translate_f 109/223
6/1/2021 Intitulado
Subproceso Diccionario (ws como hoja de trabajo)
Dim i tan largo, rng como rango
Dictado estático como objeto
https://riptutorial.com/ 112
Página 128
Con ws
Terminar con
End Sub
Fragmento 2: cree una UDF de hoja de trabajo que enlace tarde el objeto VBScript.RegExp
Opción explícita
Con rgx
.Global = Verdadero
.MultiLine = Verdadero
.Patrón = "[0-9] {1,999}"
Si .Test (str) Entonces
Establecer cmat = .Execute (str)
'cambiar el tamaño de la matriz nums para aceptar las coincidencias
ReDim nums (recuento cmat - 1)
'rellenar la matriz nums con las coincidencias
Para n = LBound (nums) a UBound (nums)
nums (n) = cmat.Item (n)
Siguiente n
'convierte la matriz nums en una cadena delimitada
numbersOnly = Unir (nums, delim)
Más
numerosOnly = vbNullString
Terminara si
Terminar con
Función final
https://translate.googleusercontent.com/translate_f 110/223
6/1/2021 Intitulado
https://riptutorial.com/ 113
Página 129
Ejemplo de UDF con objeto estático llenado a través de medio millón de filas
Recuerde que una UDF no se calcula una sola vez en la vida útil de un libro. Incluso un no volátil
UDF volverá a calcular siempre que los valores dentro del rango (s) a los que hace referencia estén sujetos a cambios.
Cada evento de recálculo posterior solo aumenta los beneficios de una variable declarada estáticamente.
• Una variable estática está disponible durante la vida útil del módulo, no el procedimiento o la función en
que fue declarado y asignado.
• Las variables estáticas solo se pueden declarar localmente.
• La variable estática tiene muchas de las mismas propiedades de una variable de nivel de módulo privado pero con una
alcance más restringido.
https://riptutorial.com/ 114
Página 130
https://translate.googleusercontent.com/translate_f 111/223
6/1/2021 Intitulado
Cuando ocurre un error en tiempo de ejecución, un buen código debería manejarlo. La mejor estrategia de manejo de errores es
escribir código que compruebe condiciones de error y simplemente evite ejecutar código que resulte en una
Error de tiempo de ejecución.
Un elemento clave para reducir los errores en tiempo de ejecución es escribir pequeños procedimientos que hagan una sola cosa . los
Menos razones por las que los procedimientos tienen que fallar, más fácil es depurar el código en su conjunto.
Este error se generará cuando se utilice un objeto antes de que se asigne su referencia. Uno podría tener un
procedimiento que recibe un parámetro de objeto:
Si al objetivo no se le asigna una referencia, el código anterior generará un error que se puede evitar fácilmente mediante
comprobar si el objeto contiene una referencia de objeto real:
Si el destino no tiene asignada una referencia, la referencia no asignada nunca se usa y no hay error
ocurre.
Esta forma de salir anticipadamente de un procedimiento cuando uno o más parámetros no son válidos, se denomina guardia
cláusula .
Este error se genera cuando se accede a una matriz fuera de sus límites.
Dado un índice mayor que el número de hojas de trabajo en ActiveWorkbook , el código anterior
generar un error de tiempo de ejecución. Una simple cláusula de protección puede evitar que:
https://riptutorial.com/ 115
Página 131
La mayoría de los errores en tiempo de ejecución se pueden evitar verificando cuidadosamente los valores que estamos usando antes de usar
ellos, y ramificarse en otra ruta de ejecución en consecuencia utilizando una declaración If simple - en guardia
cláusulas que no hacen suposiciones y validan los parámetros de un procedimiento, o incluso en el cuerpo
https://translate.googleusercontent.com/translate_f 112/223
6/1/2021 Intitulado
de procedimientos más grandes.
En declaración de error
Incluso con las cláusulas de protección , uno no siempre puede tener en cuenta de manera realista todas las posibles condiciones de error.
que podría plantearse en el cuerpo de un procedimiento. La instrucción On Error GoTo indica a VBA que salte
a una etiqueta de línea e ingrese al "modo de manejo de errores" siempre que ocurra un error inesperado en tiempo de ejecución.
Después de manejar un error, el código puede reanudar su ejecución "normal" usando la palabra clave Resume .
Las etiquetas de línea denotan subrutinas : porque las subrutinas se originan a partir del código BASIC heredado y utiliza
GoTo y GoSub saltos
y declaraciones de retorno para volver a la rutina "principal", es bastante fácil
escriba un código espagueti difícil de seguir si las cosas no están estructuradas rigurosamente. Por eso es mejor
ese:
Esto significa que un procedimiento que maneja sus errores debe estructurarse así:
Limpiar Salida:
'código de limpieza aquí
Salir de Sub
CleanFail:
'código de manejo de errores aquí
Reanudar Limpiar Salir
End Sub
Limpiar Salida:
https://riptutorial.com/ 116
Página 132
Salir de Sub
CleanFail:
Seleccione Número de error de caso
Caso 9
MsgBox "El número especificado no existe. Vuelva a intentarlo", vbExclamation
Currículum
Caso 91
'woah, esto no debería estar pasando.
Detener la ejecución se romperá aquí
Reanudar 'presione F8 para saltar a la línea que generó el error
Caso otro
MsgBox "Se ha producido un error inesperado:" & vbNewLine & Err.Description,
vbCritical
Reanudar Limpiar Salir
Finalizar Seleccionar
End Sub
Como pauta general, considere activar el manejo de errores para toda la subrutina o función, y
manejar todos los errores que puedan ocurrir dentro de su alcance. Si solo necesita manejar errores en los pequeños
sección sección del código: active y desactive el manejo de errores en el mismo nivel:
https://translate.googleusercontent.com/translate_f 113/223
6/1/2021 Intitulado
Si CheckValue = 0 entonces
On Error GoTo ErrorHandler 'activa el manejo de errores
'código que puede resultar en error
En caso de error, vaya a 0 'desactivar el manejo de errores - mismo nivel
Terminara si
Limpiar Salida:
Salir de Sub
ErrorHandler:
'código de manejo de errores aquí
'no desactive el manejo de errores aquí
Currículum
End Sub
Línea de números
VBA admite números de línea de estilo heredado (por ejemplo, QBASIC). La propiedad oculta Erl se puede utilizar para
identifique el número de línea que generó el último error. Si no está utilizando números de línea, Erl solo
devuelve 0.
Sub DoSomething ()
10 En caso de error, vaya a 50
20 Debug.Print 42/0
30 Salir Sub
40
50 Debug.Print "Error generado en línea" & Erl 'devuelve 20
End Sub
https://riptutorial.com/ 117
Página 133
Si está utilizando números de línea, pero no de manera consistente, Erl devolverá el último número de línea antes
la instrucción que provocó el error .
Sub DoSomething ()
10 En caso de error, vaya a 50
Debug.Print 42/0
30 Salir Sub
Tenga en cuenta que Erl también solo tiene precisión Integer y se desbordará silenciosamente. Esto significa que
números de línea fuera del el rango entero dará resultados incorrectos:
Sub DoSomething ()
99997 En caso de error, vaya a 99999
99998 Debug.Print 42/0
99999
Debug.Print Erl 'Prints 34462
End Sub
El número de línea no es tan relevante como la declaración que causó el error y la numeración
Las líneas rápidamente se vuelven tediosas y no son fáciles de mantener.
https://translate.googleusercontent.com/translate_f 114/223
6/1/2021 Intitulado
• ejecutar hasta el final del procedimiento, en cuyo caso la ejecución se reanuda en el procedimiento de llamada.
• o utilice la palabra clave Resume para reanudar la ejecución dentro del mismo procedimiento.
La palabra clave Resume solo debe usarse dentro de una subrutina de manejo de errores, porque si VBA
encuentra Reanudar sin estar en un estado de error, el error de tiempo de ejecución 20 "Reanudar sin error" es
elevado.
Hay varias formas en que una subrutina de manejo de errores puede usar la palabra clave Resume :
https://riptutorial.com/ 118
Página 134
El énfasis anterior no se puede enfatizar lo suficiente. En caso de error, reanudar siguiente ignora efectivamente
todos los errores y los mete debajo de la alfombra . Un programa que explota con un error de ejecución
una entrada no válida dada es un mejor programa que uno que sigue ejecutándose con datos desconocidos / no deseados
- ya sea porque el error es mucho más fácil de identificar. En caso de error, reanudar siguiente se puede ocultar fácilmente
bichos .
La instrucción On Error tiene un alcance de procedimiento, por eso normalmente debería haber solo una , una
tal declaración On Error en un procedimiento dado.
Sin embargo, a veces una condición de error no se puede evitar del todo y saltar a un manejo de errores
subrutina solo para Reanudar Siguiente simplemente no se siente bien. En este caso específico, el conocido o posiblemente
La declaración de error se puede envolver entre dos declaraciones de error :
La instrucción On Error GoTo 0 restablece el manejo de errores en el procedimiento actual, de modo que cualquier
instrucciones adicionales que causen un error en tiempo de ejecución no se manejarían dentro de ese procedimiento y, en su lugar,
pasa la pila de llamadas hasta que es detectada por un controlador de errores activo. Si no hay error activo
handler en la pila de llamadas, se tratará como una excepción no controlada.
https://translate.googleusercontent.com/translate_f 115/223
6/1/2021 Intitulado
Llamado
Salir de Sub
Manipulador:
Debug.Print "Error" & Err.Number & "in Caller".
End Sub
Salir de Sub
Manipulador:
https://riptutorial.com/ 119
Página 135
Errores personalizados
A menudo, al escribir una clase especializada, querrá que genere sus propios errores específicos y querrá
una forma limpia para que el usuario / código de llamada maneje estos errores personalizados. Una buena forma de lograrlo es
definir un tipo de Enum dedicado :
Opción explícita
Public Enum FoobarError
Err_FooWasNotBarred = vbObjectError + 1024
Err_BarNotInitialized
Err_SomethingElseHappened
End Enum
El uso de la constante incorporada vbObjectError garantiza que los códigos de error personalizados no se superpongan con
códigos de error reservados / existentes. Solo el primer valor de enumeración debe especificarse explícitamente, para el
El valor subyacente de cada miembro Enum es 1 mayor que el miembro anterior, por lo que el
El valor de Err_BarNotInitialized es implícitamente vbObjectError + 1025 .
Err.Raise Err_FooWasNotBarred
El método Err.Raise también puede tomar parámetros personalizados de Descripción y Fuente , por esta razón es
Es una buena idea definir también constantes para contener la descripción de cada error personalizado:
https://translate.googleusercontent.com/translate_f 116/223
6/1/2021 Intitulado
La implementación de la clase puede simplemente llamar a estos procedimientos especializados para generar el error:
https://riptutorial.com/ 120
Página 136
El código del cliente puede manejar Err_BarNotInitialized como lo haría con cualquier otro error, dentro de su propio
subrutina de manejo de errores.
Nota: la palabra clave heredada Error también se puede utilizar en lugar de Err.Raise , pero es
obsoleto / desaprobado.
https://riptutorial.com/ 121
Página 137
https://translate.googleusercontent.com/translate_f 117/223
6/1/2021 Intitulado
Observaciones
• Un evento solo puede ser público . El modificador es opcional porque los miembros del módulo de clase
(incluidos los eventos) son implícitamente públicos de forma predeterminada.
• Una variable WithEvents puede ser Privada o Pública , pero no Amiga . El modificador es obligatorio
porque WithEvents no es una palabra clave que declara una variable, sino una palabra clave modificadora que forma parte de
la sintaxis de declaración de variable. Por lo tanto, la palabra clave Dim debe usarse si un modificador de acceso
no está presente.
Ejemplos
Fuentes y controladores
Las API a menudo exponen objetos que generan una serie de eventos en respuesta a varios estados. por
ejemplo, un objeto Excel.Application genera un evento cada vez que se crea un nuevo libro,
abierto, activado o cerrado. O cada vez que se calcula una hoja de trabajo. O justo antes de que un archivo sea
salvado. O inmediatamente después. Un botón en un formulario genera un evento Click cuando el usuario hace clic en él,
el formulario de usuario genera un evento justo después de que se activa, y otro justo antes de que se cierre.
Desde la perspectiva de la API, los eventos son puntos de extensión : el código del cliente puede elegir implementar
código que maneja estos eventos y ejecuta código personalizado cada vez que se disparan estos eventos: eso es
cómo puede ejecutar su código personalizado automáticamente cada vez que la selección cambia en cualquier
hoja de trabajo: manejando el evento que se activa cuando la selección cambia en cualquier hoja de trabajo.
Un objeto que expone eventos es una fuente de eventos . Un método que maneja un evento es un controlador .
Manipuladores
https://riptutorial.com/ 122
Página 138
Los módulos de documentos de VBA (por ejemplo , ThisDocument , ThisWorkbook , Sheet1 , etc.) y los módulos de UserForm son
módulos de clase que implementan interfaces especiales que exponen una serie de eventos . Puedes navegar
estas interfaces en el menú desplegable del lado izquierdo en la parte superior del panel de código:
https://translate.googleusercontent.com/translate_f 118/223
6/1/2021 Intitulado
El menú desplegable del lado derecho enumera los miembros de la interfaz seleccionados en el menú desplegable del lado izquierdo:
El VBE genera automáticamente un código auxiliar del controlador de eventos cuando se selecciona un elemento en el lado derecho
list, o navega allí si el controlador existe.
Cada declaración WithEvents está disponible para seleccionar en el menú desplegable del lado izquierdo. Cuando un
El evento está seleccionado en el menú desplegable del lado derecho, el VBE genera un código auxiliar del controlador de eventos llamado
después del objeto WithEvents y el nombre del evento, unido con un guión bajo:
End Sub
End Sub
Únicos tipos que exponen al menos un evento se pueden utilizar con WithEvents y WithEvents declaraciones
no se le puede asignar una referencia sobre el terreno con la palabra clave New . Este código es ilegal:
https://riptutorial.com/ 123
Página 139
La referencia al objeto debe establecerse explícitamente; en un módulo de clase, un buen lugar para hacerlo es a menudo en
el controlador Class_Initialize , porque entonces la clase maneja los eventos de ese objeto durante el tiempo que sea
existe una instancia.
Fuentes
Cualquier módulo de clase (o módulo de documento o formulario de usuario) puede ser un origen de eventos. Usa el evento
palabra clave para definir la firma del evento, en la sección de declaraciones del módulo:
La firma del evento determina cómo se genera el evento y qué harán los controladores de eventos.
parece.
https://translate.googleusercontent.com/translate_f 119/223
6/1/2021 Intitulado
Los eventos solo se pueden generar dentro de la clase en la que están definidos; el código del cliente solo puede manejarlos .
Los eventos se generan con la palabra clave RaiseEvent ; Los argumentos del evento se proporcionan en ese punto:
Sin el código que maneja el evento SomethingHappened , la ejecución del procedimiento DoSomething seguirá
plantee el evento, pero no pasará nada. Suponiendo que la fuente del evento es el código anterior en una clase
llamado Algo , este código en ThisWorkbook mostraría un cuadro de mensaje que decía "hola" siempre que
test.DoSomething se llama:
https://riptutorial.com/ 124
Página 140
RaiseEvent AfterAlgo
End Sub
Si el evento BeforeSomething tiene un controlador que establece su parámetro de cancelación en True , entonces cuando
La ejecución regresa del controlador, cancel será True y AfterSomething nunca se generará.
Suponiendo que la referencia del objeto foo está asignada en algún lugar, cuando se ejecuta foo.DoSomething , aparece un mensaje
cuadro pregunta si se debe cancelar, y un segundo cuadro de mensaje dice "no canceló" solo cuando no se
seleccionado.
https://translate.googleusercontent.com/translate_f 120/223
6/1/2021 Intitulado
Combinado con el tipo Variant , esto se puede usar para crear formas bastante no obvias de devolver un
valor para la persona que llama:
https://riptutorial.com/ 125
Página 141
Private Sub source_SomeEvent (ByVal foo As Variant) 'foo es en realidad un objeto ReturnBoolean
foo = True 'True está realmente asignado a foo.ReturnValue, el miembro predeterminado de la clase
End Sub
https://translate.googleusercontent.com/translate_f 121/223
6/1/2021 Intitulado
https://riptutorial.com/ 126
Página 142
Seleccione el caso
Seleccionar caso se
puede utilizar cuando son posibles muchas condiciones diferentes. Se comprueban las condiciones
de arriba a abajo y solo se ejecutará el primer caso que coincida.
Sub TestCase ()
Dim MyVar como cadena
La lógica del bloque Seleccionar caso se puede invertir para admitir la prueba de diferentes variables también, en
En este tipo de escenario también podemos utilizar operadores lógicos:
x=2
y=5
https://translate.googleusercontent.com/translate_f 122/223
6/1/2021 Intitulado
MsgBox "y es menor que 2"
Caso x = 1
MsgBox "x es igual a 1"
Caso x = 2 Xor y = 3
MsgBox "Ir a leer sobre" "Xor" ""
https://riptutorial.com/ 127
Página 143
Caso no y = 5
MsgBox "y no es 5"
Caso x = 3 O x = 10
MsgBox "x = 3 o 10"
Caso y <10 y x <10
MsgBox "xey son menores que 10"
Caso otro
MsgBox "No se encontró ninguna coincidencia"
Finalizar Seleccionar
Las declaraciones de casos también pueden utilizar operadores aritméticos. Donde se usa un operador aritmético
en comparación con el valor Seleccionar caso , debe ir precedido de la palabra clave Is :
x=5
Seleccionar caso x
Caso 1
MsgBox "x es igual a 1"
Caso 2, 3, 4
MsgBox "x es 2, 3 o 4"
Caso 7 a 10
MsgBox "x está entre 7 y 10 (inclusive)"
El caso es <2
MsgBox "x es menor que uno"
El caso es> = 7
MsgBox "x es mayor o igual que 7"
Caso otro
MsgBox "no se encontró ninguna coincidencia"
Finalizar Seleccionar
La construcción de bucle For Each es ideal para iterar todos los elementos de una colección.
End Sub
https://riptutorial.com/ 128
https://translate.googleusercontent.com/translate_f 123/223
6/1/2021 Intitulado
Página 144
Evite For Each al iterar matrices; un bucle For ofrecerá un rendimiento significativamente mejor con
matrices. Por el contrario, un bucle For Each ofrecerá un mejor rendimiento al iterar una colección .
Sintaxis
Para cada [artículo] en [colección]
[declaraciones]
Proximo articulo]
La palabra clave Next puede ir seguida opcionalmente por la variable iteradora; esto puede ayudar a aclarar anidado
bucles, aunque hay mejores formas de aclarar el código anidado, como extraer el bucle interno en
su propio procedimiento.
Debug.Print book.FullName
Hacer bucle
https://riptutorial.com/ 129
Página 145
https://translate.googleusercontent.com/translate_f 124/223
6/1/2021 Intitulado
Mientras bucle
En bucle
El ciclo For se utiliza para repetir la sección adjunta de código un número determinado de veces. El seguimiento
Un ejemplo simple ilustra la sintaxis básica:
El código anterior declara un entero i . El bucle For asigna todos los valores entre 1 y 10 a i
y luego ejecuta Debug.Print i - es decir, el código imprime los números del 1 al 10 en el
ventana. Tenga en cuenta que la variable de bucle se incrementa con la siguiente instrucción, es decir, después de la adjunta
el código se ejecuta en lugar de antes de que se ejecute.
De forma predeterminada, el contador se incrementará en 1 cada vez que se ejecute el ciclo. Sin embargo, un paso puede
ser especificado para cambiar la cantidad del incremento como un valor literal o de retorno de un
función. Si el valor inicial, el valor final o el valor de Paso es un número de punto flotante, será
redondeado al valor entero más cercano. El paso puede ser un valor positivo o negativo.
En general, un bucle For se usaría en situaciones en las que se sabe antes de que comience el bucle cómo
muchas veces para ejecutar el código adjunto (de lo contrario, un bucle Do o While puede ser más apropiado).
Esto se debe a que la condición de salida se corrige después de la primera entrada en el ciclo, como lo demuestra este código:
https://riptutorial.com/ 130
Página 146
Subejemplo público ()
Dim i tan largo
Iteraciones = 10
Para i = 1 a iteraciones
Debug.Print Iterations 'Imprime de 10 a 1, en orden descendente.
Iteraciones = Iteraciones - 1
próximo
End Sub
Para i = 1 a 10
Si i> 5 Entonces
Salir para
Terminara si
https://translate.googleusercontent.com/translate_f 125/223
6/1/2021 Intitulado
Debug.Print i 'Imprime 1, 2, 3, 4, 5 antes de que el ciclo salga antes.
próximo
https://riptutorial.com/ 131
Página 147
¿Cómo encuentras el texto entre dos términos de búsqueda (digamos: después de dos puntos y antes de una coma)?
¿Cómo se obtiene el resto de una palabra (utilizando MID o RIGHT)? Cual de estas funciones
utilizar parámetros de base cero y códigos de retorno frente a uno? ¿Qué pasa cuando las cosas salen mal?
¿Cómo manejan cadenas vacías, resultados no encontrados y números negativos?
Ejemplos
Mejor MID () y otros ejemplos de extracción de cadenas, que actualmente no se encuentran en la web. por favor, ayúdame
haz un buen ejemplo, o completa este aquí. Algo como esto:
DIM strEmpty como cadena, strNull como cadena, el texto como cadena
DIM idx como entero
https://translate.googleusercontent.com/translate_f 126/223
6/1/2021 Intitulado
DIM letterCount como entero
Resultado DIM como String
strNull = NADA
strEmpty = ""
theText = "1234, 78910"
'-----------------
'Extrae la palabra después de la coma "," y antes de "910" resultado: "78" ***
'-----------------
https://riptutorial.com/ 132
Página 148
https://translate.googleusercontent.com/translate_f 127/223
6/1/2021 Intitulado
https://riptutorial.com/ 133
Página 149
En VBA, el uso de interfaces le permite al compilador verificar que un módulo implementa todos sus métodos. UN
La variable o el parámetro se pueden definir en términos de una interfaz en lugar de una clase específica.
Ejemplos
Submarino público ()
' Sin código.
End Sub
Un módulo de clase, Aeroplano , usa la palabra clave Implements para decirle al compilador que genere un error a menos que
tiene dos métodos: un sub Flyable_Fly () y una función Flyable_GetAltitude () que devuelve un Long .
Implementos Flyable
Implementos Flyable
https://translate.googleusercontent.com/translate_f 128/223
6/1/2021 Intitulado
Debug.Print "¡Volando con alas!"
End Sub
https://riptutorial.com/ 134
Página 150
Podemos escribir una rutina que acepte cualquier valor Flyable , sabiendo que responderá a un comando
de Fly o GetAltitude :
Debido a que la interfaz está definida, la ventana emergente de IntelliSense mostrará Fly y GetAltitude para F
.
FlyAndCheckAltitude MyDuck
FlyAndCheckAltitude MyAirplane
La salida es:
Tenga en cuenta que aunque la subrutina se denomina Flyable_Fly tanto en Airplane como en Duck , se puede
llamado Fly cuando la variable o parámetro se define como Flyable . Si la variable está definida
específicamente como pato , tendría que llamarse Flyable_Fly .
Usando el ejemplo de Flyable como punto de partida, podemos agregar una segunda interfaz, Swimmable , con el
siguiente código:
Sub Swim ()
' Sin código
End Sub
Implementos Flyable
Implementos Swimmable
https://riptutorial.com/ 135
https://translate.googleusercontent.com/translate_f 129/223
6/1/2021 Intitulado
Página 151
Implementos Swimmable
Ahora, podemos ver que el objeto Duck se puede pasar a un Sub como Flyable en una mano, y un
Nadable en el otro:
FlyAndCheckAltitude MyDuck
FlyAndCheckAltitude MyAirplane
TrySwimming MyDuck
TrySwimming MyFish
End Sub
30
10000
https://riptutorial.com/ 136
Página 152
Flotando en el agua
https://translate.googleusercontent.com/translate_f 130/223
6/1/2021 Intitulado
https://riptutorial.com/ 137
Página 153
Para ejecutar macros y mantener la seguridad que brindan las aplicaciones de Office contra códigos maliciosos,
necesario para firmar digitalmente el VBAProject.OTM desde el editor VBA> Herramientas> Firma digital .
https://translate.googleusercontent.com/translate_f 131/223
6/1/2021 Intitulado
Office viene con una utilidad para crear un certificado digital autofirmado que puede emplear en la PC
para firmar tus proyectos.
Haga clic en Certificado digital para proyectos VBA para abrir el asistente de certificados .
En el cuadro de diálogo, introduzca un nombre adecuado para el certificado y haga clic en Aceptar.
https://riptutorial.com/ 138
Página 154
https://translate.googleusercontent.com/translate_f 132/223
6/1/2021 Intitulado
Ahora puede cerrar el asistente SELFCERT y centrar su atención en el certificado que tiene
creado.
https://riptutorial.com/ 139
Página 155
https://translate.googleusercontent.com/translate_f 133/223
6/1/2021 Intitulado
Al presionar la tecla de Windows + R, se abrirá la ventana 'Ejecutar'. luego ingrese 'mmc' en la ventana como
https://riptutorial.com/ 140
Página 156
https://translate.googleusercontent.com/translate_f 134/223
6/1/2021 Intitulado
En el menú Archivo, seleccione Agregar o quitar complemento ... Luego, en el cuadro de diálogo siguiente, haga doble clic
Certificados y luego haga clic en Aceptar
https://riptutorial.com/ 141
Página 157
Expanda el menú desplegable en la ventana izquierda para Certificados - Usuario actual 'y seleccione certificados como
mostrado a continuación. El panel central luego mostrará los certificados en esa ubicación, que incluirá
el certificado que creó anteriormente:
https://riptutorial.com/ 142
https://translate.googleusercontent.com/translate_f 135/223
6/1/2021 Intitulado
Página 158
Haga clic con el botón derecho en el certificado y seleccione Todas las tareas> Exportar:
https://riptutorial.com/ 143
Página 159
https://translate.googleusercontent.com/translate_f 136/223
6/1/2021 Intitulado
Asistente de exportación
https://riptutorial.com/ 144
Página 160
https://translate.googleusercontent.com/translate_f 137/223
6/1/2021 Intitulado
https://riptutorial.com/ 145
Página 161
la única opción preseleccionada estará disponible, así que haga clic en 'Siguiente' nuevamente:
https://translate.googleusercontent.com/translate_f 138/223
6/1/2021 Intitulado
El elemento superior ya estará preseleccionado. Haga clic en Siguiente nuevamente y elija un nombre y una ubicación para
guarde el certificado exportado.
https://riptutorial.com/ 146
Página 162
https://translate.googleusercontent.com/translate_f 139/223
6/1/2021 Intitulado
https://riptutorial.com/ 147
Página 163
https://translate.googleusercontent.com/translate_f 140/223
6/1/2021 Intitulado
https://riptutorial.com/ 148
Página 164
https://translate.googleusercontent.com/translate_f 141/223
6/1/2021 Intitulado
https://riptutorial.com/ 149
Página 165
Si ahora usa el certificado y verifica sus propiedades, verá que es un certificado confiable
y puedes usarlo para firmar tu proyecto:
https://riptutorial.com/ 150
Página 166
https://translate.googleusercontent.com/translate_f 142/223
6/1/2021 Intitulado
Observaciones
La longitud de una cuerda se puede medir de dos formas: La medida de longitud más utilizada es la
número de caracteres que utilizan las funciones de Len , pero VBA también puede revelar el número de bytes utilizando
Funciones LenB . Un carácter de doble byte o Unicode tiene más de un byte de longitud.
Ejemplos
Al verificar si una cadena tiene longitud cero, es una mejor práctica y más eficiente inspeccionar el
longitud de la cadena en lugar de comparar la cadena con una cadena vacía.
'Evite usar este método al verificar si myString es una cadena de longitud cero
Si myString = vbNullString Entonces
Debug.Print "myString es de longitud cero"
Terminara si
https://riptutorial.com/ 151
Página 167
Nombres de variables
Las variables contienen datos. Nómbrelos según para qué se utilizan, no según su tipo de datos o alcance,
usando un sustantivo . Si se siente obligado a numerar sus variables (por ejemplo , cosa1, cosa2, cosa3 ), entonces
en su lugar, considere utilizar una estructura de datos adecuada (por ejemplo, una matriz, una colección o un diccionario ).
Nombres de variables que representan un conjunto iterable de valores, por ejemplo, una matriz, una colección , una
https://translate.googleusercontent.com/translate_f 143/223
6/1/2021 Intitulado
El diccionario , o un rango de celdas, debe estar en plural.
el caso de Carmel
End Sub
PascalCase
Para constantes:
End Sub
Sin embargo, los nombres de PascalCase crean un código de aspecto más limpio y son igual de buenos, dado IntelliSense
utiliza diferentes iconos para variables y constantes:
https://riptutorial.com/ 152
Página 168
Notación húngara
Nómbrelos según para qué se utilizan, no según su tipo de datos o alcance.
"La notación húngara hace que sea más fácil ver cuál es el tipo de variable"
Si escribe su código, como los procedimientos, se adhiere al principio de responsabilidad única (ya que
debería), nunca debería mirar una pantalla llena de declaraciones de variables en la parte superior de cualquier
procedimiento; declarar las variables lo más cerca posible de su primer uso, y su tipo de datos
estar siempre a la vista si los declara con un tipo explícito. El atajo Ctrl + i de VBE se puede
https://translate.googleusercontent.com/translate_f 144/223
6/1/2021 Intitulado
también se usa para mostrar el tipo de una variable en una información sobre herramientas.
Para qué se utiliza una variable es información mucho más útil que su tipo de datos, especialmente en un
lenguaje como VBA que feliz e implícitamente convierte un tipo en otro según sea necesario.
Función bReadFile (ByVal strFile como cadena, ByRef strData como cadena) como booleano
Dim bRetVal como booleano
Dim iFile como entero
iFile = FreeFile
Abra strFile para la entrada como #iFile
Entrada #iFile, strData
bRetVal = Verdadero
Limpiar Salida:
Cerrar #iFile
bReadFile = bRetVal
Función de salida
CleanFail:
bRetVal = Falso
Reanudar Limpiar Salir
Función final
Comparar con:
Función CanReadFile (ruta ByVal como cadena, ByRef outContent como cadena) como booleano
https://riptutorial.com/ 153
Página 169
Limpiar Salida:
Cerrar #handle
CanReadFile = resultado
Función de salida
CleanFail:
resultado = Falso
Reanudar Limpiar Salir
Función final
strData se
pasa ByRef en el ejemplo superior, pero además del hecho de que tenemos la suerte de verlo
se pasa explícitamente como tal, no hay ninguna indicación de que strData sea realmente devuelto por la función.
El ejemplo inferior lo nombra outContent ; esto a cabo prefijo es lo que se inventó la notación húngara
para: para ayudar a aclarar para qué se utiliza una variable , en este caso para identificarla claramente como una "salida"
parámetro.
Esto es útil, porque IntelliSense por sí mismo no muestra ByRef , incluso cuando el parámetro es
pasado explícitamente por referencia:
https://translate.googleusercontent.com/translate_f 145/223
6/1/2021 Intitulado
La notación húngara originalmente no tenía nada que ver con los tipos de variables. De hecho, húngaro
La notación bien hecha es realmente útil. Considere este pequeño ejemplo ( ByVal y As Integer eliminado
por brevedad):
Comparar con:
https://riptutorial.com/ 154
Página 170
Por supuesto, hay una mejor manera de transmitirlo todo, utilizando la abstracción adecuada y palabras reales que pueden ser
pronunciado en voz alta y tiene sentido, como un ejemplo artificial:
Tipo de coordenadas
RowIndex tan largo
ColumnIndex tan largo
Tipo final
Nombres de procedimientos
Los procedimientos hacen algo . Nómbrelos por lo que están haciendo, usando un verbo . Si nombra con precisión
un procedimiento no es posible, es probable que el procedimiento esté haciendo demasiadas cosas y deba romperse
en procedimientos más pequeños y especializados.
PascalCase
End Sub
Función final
ObjectName_EventName
End Sub
End Sub
https://translate.googleusercontent.com/translate_f 146/223
6/1/2021 Intitulado
Los controladores de eventos suelen ser nombrados automáticamente por el VBE; renombrarlos sin renombrar el
objeto y / o el evento manejado romperá el código - el código se ejecutará y compilará, pero el controlador
El procedimiento quedará huérfano y nunca se ejecutará.
Miembros booleanos
Función bReadFile (ByVal strFile como cadena, ByRef strData como cadena) como booleano
https://riptutorial.com/ 155
Página 171
Función final
Comparar con:
Función CanReadFile (ruta ByVal como cadena, ByRef outContent como cadena) como booleano
Función final
El prefijo Can tiene el mismo propósito que el prefijo b : identifica el valor de retorno de la función
como booleano . Pero Can se lee mejor que b :
Comparado con:
Considere usar prefijos como Can , Is o Has delante de los miembros que devuelven booleanos (funciones
y propiedades), pero solo cuando aporta valor. Esto se ajusta a laactual Microsoft namin g
directrices .
https://translate.googleusercontent.com/translate_f 147/223
6/1/2021 Intitulado
https://riptutorial.com/ 156
Página 172
Ejemplos
ﻌﻄﺎر
ِ ِﻀﺠﯿ ُﻊ ﺑِﮭﺎ ﻧَﺠﻼ َء ﻣ ِ ﺻﻒ ﺧَﻠﻖَ ﺧَﻮ ِد َﻛﻤِ ﺜ ِﻞ اﻟﺸ
َ ﯾَﺤﻈﻰ اﻟ- َﻤﺲ إِذ ﺑَﺰَ ﻏَﺖ ِ
VBA proporciona las funciones AscW y ChrW para trabajar con códigos de caracteres multibyte. También podemos
use matrices de bytes para manipular la variable de cadena directamente:
Sub NonLatinStrings ()
'Funciones AscW
Dim char como cadena
char = AscW (Izquierda (MyString, 1))
Debug.Print "Primer carácter (ChrW):" & char
Debug.Print "Primer carácter (binario):" & BinaryFormat (carácter, 12)
'Funciones ChrW
Dim uString como cadena
uString = ChrW (carácter)
Debug.Print "Valor de cadena (texto):" & uString ¡Falla! Aparece como '?'
Debug.Print "Valor de cadena (AscW):" & AscW (uString)
https://riptutorial.com/ 157
Página 173
Lazo
End Sub
https://translate.googleusercontent.com/translate_f 148/223
6/1/2021 Intitulado
Cadena entera
??? ????? ????? ??????? ??????? ??? ??????? - ????? ???????? ???? ???????
???????
Tenga en cuenta que VBA no puede imprimir texto no latino en la ventana inmediata aunque la cadena
las funciones funcionan correctamente. Esta es una limitación del IDE y no del idioma.
Los identificadores de VBA (nombres de variables y funciones) pueden usar la escritura latina y también pueden usar
japonés ,Corea ,Chino simplificado yEscrituras tradicionales chinas .
La escritura latina extendida tiene una cobertura completa para muchos idiomas:
Inglés, francés, español, alemán, italiano, bretón, catalán, danés, estonio, finlandés, islandés,
Indonesio, irlandés, lojban, mapudungun, noruego, portugués, gaélico escocés, sueco,
Tagalo
https://riptutorial.com/ 158
Página 174
Tenga en cuenta que en el IDE de VBA, un solo apóstrofo dentro de un nombre de variable no convierte la línea en un
comentario (como lo hace en Stack Overflow).
Además, los idiomas que utilizan dos ángulos para indicar una cita «» pueden utilizar los de variable
los nombres describen el hecho de que las comillas de tipo "" no lo son.
https://translate.googleusercontent.com/translate_f 149/223
6/1/2021 Intitulado
https://riptutorial.com/ 159
Página 175
Abstracción
La abstracción se logra implementando funcionalidad con código cada vez más detallado. La entrada
El punto de una macro debe ser un pequeño procedimiento con un alto nivel de abstracción que facilite la
capte de un vistazo lo que está pasando:
https://translate.googleusercontent.com/translate_f 150/223
6/1/2021 Intitulado
El procedimiento DoSomething tiene un alto nivel de abstracción : podemos decir que está mostrando un formulario y
creando algún modelo y pasando ese objeto a algún procedimiento ProcessUserData que sepa qué
que ver con eso - cómo se crea el modelo es el trabajo de otro procedimiento:
La función CreateViewModel solo es responsable de crear alguna instancia de ISomeModel . Parte de eso
La responsabilidad es adquirir una variedad de elementos disponibles ; cómo se adquieren estos elementos es una
detalles de implementación que se resumen detrás del procedimiento GetAvailableItems :
Aquí el procedimiento es la lectura de los valores disponibles de un rango con nombre en una Hoja de datos de hoja de cálculo.
También podría leerlos de una base de datos, o los valores podrían estar codificados: es un
detalles de implementación que no son motivo de preocupación para ninguno de los niveles de abstracción más altos.
Encapsulamiento
https://riptutorial.com/ 160
Página 176
los El ejemplo de manejo de QueryClose demuestra la encapsulación: el formulario tiene un control de casilla de verificación,
pero su código de cliente no funciona con él directamente: la casilla de verificación es un detalle de implementación , lo que
El código del cliente necesita saber si la configuración está habilitada o no.
Cuando el valor de la casilla de verificación cambia, el controlador asigna un miembro de campo privado:
'...
Y cuando el código del cliente quiere leer ese valor, no necesita preocuparse por una casilla de verificación:
en su lugar, simplemente usa la propiedad SomeOtherSetting :
La propiedad SomeOtherSetting encapsula el estado de la casilla de verificación; el código del cliente no necesita saber
que hay una casilla de verificación involucrada, solo que hay una configuración con un valor booleano. por encapsulado
el valor booleano , hemos agregado una capa de abstracción alrededor de la casilla de verificación.
https://translate.googleusercontent.com/translate_f 151/223
6/1/2021 Intitulado
Llevemos eso un paso más allá encapsulando el modelo del formulario en un módulo de clase dedicado. Pero si
hicimos una propiedad pública para el nombre de usuario y la marca de tiempo , tendríamos que exponer la propiedad Let
accesores, haciendo que las propiedades sean mutables, y no queremos que el código del cliente tenga la capacidad de
cambie estos valores una vez establecidos.
La función CreateViewModel en el ejemplo de Abstraction devuelve una clase ISomeModel : esa es nuestra
interfaz , y se parece a esto:
Opción explícita
https://riptutorial.com/ 161
Página 177
Propiedad final
Observe que las propiedades de marca de tiempo y nombre de usuario solo exponen un descriptor de acceso de obtención de propiedad . Ahora el SomeModel
la clase puede implementar esa interfaz:
Opción explícita
Implementa ISomeModel
https://translate.googleusercontent.com/translate_f 152/223
6/1/2021 Intitulado
https://riptutorial.com/ 162
Página 178
Los miembros de la interfaz son todos privados y todos los miembros de la interfaz deben implementarse para
el código para compilar. Los miembros públicos no forman parte de la interfaz y, por lo tanto, no
expuestos al código escrito en la interfaz ISomeModel .
Usando un Atributo VB_PredeclaredId , podemos hacer que laclase SomeModel tenga una instancia predeterminada , y
escriba una función que funcione como un miembro de nivel de tipo ( compartido en VB.NET, estático en C #) que el cliente
el código puede llamar sin necesidad de crear primero una instancia, como hicimos aquí:
https://translate.googleusercontent.com/translate_f 153/223
6/1/2021 Intitulado
https://riptutorial.com/ 163
Página 179
Función final
Este método de fábrica asigna los valores de propiedad que son de solo lectura cuando se accede desde el
Interfaz ISomeModel , aquí Timestamp y UserName :
Función pública Crear (ByVal pTimeStamp como fecha, ByVal pUserName como cadena) como ISomeModel
Con nuevo SomeModel
.Timestamp = pTimeStamp
.UserName = pUserName
Establecer Crear = .Self
Terminar con
Función final
Y ahora podemos codificar contra la interfaz ISomeModel , que expone Timestamp y UserName como
propiedades de solo lectura que nunca se pueden reasignar (siempre que el código esté escrito en
interfaz).
Polimorfismo
Supongamos que tiene una interfaz ISomeView que implementa el formulario en sí:
Opción explícita
Opción explícita
Implementa ISomeView
https://riptutorial.com/ 164
Página 180
Tipo final
Privado esto como TView
https://translate.googleusercontent.com/translate_f 154/223
6/1/2021 Intitulado
Propiedad privada Obtenga ISomeView_IsCancelled () como booleano
ISomeView_IsCancelled = this.IsCancelled
Propiedad final
Pero entonces, nada prohíbe la creación de otro módulo de clase que implemente la interfaz ISomeView
sin ser un formulario de usuario , esto podría ser una clase SomeViewMock :
Opción explícita
Implementa ISomeView
https://riptutorial.com/ 165
Página 181
Propiedad final
https://translate.googleusercontent.com/translate_f 155/223
6/1/2021 Intitulado
Sub privado ISomeView_Show ()
'hacer nada
End Sub
Y ahora podemos cambiar el código que funciona con un UserForm y hacerlo funcionar desde ISomeView
interfaz, por ejemplo, dándole el formulario como parámetro en lugar de instanciarlo:
Debido a que el HacerAlgo método depende de una interfaz (es decir, una abstracción ) y no un hormigón
clase (por ejemplo, un UserForm específico ), podemos escribir una prueba unitaria automatizada que asegure que
ProcessUserData no se ejecuta cuando view.IsCancelled es True , al hacer que nuestra prueba cree un
SomeViewMock , estableciendo su propiedad IsCancelled en True y pasándola a DoSomething .
Se pueden escribir pruebas unitarias en VBA, hay complementos que incluso lo integran en el
IDE. Pero cuando el código está estrechamente vinculado con una hoja de trabajo, una base de datos, un formulario o el sistema de archivos,
luego, la prueba unitaria comienza a requerir una hoja de trabajo, base de datos, formulario o sistema de archivos real, y estos
Las dependencias son nuevos puntos de falla fuera de control que el código comprobable debe aislar, de modo que la unidad
las pruebas no requieren una hoja de trabajo, una base de datos, un formulario o un sistema de archivos reales.
Escribiendo código contra interfaces, de una manera que permita que el código de prueba inyecte stub / mock
implementaciones (como el ejemplo anterior de SomeViewMock ), puede escribir pruebas en un "control
entorno ", y simular lo que sucede cuando cada una de las 42 posibles permutaciones
de las interacciones del usuario en los datos del formulario, sin siquiera mostrar un formulario y hacer clic manualmente
en un control de formulario.
https://riptutorial.com/ 166
Página 182
• Operadores matemáticos
• Operadores bit a bit
• Operadores de concatenación
• Operadores de comparación
• Operadores logicos
Los operadores con precedencia coincidente se evalúan de izquierda a derecha. El orden predeterminado puede ser
anulado mediante el uso de paréntesis ( y ) para agrupar expresiones.
Ejemplos
https://translate.googleusercontent.com/translate_f 156/223
6/1/2021 Intitulado
Operadores matemáticos
Listados en orden de precedencia:
https://riptutorial.com/ 167
Página 183
Devuelve la suma de 2 operandos. Tenga en cuenta que este token también se trata como
+ Adición 2 un operador de concatenación cuando se aplica a una cadena . Ver
Operadores de concatenación .
Operadores de concatenación
VBA admite 2 operadores de concatenación diferentes, + y &, y ambos realizan exactamente lo mismo
función cuando se utiliza con Cuerda tipos - de la derecha de cadena se añade al final de la izquierda
cuerda de mano .
Si el operador & se usa con un tipo de variable que no sea String , se convierte implícitamente en String
antes de ser concatenados.
https://translate.googleusercontent.com/translate_f 157/223
6/1/2021 Intitulado
Tenga en cuenta que el operador de concatenación + es una sobrecarga del operador de suma + . El comportamiento de +
está determinado por el tipos de variables de los operandos y precedencia de los tipos de operadores. Si ambos
los operandos se escriben como String o Variant con un subtipo de String , están concatenados:
Subejemplo público ()
Atenuar a la izquierda como cadena
Dim right As String
izquierda = "5"
derecha = "5"
Si cualquiera de los lados es de tipo numérico y el otro lado es una cadena que se puede convertir en un número,
la precedencia de tipos de los operadores matemáticos hace que el operador sea tratado como la suma
operador y se añaden los valores numéricos:
Subejemplo público ()
Atenuar a la izquierda como variante
Dim right As String
https://riptutorial.com/ 168
Página 184
izquierda = 5
derecha = "5"
Este comportamiento puede provocar errores sutiles y difíciles de depurar, especialmente si se utilizan tipos de variantes ,
por lo que solo se debe usar el operador & para la concatenación.
Operadores de comparación
https://translate.googleusercontent.com/translate_f 158/223
6/1/2021 Intitulado
un
La objeto (ya seadará
comparación un subtipo no objetoun
como resultado o vtEmpty ), elen tiempo de ejecución: "Objeto
error 424
required ". Si alguno de los operandos pertenece a una interfaz diferente
del mismo objeto, la comparación devolverá True . Si tu
necesidad de probar la equidad tanto de la instancia como de la
interfaz, utilice ObjPtr (izquierda) = ObjPtr (derecha) en su lugar.
Notas
https://riptutorial.com/ 169
Página 185
La sintaxis de VBA permite "cadenas" de operadores de comparación, pero estas construcciones deben
generalmente debe evitarse. Las comparaciones siempre se realizan de izquierda a derecha en solo 2 operandos a la vez.
time, y cada comparación da como resultado un booleano . Por ejemplo, la expresión ...
a = 2: b = 1: c = 0
expr = a> b> c
... puede ser leído en algunos contextos como una prueba de si b es entre una y c . En VBA, esto evalúa
como sigue:
a = 2: b = 1: c = 0
expr = a> b> c
expr = (2> 1)> 0
expr = Verdadero> 0
expr = -1> 0 'CInt (verdadero) = -1
expr = Falso
Cualquier operador de comparación que no sea Se usa con un Objeto como operando se ejecutará en
el valor de retorno del objeto s'miembro predeterminado . Si el objeto no tiene un miembro predeterminado, el
la comparación dará como resultado un error 438 en tiempo de ejecución: "El objeto no admite su propiedad o método".
Si el objeto no está inicializado, la comparación dará como resultado un error en tiempo de ejecución 91 - "Variable de objeto o
Con variable de bloque no establecida ".
Si el literal Nothing se usa con cualquier operador de comparación que no sea Is , resultará en una compilación
error - "Uso no válido del objeto".
Si el miembro predeterminado del objeto es otro objeto , VBA llamará continuamente al miembro predeterminado
de cada valor de retorno sucesivo hasta que se devuelve un tipo primitivo o se genera un error. Por ejemplo,
suponga que SomeClass tiene un miembro predeterminado de Value , que es una instancia de ChildClass con un valor predeterminado
miembro de ChildValue . La comparación...
Si alguno de los operandos es de tipo numérico y el otro operando es una cadena o una variante del subtipo Cadena ,
se realizará una comparación numérica. En este caso, si la Cadena no se puede convertir en un número, un
Error de tiempo de ejecución 13 - "No coinciden los tipos" como resultado de la comparación.
Si ambos operandos son una Cadena o una Variante del subtipo Cadena , se realizará una comparación de cadenas
basado en el Opción Comparar configuración del módulo de código. Estas comparaciones se realizan en un
carácter por carácter. Tenga en cuenta que la representación de caracteres de una cadena que contiene un
https://translate.googleusercontent.com/translate_f 159/223
6/1/2021 Intitulado
número no es lo mismo que una comparación de los valores numéricos:
https://riptutorial.com/ 170
Página 186
Subejemplo público ()
Atenuar a la izquierda como variante
Dim a la derecha como variante
izquierda = "42"
derecha = "5"
Depurar Imprimir izquierda> derecha 'Imprime falso
Debug.Print Val (izquierda)> Val (derecha) 'Prints True
End Sub
Por esta razón, asegúrese de que las variables String o Variant se conviertan en números antes de realizar
comparaciones numéricas de desigualdad sobre ellos.
Si un operando es una fecha , se realizará una comparación numérica del valor Double subyacente si
el otro operando es numérico o se puede convertir a un tipo numérico.
Si el otro operando es una Cadena o una Variante del subtipo Cadena que se puede convertir a una Fecha usando el
configuración regional actual, la cadena se convertirá en una fecha . Si no se puede convertir a una fecha en la configuración regional actual,
Error de tiempo de ejecución 13 - "No coinciden los tipos" como resultado de la comparación.
Se debe tener cuidado al hacer comparaciones entre valores dobles o simples yBooleanos.
A diferencia de otros tipos numéricos, no se puede suponer que los valores distintos de cero sean verdaderos debido al comportamiento de VBA
de promover el tipo de datos de una comparación que involucra un número de punto flotante a Double :
Subejemplo público ()
Prueba de atenuación como doble
Todos los operadores lógicos en VBA se pueden considerar como "anulaciones" de los operadores bit a bit del
mismo nombre. Técnicamente, siempre se tratan como operadores bit a bit. Toda la comparación
los operadores en VBA devuelven un Booleano , que siempre no tendrá ninguno de sus bits establecido ( Falso ) o todos sus
bits establecidos ( Verdadero ). Pero tratará un valor con cualquier bit establecido como Verdadero . Esto significa que el resultado de la
convertir el resultado bit a bit de una expresión en un booleano (ver Operadores de comparación) siempre será
lo mismo que tratarlo como una expresión lógica.
Asignar el resultado de una expresión usando uno de estos operadores dará el resultado bit a bit. Nota
que en las tablas de verdad a continuación, 0 es equivalente a Falso y 1 es equivalente a Verdadero .
https://riptutorial.com/ 171
Página 187
https://translate.googleusercontent.com/translate_f 160/223
6/1/2021 Intitulado
0 0 0
0 1 0
1 0 0
1 1 1
0 0 0
0 1 1
1 0 1
1 1 1
No
Devuelve True si la expresión se evalúa como False y False si la expresión se evalúa como True .
0 1
1 0
No esel único operando sin operando a la izquierda. El Editor de Visual Basic automáticamente
simplificar expresiones con un argumento a la izquierda. Si escribe ...
Debug.Print x No y
Debug.Print No x
Se harán simplificaciones similares a cualquier expresión que contenga un operando de la izquierda (incluyendo
expresiones) para Not .
Xor
https://riptutorial.com/ 172
Página 188
También conocido como "exclusivo o". Devuelve True si ambas expresiones evalúan resultados diferentes.
0 0 0
0 1 1
1 0 1
https://translate.googleusercontent.com/translate_f 161/223
6/1/2021 Intitulado
1 1 0
Tenga en cuenta que aunque el operador Xor se puede utilizar como un operador lógico, no hay absolutamente ningún
razón para hacerlo, ya que da el mismo resultado que el operador de comparación <> .
Eqv
También conocido como "equivalencia". Devuelve True cuando ambas expresiones evalúan el mismo resultado.
0 0 1
0 1 0
1 0 0
1 1 1
Tenga en cuenta que la función Eqv se usa muy raramente ya que x Eqv y es equivalente a la mucho más legible
No (x Xor y) .
Diablillo
También conocido como "implicación". Devuelve True si ambos operandos son iguales o si el segundo operando es
Cierto .
0 0 1
0 1 1
1 0 0
1 1 1
Tenga en cuenta que la función Imp se utiliza muy raramente. Una buena regla general es que si no puede explicar qué
https://riptutorial.com/ 173
Página 189
https://translate.googleusercontent.com/translate_f 162/223
6/1/2021 Intitulado
https://riptutorial.com/ 174
Página 190
Nota En muchos otros lenguajes de programación (incluido VB.NET), los parámetros se pasan implícitamente
por valor si no se especifica ningún modificador: considere especificar los modificadores ByRef explícitamente para evitar posibles
confusión.
Observaciones
Pasando matrices
Las matrices deben pasarse por referencia. Este código se compila, pero genera el error 424 en tiempo de ejecución "Objeto
Necesario":
Subprueba pública ()
Matriz DoSomething (1, 2, 3)
End Sub
https://translate.googleusercontent.com/translate_f 163/223
6/1/2021 Intitulado
foo.Añadir 42
End Sub
Private Sub DoSomething (ByVal foo () As Variant) 'ByVal es ilegal para matrices
foo.Añadir 42
End Sub
Ejemplos
https://riptutorial.com/ 175
Página 191
Sub CallingProcedure ()
Dim A tan largo
Dim B tan largo
A = 123
B = 456
Debug.Print "ANTES DE LLAMAR => A:" & CStr (A), "B:" & CStr (B)
'' Resultado: ANTES DE LLAMAR => A: 123 B: 456
Procedimiento llamado X: = A, Y: = B
Debug.Print "AFTER CALL = A:" & CStr (A), "B:" & CStr (B)
'' Resultado: DESPUÉS DE LLAMADA => A: 321 B: 456
End Sub
Otro ejemplo:
Sub principal()
Dim IntVarByVal como entero
Dim IntVarByRef como entero
IntVarByVal = 5
IntVarByRef = 10
SubChangeArguments IntVarByVal, IntVarByRef '5 entra como una "copia". 10 entra como
referencia
Debug.Print "IntVarByVal:" & IntVarByVal 'imprime 5 (sin cambios realizados por SubChangeArguments)
Debug.Print "IntVarByRef:" & IntVarByRef 'imprime 99 (la variable se cambió en
SubChangeArguments)
End Sub
Sub SubChangeArguments (ByVal ParameterByVal como entero, ByRef ParameterByRef como entero)
ParameterByVal = ParameterByVal + 2 '5 + 2 = 7 (cambiado solo dentro de este Sub)
ParameterByRef = ParameterByRef + 89 '10 + 89 = 99 (cambia el propio IntVarByRef - en
el Sub principal)
https://translate.googleusercontent.com/translate_f 164/223
6/1/2021 Intitulado
End Sub
ByRef
Modificador predeterminado
Si no se especifica ningún modificador para un parámetro, ese parámetro se pasa implícitamente por referencia.
https://riptutorial.com/ 176
Página 192
End Sub
Subprueba pública ()
Dim foo tan largo
foo = 42
Hacer algo foo
Debug.Print foo
End Sub
Llamar a las salidas 84 del procedimiento de prueba anterior . DoSomething recibe foo y recibe un
referencia al valor y, por lo tanto, funciona con la misma dirección de memoria que la persona que llama.
• Cuando se pasa una referencia ByRef , el procedimiento recibe una referencia al puntero.
Subprueba pública ()
Colección Dim foo As
Set foo = Nueva colección
Hacer algo foo
Debug.Print foo.Count
End Sub
El código anterior plantea error 91 en tiempo de ejecución , porque la persona que llama está llamando almiembro Count de
un objeto que ya no existe, porque DoSomething recibió una referencia al objeto
puntero y lo asignó a Nothing antes de regresar.
https://translate.googleusercontent.com/translate_f 165/223
6/1/2021 Intitulado
https://riptutorial.com/ 177
Página 193
Usando paréntesis en el sitio de la llamada, puede anular ByRef y forzar que se pase un argumento
ByVal :
Subprueba pública ()
Dim foo tan largo
foo = 42
Hacer algo (foo)
Debug.Print foo
End Sub
bar = DoSomething (foo) 'llamada a la función, sin espacios en blanco; parens son parte de la lista de argumentos
Llamada al procedimiento DoSomething (foo) ', observe los espacios en blanco; parens NO son parte de argumentos
lista
La llamada al procedimiento DoSomething foo 'no obliga al parámetro foo a ser ByVal
ByVal
• Cuando se pasa un valor ByVal , el procedimiento recibe una copia del valor.
Subprueba pública ()
Dim foo tan largo
foo = 42
Hacer algo foo
Debug.Print foo
End Sub
Llamar a las salidas 42 del procedimiento de prueba anterior . DoSomething recibe foo y recibe una copia de
el valor. La copia se multiplica por 2 y luego se descarta cuando finaliza el procedimiento; la
la copia de la persona que llama nunca fue alterada.
• Cuando se pasa una referencia ByVal , el procedimiento recibe una copia del puntero.
Subprueba pública ()
Colección Dim foo As
Set foo = Nueva colección
Hacer algo foo
Debug.Print foo.Count
https://riptutorial.com/ 178
Página 194
https://translate.googleusercontent.com/translate_f 166/223
6/1/2021 Intitulado
End Sub
Llamar a las salidas del procedimiento de prueba anteriores 1. DoSomething recibe foo y recibe una copia de
el puntero al objeto Collection . Porque la variable de objeto foo en los puntos de alcance de prueba
al mismo objeto, agregar un elemento en DoSomething agrega el elemento al mismo objeto. Porque
es una copia del puntero, establecer su referencia en Nothing no afecta la propia copia de la persona que llama.
https://riptutorial.com/ 179
Página 195
https://translate.googleusercontent.com/translate_f 167/223
6/1/2021 Intitulado
• [Let | Set] IdentifierName [ (argumentos) ] = expresión
Parámetros
Parámetro Información
argumentos Una lista de argumentos separados por comas que se pasarán al procedimiento.
Observaciones
Las dos primeras sintaxis son para llamar a procedimientos Sub ; observe que la primera sintaxis no implica
paréntesis.
Ver Esto es confuso. ¿Por qué no usar siempre paréntesis? para una explicación detallada del
diferencias entre las dos primeras sintaxis.
La tercera sintaxis es para llamar a los procedimientos de obtención de funciones y propiedades ; cuando hay parámetros,
los paréntesis son siempre obligatorios. La palabra clave Let es opcional al asignar un valor , pero
la palabra clave Set es necesaria al asignar una referencia .
La cuarta sintaxis es para llamar a los procedimientos Property Let y Property Set ; la expresión de la derecha
El lado de la mano de la asignación se pasa al parámetro de valor de la propiedad.
Ejemplos
Caso extremo
https://riptutorial.com/ 180
Página 196
Valores devueltos
Para recuperar el resultado de una llamada a procedimiento (por ejemplo, procedimientos de obtención de función o propiedad ), coloque la llamada en
el lado derecho de una tarea:
resultado = nombreProcedimiento
resultado = nombreProcedimiento (argumento1, argumento2)
https://translate.googleusercontent.com/translate_f 168/223
6/1/2021 Intitulado
Los paréntesis deben estar presentes si hay parámetros. Si el procedimiento no tiene parámetros, el
los paréntesis son redundantes.
Los paréntesis se utilizan para encerrar los argumentos de las llamadas a funciones . Usándolos para llamadas a procedimientos
puede causar problemas inesperados.
Debido a que pueden introducir errores, tanto en tiempo de ejecución pasando un valor posiblemente no intencionado al
procedimiento, y en tiempo de compilación simplemente siendo sintaxis inválida.
Tiempo de ejecución
Los paréntesis redundantes pueden introducir errores. Dado un procedimiento que toma una referencia de objeto como
un parámetro ...
Esto generará un error de tiempo de ejecución "Objeto requerido" # 424. Otros errores son posibles en otros
circunstancias: aquí la referencia del objeto Application.ActiveCell Range se está evaluando y
pasado por valor independientemente de la firma del procedimiento que especifica que el objetivo se pasaría
ByRef . El valor real pasado ByVal a DoSomething en el fragmento anterior es
Application.ActiveCell.Value .
https://riptutorial.com/ 181
Página 197
Los paréntesis obligan a VBA a evaluar el valor de la expresión entre corchetes y pasar el resultado
ByVal al
procedimiento llamado. Cuando el tipo de resultado evaluado no coincide con el
tipo esperado y no se puede convertir implícitamente, se genera un error de tiempo de ejecución.
Tiempo de compilación
Este código no se podrá compilar:
La sintaxis de llamada explícita requiere la palabra clave Call y paréntesis alrededor de la lista de argumentos;
los paréntesis son redundantes si no hay parámetros. Esta sintaxis se volvió obsoleta cuando el
https://translate.googleusercontent.com/translate_f 169/223
6/1/2021 Intitulado
Se agregó una sintaxis de llamada implícita más moderna a VB.
Argumentos opcionales
Algunos procedimientos tienen argumentos opcionales. Los argumentos opcionales siempre vienen después de required
argumentos, pero el procedimiento se puede llamar sin ellos.
https://riptutorial.com/ 182
Página 198
Función Nombre del procedimiento (argumento1 como cadena, argumento2 como cadena, opcional optArgument3 como
String) como cadena
La palabra clave opcional indica que este argumento se puede omitir. Como se mencionó antes, cualquier
Los argumentos opcionales introducidos en el encabezado deben aparecer al final, después de cualquier requisito
argumentos.
También puede proporcionar un valor predeterminado para el argumento en el caso de que no se pase un valor al
función:
Función Nombre del procedimiento (argumento1 como cadena, argumento2 como cadena, opcional optArgument3 como
String = "C") como cadena
En esta función, si no se proporciona el argumento para c , su valor será por defecto "C" . Si se proporciona un valor
entonces esto anulará el valor predeterminado.
https://translate.googleusercontent.com/translate_f 170/223
6/1/2021 Intitulado
https://riptutorial.com/ 183
Página 199
También demuestre (Leer parte) para calcular File Hashes sin un programa externo como fciv.exe
de Microsoft.
Observaciones
OpenFile ( sFileNam e
Abre el archivo especificado por el argumento sFileName.
Como cuerda)
ReadBytes ( Lee ByteCount bytes y los devuelve en una matriz de bytes Variant y
ByteCount tan largo) mueve el puntero.
Mueve el puntero del archivo hasta +/- 2GB desde la ubicación actual. usted
SeekRelative ( Desplazamiento
https://translate.googleusercontent.com/translate_f 171/223
6/1/2021 Intitulado
Tanto tiempo) puede reescribir este método para permitir compensaciones superiores a 2 GB por
convertir un desplazamiento con signo de 64 bits en dos valores de 32 bits.
https://riptutorial.com/ 184
Página 200
Propiedad Descripción
El identificador de archivo para el archivo abierto actualmente. Esto no es compatible con el archivo VBA
FileHandle
manejas.
MÓDULO NORMAL
Función Notas
Simplemente agregue la ruta completa para aplicar el hash, Blocksize para usar
GetFileHash ( sFile As
(número de bytes) y el tipo de Hash que se utilizará, uno de los
String, uBlockSize As
constantes: HashTypeMD5 , HashTypeSHA1 , HashTypeSHA256 ,
Doble, sHashType como
HashTypeSHA384 , HashTypeSHA512 . Esto fue diseñado para ser
Cuerda)
tan genérico como sea posible.
Debe anular / comentar uFileSize como doble en consecuencia. He probado MD5 y SHA1.
Ejemplos
Esto tiene que estar en un módulo de clase, los ejemplos más adelante se denominarán "aleatorios"
Opción explícita
https://riptutorial.com/ 185
Página 201
https://translate.googleusercontent.com/translate_f 172/223
6/1/2021 Intitulado
Función de declaración privada CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Función de declaración privada FlushFileBuffers Lib "kernel32" (ByVal hFile As Long) As Long
HFile privado tan largo, sFName como cadena, fAutoFlush como booleano
https://riptutorial.com/ 186
Página 202
https://translate.googleusercontent.com/translate_f 173/223
6/1/2021 Intitulado
https://riptutorial.com/ 187
Página 203
Public Sub SeekAbsolute (ByVal HighPos como largo, ByVal LowPos como largo)
Si hFile = INVALID_HANDLE_VALUE Entonces
RaiseError W32F_FILE_ALREADY_CLOSED
Terminara si
LowPos = SetFilePointer (hFile, LowPos, HighPos, FILE_BEGIN)
End Sub
https://translate.googleusercontent.com/translate_f 174/223
6/1/2021 Intitulado
Si TempErr entonces
RaiseError W32F_Problem_seeking, "Error" & TempErr & "." & vbCrLf y CStr (TempErr)
Terminara si
Terminara si
End Sub
Subclase privada_Terminate ()
Si hFile <> INVALID_HANDLE_VALUE, entonces CloseHandle hFile
End Sub
https://riptutorial.com/ 188
Página 204
Sub FileHashes ()
Dim tStart As Date, tFinish As Date, sHash como cadena, aTestFiles como variante, oTestFile como
Variante, aBlockSizes como variante, oBlockSize como variante
Atenuar BLOCKSIZE como doble
https://translate.googleusercontent.com/translate_f 175/223
6/1/2021 Intitulado
"2 ^ 19-1", "2 ^ 20-1", "2 ^ 21-1", "2 ^ 22-1", "2 ^ 23-1", "2 ^ 24-1", "2 ^ 25-1 "," 2 ^ 26-1 ")
aTestFiles = Array ("C: \ ISO \ clonezilla-live-2.2.2-37-amd64.iso",
"C: \ ISO \ HPIP201.2014_0902.29.iso",
"C: \ ISO \ SW_DVD5_Windows_Vista_Business_W32_32BIT_English.ISO",
"C: \ ISO \ Win10_1607_English_x64.iso",
"C: \ ISO \ SW_DVD9_Windows_Svr_Std_and_DataCtr_2012_R2_64Bit_English.ISO")
Debug.Print "Archivos de prueba:" & Join (aTestFiles, "|")
Debug.Print "BlockSizes:" & Join (aBlockSizes, "|")
Para cada oTestFile en aTestFiles
Debug.Print oTestFile
Para cada oBlockSize en aBlockSizes
BLOCKSIZE = Evaluar (oBlockSize)
tStart = Ahora
sHash = GetFileHash (CStr (oTestFile), BLOCKSIZE, HashTypeMD5)
tFinish = Ahora
Debug.Print sHash, uFileSize, Format (tFinish - tStart, "hh: mm: ss"), oBlockSize & "
(" & TAMAÑO DE BLOQUE & ")"
próximo
próximo
End Sub
Función privada GetFileHash (ByVal sFile como cadena, ByVal uBlockSize como doble, ByVal
sHashType como cadena) como cadena
Dim oFSO As Object '"Scripting.FileSystemObject"
Dim oCSP As Object 'Uno de los "CryptoServiceProvider"
Dim oRnd As Random 'La clase "Random" de Microsoft, debe estar en el mismo archivo
Dim uBytesRead como doble, uBytesToRead como doble, bDone como booleano
https://riptutorial.com/ 189
Página 205
Application.ScreenUpdating = Falso
'Procesar el archivo en trozos de uBlockSize o menos
Si uFileSize = 0 entonces
ReDim aBlock (0)
oCSP.TransformFinalBlock aBlock, 0, 0
bDone = Verdadero
Más
Con oRnd
.OpenFile sFile
Hacer
Si uBytesRead + uBlockSize <uFileSize, entonces
uBytesToRead = uBlockSize
Más
uBytesToRead = uFileSize - uBytesRead
bDone = Verdadero
Terminara si
'Leer en algunos bytes
aBytes = .ReadBytes (uBytesToRead)
aBlock = aBytes
Si bDone entonces
oCSP.TransformFinalBlock aBlock, 0, uBytesToRead
uBytesRead = uBytesRead + uBytesToRead
Más
uBytesRead = uBytesRead + oCSP.TransformBlock (aBlock, 0, uBytesToRead,
aBloque, 0)
Terminara si
https://translate.googleusercontent.com/translate_f 176/223
6/1/2021 Intitulado
DoEvents
Bucle hasta bDone
.Cerrar el archivo
Terminar con
Terminara si
Si bDone entonces
'convierte la matriz de bytes Hash en una cadena hexadecimal
aHash = oCSP.hash
Para i = 0 a UBound (aHash)
Mid $ (sHash, i * 2 + (aHash (i)> 15) + 2) = Hex (aHash (i))
próximo
Terminara si
Application.ScreenUpdating = True
' Limpiar
oCSP.Clear
Limpiar:
https://riptutorial.com/ 190
Página 206
La salida es bastante interesante, mis archivos de prueba indican que BLOCKSIZE = 131071 (2 ^ 17-1)
ofrece el mejor rendimiento general con Office 2010 de 32 bits en Windows 7 x64, el siguiente mejor es
2 ^ 16-1 (65535) . Nota 2 ^ 27-1 produce Memoria insuficiente .
146,800,640 clonezilla-live-2.2.2-37-amd64.iso
798,210,048 HPIP201.2014_0902.29.iso
2,073,016,320 SW_DVD5_Windows_Vista_Business_W32_32BIT_English.ISO
4.380.387.328 Win10_1607_English_x64.iso
5.400.115.200 SW_DVD9_Windows_Svr_Std_and_DataCtr_2012_R2_64Bit_English.ISO
Otra variación del código anterior le brinda más rendimiento cuando desea obtener hash
códigos de todos los archivos de una carpeta raíz, incluidas todas las subcarpetas.
Código
Opción explícita
https://translate.googleusercontent.com/translate_f 177/223
6/1/2021 Intitulado
Private Const HashTypeSHA512 As String = "SHA512" 'https://msdn.microsoft.com/en-
us / library / system.security.cryptography.sha512cryptoserviceprovider (v = frente a 110) .aspx
https://riptutorial.com/ 191
Página 207
uFileCount = 0
Si oRnd no es nada, entonces establezca oRnd = New Random 'Class de Microsoft: Random
Si oFSO no es nada, establezca oFSO = CreateObject ("Scripting.FileSystemObject") 'Solo para
obtener FileSize correcto
Si oCSP no es nada, establezca oCSP = CreateObject ("System.Security.Cryptography." &
sHashType y "CryptoServiceProvider")
Application.StatusBar = False
Application.ScreenUpdating = True
oCSP.Clear
Establecer oCSP = Nada
Establecer oRng = Nada
Establecer oFSO = Nada
Establecer oRnd = Nada
Debug.Print "Recuento total de archivos:" & uFileCount
End Sub
https://riptutorial.com/ 192
Página 208
https://translate.googleusercontent.com/translate_f 178/223
6/1/2021 Intitulado
Función privada GetFileHash (ByVal sFile como cadena, ByVal uBlockSize como doble, ByVal
sHashType como cadena) como cadena
Dim uBytesRead como doble, uBytesToRead como doble, bDone como booleano
Dim aBlock () As Byte, aBytes As Variant 'Arrays para almacenar bytes
Dim aHash () como byte, sHash como cadena, i tan largo, oTmp como variante
Dim uFileSize As Double 'Un-Comment si GetFileHash () se va a utilizar individualmente
Si oRnd no es nada, entonces establezca oRnd = New Random 'Class de Microsoft: Random
Si oFSO no es nada, establezca oFSO = CreateObject ("Scripting.FileSystemObject") 'Solo para
obtener FileSize correcto
Si oCSP no es nada, establezca oCSP = CreateObject ("System.Security.Cryptography." &
sHashType y "CryptoServiceProvider")
https://riptutorial.com/ 193
Página 209
uBytesToRead = uBlockSize
Más
uBytesToRead = uFileSize - uBytesRead
bDone = Verdadero
Terminara si
'Leer en algunos bytes
aBytes = .ReadBytes (uBytesToRead)
aBlock = aBytes
Si bDone entonces
https://translate.googleusercontent.com/translate_f 179/223
6/1/2021 Intitulado
oCSP.TransformFinalBlock aBlock, 0, uBytesToRead
uBytesRead = uBytesRead + uBytesToRead
Más
uBytesRead = uBytesRead + oCSP.TransformBlock (aBlock, 0, uBytesToRead,
aBloque, 0)
Terminara si
DoEvents
Bucle hasta bDone
.Cerrar el archivo
No puede abrir el archivo:
If Err.Number <> 0 Then 'Cambie el código hash a la descripción del error
oTmp = Dividir (Err.Description, vbCrLf)
sHash = oTmp (1) & ":" & oTmp (2)
Terminara si
Terminar con
Terminara si
Si bDone entonces
'convierte la matriz de bytes Hash en una cadena hexadecimal
aHash = oCSP.hash
Para i = 0 a UBound (aHash)
Mid $ (sHash, i * 2 + (aHash (i)> 15) + 2) = Hex (aHash (i))
próximo
Terminara si
GetFileHash = sHash
Función final
https://riptutorial.com/ 194
Página 210
Ver Recurrencia .
Observaciones
La recursividad permite llamadas repetidas y autoreferenciadas de un procedimiento.
https://translate.googleusercontent.com/translate_f 180/223
6/1/2021 Intitulado
Ejemplos
Factoriales
Recurrencia de carpeta
Sub EnumerateFilesAndFolders (_
FolderPath como cadena, _
MaxDepth opcional siempre que = -1, _
CurrentDepth opcional tan largo = 0, _
Sangría opcional tan larga = 2)
https://riptutorial.com/ 195
Página 211
https://translate.googleusercontent.com/translate_f 181/223
6/1/2021 Intitulado
https://riptutorial.com/ 196
Página 212
Debe agregar Microsoft Scripting Runtime al proyecto VBA a través de las herramientas de VBE →
Comando de referencias para implementar el enlace anticipado del objeto Diccionario de secuencias de comandos. Esta
la referencia de la biblioteca se lleva con el proyecto; no tiene que ser re-referenciado cuando el VBA
El proyecto se distribuye y ejecuta en otra computadora.
Ejemplos
Propiedades y métodos
UN El objeto Diccionario de secuencias de comandos almacena información en pares Clave / Elemento. Las claves deben ser únicas y
no es una matriz, pero los elementos asociados se pueden repetir (su singularidad está en manos del compañero
Key) y puede ser de cualquier tipo de variante u objeto.
Un diccionario puede considerarse como una base de datos en memoria de dos campos con un índice primario único en
el primer 'campo' (la Clave ). Este índice único en la propiedad Keys permite 'búsquedas' muy rápidas para
recuperar el valor del artículo asociado a una clave.
Propiedades
https://translate.googleusercontent.com/translate_f 182/223
6/1/2021 Intitulado
Contar leer
solamente largo sin firmar
entero Un recuento
objeto basado endeuno
de diccionario de los pares
secuencias clave / elemento en el
de comandos.
Métodos
https://riptutorial.com/ 197
Página 213
nombre descripción
Agrega una clave y un elemento nuevos al diccionario. La nueva clave no debe existir en el
Agregar ( clave ,
colección de claves actual del diccionario, pero un elemento se puede repetir entre muchos
Artículo )
claves únicas.
Existe ( clave ) Prueba booleana para determinar si una clave ya existe en el diccionario.
Eliminar(
Elimina una clave de diccionario individual y su elemento asociado.
Clave )
Código de muestra
'rellenar el diccionario
dict.Add Key: = "Red", Item: = "Balloon"
dict.Add Key: = "Green", Item: = "Balloon"
dict.Add Key: = "Blue", Item: = "Balloon"
End Sub
https://translate.googleusercontent.com/translate_f 183/223
6/1/2021 Intitulado
'rellenar el diccionario
dict.Add Key: = "Red", Item: = "Balloon"
https://riptutorial.com/ 198
Página 214
End Sub
Los diccionarios son excelentes para administrar información donde ocurren múltiples entradas, pero solo
relacionado con un solo valor para cada conjunto de entradas: el primer o último valor, el mínimo o
valor máximo, un promedio, una suma, etc.
Considere un libro de trabajo que contiene un registro de la actividad del usuario, con un script que inserta el nombre de usuario y
editar la fecha cada vez que alguien edita el libro de trabajo:
UN segundo
https://riptutorial.com/ 199
https://translate.googleusercontent.com/translate_f 184/223
6/1/2021 Intitulado
Página 215
UN segundo
Supongamos que desea generar la última hora de edición para cada usuario, en una hoja de trabajo llamada Resumen .
Notas:
1. Se supone que los datos están en ActiveWorkbook .
2. Estamos usando una matriz para extraer los valores de la hoja de trabajo; esto es más eficiente que iterar sobre cada celda.
3. El diccionario se crea utilizando el enlace anticipado.
Sub LastEdit ()
Dim vLog como variante, vKey como variante
Dim dict como nueva secuencia de comandos.
Atenuar lastRow como entero, lastColumn como entero
Dim i as Long
Ancla tenue como rango
Con ActiveWorkbook
Con .Sheets ("Registro")
'Extraiga las entradas del "registro" en una matriz de variantes
lastRow = .Range ("a" & .Rows.Count) .End (xlUp) .Row
vlog = .Range ("a1", .Cells (lastRow, 2)). Value2
https://riptutorial.com/ 200
Página 216
UN segundo
https://translate.googleusercontent.com/translate_f 185/223
6/1/2021 Intitulado
Si, por otro lado, desea generar la cantidad de veces que cada usuario editó el libro de trabajo, el cuerpo
del bucle For debería verse así:
UN segundo
Beto 2
alicia 3
El Diccionario permite obtener un conjunto único de valores de forma muy sencilla. Considere la siguiente función:
https://riptutorial.com/ 201
Página 217
https://translate.googleusercontent.com/translate_f 186/223
6/1/2021 Intitulado
https://riptutorial.com/ 202
Página 218
Creando un FileSystemObject
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
Sub FsoExample ()
Dim fso As Object 'declarar variable
Establecer fso = CreateObject ("Scripting.FileSystemObject") 'Establecer como un objeto del sistema de archivos
https://translate.googleusercontent.com/translate_f 187/223
6/1/2021 Intitulado
Leer un archivo de texto usando un FileSystemObject
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
Sub ReadTextFileExample ()
Dim fso como objeto
Establecer fso = CreateObject ("Scripting.FileSystemObject")
https://riptutorial.com/ 203
Página 219
Sub CreateTextFileExample ()
Dim fso como objeto
Establecer fso = CreateObject ("Scripting.FileSystemObject")
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
Sub WriteTextFileExample ()
Dim oFso
Establecer oFso = CreateObject ("Scripting.FileSystemObject")
https://translate.googleusercontent.com/translate_f 188/223
6/1/2021 Intitulado
Establecer oFile = oFso.OpenTextFile (myFilePath, ForWriting)
Más
'crea el archivo en su lugar
Establecer oFile = oFso.CreateTextFile (myFilePath) 'omitiendo el booleano opcional para
sobrescribir si existe ya que ya comprobamos que el archivo no existe.
Terminara si
oFile.Write "Este es un texto nuevo"
oFile.Write "Y este texto aparecerá justo después del primer fragmento de texto".
oFile.WriteLine "Este fragmento de texto incluye un carácter de nueva línea para garantizar que cada escritura tenga
su propia línea ".
oFile.Close 'cierra el archivo
End Sub
https://riptutorial.com/ 204
Página 220
Límite tardío:
Sub EnumerateFilesAndFolders (_
FolderPath como cadena, _
MaxDepth opcional siempre que = -1, _
CurrentDepth opcional tan largo = 0, _
Sangría opcional tan larga = 2)
https://translate.googleusercontent.com/translate_f 189/223
6/1/2021 Intitulado
'Enumerar las subcarpetas
Dim subFldr como carpeta de scripts
Para cada subFldr en fldr.SubFolders
Espacio de impresión de depuración $ ((CurrentDepth + 1) * Sangría) & subFldr.Name
Si CurrentDepth <MaxDepth o MaxDepth = -1, entonces
'Llamar recursivamente a EnumerateFilesAndFolders
EnumerateFilesAndFolders subFldr.Path, MaxDepth, CurrentDepth + 1, Sangría
https://riptutorial.com/ 205
Página 221
Terminara si
Siguiente subFldr
C: \ Prueba
Documentos
Personal
Budget.xls
Recipes.doc
Trabajo
Planning.doc
Descargas
FooBar.exe
ReadMe.txt
C: \ Prueba
Documentos
Descargas
ReadMe.txt
C: \ Prueba
Documentos
Personal
Trabajo
Descargas
FooBar.exe
ReadMe.txt
Imprime MyFile.something
Tenga en cuenta que el método GetBaseName () ya maneja varios períodos en un nombre de archivo.
https://riptutorial.com/ 206
https://translate.googleusercontent.com/translate_f 190/223
6/1/2021 Intitulado
Página 222
Imprime txt Tenga en cuenta que el método GetExtensionName () ya maneja varios puntos en un nombre de archivo.
El método GetParentFolderName devuelve la carpeta principal para cualquier ruta. Si bien esto también puede ser
utilizado con carpetas, podría decirse que es más útil para extraer la ruta de una ruta de archivo absoluta:
Usando FSO.BuildPath para construir una ruta completa a partir de la ruta de la carpeta y el nombre del archivo
Si acepta la entrada del usuario para las rutas de las carpetas, es posible que deba verificar si hay barras diagonales inversas al final ( \ )
antes de crear una ruta de archivo. El método FSO.BuildPath simplifica esto:
Const sourceFilePath As String = "C: \ Temp" '<- Sin barra invertida al final
Const targetFilePath As String = "C: \ Temp \" '<- Con barra invertida al final
Salida:
C: \ Temp \ Results.txt
C: \ Temp \ Results.txt
https://riptutorial.com/ 207
Página 223
Observaciones
Cuando necesita verificar la presencia o posición de una subcadena dentro de una cadena, VBA ofrece la
Funciones InStr e InStrRev que devuelven la posición del carácter de la subcadena en la cadena, si es
presente.
Ejemplos
https://riptutorial.com/ 208
Página 224
Hay dos tipos de soluciones: 1) implementar un algoritmo de clasificación desde cero, o 2) usar
ordenar rutinas en otras bibliotecas comúnmente disponibles.
Ejemplos
https://translate.googleusercontent.com/translate_f 192/223
6/1/2021 Intitulado
Implementación de algoritmos: clasificación rápida en una matriz unidimensional
Public Sub QuickSort (vArray como variante, inLow tan largo, inHi tan largo)
tmpLow = inLow
tmpHi = inHi
Encaminarse a
End Sub
https://riptutorial.com/ 209
Página 225
SubpruebaExcelSort ()
InitArray arr
ExcelSort arr
End Sub
Const tamaño = 10
ReDim arr (tamaño)
https://translate.googleusercontent.com/translate_f 193/223
6/1/2021 Intitulado
arr (i) = tamaño - i
Siguiente yo
End Sub
Con MySort
.SortFields.Clear
.SortFields.Add rng, xlSortOnValues, xlAscending, xlSortNormal
.SetRange rng
.Encabezado = xlNo
.Aplicar
Terminar con
https://riptutorial.com/ 210
Página 226
End Sub
End Sub
https://translate.googleusercontent.com/translate_f 194/223
6/1/2021 Intitulado
https://riptutorial.com/ 211
Página 227
Al asignar cadenas literales que contienen caracteres específicos de una determinada página de códigos,
Es posible que deba considerar las preocupaciones de internacionalización asignando una cadena de un Unicode separado
archivo de recursos.
Ejemplos
La sintaxis de VBA requiere que aparezca un literal de cadena dentro de las marcas " , por lo que cuando su cadena necesita
contienen comillas, necesitará escapar / anteponer el " carácter con un extra " para que VBA
entiende que tiene la intención de que "" se interprete como una " cadena.
'Salida:
'El hombre dijo: "Nunca uses comillas de aire"
'El hombre dijo: "Nunca uses comillas de aire"
El editor de VBA solo permite 1023 caracteres por línea, pero generalmente solo los primeros 100-150 caracteres
son visibles sin desplazarse. Si necesita asignar literales de cadena larga, pero desea mantener su
código legible, necesitará usar continuaciones de línea y concatenación para asignar su cadena.
Debug.Print "Lorem ipsum dolor sit amet, consectetur adipiscing elit." & _
"Integer hendrerit maximus arcu, ut elementum odio varius" & _
"nec. Integer ipsum enim, iaculis et egestas ac, condiment" & _
"Um ut tellus".
https://translate.googleusercontent.com/translate_f 195/223
6/1/2021 Intitulado
'Salida:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Entero hendrerit maximus arcu, ut
elementum odio varius nec. Integer ipsum enim, iaculis et egestas ac, condimentum ut tellus.
VBA le permitirá usar un número limitado de continuaciones de línea (el número real varía según la longitud
de cada línea dentro del bloque continuo), por lo que si tiene cadenas muy largas, deberá asignar y
reasignar con concatenación.
https://riptutorial.com/ 212
Página 228
Debug.Print loremIpsum
'Salida:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Entero hendrerit maximus arcu, ut
elementum odio varius nec. Integer ipsum enim, iaculis et egestas ac, condimentum ut tellus.
VBA define una serie de constantes de cadena para caracteres especiales como:
Puede usar estas constantes con concatenación y otras funciones de cadena para construir cadenas literales
con caracteres especiales.
El uso de vbNullString se considera una mejor práctica que el valor equivalente de "" debido a diferencias
en cómo se compila el código. Se accede a las cadenas mediante un puntero a un área asignada de memoria,
y el compilador de VBA es lo suficientemente inteligente como para usar un puntero nulo para representar vbNullString . El literal ""
se asigna memoria como si fuera una Variante de tipo String, lo que hace que el uso de la constante sea mucho más
eficiente:
https://riptutorial.com/ 213
https://translate.googleusercontent.com/translate_f 196/223
6/1/2021 Intitulado
Página 229
https://riptutorial.com/ 214
Página 230
VBA tiene funciones integradas para extraer partes específicas de cadenas, que incluyen:
• Izquierda / Izquierda $
• Derecha / Derecha $
• Medio / Medio $
• Recortar / Recortar $
Para evitar la conversión de tipo implícita en la sobrecarga (y, por lo tanto, para un mejor rendimiento), use $ -
versión con sufijo de la función cuando se pasa una variable de cadena a la función, y / o si el resultado
de la función se asigna a una variable de cadena.
Pasar un valor de parámetro nulo a una función $ -suffixed generará un error de tiempo de ejecución ("uso no válido de
null "): esto es especialmente relevante para el código que involucra una base de datos.
Ejemplos
Use Left o Left $ para obtener los 3 caracteres más a la izquierda en una cadena
Use Right o Right $ para obtener los 3 caracteres más a la derecha en una cadena
Use Mid o Mid $ para obtener caracteres específicos dentro de una cadena
Utilice Recortar para obtener una copia de la cadena sin espacios iniciales o finales
https://riptutorial.com/ 215
Página 231
https://translate.googleusercontent.com/translate_f 198/223
6/1/2021 Intitulado
https://riptutorial.com/ 216
Página 232
Mejores prácticas
Un UserForm es un módulo de clase con un diseñador y una instancia predeterminada. El diseñador puede ser
se accede presionando Shift + F7 mientras se visualiza el código subyacente , y el código subyacente se puede
se accede presionando F7 mientras se ve el diseñador .
Al ser un módulo de clase , un formulario es, por tanto, un modelo para un objeto . Porque una forma puede contener un estado
y datos, es una mejor práctica trabajar con una nueva instancia de la clase, en lugar de con el
predeterminado / global:
https://translate.googleusercontent.com/translate_f 199/223
6/1/2021 Intitulado
Terminara si
Terminar con
En vez de:
UserForm1.Show vbModal
Si no es UserForm1.IsCancelled, entonces
'...
Terminara si
Trabajar con la instancia predeterminada puede generar errores sutiles cuando el formulario se cierra con la "X" roja
y / o cuando se usa Unload Me en el código subyacente.
Un formulario no debe preocuparse más que por la presentación : un botón Controlador de clic que se conecta a
una base de datos y ejecuta una consulta parametrizada basada en la entrada del usuario, está haciendo demasiadas cosas .
Escriba el código de tal manera que UserForm solo sea responsable de saber cómo
mostrar y recopilar datos: de dónde provienen los datos, o qué sucede con los datos después, es
nada de su preocupación.
https://riptutorial.com/ 217
Página 233
Cree un modelo bien definido para que el formulario funcione, ya sea en su propio módulo de clase dedicado o
encapsulado dentro del código subyacente del formulario: exponga el modelo con Property Get
procedimientos, y haga que el código del cliente trabaje con estos: esto hace que el formulario sea una abstracción sobre
controles y sus detalles esenciales, exponiendo solo los datos relevantes al código del cliente.
En lugar de esto:
Los formularios suelen tener un botón Cerrar , y los mensajes / diálogos tienen botones Aceptar y Cancelar ; el usuario puede
cierre el formulario usando el cuadro de control del formulario (el botón rojo "X"), que destruye la instancia del formulario
por defecto (otra buena razón para trabajar con una nueva instancia cada vez ).
https://translate.googleusercontent.com/translate_f 200/223
6/1/2021 Intitulado
If Not .IsCancelled Then 'si QueryClose no se maneja, esto puede generar un error de tiempo de ejecución.
'...
Terminar con
Terminar con
La forma más sencilla de manejar el evento QueryClose es establecer el parámetro Cancel en True y luego en
ocultar el formulario en lugar de cerrarlo :
De esa manera, el botón "X" nunca destruirá la instancia y la persona que llama puede acceder de manera segura a todos los
miembros públicos.
https://riptutorial.com/ 218
Página 234
Escóndete, no cierres.
Evite usar Unload Me en el código subyacente de un formulario. Call Me.Hide en su lugar, para que el código de llamada pueda
todavía usa el objeto que creó cuando se cierra el formulario.
Nombra cosas.
Utilice la ventana de herramientas de propiedades ( F4 ) para nombrar cuidadosamente cada control en un formulario. El nombre de un
control se usa en el código subyacente, por lo que a menos que esté usando una herramienta de refactorización que pueda manejar esto,
cambiar el nombre de un control romperá el código , por lo que es mucho más fácil hacer las cosas bien en primer lugar,
que tratar de descifrar exactamente cuál de los 20 cuadros de texto representa TextBox12 .
El problema es que cuando, por ejemplo, la interfaz de usuario se rediseña y un ComboBox cambia a un ListBox , el
El nombre debe cambiar para reflejar el nuevo tipo de control: es mejor nombrar los controles para lo que
representar, en lugar de su tipo de control, para desacoplar el código de la interfaz de usuario tanto como
posible.
Cualquiera que sea el estilo elegido, cualquier cosa es mejor que dejar todos los controles con sus nombres predeterminados.
La coherencia en el estilo de los nombres también es ideal.
Manejo de QueryClose
El evento QueryClose se genera cada vez que un formulario está a punto de cerrarse, ya sea a través de la acción del usuario
o programáticamente. El parámetro CloseMode contiene un valor de enumeración VbQueryClose que indica
cómo se cerró el formulario:
https://translate.googleusercontent.com/translate_f 201/223
6/1/2021 Intitulado
https://riptutorial.com/ 219
Página 235
Para una mejor legibilidad, es mejor usar estas constantes en lugar de usar su valor directamente.
Opción explícita
TView de tipo privado
IsCancelled como booleano
SomeOtherSetting como booleano
'otras propiedades omitidas por brevedad
Tipo final
Privado esto como TView
https://translate.googleusercontent.com/translate_f 202/223
6/1/2021 Intitulado
https://riptutorial.com/ 220
Página 236
La propiedad IsCancelled devuelve True cuando se hace clic en el botón Cancelar o cuando el usuario cierra
el formulario usando la caja de control .
https://riptutorial.com/ 221
Página 237
https://translate.googleusercontent.com/translate_f 203/223
6/1/2021 Intitulado
Sintaxis
• Opción optionName [valor]
• Opción explícita
• Opción Comparar {Texto | Binario | Base de datos}
• Opción Módulo Privado
• Base de opciones {0 | 1}
Parámetros
Opción Detalle
Hace que las comparaciones de cadenas del módulo no distingan entre mayúsculas y minúsculas, según
Comparar texto
configuración regional del sistema, priorizando la equivalencia alfabética (por ejemplo, "a" = "A").
(Solo MS-Access) Hace que las comparaciones de cadenas del módulo funcionen
Comparar base de datos
como lo harían en una declaración SQL.
Observaciones
Es mucho más fácil controlar los límites de las matrices declarando los límites explícitamente en lugar de
que dejar que el compilador recurra a una declaración {0 | 1} de Option Base . Esto se puede hacer así:
https://riptutorial.com/ 222
Página 238
Ejemplos
Opción explícita
Se considera una buena práctica usar siempre Option Explicit en VBA, ya que obliga al desarrollador a
declare todas sus variables antes de su uso. Esto también tiene otros beneficios, como la capitalización automática de
nombres de variables declaradas e IntelliSense.
https://translate.googleusercontent.com/translate_f 204/223
6/1/2021 Intitulado
Opción explícita
Sub OptionExplicit ()
Atenuar como entero
a=5
b = 10 '// Provoca un error de compilación ya que' b 'no está declarado
End Sub
Configuración Requerir declaración de variable dentro de las herramientas de VBE ► Opciones ► Editor
página de propiedades colocará la instrucción Option Explicit en la parte superior de cada nueva creación
hoja de código.
Esto evitará errores de codificación tontos, como errores ortográficos, además de influir en el uso de los
tipo de variable en la declaración de variable. (Algunos ejemplos más se dan enSIEMPRE use la opción "
Explícito " .)
https://riptutorial.com/ 223
Página 239
La comparación binaria hace que todas las verificaciones de la igualdad de cadenas dentro de un módulo / clase sean sensibles a mayúsculas y minúsculas .
Técnicamente, con esta opción, las comparaciones de cadenas se realizan utilizando el orden de clasificación del binario
representaciones de cada personaje.
Sub CompareBinary ()
https://translate.googleusercontent.com/translate_f 205/223
6/1/2021 Intitulado
End Sub
(A | a) <(B | b) <(Z | z)
Sub CompareText ()
https://riptutorial.com/ 224
Página 240
foo = "abc"
bar = "ABC"
End Sub
Nota: Se desaconseja el uso de esta configuración a menos que el módulo se utilice para escribir acceso personalizado
UDF (funciones definidas por el usuario) que deben tratar las comparaciones de texto de la misma manera que SQL
consultas en esa base de datos.
Base de opciones {0 | 1}
Option Base se
utiliza para declarar el límite inferior predeterminado de los elementos de la matriz . Se declara en el módulo
nivel y es válido solo para el módulo actual.
De forma predeterminada (y por lo tanto si no se especifica ninguna base de opción), la base es 0. Lo que significa que la primera
https://translate.googleusercontent.com/translate_f 206/223
6/1/2021 Intitulado
Ejemplo en Base 0:
Opción Base 0
Sub BaseZero ()
https://riptutorial.com/ 225
Página 241
Debug.Print myStrings (i) 'Esto imprimirá "Apple", luego "Orange", luego "Peach"
Siguiente yo
End Sub
Sub BaseOne ()
Siguiente yo
End Sub
El segundo ejemplo generó una Subíndice fuera de rango (Error 9) en la primera etapa del ciclo porque
se hizo un intento de acceder al índice 0 de la matriz, y este índice no existe como el
el módulo se declara con Base 1
Debug.Print myStrings (i) 'Esto imprimirá "Apple", luego "Orange", luego "Peach"
Siguiente yo
Cabe señalar que el La función de división siempre crea una matriz con un índice de elemento de base cero
https://translate.googleusercontent.com/translate_f 207/223
6/1/2021 Intitulado
independientemente de cualquier configuración de Option Base . Se pueden encontrar ejemplos sobre cómo usar la función Split
aquí
Función dividida
Devuelve una matriz unidimensional de base cero que contiene un número específico de subcadenas.
En Excel, las propiedades Range.Value y Range.Formula para un rango multicelular siempre devuelven un 1-
matriz de variantes 2D basada.
https://riptutorial.com/ 226
Página 242
Del mismo modo, en ADO, el método Recordset.GetRows siempre devuelve una matriz 2D basada en 1.
Una 'mejor práctica' recomendada es utilizar siempre el LBound yFunciones UBound para determinar
las extensiones de una matriz.
La Option Base 1 debe estar en la parte superior de cada módulo de código donde se crea o se vuelve a
dimensionado si las matrices se van a crear de forma coherente con un límite inferior de 1.
https://translate.googleusercontent.com/translate_f 208/223
6/1/2021 Intitulado
https://riptutorial.com/ 227
Página 243
Ejemplos
Código incorrecto
Sub DoSomething ()
GoSub DoThis
Hacer esto:
Debug.Print "¡Hola!"
Regreso
End Sub
La ejecución ingresa al procedimiento DoSomething , salta a la etiqueta DoThis , imprime "¡Hola!" a la depuración
salida, vuelve a la instrucción inmediatamente después de la llamada a GoSub , imprime "¡Hola!" otra vez, y luego
encuentra una declaración de retorno , pero no hay ningún lugar al que regresar ahora, porque no llegamos aquí
con una declaración GoSub .
Código correcto
Sub DoSomething ()
GoSub DoThis
Salir de Sub
Hacer esto:
Debug.Print "¡Hola!"
Regreso
End Sub
Al introducir una instrucción Exit Sub antes de la etiqueta de línea DoThis , hemos separado el DoThis
subrutina del resto del cuerpo del procedimiento: la única forma de ejecutar la subrutina DoThis es
a través del salto GoSub .
Otras notas
https://riptutorial.com/ 228
Página 244
https://translate.googleusercontent.com/translate_f 209/223
6/1/2021 Intitulado
Esto es muy similar a Error en tiempo de ejecución '20': reanudar sin error; en ambas situaciones, la solución es
para garantizar que la ruta de ejecución normal no pueda ingresar a una subrutina (identificada por una etiqueta de línea)
sin un salto explícito (asumiendo que On Error GoTo se considera un salto explícito ).
código incorrecto
Sub DoSomething ()
Atenuar fila como entero
Para fila = 1 a 100000
'hacer cosas
próximo
End Sub
El tipo de datos Integer es un entero de 16 bits con signo con un valor máximo de 32,767; asignándolo a
cualquier cosa más grande que eso desbordará el tipo y generará este error.
Código correcto
Sub DoSomething ()
Fila tenue tan larga
Para fila = 1 a 100000
'hacer cosas
próximo
End Sub
Al usar un entero largo (32 bits) en su lugar, ahora podemos hacer un bucle que itera más de 32,767
veces sin desbordar el tipo de variable de contador.
Otras notas
Ver Tipos de datos y límites para obtener más información.
código incorrecto
Sub DoSomething ()
Dim foo (1 a 10)
https://riptutorial.com/ 229
Página 245
foo esuna matriz que contiene 10 elementos. Cuando el contador del ciclo i alcanza un valor de 11, foo (i) está fuera
de rango . Este error ocurre siempre que se accede a una matriz o colección con un índice que no
existen en esa matriz o colección.
https://translate.googleusercontent.com/translate_f 210/223
6/1/2021 Intitulado
Código correcto
Sub DoSomething ()
Dim foo (1 a 10)
Dim i tan largo
Para i = LBound (foo) To UBound (foo)
foo (i) = i
próximo
End Sub
Utilice las funciones LBound y UBound para determinar los límites superior e inferior de una matriz,
respectivamente.
Otras notas
Cuando el índice es una cadena, por ejemplo, ThisWorkbook.Worksheets ("No existo") , este error significa que
El nombre proporcionado no existe en la colección consultada.
Sin embargo, el error real es específico de la implementación; La recopilación generará un error de tiempo de ejecución 5 "No válido
llamada a procedimiento o argumento "en su lugar:
Sub RaisesRunTimeError5 ()
Dim foo como nueva colección
foo.Añadir "foo", "foo"
Debug.Print foo ("barra")
End Sub
código incorrecto
https://riptutorial.com/ 230
Página 246
VBA está intentando realmente convertir el "42?" argumento en un valor de fecha . Cuando falla, la llamada a
DoSomethingElse no
se puede ejecutar, porque VBA no sabe qué fecha pasar, por lo que genera
error 13 en tiempo de ejecución no coincide , porque el tipo de argumento no coincide con el esperado
type (y tampoco se puede convertir implícitamente).
Código correcto
Sub público DoSomething ()
Hacer algo más ahora
End Sub
https://translate.googleusercontent.com/translate_f 211/223
6/1/2021 Intitulado
Al pasar un argumento de fecha a un procedimiento que espera un parámetro de fecha , la llamada puede tener éxito.
Error en tiempo de ejecución '91': variable de objeto o con variable de bloque no establecida
código incorrecto
Sub DoSomething ()
Colección Dim foo As
Con foo
.Añadir "ABC"
.Añadir "XYZ"
Terminar con
End Sub
Las variables de objeto contienen una referencia y las referencias deben establecerse mediante la palabra clave Set . Este error
ocurre siempre que se realiza una llamada de miembro a un objeto cuya referencia es Nothing . En este caso foo
es una referencia de colección , pero no está inicializada, por lo que la referencia contiene Nothing , y no podemos
llamar .Add en nada .
Código correcto
https://riptutorial.com/ 231
Página 247
Sub DoSomething ()
Colección Dim foo As
Set foo = Nueva colección
Con foo
.Añadir "ABC"
.Añadir "XYZ"
Terminar con
End Sub
Al asignar a la variable de objeto una referencia válida mediante la palabra clave Set , las llamadas .Add se realizan correctamente.
Otras notas
A menudo, una función o propiedad puede devolver una referencia de objeto; un ejemplo común es Excel
Método Range.Find , que devuelve un objeto Range :
Sin embargo, la función puede devolver Nothing (si no se encuentra el término de búsqueda), por lo que es probable que
la llamada del miembro .Row encadenada falla.
Antes de llamar a los miembros del objeto, verifique que la referencia esté configurada con Si no, xxxx no es nada
condición:
https://translate.googleusercontent.com/translate_f 212/223
6/1/2021 Intitulado
Si el resultado no es nada, entonces resultRow = result.Row
código incorrecto
Sub DoSomething ()
En caso de error, vaya a CleanFail
Hacer algo más
CleanFail:
Debug.Print Err.Number
Reanudar Siguiente
End Sub
Si el procedimiento DoSomethingElse genera un error, la ejecución salta a la etiqueta de línea CleanFail , imprime
el número de error, y la instrucción Reanudar siguiente salta a la instrucción que inmediatamente
https://riptutorial.com/ 232
Página 248
sigue la línea donde ocurrió el error, que en este caso es la instrucción Debug.Print : el error-
la subrutina de manejo se ejecuta sin un contexto de error, y cuando la instrucción Resume Next es
alcanzado, se genera el error 20 en tiempo de ejecución porque no hay ningún lugar al que reanudar.
Código correcto
Sub DoSomething ()
En caso de error, vaya a CleanFail
Hacer algo más
Salir de Sub
CleanFail:
Debug.Print Err.Number
Reanudar Siguiente
End Sub
Al introducir una instrucción Exit Sub antes de la etiqueta de línea CleanFail , hemos segregado
Subrutina de
manejo de errores CleanFail del resto del cuerpo del procedimiento: la única forma de ejecutar
la subrutina de manejo de errores es mediante un salto en caso de error ; por lo tanto, ninguna ruta de ejecución llega al
Reanudar la instrucción fuera de un contexto de error, lo que evita el error 20 en tiempo de ejecución.
Otras notas
Esto es muy similar a Error en tiempo de ejecución '3': retorno sin GoSub ; en ambas situaciones, la solución es
Asegúrese de que la ruta de ejecución normal no pueda entrar en una subrutina (identificada por una etiqueta de línea) sin
un salto explícito (asumiendo que On Error GoTo se considera un salto explícito ).
https://translate.googleusercontent.com/translate_f 213/223
6/1/2021 Intitulado
https://riptutorial.com/ 233
Página 249
Ejemplos
El primer paso para acceder a una fuente de datos a través de ADO es crear un objeto de conexión ADO . Esto es
Normalmente se hace usando una cadena de conexión para especificar los parámetros de la fuente de datos, aunque también es
es posible abrir una conexión DSN pasando el DSN, el ID de usuario y la contraseña al .Open
método.
Tenga en cuenta que no se requiere un DSN para conectarse a una fuente de datos a través de ADO, cualquier fuente de datos que tenga un
El proveedor de ODBC se puede conectar con la cadena de conexión adecuada. Aunque específico
Las cadenas de conexión para diferentes proveedores están fuera del alcance de este tema.
ConnectionStrings.com es una excelente referencia para encontrar la cadena adecuada para su
proveedor.
Subejemplo público ()
Dim base de datos como ADODB.Connection
Establecer base de datos = OpenDatabaseConnection (SomeDSN)
Si la base de datos no es nada, entonces
'... Hacer trabajo.
base de datos.Cerrar 'Asegúrese de cerrar todas las conexiones a la base de datos.
Terminara si
End Sub
Función de salida
Manipulador:
Debug.Print "Error en la conexión a la base de datos. Verifique la cadena de conexión".
https://translate.googleusercontent.com/translate_f 214/223
6/1/2021 Intitulado
https://riptutorial.com/ 234
Página 250
Función final
Tenga en cuenta que la contraseña de la base de datos se incluye en la cadena de conexión en el ejemplo anterior solo para
en aras de la claridad. Las mejores prácticas dictarían no almacenar las contraseñas de la base de datos en el código. Esto puede
puede lograrse tomando la contraseña a través de la entrada del usuario o usando la autenticación de Windows.
Las consultas se pueden realizar de dos formas, las cuales devuelven un objeto Recordset de ADO que es un
colección de filas devueltas. Tenga en cuenta que los dos ejemplos siguientes utilizan OpenDatabaseConnection
función de la Hacer una conexión a un ejemplo de fuente de datos por razones de brevedad.
Recuerde que la sintaxis del SQL que se pasa a la fuente de datos es específica del proveedor.
El primer método es pasar la instrucción SQL directamente al objeto Connection, y es el más fácil
método para ejecutar consultas simples:
El segundo método consiste en crear un objeto de comando ADO para la consulta que desea ejecutar. Esta
requiere un poco más de código, pero es necesario para utilizar consultas parametrizadas:
https://riptutorial.com/ 235
Página 251
https://translate.googleusercontent.com/translate_f 215/223
6/1/2021 Intitulado
.ActiveConnection = base de datos
.CommandText = "SELECT DISTINCT Item FROM Table"
.CommandType = adCmdText
Terminar con
Atenuar registros como ADODB.Recordset
'Ejecute el comando para recuperar el juego de registros.
Establecer registros = query.Execute ()
Tenga en cuenta que los comandos enviados a la fuente de datos son vulnerables a la inyección de SQL , ya sea intencionalmente
o no intencional. En general, las consultas no deben crearse concatenando la entrada del usuario de ningún tipo.
En su lugar, deben parametrizarse (ver Creación de comandos parametrizados ).
Las conexiones ADO se pueden utilizar para realizar prácticamente cualquier función de base de datos que el proveedor
Soporta vía SQL. En este caso, no siempre es necesario utilizar el Recordset devuelto por el
Función de ejecución , aunque puede ser útil para obtener asignaciones de teclas después de instrucciones INSERT
con @@ Identity o comandos SQL similares. Tenga en cuenta que el ejemplo siguiente utiliza la
Función OpenDatabaseConnection de laHacer una conexión a un ejemplo de fuente de datos para el
propósito de la brevedad.
https://riptutorial.com/ 236
Página 252
Tenga en cuenta que los comandos enviados a la fuente de datos son vulnerables a la inyección de SQL , ya sea intencionalmente
o no intencional. En general, las sentencias SQL no deben crearse concatenando la entrada del usuario de
cualquier tipo. En su lugar, deben parametrizarse (verCreación de comandos parametrizados ).
https://translate.googleusercontent.com/translate_f 216/223
6/1/2021 Intitulado
Siempre que SQL ejecutado a través de una conexión ADO necesita contener la entrada del usuario, se considera
la mejor práctica para parametrizarlo con el fin de minimizar la posibilidad de inyección SQL. Este método es
también más legible que las concatenaciones largas y facilita un código más robusto y fácil de mantener
(es decir, utilizando una función que devuelve una matriz de parámetros ).
En la sintaxis estándar de ODBC, ¿se dan los parámetros ? "marcadores de posición" en el texto de la consulta y luego
los parámetros se añaden al comando en el mismo orden en que aparecen en la consulta.
https://riptutorial.com/ 237
Página 253
Nota: El ejemplo anterior muestra una instrucción UPDATE parametrizada, pero cualquier SQL
La declaración puede tener parámetros.
https://translate.googleusercontent.com/translate_f 217/223
6/1/2021 Intitulado
https://riptutorial.com/ 238
Página 254
Ejemplos
Archivos:
Para determinar si existe un archivo, simplemente pase el nombre del archivo a la función Dir $ y pruebe para ver si
devuelve un resultado. Tenga en cuenta que Dir $ admite comodines, por lo que para probar un archivo específico , el
pathName debe probarse para asegurarse de que no los contenga. El siguiente ejemplo plantea una
error: si este no es el comportamiento deseado, la función se puede cambiar para simplemente devolver False .
Archivo de función pública Existe (nombre de ruta como cadena) como booleano
Si InStr (1, pathName, "*") O InStr (1, pathName, "?") Entonces
'Función de salida' Devuelve falso en comodines.
Err.Raise 52 'Error de subida en comodines.
Terminara si
FileExists = Dir $ (nombre de ruta) <> vbNullString
Función final
https://translate.googleusercontent.com/translate_f 218/223
6/1/2021 Intitulado
La función Dir $ () también se puede utilizar para determinar si existe una carpeta especificando el paso
vbDirectory para
el parámetro de atributos opcionales . En este caso, el valor de pathName pasado debe terminar
con un separador de ruta ( \ ), ya que los nombres de archivo coincidentes provocarán falsos positivos. Tenga en cuenta que salvaje
Las tarjetas solo se permiten después del último separador de ruta, por lo que la función de ejemplo a continuación arrojará un
error de tiempo de ejecución 52 - "Nombre o número de archivo incorrecto" si la entrada contiene un comodín. Si este no es el
comportamiento deseado, descomente On Error Resume Next en la parte superior de la función. También recuerda que
Dir $ admiterutas de archivo relativas (es decir, .. \ Foo \ Bar ), por lo que solo se garantiza que los resultados sean válidos mientras
ya que el directorio de trabajo actual no se modifica.
https://riptutorial.com/ 239
Página 255
Función final
La instrucción ChDir también se puede utilizar para probar si existe una carpeta. Tenga en cuenta que este método
cambiar temporalmente el entorno en el que se ejecuta VBA, por lo que si eso es una consideración, el Dir $
en su lugar, debería utilizarse el método. Tiene la ventaja de ser mucho menos indulgente con su
parámetro. Este método también admite rutas de archivo relativas, por lo que tiene la misma advertencia que Dir $
método.
NOTA: Para mayor brevedad, los ejemplos siguientes utilizan la función FolderExists de Determining If
Ejemplo de Carpetas y archivos existentes en este tema.
La instrucción MkDir se puede utilizar para crear una nueva carpeta. Acepta rutas que contienen letras de unidad (
C: \ Foo ), nombres UNC ( \\ Server \ Foo ), rutas relativas ( .. \ Foo ) o el directorio de trabajo actual ( Foo ).
Si se omite el nombre de la unidad o UNC (es decir, \ Foo ), la carpeta se crea en la unidad actual. Esto puede
o puede que no sea la misma unidad que el directorio de trabajo actual.
https://translate.googleusercontent.com/translate_f 219/223
6/1/2021 Intitulado
Nombre de ruta de MkDir
End Sub
La instrucción RmDir se puede utilizar para eliminar carpetas existentes. Acepta caminos en las mismas formas que
MkDir yusa la misma relación con el directorio de trabajo y la unidad actuales. Tenga en cuenta que el
La declaración es similar al comando de shell rd de Windows , por lo que arrojará un error 75 en tiempo de ejecución: "Ruta / Archivo
error de acceso "si el directorio de destino no está vacío.
https://riptutorial.com/ 240
Página 256
https://translate.googleusercontent.com/translate_f 220/223
6/1/2021 Intitulado
https://riptutorial.com/ 241
Página 257
Créditos
S.
Capítulos Colaboradores
No
7 Colecciones Comintern
Copiar, devolver y
12 Mark.R
pasando matrices
CreateObject vs.
13 Branislav Kollár ,Dave , Tim
GetObject
https://riptutorial.com/ 242
Página 258
Declarar y asignar
19 Comintern ,ThunderFrame
instrumentos de cuerda
Midiendo la longitud de
27 Steve Rindsberg, ThunderFrame
instrumentos de cuerda
Pasando argumentos por Ref Branislav Kollár ,Comintern, Taza de Mat, R3uK ,
32
o ByVal RamenChef ,ZygD
33 Llamadas a procedimientos Macro hombre ,Taza de Mat, Neil Mussett, Sam Johnson
https://riptutorial.com/ 243
Página 259
https://translate.googleusercontent.com/translate_f 222/223
6/1/2021 Intitulado
39 Clasificación Neil Mussett
Literales de cadena - Escapar,
40 caracteres no imprimibles Comintern ,ThunderFrame
y continuaciones de línea
44 Errores en tiempo de ejecución de VBA Branislav Kollár ,Hombre macro, Taza de Mat
https://riptutorial.com/ 244
https://translate.googleusercontent.com/translate_f 223/223