Los métodos de la clase de acceso a la base de datos utilizarán el motor Jet para acceder a la base de datos, a través de las funciones que DAO proporciona.
Ejemplo resuelto
Utilizaremos la clase ClaFicha ya definida.
Utilizaremos la clase ClaFicha ya definida.
ModDefiniciones
'_______________________________________________________________________
' Ejemplo 6 del Curso de Visual Basic Avanzado
'' Archivo con el estándar de devolución de las funciones.
'_______________________________________________________________________
Option Explicit
Public Enum CodigoRetorno
Error = 0
Ok = 1
'_______________________________________________________________________
'' Archivo con el estándar de devolución de las funciones.
'_______________________________________________________________________
Option Explicit
Public Enum CodigoRetorno
Error = 0
Ok = 1
FrmAgenda
'_______________________________________________________________________
' Ejemplo 6 del Curso de Visual Basic Avanzado
'' Interfaz del usuario con la base de datos, aquí están los métodos de mantenimiento de
' la base de datos.
'_______________________________________________________________________
Option Explicit
Dim ObjAgenda As New ClaAgenda
Dim IntNumFichaActual As Integer
Private Sub ButBorrarFicha_Click()
' Confirmamos el borrado
If MsgBox("¿Desea eliminar la ficha actual?", vbYesNo, "Borrado de ficha") = vbNo Then
Exit Sub
End If
' Borramos la ficha actual
ObjAgenda.BorrarFicha IntNumFichaActual
' Actualizamos el número de elementos de la barra de scroll
If ObjAgenda.IntNumFichas > 0 Then
HScroll1.Max = ObjAgenda.IntNumFichas - 1
Else
HScroll1.Max = 0
End If
' Actualizamos la barra de scroll
ActualizarFormulario
End Sub
Private Sub ButCrearFicha_Click()
' Creamos una nueva ficha con los datos introducidos por el
' usuario, y obtenemos el código de la ficha creada
IntNumFichaActual = ObjAgenda.CrearFicha(TxtNombre, TxtApellidos, TxtDireccion, _
TxtTelefono)
' Comprobamos si no ha podido insertar una nueva ficha, lo que
' sucederá si IntNumFichaActual=0
If IntNumFichaActual = 0 Then
' Decrementamos el número de elementos de la barra de
' scroll
HScroll1.Max = HScroll1.Max - 1
' Actualizamos el formulario
ActualizarFormulario
Exit Sub
End If
' Actualizamos el título del frame
Frame1.Caption = "Ficha " & IntNumFichaActual
' Deshabilitamos el botón de crear ficha y el frame
ButCrearFicha.Enabled = False
Frame1.Enabled = False
' Habilitamos los botones de nueva ficha y borrar
' ficha, así como la barra de scroll
ButNuevaFicha.Enabled = True
ButBorrarFicha.Enabled = True
HScroll1.Enabled = True
End Sub
Private Sub ButNuevaFicha_Click()
Dim IntNumFichas As Integer
' Actualizamos la barra de scroll
IntNumFichas = ObjAgenda.IntNumFichas
If IntNumFichas = 0 Then
' Con la primera ficha creada, habilitamos
' la barra de scroll
HScroll1.Enabled = True
Frame1.Enabled = True
Else
' Establecemos el número de elementos de
' la barra de scroll
HScroll1.Max = HScroll1.Max + 1
HScroll1.Value = HScroll1.Max
End If
' Habilitamos el botón de crear ficha y el frame
ButCrearFicha.Enabled = True
Frame1.Enabled = True
' Deshabilitamos los botones de nueva ficha y borrar
' ficha, así como la barra de scroll
ButNuevaFicha.Enabled = False
ButBorrarFicha.Enabled = False
HScroll1.Enabled = False
End Sub
Private Sub Form_Load()
Dim IntNumFichas As Integer
' Comprobamos si no hay datos en la agenda para
' deshabilitar las opciones
IntNumFichas = ObjAgenda.IntNumFichas
If IntNumFichas = 0 Then
' Deshabilitamos el frame, la barra de scroll,
' el botón de crear ficha y el botón de borrar ficha
Frame1.Enabled = False
HScroll1.Enabled = False
ButCrearFicha.Enabled = False
ButBorrarFicha.Enabled = False
' Establecemos los límites de la barra de scroll
HScroll1.Max = 0
Else
' Establecemos el máximo de la barra de scroll
HScroll1.Max = IntNumFichas - 1
' Actualizamos el formulario
ActualizarFormulario
End If
End Sub
Private Sub Form_Unload(Cancel As Integer)
' Eliminamos la agenda
Set ObjAgenda = Nothing
End Sub
Private Sub HScroll1_Change()
' Actualizamos la barra de scroll
ActualizarFormulario
End Sub
Private Function ActualizarFormulario()
Dim ObjFicha As ClaFicha
' Comprobamos si no hay fichas o estamos creando una ficha nueva
If HScroll1.Max = ObjAgenda.IntNumFichas Then
' Limpiamos los datos del frame
TxtNombre = vbNullString
TxtApellidos = vbNullString
TxtDireccion = vbNullString
TxtTelefono = vbNullString
' Actualizamos el título del frame
Frame1.Caption = vbNullString
' Deshabilitamos el botón de borrado
ButBorrarFicha.Enabled = False
Else
' Obtenemos la ficha correspondiente de la agenda
' (buscamos por índice, no por código de ficha)
Set ObjFicha = New ClaFicha
Set ObjFicha = ObjAgenda.Ficha(HScroll1.Value + 1)
' Sacamos los datos de la ficha
If Not ObjFicha Is Nothing Then
TxtNombre = ObjFicha.StrNombre
TxtApellidos = ObjFicha.StrApellidos
TxtDireccion = ObjFicha.StrDireccion
TxtTelefono = ObjFicha.StrTelefono
' Actualizamos el código de la ficha actual
IntNumFichaActual = ObjFicha.IntNumFicha
' Eliminamos el objeto ficha creado
Set ObjFicha = Nothing
' Actualizamos el frame
Frame1.Caption = "Ficha " & IntNumFichaActual
End If
End If
End Function
'_______________________________________________________________________
' Ejemplo 6 del Curso de Visual Basic Avanzado
'' Interfaz del usuario con la base de datos, aquí están los métodos de mantenimiento de
' la base de datos.
'_______________________________________________________________________
Option Explicit
Dim ObjAgenda As New ClaAgenda
Dim IntNumFichaActual As Integer
Private Sub ButBorrarFicha_Click()
' Confirmamos el borrado
If MsgBox("¿Desea eliminar la ficha actual?", vbYesNo, "Borrado de ficha") = vbNo Then
Exit Sub
End If
' Borramos la ficha actual
ObjAgenda.BorrarFicha IntNumFichaActual
' Actualizamos el número de elementos de la barra de scroll
If ObjAgenda.IntNumFichas > 0 Then
HScroll1.Max = ObjAgenda.IntNumFichas - 1
Else
HScroll1.Max = 0
End If
' Actualizamos la barra de scroll
ActualizarFormulario
End Sub
Private Sub ButCrearFicha_Click()
' Creamos una nueva ficha con los datos introducidos por el
' usuario, y obtenemos el código de la ficha creada
IntNumFichaActual = ObjAgenda.CrearFicha(TxtNombre, TxtApellidos, TxtDireccion, _
TxtTelefono)
' Comprobamos si no ha podido insertar una nueva ficha, lo que
' sucederá si IntNumFichaActual=0
If IntNumFichaActual = 0 Then
' Decrementamos el número de elementos de la barra de
' scroll
HScroll1.Max = HScroll1.Max - 1
' Actualizamos el formulario
ActualizarFormulario
Exit Sub
End If
' Actualizamos el título del frame
Frame1.Caption = "Ficha " & IntNumFichaActual
' Deshabilitamos el botón de crear ficha y el frame
ButCrearFicha.Enabled = False
Frame1.Enabled = False
' Habilitamos los botones de nueva ficha y borrar
' ficha, así como la barra de scroll
ButNuevaFicha.Enabled = True
ButBorrarFicha.Enabled = True
HScroll1.Enabled = True
End Sub
Private Sub ButNuevaFicha_Click()
Dim IntNumFichas As Integer
' Actualizamos la barra de scroll
IntNumFichas = ObjAgenda.IntNumFichas
If IntNumFichas = 0 Then
' Con la primera ficha creada, habilitamos
' la barra de scroll
HScroll1.Enabled = True
Frame1.Enabled = True
Else
' Establecemos el número de elementos de
' la barra de scroll
HScroll1.Max = HScroll1.Max + 1
HScroll1.Value = HScroll1.Max
End If
' Habilitamos el botón de crear ficha y el frame
ButCrearFicha.Enabled = True
Frame1.Enabled = True
' Deshabilitamos los botones de nueva ficha y borrar
' ficha, así como la barra de scroll
ButNuevaFicha.Enabled = False
ButBorrarFicha.Enabled = False
HScroll1.Enabled = False
End Sub
Private Sub Form_Load()
Dim IntNumFichas As Integer
' Comprobamos si no hay datos en la agenda para
' deshabilitar las opciones
IntNumFichas = ObjAgenda.IntNumFichas
If IntNumFichas = 0 Then
' Deshabilitamos el frame, la barra de scroll,
' el botón de crear ficha y el botón de borrar ficha
Frame1.Enabled = False
HScroll1.Enabled = False
ButCrearFicha.Enabled = False
ButBorrarFicha.Enabled = False
' Establecemos los límites de la barra de scroll
HScroll1.Max = 0
Else
' Establecemos el máximo de la barra de scroll
HScroll1.Max = IntNumFichas - 1
' Actualizamos el formulario
ActualizarFormulario
End If
End Sub
Private Sub Form_Unload(Cancel As Integer)
' Eliminamos la agenda
Set ObjAgenda = Nothing
End Sub
Private Sub HScroll1_Change()
' Actualizamos la barra de scroll
ActualizarFormulario
End Sub
Private Function ActualizarFormulario()
Dim ObjFicha As ClaFicha
' Comprobamos si no hay fichas o estamos creando una ficha nueva
If HScroll1.Max = ObjAgenda.IntNumFichas Then
' Limpiamos los datos del frame
TxtNombre = vbNullString
TxtApellidos = vbNullString
TxtDireccion = vbNullString
TxtTelefono = vbNullString
' Actualizamos el título del frame
Frame1.Caption = vbNullString
' Deshabilitamos el botón de borrado
ButBorrarFicha.Enabled = False
Else
' Obtenemos la ficha correspondiente de la agenda
' (buscamos por índice, no por código de ficha)
Set ObjFicha = New ClaFicha
Set ObjFicha = ObjAgenda.Ficha(HScroll1.Value + 1)
' Sacamos los datos de la ficha
If Not ObjFicha Is Nothing Then
TxtNombre = ObjFicha.StrNombre
TxtApellidos = ObjFicha.StrApellidos
TxtDireccion = ObjFicha.StrDireccion
TxtTelefono = ObjFicha.StrTelefono
' Actualizamos el código de la ficha actual
IntNumFichaActual = ObjFicha.IntNumFicha
' Eliminamos el objeto ficha creado
Set ObjFicha = Nothing
' Actualizamos el frame
Frame1.Caption = "Ficha " & IntNumFichaActual
End If
End If
End Function
'_______________________________________________________________________
' Ejemplo 6 del Curso de Visual Basic Avanzado
'' Métodos para acceder a los métodos de la clase, que serán los que tienen acceso a la
' base de datos.
'_______________________________________________________________________
Option Explicit
Private ObjAccesoBD As New ClaDAO_Jet 'Objeto de acceso a la base de datos
' Método para obtener el número de fichas de la agenda
Public Property Get IntNumFichas() As Integer
IntNumFichas = ObjAccesoBD.NumFichas
End Property
' Método para crear una ficha nueva en la agenda
Public Function CrearFicha(ByVal StrNombre As String, _
ByVal StrApellidos As String, ByVal StrDireccion As String, _
ByVal StrTelefono As String) As Integer
Static IntNumFicha As Integer
Dim ObjFicha As ClaFicha
' Creamos un nuevo objeto de la clase ficha
Set ObjFicha = New ClaFicha
' Establecemos las propiedades de la nueva ficha
ObjFicha.StrNombre = StrNombre
ObjFicha.StrApellidos = StrApellidos
ObjFicha.StrDireccion = StrDireccion
ObjFicha.StrTelefono = StrTelefono
' Insertamos la nueva ficha en la base de datos
If ObjAccesoBD.GuardarFicha(ObjFicha, IntNumFicha) = Ok Then
' Devolvemos el código de la ficha creada
CrearFicha = IntNumFicha
Else
' Devolvemos 0, porque es un valor que nunca aparecerá
' en un campo autonumérico
CrearFicha = 0
MsgBox "Imposible agregar una nueva ficha"
End If
' Eliminamos el objeto Ficha creado
Set ObjFicha = Nothing
End Function
' Método para borrar una ficha de la agenda
Public Function BorrarFicha(ByVal IntNumFicha As Integer)
Dim ObjFicha As ClaFicha
If ObjAccesoBD.BorrarFicha(IntNumFicha) = Error Then
MsgBox "Imposible borrar la ficha nº " & IntNumFicha
End If
End Function
' Al eliminar la agenda, cerraremos la base de datos y
' eliminaremos el objeto de acceso a la base de datos
Private Sub Class_Terminate()
If ObjAccesoBD.CerrarAgenda() = Error Then
MsgBox "Imposible cerrar la agenda"
End If
Set ObjAccesoBD = Nothing
End Sub
' Método para obtener una ficha específica de la agenda, ya sea
' por índice o por número de ficha
'
' NOTA: la función crea un nuevo objeto Ficha, que habrá que
' eliminar en la función de llamada
Public Function Ficha(Optional ByVal IntIndice As Integer, _
Optional ByVal IntNumFicha As Integer) As ClaFicha
Dim ObjFicha As New ClaFicha
' Comprobamos si se busca por índice
If Not IsMissing(IntIndice) Then
If ObjAccesoBD.ObtenerFicha(ObjFicha, IntIndice) = Error Then
MsgBox "Imposible obtener la ficha de la posición nº " & IntIndice
Exit Function
End If
ElseIf Not IsMissing(IntNumFicha) Then
If ObjAccesoBD.ObtenerFicha(ObjFicha, , IntNumFicha) = Error Then
MsgBox "Imposible obtener la ficha nº " & IntNumFicha
Exit Function
End If
End If
Set Ficha = ObjFicha
Set ObjFicha = Nothing
End Function
'_______________________________________________________________________
' Ejemplo 6 del Curso de Visual Basic Avanzado
'' Métodos para acceder a los métodos de la clase, que serán los que tienen acceso a la
' base de datos.
'_______________________________________________________________________
Option Explicit
Private ObjAccesoBD As New ClaDAO_Jet 'Objeto de acceso a la base de datos
' Método para obtener el número de fichas de la agenda
Public Property Get IntNumFichas() As Integer
IntNumFichas = ObjAccesoBD.NumFichas
End Property
' Método para crear una ficha nueva en la agenda
Public Function CrearFicha(ByVal StrNombre As String, _
ByVal StrApellidos As String, ByVal StrDireccion As String, _
ByVal StrTelefono As String) As Integer
Static IntNumFicha As Integer
Dim ObjFicha As ClaFicha
' Creamos un nuevo objeto de la clase ficha
Set ObjFicha = New ClaFicha
' Establecemos las propiedades de la nueva ficha
ObjFicha.StrNombre = StrNombre
ObjFicha.StrApellidos = StrApellidos
ObjFicha.StrDireccion = StrDireccion
ObjFicha.StrTelefono = StrTelefono
' Insertamos la nueva ficha en la base de datos
If ObjAccesoBD.GuardarFicha(ObjFicha, IntNumFicha) = Ok Then
' Devolvemos el código de la ficha creada
CrearFicha = IntNumFicha
Else
' Devolvemos 0, porque es un valor que nunca aparecerá
' en un campo autonumérico
CrearFicha = 0
MsgBox "Imposible agregar una nueva ficha"
End If
' Eliminamos el objeto Ficha creado
Set ObjFicha = Nothing
End Function
' Método para borrar una ficha de la agenda
Public Function BorrarFicha(ByVal IntNumFicha As Integer)
Dim ObjFicha As ClaFicha
If ObjAccesoBD.BorrarFicha(IntNumFicha) = Error Then
MsgBox "Imposible borrar la ficha nº " & IntNumFicha
End If
End Function
' Al eliminar la agenda, cerraremos la base de datos y
' eliminaremos el objeto de acceso a la base de datos
Private Sub Class_Terminate()
If ObjAccesoBD.CerrarAgenda() = Error Then
MsgBox "Imposible cerrar la agenda"
End If
Set ObjAccesoBD = Nothing
End Sub
' Método para obtener una ficha específica de la agenda, ya sea
' por índice o por número de ficha
'
' NOTA: la función crea un nuevo objeto Ficha, que habrá que
' eliminar en la función de llamada
Public Function Ficha(Optional ByVal IntIndice As Integer, _
Optional ByVal IntNumFicha As Integer) As ClaFicha
Dim ObjFicha As New ClaFicha
' Comprobamos si se busca por índice
If Not IsMissing(IntIndice) Then
If ObjAccesoBD.ObtenerFicha(ObjFicha, IntIndice) = Error Then
MsgBox "Imposible obtener la ficha de la posición nº " & IntIndice
Exit Function
End If
ElseIf Not IsMissing(IntNumFicha) Then
If ObjAccesoBD.ObtenerFicha(ObjFicha, , IntNumFicha) = Error Then
MsgBox "Imposible obtener la ficha nº " & IntNumFicha
Exit Function
End If
End If
Set Ficha = ObjFicha
Set ObjFicha = Nothing
End Function
ClaDAO_Jet
'_______________________________________________________________________
' Ejemplo 6 del Curso de Visual Basic Avanzado
'' Clase de acceso a bases de datos utilizando DAO y
' funciones EXCLUSIVAS de Jet
'_______________________________________________________________________
Option Explicit
Private VarBD As Database
Private VarPathBD As String
Private Const ConNombreTabla = "Agenda"
Public Property Get NumFichas() As Integer
On Error GoTo TratamientoError
Dim RsetTabla As Recordset
' Abrimos un recordset de tipo dbOpentable
Set RsetTabla = VarBD.OpenRecordset(ConNombreTabla, dbOpenTable)
' Obtenemos el número de elementos
NumFichas = RsetTabla.RecordCount
' Cerramos el Recordset
RsetTabla.Close
Exit Property
TratamientoError:
NumFichas = -1
End Property
Public Function AbrirAgenda() As CodigoRetorno
On Error GoTo TratamientoError
' Abrimos la base de datos, utilizando el Workspace
' por defecto
Set VarBD = DBEngine.Workspaces(0).OpenDatabase(VarPathBD)
AbrirAgenda = Ok
Exit Function
TratamientoError:
AbrirAgenda = Error
End Function
Public Function CerrarAgenda() As CodigoRetorno
On Error GoTo TratamientoError
' Cerramos la base de datos
VarBD.Close
CerrarAgenda = Ok
Exit Function
TratamientoError:
CerrarAgenda = Error
End Function
Public Function GuardarFicha(ByVal ObjFicha As ClaFicha, _
Optional ByRef IntNumFicha As Integer) As CodigoRetorno
On Error GoTo TratamientoError
Dim RsetTabla As Recordset
' Abrimos un recordset de tipo dbOpenTable (sólo funciona
' en Jet)
Set RsetTabla = VarBD.OpenRecordset(ConNombreTabla, dbOpenTable)
With RsetTabla
' Añadimos una nueva ficha
.AddNew
!Nombre = ObjFicha.StrNombre
!Apellidos = ObjFicha.StrApellidos
!Direccion = ObjFicha.StrDireccion
!Telefono = ObjFicha.StrTelefono
' Obtenemos el campo NumFicha
IntNumFicha = !NumFicha
.Update
End With
' Cerramos el recordset
RsetTabla.Close
GuardarFicha = Ok
Exit Function
TratamientoError:
GuardarFicha = Error
End Function
Public Function ObtenerFicha(ByRef ObjFicha As ClaFicha, _
Optional ByVal IntIndice As Integer, _
Optional ByVal IntNumFicha As Integer) As CodigoRetorno
On Error GoTo TratamientoError
Dim RsetTabla As Recordset
' Comprobamos si hay que buscar por índice
If Not IsMissing(IntIndice) Then
' Abrimos un recordset de tipo dbOpenForwardOnly, para poder
' movernos con MoveNext (lo abrimos ForwardOnly porque sólo
' necesitamos desplazarnos hacia delante)
Set RsetTabla = VarBD.OpenRecordset(ConNombreTabla, dbOpenForwardOnly)
' Recorremos el Recordset hasta encontrar la ficha indicada
With RsetTabla
Do Until .EOF
If .RecordCount = IntIndice Then
Exit Do
End If
.MoveNext
Loop
End With
' Comprobamos si hay que buscar por número de ficha
ElseIf Not IsMissing(IntNumFicha) Then
' Abrimos un recordset de tipo dbOpenSnapshot, para poder
' buscar con FindFirst
Set RsetTabla = VarBD.OpenRecordset(ConNombreTabla, dbOpenSnapshot)
With RsetTabla
' Llenamos el Recordset
.MoveLast
' Encontramos el primer registro con ese número
.FindFirst "NumFicha=" & IntNumFicha
End With
End If
' Comprobamos si la hemos encontrado, o hemos llegado al
' final del Recordset sin encontrarla
With RsetTabla
If .EOF Or .NoMatch = True Then
ObtenerFicha = Error
Else
' Guardamos los datos obtenidos
ObjFicha.StrNombre = !Nombre
ObjFicha.StrApellidos = !Apellidos
ObjFicha.StrDireccion = !Direccion
ObjFicha.StrTelefono = !Telefono
ObjFicha.IntNumFicha = !NumFicha
ObtenerFicha = Ok
End If
End With
' Cerramos el Recordset
RsetTabla.Close
Exit Function
TratamientoError:
ObtenerFicha = Error
End Function
Public Function BorrarFicha(ByVal IntNumFicha) As CodigoRetorno
On Error GoTo TratamientoError
Dim RsetTabla As Recordset
' Abrimos un recordset de tipo dbOpenDynaset, para poder
' buscar con FindFirst y borrar con Delete
Set RsetTabla = VarBD.OpenRecordset(ConNombreTabla, dbOpenDynaset)
' Buscamos la ficha correspondiente
With RsetTabla
' Llenamos el Recordset
.MoveLast
' Encontramos el primer registro con ese número
.FindFirst "NumFicha=" & IntNumFicha
' Comprobamos si hemos encontrado algún registro
If .NoMatch Then
BorrarFicha = Error
Else
' Borramos la ficha obtenida
.Delete
BorrarFicha = Ok
End If
' Cerramos el Recordset
.Close
End With
BorrarFicha = Ok
Exit Function
TratamientoError:
BorrarFicha = Error
End Function
Private Sub Class_Initialize()
' Establecemos el path donde está el archivo de
' la base de datos
VarPathBD = App.Path & "\bdAgenda.mdb"
' Abrirmos la base de datos
AbrirAgenda
End Sub
'_______________________________________________________________________
' Ejemplo 6 del Curso de Visual Basic Avanzado
'' Clase de acceso a bases de datos utilizando DAO y
' funciones EXCLUSIVAS de Jet
'_______________________________________________________________________
Option Explicit
Private VarBD As Database
Private VarPathBD As String
Private Const ConNombreTabla = "Agenda"
Public Property Get NumFichas() As Integer
On Error GoTo TratamientoError
Dim RsetTabla As Recordset
' Abrimos un recordset de tipo dbOpentable
Set RsetTabla = VarBD.OpenRecordset(ConNombreTabla, dbOpenTable)
' Obtenemos el número de elementos
NumFichas = RsetTabla.RecordCount
' Cerramos el Recordset
RsetTabla.Close
Exit Property
TratamientoError:
NumFichas = -1
End Property
Public Function AbrirAgenda() As CodigoRetorno
On Error GoTo TratamientoError
' Abrimos la base de datos, utilizando el Workspace
' por defecto
Set VarBD = DBEngine.Workspaces(0).OpenDatabase(VarPathBD)
AbrirAgenda = Ok
Exit Function
TratamientoError:
AbrirAgenda = Error
End Function
Public Function CerrarAgenda() As CodigoRetorno
On Error GoTo TratamientoError
' Cerramos la base de datos
VarBD.Close
CerrarAgenda = Ok
Exit Function
TratamientoError:
CerrarAgenda = Error
End Function
Public Function GuardarFicha(ByVal ObjFicha As ClaFicha, _
Optional ByRef IntNumFicha As Integer) As CodigoRetorno
On Error GoTo TratamientoError
Dim RsetTabla As Recordset
' Abrimos un recordset de tipo dbOpenTable (sólo funciona
' en Jet)
Set RsetTabla = VarBD.OpenRecordset(ConNombreTabla, dbOpenTable)
With RsetTabla
' Añadimos una nueva ficha
.AddNew
!Nombre = ObjFicha.StrNombre
!Apellidos = ObjFicha.StrApellidos
!Direccion = ObjFicha.StrDireccion
!Telefono = ObjFicha.StrTelefono
' Obtenemos el campo NumFicha
IntNumFicha = !NumFicha
.Update
End With
' Cerramos el recordset
RsetTabla.Close
GuardarFicha = Ok
Exit Function
TratamientoError:
GuardarFicha = Error
End Function
Public Function ObtenerFicha(ByRef ObjFicha As ClaFicha, _
Optional ByVal IntIndice As Integer, _
Optional ByVal IntNumFicha As Integer) As CodigoRetorno
On Error GoTo TratamientoError
Dim RsetTabla As Recordset
' Comprobamos si hay que buscar por índice
If Not IsMissing(IntIndice) Then
' Abrimos un recordset de tipo dbOpenForwardOnly, para poder
' movernos con MoveNext (lo abrimos ForwardOnly porque sólo
' necesitamos desplazarnos hacia delante)
Set RsetTabla = VarBD.OpenRecordset(ConNombreTabla, dbOpenForwardOnly)
' Recorremos el Recordset hasta encontrar la ficha indicada
With RsetTabla
Do Until .EOF
If .RecordCount = IntIndice Then
Exit Do
End If
.MoveNext
Loop
End With
' Comprobamos si hay que buscar por número de ficha
ElseIf Not IsMissing(IntNumFicha) Then
' Abrimos un recordset de tipo dbOpenSnapshot, para poder
' buscar con FindFirst
Set RsetTabla = VarBD.OpenRecordset(ConNombreTabla, dbOpenSnapshot)
With RsetTabla
' Llenamos el Recordset
.MoveLast
' Encontramos el primer registro con ese número
.FindFirst "NumFicha=" & IntNumFicha
End With
End If
' Comprobamos si la hemos encontrado, o hemos llegado al
' final del Recordset sin encontrarla
With RsetTabla
If .EOF Or .NoMatch = True Then
ObtenerFicha = Error
Else
' Guardamos los datos obtenidos
ObjFicha.StrNombre = !Nombre
ObjFicha.StrApellidos = !Apellidos
ObjFicha.StrDireccion = !Direccion
ObjFicha.StrTelefono = !Telefono
ObjFicha.IntNumFicha = !NumFicha
ObtenerFicha = Ok
End If
End With
' Cerramos el Recordset
RsetTabla.Close
Exit Function
TratamientoError:
ObtenerFicha = Error
End Function
Public Function BorrarFicha(ByVal IntNumFicha) As CodigoRetorno
On Error GoTo TratamientoError
Dim RsetTabla As Recordset
' Abrimos un recordset de tipo dbOpenDynaset, para poder
' buscar con FindFirst y borrar con Delete
Set RsetTabla = VarBD.OpenRecordset(ConNombreTabla, dbOpenDynaset)
' Buscamos la ficha correspondiente
With RsetTabla
' Llenamos el Recordset
.MoveLast
' Encontramos el primer registro con ese número
.FindFirst "NumFicha=" & IntNumFicha
' Comprobamos si hemos encontrado algún registro
If .NoMatch Then
BorrarFicha = Error
Else
' Borramos la ficha obtenida
.Delete
BorrarFicha = Ok
End If
' Cerramos el Recordset
.Close
End With
BorrarFicha = Ok
Exit Function
TratamientoError:
BorrarFicha = Error
End Function
Private Sub Class_Initialize()
' Establecemos el path donde está el archivo de
' la base de datos
VarPathBD = App.Path & "\bdAgenda.mdb"
' Abrirmos la base de datos
AbrirAgenda
End Sub
7. Acceso a bases de datos (DAO y ODBCDirect)
Introducción
Hasta ahora hemos explicado cómo podemos acceder a una base de datos en local a través del motor Jet. En este capítulo y en el siguiente mostraremos cómo se puede acceder a un servidor de bases de datos.
Al trabajar con bases de datos localizadas en un servidor podemos diferenciar dos métodos de trabajo, dependiendo de la localización del motor de base de datos:
· cliente-servidor: el motor de base de datos está en el servidor.
Normalmente se utiliza el modelo cliente-servidor para acceder a bases de datos localizadas en un servidor, ya que aporta bastantes ventajas:
· Operaciones más fiables y robustas, puesto que existe un único servidor de base de datos que interactúa con todos los clientes.
· Notable aumento del rendimiento de algunas operaciones, especialmente cuando las estaciones de trabajo de los usuarios son equipos de gama baja.
· Reducción del tráfico de la red gracias a una transmisión de datos más eficiente. Sólo se transfieren los datos que la aplicación necesita.
· Características críticas como los registros de transacciones, las capacidades de copia de seguridad complejas, las matrices de discos redundantes y las herramientas de recuperación de fallos.
La forma más común de acceder a un servidor de bases de datos es a través de ODBC. ODBC es una capa intermedia entre las aplicaciones que se ejecutan en el cliente y el servidor de bases de datos. El controlador ODBC del cliente recibe peticiones de la aplicación, las traduce a peticiones ODBC y las envía al servidor. El servidor responde al controlador ODBC del cliente, y éste pasa la respuesta a la aplicación. La ventaja de usar ODBC es la independencia del SGBD (Sistema Gestor de Bases de Datos) utilizado, pudiendo cambiar éste realizando cambios mínimos en el código de la aplicación.
Conocimientos teóricos
Opciones de utilización de ODBC con DAO
Existen dos formas de acceder a orígenes de datos remotos utilizando DAO:
· Jet-ODBC: utiliza el motor Jet para acceder al SGBD.
· ODBCDirect: no utiliza el motor Jet. En realidad no es más que un interfaz DAO con las bibliotecas de RDO, lo que permite un rendimiento mayor que al utilizar Jet-ODBC con la pega de que no puede utilizar todas las características de Jet.
Estructura de una aplicación de bases de datos en Visual basic con DAO y ODBCDirect
Programación con DAO y ODBCDirect
En las siguientes líneas vamos a comentar cómo programar una aplicación que acceda a una base de datos a través de DAO y ODBCDirect, explicando las acciones más comunes que deberemos implementar. Al igual que en el capítulo anterior, existen muchas posibilidades que no comentaremos.
Si programamos con Visual Basic 5.0, es necesario incluir en el proyecto una referencia a Microsoft DAO 3.5 Object Library.
Como ejemplo utilizaremos la base de datos descrita en el capítulo anterior. Para acceder a dicha base de datos necesitamos crear un DSN (Data Source Name) desde Panel de ControlàODBC 32 bits, que llamaremos MiDSN.
En los siguientes ejemplos utilizaremos dos variables, VarWks y VarConexion, para definir el espacio de trabajo y la conexión con el SGBD, respectivamente. Además, para establecer la cadena de conexión ODBC utilizaremos la constante ConCadenaConexion:
Dim VarWks As Workspace
Dim VarConexion As Connection
Dim Const ConCadenaConexion = "ODBC;DATABASE=MiBD;UID=;PWD=;DSN=MiDSN"
Conexión con el SGBD:
Primero necesitamos crear un espacio de trabajo específico para ODBC utilizando la sentencia CreateWorkspace. Una vez creado, estableceremos la conexión con el SGBD utilizando el método OpenConnection de dicho espacio de trabajo.
Set VarWks = CreateWorkspace("", "", "", dbUseODBC)
Set VarConexion = VarWks.OpenConnection("", , , ConCadenaConexion)
Los Recordsets creados con ODBCDirect son, en realidad, Resultsets de RDO. La forma de trabajar con estos Recordsets será crear la consulta SQL que genere el conjunto de registros buscado y pasársela al método OpenRecordset de la conexión creada.
Ejemplos de utilización de Recordsets:
Para sacar en la pantalla Debug los datos de cada registro de la tabla “MiTabla” utilizaremos el método OpenRecordset de la conexión, pasándole la consulta SQL que obtiene todos los datos de la tabla. Para acceder a cada uno de los campos del registro actual, utilizaremos la colección Fields del Recordset, que contiene todos los campos del registro actual.
Dim RsetDatos As Recordset
Set RsetDatos = VarConexion.OpenRecordset("select * from MiTabla")
With RsetDatos
Do While Not .EOF
Debug.Print “DNI: ” & .Fields(0).Value & vbCRLF & _
“Nombre: “ & .Fields(1).Value & vbCRLF & _
“Apellidos: “ & .Fields(2).Value
.MoveNext
Loop
End With
Sentencias que no devuelven datos:
Cuando queremos realizar una acción sobre la base de datos que no devuelve ningún conjunto de registros (insert, update, delete, etc) utilizaremos el método Execute de la conexión, pasándole la sentencia SQL a ejecutar. Para determinar si la acción se ha realizado correctamente, consultaremos la propiedad RowsAfected de la conexión.
Ejemplos de ejecución de sentencias que no devuelven datos:
Por ejemplo, si queremos eliminar el registro con DNI=”12345678”:
VarConexion.Execute "delete from MiTabla where DNI=’12345678’”
If VarConexion.RecordsAffected = 1 Then
MsgBox “Registro borrado”
Else
MsgBox “Error al borrar el registro”
End If
Ejemplo propuesto
Objetivo
El objetivo de este ejemplo es cambiar la capa de acceso a la base de datos desarrollada en el ejemplo anterior para que utilice DAO y ODBCDirect en lugar de Jet para acceder a la misma base de datos, pero a través de ODBC.
Desarrollo del ejemplo
Crearemos un DSN para la base de datos (se llamará “Agenda”), y cambiaremos la clase ClaDAO_Jet por otra clase ClaDAO_ODBCDirect, que constará de los mismos métodos, pero utilizará ODBCDirect para acceder a través de ODBC a la base de datos.
Una vez creada esta clase, el único cambio a realizar en la aplicación es sustituir en la clase agenda (ClaAgenda) la sentencia
por
Private ObjAccesoBD As New ClaDAO_ODBCDirect
Private ObjAccesoBD As New ClaDAO_ODBCDirect
Ejemplo resuelto
Utilizaremos el formulario FrmAgenda, el módulo ModDefiniciones y las clase ClaFicha y ClaAgenda (con la modificación comentada).
8. Acceso a bases de datos (RDO)
Introducción
RDO está diseñado para aprovechar al máximo la potencia de servidores de bases de datos inteligentes, especialmente SQL Server. Tiene multitud de opciones que permiten incrementar el rendimiento de las aplicaciones que utilicen RDO, por eso es el mas utilizado en cliente-servidor.
Conocimientos teóricos
El modelo de objetos RDO
Los objetos y las colecciones de RDO proporcionan un marco para utilizar código con el fin de crear y manipular componentes de un sistema de base de datos remota de ODBC.
Al igual que DAO, las clases de los objetos de acceso a datos se organizan en una jerarquía, en la que la mayoría de las clases pertenecen a una clase de colección, que a su vez pertenece a otra clase en la jerarquía. La figura de la derecha muestra la jerarquía completa de RDO.
Estructura de una aplicación de bases de datos en Visual basic con RDO
La estructura de una aplicación de bases de datos en Visual Basic que utiliza RDO es casi idéntica a la de la aplicaciones que utilizan DAO con ODBCDirect. Los modelos DAO y RDO son equivalentes en cuanto a objetos, la diferencia es que están programados internamente para trabajar a través de ODBC o en local, pero para el programador, conociendo la manera de programar con uno, le debe ser fácil trabajar con el otro. En la siguiente tabla se recogen las correspondencias entre los objetos utilizados en RDO y sus objetos equivalentes en DAO:
Programación con RDO
En las siguientes líneas vamos a comentar cómo programar una aplicación que acceda a una base de datos a través de RDO, explicando las acciones más comunes que deberemos implementar. En los dos capítulos anteriores comentamos que existen muchas posibilidades que no hemos tratado. Esto se aplica especialmente a RDO, pues proporciona muchas posibilidades en función del SGBD con el que trabajemos (sobre todo con SQL Server), como consultas asíncronas, cursores del lado del servidor, ejecución de procedimientos en el servidor, etc.
Si programamos con Visual Basic 5.0, es necesario incluir en el proyecto una referencia a Microsoft Remote Data Object 2.0.
Utilizaremos la misma base de datos descrita en el capítulo anterior, así como el mismo DSN.
Variables utilizadas:
En los siguientes ejemplos utilizaremos una variable VarConexion que representará la conexión con el SGBD y la misma constante para la cadena de conexión ODBC que utilizamos en el capítulo anterior:
Dim VarConexion As New rdoConnection
Conexión con el SGBD:
Estableceremos la conexión con el SGBD utilizando el método EstablishConnection de la conexión. Antes de abrir la conexión, tenemos que especificar el tipo de cursor a utilizar utilizando la propiedad CursorDriver de la conexión (especificaremos rdUseOdbc), así como la cadena de conexión usando la propiedad Connect:
With VarConexion
.CursorDriver = rdUseOdbc
.Connect = ConCadenaConexion
.EstablishConnection rdDriverNoPrompt
End With
Utilización de Resultsets:
Como ya dijimos en el capítulo anterior, los Recordsets creados con ODBCDirect son en realidad Resultsets de RDO. Por lo tanto, la forma de trabajar con estos Resultsets será muy semejante a la que ya conocemos. Para abrir un Resultset, crearemos la consulta SQL que genere el conjunto de registros buscado y utilizaremos el método OpenResultset de la conexión para lanzarla.
Ejemplo de utilización de Resultsets:
Para sacar en la pantalla Debug los datos de cada registro de la tabla “MiTabla” utilizaremos el método OpenResultset de la conexión, pasándole la consulta SQL que obtiene todos los datos de la tabla. Para acceder a cada uno de los campos del registro actual, utilizaremos la colección rdoColumns del Resultset, que contiene todos los campos del registro actual.
Dim RsetDatos As rdoResultset
Set RsetDatos = VarConexion.OpenResultset("select * from MiTabla")
With RsetDatos
Debug.Print “DNI: ” & .rdoColumns(0).Value & vbCRLF & _
“Nombre: “ & . rdoColumns(1).Value & vbCRLF & _
“Apellidos: “ & . rdoColumns(2).Value
.MoveNext
Loop
End With
Sentencias que no devuelven datos:
La forma de ejecutar sentencias que no devuelven datos en RDO es idéntica a la que ya hemos visto con ODBCDirect.
Ejemplo propuesto
Objetivo
El objetivo de este ejemplo es cambiar la capa de acceso a la base de datos desarrollada en el ejemplo anterior para que utilice RDO en lugar de DAO y ODBCDirect para acceder a la misma base de datos a través de ODBC.
Desarrollo del ejemplo
Utilizaremos el DSN creado en el ejemplo anterior y cambiaremos la clase ClaDAO_ODBCDirect por una nueva clase ClaRDO, que constará de los mismo métodos pero utilizará RDO para acceder a través de ODBC a la base de datos.
Una vez creada esta clase, el único cambio a realizar en la aplicación es sustituir en la clase agenda (ClaAgenda) la sentencia
Private ObjAccesoBD As New ClaDAO_ODBCDirect
por
Private ObjAccesoBD As New ClaRDO
Ejemplo resuelto
Utilizaremos el formulario FrmAgenda, el módulo ModDefiniciones y las clase ClaFicha y ClaAgenda (con la modificación comentada).
ClaRDO
'_______________________________________________________________________
' Ejemplo 8 del Curso de Visual Basic Avanzado
'' Clase de acceso a bases de datos utilizando RDO
'_______________________________________________________________________
Option Explicit
Private VarConexion As New rdoConnection
Private Const ConCadenaConexion = "ODBC;DATABASE=Agenda;UID=;PWD=;DSN=Agenda"
Public Property Get NumFichas() As Integer
On Error GoTo TratamientoError
Dim RsetDatos As rdoResultset
Dim CadenaConexion As String
' Construimos la sentencia SQL
CadenaConexion = "select count(*) from agenda"
' Ejecutamos la consulta
Set RsetDatos = VarConexion.OpenResultset(CadenaConexion)
' Obtenemos el número de fichas
NumFichas = RsetDatos.rdoColumns(0).Value
' Cerramos el rdoresultset
RsetDatos.Close
Exit Property
TratamientoError:
NumFichas = -1
End Property
Public Function AbrirAgenda() As CodigoRetorno
On Error GoTo TratamientoError
' Abrimos la conexión utilizando la cadena
' de conexión predefinida
With VarConexion
.CursorDriver = rdUseOdbc
.Connect = ConCadenaConexion
.EstablishConnection rdDriverNoPrompt
End With
AbrirAgenda = Ok
Exit Function
TratamientoError:
AbrirAgenda = Error
End Function
Public Function CerrarAgenda() As CodigoRetorno
On Error GoTo TratamientoError
' Cerramos la base de datos
VarConexion.Close
CerrarAgenda = Ok
Exit Function
TratamientoError:
CerrarAgenda = Error
End Function
Public Function GuardarFicha(ByVal ObjFicha As ClaFicha, _
Optional ByRef IntNumFicha As Integer) As CodigoRetorno
On Error GoTo TratamientoError
Dim RsetDatos As rdoResultset
Dim CadenaSQL As String
' Construimos la sentencia SQL
CadenaSQL = "insert into agenda " & _
"(Nombre, Apellidos, Direccion, Telefono) " & _
"values (" & _
"'" & ObjFicha.StrNombre & "'," & _
"'" & ObjFicha.StrApellidos & "'," & _
"'" & ObjFicha.StrDireccion & "'," & _
"'" & ObjFicha.StrTelefono & "')"
' Ejecutamos la consulta
VarConexion.Execute CadenaSQL
' Comprobamos si se ha realizado la inserción
If VarConexion.RowsAffected <> 1 Then
GuardarFicha = Error
Exit Function
End If
' Obtenemos el número de ficha asignado por el servidor
' NOTA: en realidad, dado que el campo clave es el número
' de ficha, este sentencia puede devolver más de un
' registro, pero no lo tendremos en cuenta
CadenaSQL = "select numficha from agenda " & _
"where " & _
"Nombre='" & ObjFicha.StrNombre & "' AND " & _
"Apellidos='" & ObjFicha.StrApellidos & "' AND " & _
"Direccion='" & ObjFicha.StrDireccion & "' AND " & _
"Telefono='" & ObjFicha.StrTelefono & "'"
Set RsetDatos = VarConexion.OpenResultset(CadenaSQL)
If Not RsetDatos.EOF Then
' Obtenemos el código de la nueva ficha creada
IntNumFicha = RsetDatos.rdoColumns(0).Value
GuardarFicha = Ok
Else
GuardarFicha = Error
End If
' Cerramos el rdoresultset
RsetDatos.Close
Exit Function
TratamientoError:
GuardarFicha = Error
End Function
Public Function ObtenerFicha(ByRef ObjFicha As ClaFicha, _
Optional ByVal IntIndice As Integer, _
Optional ByVal IntNumFicha As Integer) As CodigoRetorno
On Error GoTo TratamientoError
Dim RsetDatos As rdoResultset
Dim CadenaConexion As String
Dim IntFichaActual As Integer
' Comprobamos si hay que buscar por índice
If Not IsMissing(IntIndice) Then
' Abrimos un rdoresultset seleccionando todos los
' registros de la tabla
CadenaConexion = "select * from agenda order by numficha"
Set RsetDatos = VarConexion.OpenResultset(CadenaConexion)
' Recorremos el rdoresultset hasta encontrar la ficha indicada
With RsetDatos
Do While Not .EOF
IntFichaActual = IntFichaActual + 1
If IntFichaActual = IntIndice Then
Exit Do
End If
.MoveNext
Loop
End With
' Comprobamos si hay que buscar por número de ficha
ElseIf Not IsMissing(IntNumFicha) Then
' Abrimos un rdoresultset seleccionando el registro
' directamente
CadenaConexion = "select * from agenda " & _
"where numficha=" & IntNumFicha & _
"order by numficha"
Set RsetDatos = VarConexion.OpenResultset(CadenaConexion)
End If
' Comprobamos si la hemos encontrado, o hemos llegado al
' final del rdoresultset sin encontrarla
With RsetDatos
If .EOF Then
ObtenerFicha = Error
Else
' Guardamos los datos obtenidos
ObjFicha.IntNumFicha = .rdoColumns(0).Value
ObjFicha.StrNombre = .rdoColumns(1).Value
ObjFicha.StrApellidos = .rdoColumns(2).Value
ObjFicha.StrDireccion = .rdoColumns(3).Value
ObjFicha.StrTelefono = .rdoColumns(4).Value
ObtenerFicha = Ok
End If
End With
' Cerramos el rdoresultset
RsetDatos.Close
Exit Function
TratamientoError:
ObtenerFicha = Error
End Function
Public Function BorrarFicha(ByVal IntNumFicha) As CodigoRetorno
On Error GoTo TratamientoError
Dim CadenaSQL As String
' Construimos la sentencia SQL
CadenaSQL = "delete from agenda " & _
"where numficha=" & IntNumFicha
' Ejecutamos la sentencia SQL
VarConexion.Execute CadenaSQL
' Comprobamos cuantas filas han sido afectadas
If VarConexion.RowsAffected = 1 Then
BorrarFicha = Ok
Else
BorrarFicha = Error
End If
Exit Function
TratamientoError:
BorrarFicha = Error
End Function
Private Sub Class_Initialize()
' Conectamos con la base de datos
AbrirAgenda
End Sub
9. El registro de Windows
Introducción
El objetivo de este capítulo es introducir al lector en un tema complejo como es el tratamiento del registro de Windows. Se explicará cómo se estructura el registro de Windows, cómo podemos obtener valores almacenados en él y cómo crear nuevas claves y valores de diferentes tipos.
Pero todos los accesos al registro deben ser controlados, ya que del registro depende el correcto funcionamiento del S.O., por lo que cualquier cambio podría repercutir en el funcionamiento correcto del sistema.
El acceso al registro de Windows implica la utilización de las correspondientes funciones que proporciona el API de Windows, por lo que en este capítulo se explicará someramente qué es y cómo se utiliza dicho API (Application Programming Interface, o Interfaz para la Programación de Aplicaciones).
Conocimientos teóricos
Qué es el registro de Windows
En Windows 3.1 y en las versiones anteriores de Windows, la configuración de los programas se almacenaban normalmente en archivos .ini. En Windows NT, en Windows 95 y en las versiones posteriores de Windows, la configuración de los programas se almacena en el registro del sistema, todas las instalaciones realizadas, versiones de librerías, controles... quedan reflejados en el registro.
Cómo acceder al registro de Windows
Podemos acceder manualmente a los valores almacenados en el registro de Windows utilizando la aplicación Regedit:
También podemos acceder al registro de Windows desde Visual Basic utilizando las funciones que proporciona el API de Windows que veremos mas adelante, pero antes profundizaremos en la definición del registro.
Estructura del registro de Windows
Los elementos almacenados en el registro de Windows se dividen en dos tipos:
· claves, que se estructuran en forma de directorios.
· valores de cadena, binarios o DWORD.
Para acceder al valor contenido en una clave es necesario conocer el “path” completo de ésta (por ejemplo, para conocer el nº de versión de Windows hay que consultar la clave
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\VersionNumber).
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\VersionNumber).
Cómo utilizar el API de Windows
Para poder utilizar las funciones que proporciona el API de Windows es necesario declarar las funciones que éste implementa, así como los posibles tipos de datos y constantes que utilicen. Podemos obtener esta información utilizando el Visor de texto API que proporciona Visual Basic, abriendo el archivo Win32api.txt que estará en el directorio Winapi de la instalación de Visual Basic. Esta aplicación, como se ve en la figura, nos permite conocer el nombre de las funciones que implementa el API de Windows, así como la forma de declararlas, los argumentos que utilizan, los valores de retorno, etc.
Por ejemplo, si quisiéramos utilizar la función RegOpenKey, que nos permite abrir una clave del registro, buscaríamos el nombre de la función en el cuadro de lista superior, haríamos doble click sobre el nombre y copiaríamos la declaración en nuestro código de Visual Basic (en realidad, para utilizar esta función necesitamos obtener también ciertas constantes que indican las ramas del registro donde vamos a buscar, entre otras).
Pero el problema que tienen los visores API es que no proporcionan una breve explicación del contenido de el API seleccionada, por lo que muchas veces hay que usar la intuición para encontrar una que nos solucione el problema.
En el siguiente cuadro se muestran algunas de las funciones que proporciona el API de Windows para acceso al registro y su correspondiente declaración:
Para poder utilizar estas funciones es necesario declarar también varias constantes, que se especifican en el siguiente cuadroÄ:
Apertura de una clave existente:
Para abrir una clave existente debemos especificar la rama donde se encuentra (HKEY_CLASSES_ROOT, etc) y el “path” restante de la clave que queremos abrir. Una vez abierta, nos devolverá un valor de tipo long que identifica a esa clave, y nos permitirá trabajar con ella. Utilizaremos la función RegOpenKey, controlando si el valor de retorno es ERROR_SUCCESS, lo que indicaría que todo ha ido bien.
Por ejemplo, si queremos abrir la clave HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft utilizaríamos el siguiente código:
Dim hKey As Long
If OSRegOpenKey(HKEY_LOCAL_MACHINE, “SOFTWARE\Microsoft”, hKey) =
ERROR_SUCCESS Then
MsgBox “Clave abierta”
Else
MsgBox “Error al abrir la clave”
End If
Ä Existen más constantes de este tipo, pero sólo mencionamos las necesarias para el desarrollo del ejemplo correspondiente a este capítulo
Cerrado de una clave abierta:
Para cerrar una clave abierta, utilizaremos la función RegCloseKey, pasándole el identificador de la clave abierta. También en este caso debemos comprobar si el valor devuelto por la función es ERROR_SUCCESS. Por ejemplo, para cerrar la clave abierta en el ejemplo anterior, utilizaríamos el siguiente fragmento de código:
If OSRegCloseKey(hKey) = ERROR_SUCCESS Then
MsgBox “Clave cerrada”
Else
MsgBox “Error al cerrar la clave”
End If
Creación de una clave nueva:
Para crear una clave nueva en el registro utilizaremos la función RegCreateKey. Esta función creará la clave nueva (o la abrirá, si existe) y nos proporcionará el identificador de la clave recién creda/abierta. Como en los casos anteriores, hemos de comprobar si devuelve ERROR_SUCCESS. Por ejemplo, para crear la clave HKEY_LOCAL_MACHINE\SOFTWARE\MiClave utilizaríamos la siguiente sentencia:
If OSRegCreateKey(HKEY_LOCAL_MACHINE, "SOFTWARE\MiClave", hKeyNueva) =
ERROR_SUCCESS then
MsgBox “Clave creada”
Else
MsgBox “Error al crear la clave”
End If
Establecimiento del valor de una clave
Para establecer el valor de una clave existente utilizaremos la función RegSetValueEx, a la que pasaremos el identificador de la clave abierta, el nombre que vamos a darle a ese valor (si no se especifica, se entenderá que es el valor por defecto de dicha clave) y el propio valor. Es necesario concretar qué tipo de valor es (una cadena (REG_SZ), un valor binario (REG_BINARY) o un valor numérico (REG_DWORD)) y qué longitud tiene.
Por ejemplo, una vez creada la clave anterior, crearemos un valor nuevo dentro de ella que se llamará MiValor y contendrá la cadena “Esto es una prueba”:
If OSRegSetValueEx(hKeyNueva, “MiValor”, 0&, REG_SZ, “Esto es una prueba”,
Len(“Esto es una prueba”) + 1) = ERROR_SUCCESS then
MsgBox “Valor creado”
Else
MsgBox “Error al crear el valor”
End If
Dentro de la misma clave, crearemos un nuevo valor llamado MiNuevoValor, que contendrá el número 17 (como vamos a crearlo como REG_DWORD, el tamaño es 4):
If OSRegSetValueEx(hKeyNueva, “MiNuevoValor”, 0&, REG_DWORD, 17, 4) =
ERROR_SUCCESS then
MsgBox “Valor creado”
Else
MsgBox “Error al crear el valor”
End If
Obtención de alguno de los valores de una clave:
Para obtener alguno de los valores asociados a una clave utilizaremos la función RegQueryValueEx, a la que pasaremos el identificador de la clave abierta, el nombre del valor que queremos obtener (si no se especifica, se entenderá que es el valor por defecto de dicha clave), una variable donde se guardará el tipo del valor recogido, un buffer donde se guardará el valor recogido y una variable donde se guardará el tamaño del valor recogido.
Como es posible obtener valores de tipos y tamaños diferentes, esta función se llamará dos veces: la primera con un buffer vacío (0&) para obtener el tipo y el tamaño del valor; la segunda con el buffer correspondiente a este tipo y de tamaño correcto (¡OJO!: en el caso de REG_SZ debemos reservar expresamente espacio de memoria). Una vez obtenido el valor, hay que coger sólo el tamaño especificado del valor.
Por ejemplo, si queremos obtener el valor MiValor de la clave anterior, utilizaremos la siguiente sentencia (¡OJO!: el ByVal es importante)
Dim lValueType as Long
Dim StrBuf As String
Dim lDataBufSize As Long
If OSRegQueryValueEx(hKeyNueva, “MiValor”, 0&, lValueType, ByVal 0&, lDataBufSize) =
ERROR_SUCCESS Then
If lValueType = REG_SZ Then
StrBuf = String(lDataBufSize, " ")
If OSRegQueryValueEx(hKey, strValueName, 0&, 0&, ByVal StrBuf,
lDataBufSize) = ERROR_SUCCESS Then
RegQueryStringValue = True
StrData = Left(StrBuf, lDataBufSize - 1)
End If
End If
End If
Si queremos obtener el valor MiNuevoValor de la clave anterior, utilizaremos la sentencia:
Dim lValueType As Long
Dim lBuf As Long
Dim lDataBufSize As Long
lDataBufSize = 4
If OSRegQueryValueEx(hKeyNueva, “MiNuevoValor”, 0&, lValueType, lBuf, lDataBufSize) =
ERROR_SUCCESS Then
If lValueType = REG_DWORD Then
lData = lBuf
End If
End If
Borrado de una clave:
Para borrar una clave existente utilizaremos la funcion RegDeleteKey, a la que pasaremos el identificador de la clave abierta y la subclave que queremos borrar. Por ejemplo, para borrar la clave HKEY_LOCAL_MACHINE\SOFTWARE\MiClave y todo lo que a partir de ella hemos creado, utilizaríamos la sentencia:
If OSRegOpenKey(HKEY_LOCAL_MACHINE, “SOFTWARE”, hKey) =
ERROR_SUCCESS Then
If OSRegDeleteKey(hKey, "MiClave") = ERROR_SUCCESS then
MsgBox “Clave borrada”
End If
End If
Ejemplo propuesto
Objetivo
El objetivo de este ejemplo es crear un formulario de inicio de la aplicación que hemos desarrollado, de forma que nos permita 10 usos y luego no nos deje ejecutar más la aplicación, a no ser que la registremos. Para controlar esto utilizaremos el registro de Windows, en el llevaremos el control de veces que se ha ejecutado la aplicación y guardaremos el registro de la aplicación, tal y como hacen la mayoría de las aplicaciones del mercado.
Desarrollo del ejemplo
Crearemos un módulo ModRegistro que proporcione las siguientes funciones:
· Function RegCreateKey(ByVal hKey As Long, ByVal lpszKey As String, phkResult As Long) As Boolean
· Function RegSetStringValue(ByVal hKey As Long, ByVal strValueName As String, ByVal StrData As String) As Boolean
· Function RegSetNumericValue(ByVal hKey As Long, ByVal strValueName As String, ByVal lData As Long, Optional ByVal fLog) As Boolean
· Function RegOpenKey(ByVal hKey As Long, ByVal lpszSubKey As String, phkResult As Long) As Boolean
· Function RegDeleteKey(ByVal hKey As Long, ByVal lpszSubKey As String) As Boolean
· Function RegCloseKey(ByVal hKey As Long) As Boolean
· Function RegQueryStringValue(ByVal hKey As Long, ByVal strValueName As String, StrData As String) As Boolean
· Function RegQueryNumericValue(ByVal hKey As Long, ByVal strValueName As String, lData As Long) As Boolean
Estas funciones utilizaran sus correspondientes funciones del API de Windows, tal y como se ha explicado antes en este capítulo.
Crearemos un formulario FrmPresentacion de inicio de la aplicación como el que aparece en la siguiente figura:
Cada vez que se ejecute la aplicación se lanzararía este formulario (para este ejemplo no habrá aplicación que lanzar: tanto si la aplicación se registra como si es está en período de prueba o se supera éste, el formulario se descargará y nada más).
La primera vez que se ejecute la aplicación, este formulario creará una clave HKEY_LOCAL_MACHINE\SOFTWARE\Agenda en el registro, y en esta clave dos valores: MaxIntentos=10 y NumIntentos=1. Actualizará el caption del label inferior para mostrar el número máximo de ejecuciones permitidas y el número actual de ejecuciones.
Cada vez que se ejecute la aplicación se incrementará NumIntentos y se comprobará si es menor que MaxIntentos, de forma que si se llega al número máximo de intentos no se permita la ejecución del programa. En cada caso se actualizará el caption.
En todo momento se permitirá registrar la aplicación, en cuyo caso se lanzará un formulario como el siguiente:
Al pulsar el botón aceptar, crearemos un nuevo valor DatosRegistro en nuestra clave, que contendrá el nombre y clave de registro separados por un guión.
La aplicación debe comprobar cada vez que se ejecuta si existe el valor DatosRegistro, en cuyo caso se supone que está registrada y no se tomará en cuenta el valor de NumIntentos y MaxIntentos del registro, permitiendo siempre lanzar la aplicación (en nuestro caso siempre se descargará el formulario).
Ejemplo resuelto
FrmPresentacion
'_______________________________________________________________________
' Ejemplo 9 del Curso de Visual Basic Avanzado
'
' Formulario de presentación, en él comprobamos los usos, la registración de la aplicación...
'_______________________________________________________________________
Option Explicit
Const ConMaxIntentos = 10
Private Sub ButAceptar_Click()
' Aquí comprobaríamos si se lanza la aplicación
Unload Me
End Sub
Private Sub ButRegistrar_Click()
Dim StrClave As String
Dim StrCadenaRegistro As String
Dim hkeyExistente As Long
' Mostramos el formulario de registro
frmRegistro.Show vbModal
' Abrimos la clave del registro
If RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\Agenda", hkeyExistente) Then
' Comprobamos si está registrado
StrClave = "DatosRegistro"
If RegQueryStringValue(hkeyExistente, StrClave, StrCadenaRegistro) Then
LabTextoPresentacion.Caption = "Versión registrada, completamenta operacional." & vbCrLf & "¡¡Disfrútela!!"
LabNumUsos.Visible = False
ButRegistrar.Enabled = False
Exit Sub
End If
' Cerramos la clave del registro
RegCloseKey hkeyExistente
End If
End Sub
Private Sub Form_Load()
Dim hKey As Long
Dim hkeyExistente As Long
Dim StrClave As String
Dim StrCadenaRegistro As String
Dim LngNumIntentos As Long
Dim LngMaxIntentos As Long
' Abrimos la clave del regiStro
If RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\Agenda", hkeyExistente) Then
' Comprobamos si está registrado
StrClave = "DatosRegistro"
If RegQueryStringValue(hkeyExistente, StrClave, StrCadenaRegistro) Then
LabTextoPresentacion.Caption = "Versión registrada, completamenta operacional." & vbCrLf & "¡¡Disfrútela!!"
RegCloseKey hkeyExistente
ButRegistrar.Enabled = False
Exit Sub
End If
' Como no está registrado, obtenemos el número máximo de intentos
StrClave = "MaxIntentos"
If RegQueryNumericValue(hkeyExistente, StrClave, LngMaxIntentos) Then
' Comprobamos cuántos intentos van
StrClave = "NumIntentos"
If RegQueryNumericValue(hkeyExistente, StrClave, LngNumIntentos) Then
' Comprobamos si se ha llegado al número máximo de intentos
If LngNumIntentos < LngMaxIntentos Then
' Incrementamos el número de usos y lo guardamos en el registro
LngNumIntentos = LngNumIntentos + 1
RegSetNumericValue hkeyExistente, "NumIntentos", LngNumIntentos
' Actualizamos el formulario
LabNumUsos.Caption = "La agenda ha sido utilizada " & LngNumIntentos & " veces (máximo " & LngMaxIntentos & ")"
Else
LabNumUsos.Caption = "La agenda ha sido utilizada " & LngNumIntentos & " veces (máximo " & LngMaxIntentos & "). Registre la versión antes de continuar."
End If
End If
End If
RegCloseKey hkeyExistente
Else
' Como no existe, la creamos
If RegCreateKey(HKEY_LOCAL_MACHINE, "SOFTWARE\Agenda", hKey) Then
' Número máximo de intentos
RegSetNumericValue hKey, "MaxIntentos", ConMaxIntentos
' Número de intentos realizado
RegSetNumericValue hKey, "NumIntentos", 1
RegCloseKey hKey
' Actualizamos el formulario
LabNumUsos.Caption = "La agenda ha sido utilizada 1 vez (máximo " & ConMaxIntentos & ")"
End If
End If
End Sub
FrmRegistro
'_______________________________________________________________________
' Ejemplo 9 del Curso de Visual Basic Avanzado
'
' Formulario para introducir los datos del registro de la aplicación.
'_______________________________________________________________________
Option Explicit
Private Sub ButAceptar_Click()
Dim hkeyExistente As Long
Dim StrClave As String
Dim StrCadenaRegistro As String
' Registramos la aplicación (podríamos comprobar si es auténtico)
If RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\Agenda", hkeyExistente) Then
' Lo registramos
StrCadenaRegistro = Text1.Text & "-" & Text2.Text
StrClave = "DatosRegistro"
If RegSetStringValue(hkeyExistente, StrClave, StrCadenaRegistro) Then
MsgBox "La aplicación ha sido registrada con éxito.", , "Registro"
Unload Me
End If
End If
End Sub
Private Sub ButRegistrar_Click()
Unload Me
End Sub
ModRegistro
'_______________________________________________________________________
' Ejemplo 8 del Curso de Visual Basic Avanzado
'
' Módulo donde están las funciones de acceso al registro y las declaraciones de las API.
'_______________________________________________________________________
Option Explicit
' API de manipulación del regiStro (32 bits)
Declare Function OSRegCloseKey Lib "advapi32" Alias "RegCloseKey" (ByVal hKey As Long) As Long
Declare Function OSRegCreateKey Lib "advapi32" Alias "RegCreateKeyA" (ByVal hKey As Long, ByVal lpszSubKey As String, phkResult As Long) As Long
Declare Function OSRegDeleteKey Lib "advapi32" Alias "RegDeleteKeyA" (ByVal hKey As Long, ByVal lpszSubKey As String) As Long
Declare Function OSRegOpenKey Lib "advapi32" Alias "RegOpenKeyA" (ByVal hKey As Long, ByVal lpszSubKey As String, phkResult As Long) As Long
Declare Function OSRegQueryValueEx Lib "advapi32" Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal lpszValueName As String, ByVal dwReserved As Long, lpdwType As Long, lpbData As Any, cbData As Long) As Long
Declare Function OSRegSetValueEx Lib "advapi32" Alias "RegSetValueExA" (ByVal hKey As Long, ByVal lpszValueName As String, ByVal dwReserved As Long, ByVal fdwType As Long, lpbData As Any, ByVal cbData As Long) As Long
Global Const HKEY_CLASSES_ROOT = &H80000000
Global Const HKEY_CURRENT_USER = &H80000001
Global Const HKEY_LOCAL_MACHINE = &H80000002
Global Const HKEY_USERS = &H80000003
Const ERROR_SUCCESS = 0&
Const REG_SZ = 1
Const REG_BINARY = 3
Const REG_DWORD = 4
' Crea (o abre si ya existe) una clave en el registro del sistema
Function RegCreateKey(ByVal hKey As Long, ByVal lpszKey As String, phkResult As Long) As Boolean
On Error GoTo 0
If OSRegCreateKey(hKey, lpszKey, phkResult) = ERROR_SUCCESS Then
RegCreateKey = True
Else
RegCreateKey = False
End If
End Function
' Asocia un valor con nombre (StrValueName = nombre) o sin nombre (StrValueName = "")
' con una clave del regiStro.
Function RegSetStringValue(ByVal hKey As Long, ByVal strValueName As String, ByVal StrData As String) As Boolean
On Error GoTo 0
If hKey = 0 Then Exit Function
If OSRegSetValueEx(hKey, strValueName, 0&, REG_SZ, ByVal StrData, _
Len(StrData) + 1) = ERROR_SUCCESS Then
RegSetStringValue = True
Else
RegSetStringValue = False
End If
End Function
' Asocia un valor con nombre (strValueName = nombre) o sin nombre (strValueName = "")
' con una clave del registro.
Function RegSetNumericValue(ByVal hKey As Long, ByVal strValueName As String, ByVal lData As Long, Optional ByVal fLog) As Boolean
On Error GoTo 0
If OSRegSetValueEx(hKey, strValueName, 0&, REG_DWORD, lData, 4) = ERROR_SUCCESS Then
RegSetNumericValue = True
Else
RegSetNumericValue = False
End If
End Function
' Abre una clave existente en el registro del sistema.
Function RegOpenKey(ByVal hKey As Long, ByVal lpszSubKey As String, phkResult As Long) As Boolean
On Error GoTo 0
If OSRegOpenKey(hKey, lpszSubKey, phkResult) = ERROR_SUCCESS Then
RegOpenKey = True
Else
RegOpenKey = False
End If
End Function
' Elimina una clave existente del regiStro del sistema.
Function RegDeleteKey(ByVal hKey As Long, ByVal lpszSubKey As String) As Boolean
On Error GoTo 0
If OSRegDeleteKey(hKey, lpszSubKey) = ERROR_SUCCESS Then
RegDeleteKey = True
Else
RegDeleteKey = False
End If
End Function
' Cierra una clave abierta del registro
Function RegCloseKey(ByVal hKey As Long) As Boolean
On Error GoTo 0
If OSRegCloseKey(hKey) = ERROR_SUCCESS Then
RegCloseKey = True
Else
RegCloseKey = False
End If
End Function
' Recupera los datos de cadena para un valor con nombre
' (StrValueName = nombre) o sin nombre (StrValueName = "")
' dentro de una clave del regiStro. Si el valor con
' nombre existe, pero sus datos no son una cadena, esta
' función fallará.
Function RegQueryStringValue(ByVal hKey As Long, ByVal strValueName As String, StrData As String) As Boolean
On Error GoTo 0
Dim lValueType As Long
Dim StrBuf As String
Dim lDataBufSize As Long
RegQueryStringValue = False
' Obtiene el tipo y longitud de los datos
If OSRegQueryValueEx(hKey, strValueName, 0&, lValueType, ByVal 0&, lDataBufSize) = ERROR_SUCCESS Then
If lValueType = REG_SZ Then
StrBuf = String(lDataBufSize, " ")
If OSRegQueryValueEx(hKey, strValueName, 0&, 0&, ByVal StrBuf, lDataBufSize) = ERROR_SUCCESS Then
StrData = Left(StrBuf, lDataBufSize - 1)
RegQueryStringValue = True
End If
End If
End If
End Function
' Recupera los datos enteros para un valor con nombre
' (StrValueName = nombre) o sin nombre (StrValueName = "")
' dentro de una clave del regiStro. Si el valor con nombre
' existe, pero sus datos no son de tipo REG_DWORD, esta
' función fallará.
Function RegQueryNumericValue(ByVal hKey As Long, ByVal strValueName As String, lData As Long) As Boolean
On Error GoTo 0
Dim lValueType As Long
Dim lBuf As Long
Dim lDataBufSize As Long
RegQueryNumericValue = False
' Obtiene el tipo y longitud de los datos
lDataBufSize = 4
If OSRegQueryValueEx(hKey, strValueName, 0&, lValueType, lBuf, lDataBufSize) = ERROR_SUCCESS Then
If lValueType = REG_DWORD Then
lData = lBuf
RegQueryNumericValue = True
End If
End If
End Function
APÉNDICE A: Especificaciones, limitaciones y formatos de archivos de Visual Basic
En este apéndice se describen los requisitos de sistema, las limitaciones de un proyecto de Visual Basic, los tipos de archivos que se pueden incluir en el proyecto de Visual Basic y las descripciones de los archivos de formulario (.frm) y de proyecto (.vbp).
Requisitos del sistema para aplicaciones de Visual Basic
Para las aplicaciones de Visual Basic se requiere el siguiente hardware y software:
· Microsoft Windows NT 3.51 o posterior, o Microsoft Windows 95 o posterior.
· Microprocesador 80486 o superior.
· Pantalla VGA o de resolución superior compatible con Microsoft Windows.
· 8 MB de RAM para aplicaciones. (Esto variará dependiendo de las bibliotecas de tipos o los archivos DLL específicos que incluya en sus aplicaciones.)
· 16 MB de RAM para el entorno de desarrollo de Visual Basic.
Limitaciones de los proyectos
Un único proyecto puede contener hasta 32.000 identificadores, que incluyen entre otros formularios, controles, módulos, variables, constantes, procedimientos, funciones y objetos. Los nombres de variables en Visual Basic no pueden tener más de 255 caracteres y los nombres de formularios, controles, módulos y clases pueden tener un máximo de 40 caracteres. Visual Basic no impone ningún límite en cuanto al número de objetos distintos de un proyecto.
Limitaciones de controles
Cada control no gráfico (todos los controles excepto Shape, Line, Image y Label) utiliza una ventana. Cada ventana utiliza recursos del sistema, limitando el número total de ventanas que pueden existir al mismo tiempo. El límite exacto depende de los recursos del sistema disponibles y el tipo de controles que se utilicen.
Para reducir el consumo de recursos, utilice controles Shape, Line, Label e Image en vez de los controles PictureBox para crear o presentar gráficos.
Número total de controles
El número máximo de controles permitidos en un único formulario depende del tipo de controles que se utilicen y de los recursos disponibles del sistema. No obstante, hay un límite fijo de 254 nombres de control por formulario. En este límite una matriz de controles sólo cuenta como uno, ya que todos los controles en la matriz comparten un único nombre de control.
El límite para índices de matrices de controles es de 0 a 32.767 para todas las versiones.
Si coloca controles uno encima de otro, como por ejemplo si utiliza varios controles de marco dentro de otros marcos, Visual Basic no aceptará más de seis niveles de controles anidados.
Limitaciones para determinados controles
La siguiente tabla muestra las limitaciones de propiedades aplicables a determinados controles de Visual Basic:
Limitaciones de código
La cantidad de código que se puede cargar en un formulario, clase o módulo estándar está limitada a 65.534 líneas. Una única línea de código puede constar de 1.023 bytes como máximo. Puede haber hasta 256 espacios en blanco delante del texto en una única línea y no se pueden incluir más de veinticinco caracteres de continuación de línea ( _) en una única línea lógica.
Procedimientos, tipos y variables
No hay límite en cuanto al número de procedimientos por módulo. Cada procedimiento puede contener hasta 64 KB de código. Si un procedimiento o un módulo excede este límite, Visual Basic genera un error en tiempo de compilación. Si se encuentra con este error, puede evitarlo dividiendo los procedimientos extremadamente grandes en varios procedimientos más pequeños o trasladando las declaraciones de nivel de módulo a otro módulo.
Visual Basic utiliza tablas para almacenar los nombres de los identificadores (variables, procedimientos, constantes, etc.) en el código. Cada tabla está limitada a 64 KB.
Tabla de entradas de módulo
Limitaciones de los datos
Las siguientes limitaciones son aplicables a las variables en el lenguaje Visual Basic
Datos de formulario, módulos estándar y módulos de clase
Cada formulario, módulo estándar y módulo de clase tiene su propio segmento de datos que puede ser como máximo de 64 KB. Este segmento de datos contiene los siguientes datos:
· Variables locales declaradas con Static.
· Variables a nivel de módulo que no sean matrices y cadenas de longitud variable.
· 4 bytes para cada matriz a nivel de módulo y cadena de longitud variablez
Procedimientos, tipos y variables
Si un procedimiento o un módulo excede el límite de 64 KB, Visual Basic generará un error de tiempo de compilación. Si se encuentra con este error, puede evitarlo dividiendo los procedimientos extremadamente grandes en varios procedimientos más pequeños o trasladando las declaraciones a nivel de módulo a otro módulo.
Tipos definidos por el usuario
Ninguna variable de un tipo definido por el usuario puede exceder los 64 KB, aunque la suma de las cadenas de longitud variable en un tipo definido por el usuario puede exceder de 64 KB (las cadenas de longitud variable sólo ocupan 4 bytes cada una en el tipo definido por el usuario; el contenido real de una cadena se almacena por separado). Los tipos definidos por el usuario se pueden definir en términos de otros tipos definidos por el usuario, pero el tamaño total de los tipos no puede exceder los 64 KB.
Espacio de pila
Los argumentos y las variables locales en los procedimientos ocupan espacio de pila en tiempo de ejecución. Las variables estáticas y a nivel de módulo no ocupan espacio de pila porque se encuentran en el segmento de datos para los formularios o los módulos. Todos los procedimientos de DLL a los que se llame utilizan esta pila mientras se están ejecutando.
Visual Basic utiliza parte de la pila para sus propios usos, como el almacenamiento de valores intermedios al evaluar expresiones.
Limitaciones de los recursos del sistema
Algunas limitaciones de Visual Basic y las aplicaciones creadas con él están impuestas por Microsoft Windows. Estas limitaciones pueden cambiar cuando se instala una versión diferente de Microsoft Windows.
Recursos de Windows
Cada ventana abierta usa recursos del sistema (áreas de datos utilizadas por Microsoft Windows). Si se agotan los recursos del sistema, se producirá un error en tiempo de ejecución. Puede comprobar el porcentaje de recursos del sistema que quedan si elige Acerca de en el menú Ayuda del Administrador de programas o del Administrador de archivos en Windows NT 3.51 o, en Windows 95 y Windows NT 4.0, si elige Acerca de en el menú Ayuda del Explorador de Windows. Las aplicaciones también pueden llamar a la función GetFreeSystemResources de el API de Windows para reclamar recursos del sistema, cerrar ventanas (como formularios abiertos y ventanas de código, así como ventanas de otras aplicaciones) y finalizar la ejecución de aplicaciones.
Formatos de archivos de proyecto
Microsoft Visual Basic utiliza y crea una serie de archivos tanto en tiempo de diseño como en tiempo de ejecución. Los archivos que el proyecto o la aplicación requerirán dependen de su alcance y funcionalidad.
Extensiones de archivos de proyecto
Visual Basic crea varios archivos cuando se crea y compila un proyecto. Estos se pueden dividir como sigue: tiempo de diseño, otros desarrollos y tiempo de ejecución.
Los archivos de tiempo de diseño son los ladrillos de su proyecto: por ejemplo, módulos de Basic (.bas) y módulos de formulario (.frm).
Otros procesos y funciones del entorno de desarrollo de Visual Basic crean diversos archivos: por ejemplo, archivos de dependencias del Asistente para instalación (.dep).
Archivos varios y de tiempo de diseño
La siguiente tabla muestra todos los archivos de tiempo de diseño y otros archivos que se pueden crear al desarrollar una aplicación:
Archivos de tiempo de ejecución
Al compilar la aplicación, todos los archivos necesarios de tiempo de ejecución se incluyen en los archivos ejecutables de tiempo de ejecución. La siguiente tabla muestra los archivos de tiempo de ejecución:
Estructuras de formularios
A pesar de que muchos de los archivos de un típico proyecto de Visual Basic están en formato binario y sólo los pueden leer determinados procesos y funciones de Visual Basic o de su aplicación, los archivos de formulario (.frm) y de proyecto (.vbp) se guardan como texto ASCII. Estos archivos se pueden leer en un visor de texto (por ejemplo, el Bloc de notas).
En las siguientes secciones se describen los archivos de tiempo diseño y de tiempo de ejecución en un proyecto típico de Visual Basic y el formato de los archivos de formulario (.frm) y de proyecto (.vbp).
Los archivos de formulario de Visual Basic (.frm) se crean y se guardan en formato ASCII. La estructura de un formulario consiste en lo siguiente:
· El número de versión del formato de archivo.
· Un bloque de texto que contiene la descripción del formulario.
· Un conjunto de atributos del formulario.
· El código Basic del formulario.
La descripción del formulario contiene los valores de las propiedades del formulario. Los bloques de texto que definen las propiedades de los controles del formulario están anidados en el formulario. Los controles contenidos en otros controles tienen sus propiedades anidadas en el texto del contenedor. La figura A.1 ilustra la estructura de la descripción del formulario.
Número de versión
El número de versión para los formularios creados con Visual Basic 5.0 para Windows es 5.00. Si en un formulario se omite el número de versión, se generará un error. Al cargar una aplicación de Visual Basic que tiene un número de versión menor que 5.00, aparece un cuadro de diálogo de advertencia para informar que el archivo se guardará en el nuevo formato.
Figura A.1 Estructura de la descripción del formulario
Descripción del formulario
La descripción de un formulario empieza con una instrucción Begin y termina con una instrucción End. La sintaxis de la instrucción Begin es la siguiente:
Begin VB.{Form|MDIForm} nombre_formulario
La instrucción End indica dónde termina la descripción del formulario y dónde empieza el conjunto de atributos del formulario. Sin la instrucción End, Visual Basic intentaría leer los atributos como si se estuvieran describiendo los controles y las propiedades del formulario, por lo que se producirían errores.
Entre las instrucciones Begin Form y End están las propiedades del formulario propiamente dicho, seguidas de las descripciones de cada control del formulario. La figura A.2 muestra la estructura anidada de la descripción del formulario con más detalle.
Bloques de control
Un bloque de control consta del texto de la descripción del formulario que define las propiedades de un control individual. Al igual que la descripción del formulario, los bloques de control empiezan con una instrucción Begin y terminan con una instrucción End. La sintaxis para una instrucción Begin de un bloque de control es la siguiente:
Begin clase_control.tipo_control nombre_control
Las propiedades para el control aparecen entre la instrucción Begin y la instrucción End.
Orden de los bloques de control
El orden de los bloques de control determina el orden z de los controles. El orden z es una ordenación relativa que determina la manera en la que los controles se solapan entre sí en un formulario. El primer control de la descripción del formulario establece la parte inferior del orden z. Los controles que aparecen posteriormente en la descripción del formulario están más arriba en el orden z y, por tanto, solapan a los que están más abajo en dicho orden.
Bloques de control incrustados
Algunos controles pueden contener otros controles. Cuando un control está contenido en otro, su bloque de control está incrustado en el bloque de control del contenedor. Puede incrustar bloques de control dentro de:
· Marcos
· Cuadros de imágenes
· Menús
· Controles personalizados, dependiendo de su objetivo
Los controles incrustados se utilizan normalmente para colocar botones de opción dentro de un marco. Visual Basic debe tener toda la información necesaria para el contenedor antes de que se agregue ningún control incrustado, por lo que las propiedades para un control deben ir antes de cualquier bloque de control incrustado. Visual Basic pasa por alto todas la propiedades dentro de un bloque de control que aparezcan después de los bloques de control incrustados.
Figura A.2 Estructura anidada de la descripción del formulario
Controles de menú
Los controles de menú deben aparecer juntos al final de la descripción del formulario, justo antes de que empiece la sección de atributos. Cuando Visual Basic encuentra un control de menú durante la carga de un formulario ASCII, espera encontrar todos los controles de menú juntos. Una vez que detecta un control que no es de menú a continuación de uno o más controles de menú, supone que no hay más controles de menú en el formulario y pasa por alto cualquier control de menú que encuentre durante la carga de ese formulario.
Teclas de método abreviado
Las teclas de método abreviado son teclas que se utilizan para activar un control de menú. Los formularios ASCII usan la misma sintaxis que la instrucción SendKeys para definir las combinaciones de teclas: “+” = MAYÚSCULAS, “^” = CTRL y “{Fn}” = tecla de función, donde n es el número de la tecla. Los caracteres alfabéticos se representan a sí mismos. La sintaxis de las teclas de método abreviado es la siguiente:
Método abreviado = ^{F4} ' <CTRL><F4>
Comentarios en la descripción del formulario
Puede agregar comentarios a la descripción del formulario. Las comillas simples (') son los delimitadores de los comentarios.
Propiedades de la descripción de un formulario
Cuando Visual Basic guarda un formulario, organiza las propiedades en un orden predeterminado. No obstante, al crear un formulario las propiedades se pueden organizar en cualquier orden.
Cualquier propiedad que no enumere se establece a su valor predeterminado cuando se carga. Cuando Visual Basic guarda un formulario, sólo incluye aquellas propiedades que no usan sus valores predeterminados. Cada control determina si se guardan o no todas sus propiedades o solamente aquellas cuyos valores son distintos de los valores predeterminados.
Sintaxis
Use esta sintaxis para definir las propiedades en la descripción del formulario:
propiedad = valor
Los valores de propiedad de texto deben aparecer entre comillas dobles. Las propiedades booleanas tienen un valor – 1 para True y 0 para False. Visual Basic interpreta todos los valores distintos de – 1 o 0 como True. Las propiedades con valores enumerados incluyen sus valores numéricos con la descripción del valor incluida como comentario. Por ejemplo, la propiedad BorderStyle aparece así:
BorderStyle = 0 ' Ninguno
Valores binarios de propiedades
Algunos controles disponen de propiedades cuyos valores son datos binarios, como la propiedad Picture del cuadro de imagen y los controles de imagen o ciertas propiedades de los controles personalizados. Visual Basic guarda todos los datos binarios de un formulario en un archivo de datos binario aparte del formulario.
Visual Basic guarda el archivo de datos binario en el mismo directorio que el formulario. El archivo de datos binario tiene el mismo nombre que el formulario, pero con la extensión .frx. Visual Basic lee el archivo de datos binario cuando carga el formulario, por lo que el archivo de datos binario (.frx) debe estar disponible para el formulario cuando Visual Basic lo carga. Si comparte formularios con otras personas que usan un archivo de datos binario, asegúrese de proporcionar el archivo de datos binario (.frx), además del formulario (.frm).
Las propiedades que tengan datos binarios como valores aparecen en el formulario como una referencia a un desplazamiento de byte en el archivo de datos binario. Por ejemplo, el valor de una propiedad Picture aparece de la siguiente manera en la descripción de un formulario:
Begin VB.Image imgDemo
Picture = "Miform.frx":02EB
End
La enumeración de la propiedad significa que los datos binarios que definen la propiedad Picture de este control empiezan en el byte 2EB (hex) del archivo Miform.frx.
Propiedad Icon
El valor de la propiedad Icon de un formulario depende de qué icono se utilice para el formulario. La siguiente tabla muestra los valores de la propiedad Icon y la manera en que esas propiedades aparecen en un formulario.
Propiedad TabIndex
Si no se especifica la propiedad TabIndex, Visual Basic asigna el control a la primera ubicación posible en el orden de tabulación una vez que estén cargados todos los demás controles.
Unidades de medida
El tamaño de los controles, las coordenadas x e y, así como otros valores de propiedades que utilicen unidades de medida se expresan en twips. Cuando un control usa un modo de escala diferente a los twips y Visual Basic carga el formulario, convierte los valores en twips del formulario ASCII a las unidades de medida especificadas por la propiedad ScaleMode.
Valores de colores
Los valores de colores aparecen como valores RGB (rojo, verde y azul). Por ejemplo, la propiedad ForeColor aparece de esta manera:
ForeColor = &H00FF0000&
Visual Basic también puede leer valores de QBColor, convirtiéndolos a RGB cuando carga el formulario. Los formularios ASCII que utilicen valores de QBColor deben usar esta sintaxis:
ForeColor = QBColor(qbcolor)
donde qbcolor es un valor de 0 a 15.
Observe que el argumento qbcolor corresponde a los valores de color utilizados por las instrucciones gráficas en otras versiones de Basic, como Visual Basic para MS-DOS, Microsoft QuickBasic y el Sistema de desarrollo profesional Microsoft Basic.
Objetos de propiedades
Algunos objetos de propiedades, como por ejemplo el objeto Font, aparecen como un bloque distinto y muestran todos los valores de las diferentes propiedades del objeto. Estos bloques están delimitados por las instrucciones BeginProperty y EndProperty de la siguiente forma:
BeginProperty nombre_propiedad
propiedad1 = valor1
propiedad2 = valor2
.
.
.
EndProperty
Código de Basic
El código de Basic aparece en el formulario inmediatamente después de la sección de atributos, a continuación de la última instrucción End en la descripción del formulario. Las instrucciones en la sección Declaraciones de un formulario aparecen primero, seguidas de los procedimientos de evento, los procedimientos generales y las funciones.
Cuando Visual Basic carga un formulario en memoria, primero convierte el formulario al formato binario. Al realizar cambios en el formulario y guardar los cambios, Visual Basic vuelve a escribir el archivo en formato ASCII.
Cuando Visual Basic se encuentra con un error mientras está cargando un formulario, crea un archivo de registro e informa del error en el archivo de registro. Visual Basic agrega mensajes de error al archivo de registro cada vez que se encuentra con un error en el formulario. Cuando se ha terminado de cargar el formulario, Visual Basic presenta un mensaje que indica que se creó un archivo de registro de errores.
El archivo de registro tiene el mismo nombre que el archivo de formulario, pero con la extensión .log. Por ejemplo, si se producen errores mientras se carga Miform.frm, Visual Basic creará un archivo de registro llamado Miform.log. Si posteriormente vuelve a cargar Miform.frm y continúan produciéndose errores mientras se carga el formulario, Visual Basic reemplazará el archivo Miform.log anterior.
Mensajes de registro de error en la carga de un formulario
Los siguientes mensajes de error pueden aparecer en un archivo de registro de errores. Observe que estos mensajes de error sólo tratan problemas que pueden ocurrir cuando Visual Basic carga la descripción del formulario. No indican ningún problema que pueda existir en procedimientos de evento, en procedimientos generales o en cualquier otra parte del código de Basic.
Imposible cargar el menú nombre_menú.
Este mensaje aparece si Visual Basic encuentra un control de menú cuyo menú primario esté definido como un separador de menú. Los controles de menú que actúan como primarios para los controles de menú en un submenú no pueden ser separadores de menú. Visual Basic no carga el control de menú.
Este mensaje también aparece si Visual Basic encuentra un control de menú cuyo menú primario tiene su propiedad Checked establecida a True. Los controles de menú que actúan como primarios para los controles de menú en un submenú no pueden tener esta propiedad activada. Visual Basic no carga el control de menú.
Imposible establecer la propiedad Checked en el menú nombre_menú.
Este mensaje aparece si Visual Basic encuentra un control de menú de nivel superior con su propiedad Checked establecida a True. Los menús de nivel superior no pueden tener una marca de verificación. Visual Basic carga el control del menú, pero no establece su propiedad Checked.
Imposible establecer la propiedad Shortcut en nombre_menú.
Este mensaje aparece si Visual Basic encuentra un control de menú de nivel superior con una tecla de método abreviado definida. Los menús de nivel superior no pueden tener una tecla de método abreviado. Visual Basic carga el control del menú, pero no establece la propiedad Shortcut.
La clase nombre_clase del control nombre_control no es una clase de control cargada.
Este mensaje aparece si Visual Basic encuentra un nombre de clase que no reconoce.
Imposible cargar el control nombre_control.
Este mensaje aparece si Visual Basic encuentra un tipo de control desconocido en la descripción del formulario. Visual Basic crea un cuadro de imagen para representar el control desconocido, dando a ese cuadro de imagen todas las propiedades válidas de la descripción del control desconocido. Cuando aparece este mensaje, es probable que le sigan varios errores de propiedades no válidas.
El control nombre_control tiene una cadena entre comillas donde debería estar el nombre de la propiedad.
Este mensaje aparece si Visual Basic encuentra texto entre comillas en vez de un nombre de propiedad que no se coloca entre comillas. Por ejemplo:
"Caption" = "Comenzar la demostración"
En este caso, el nombre de propiedad Caption no debería estar entre comillas. Visual Basic pasa por alto la línea de la descripción del formulario que produce este error.
El nombre de control nombre_control no es válido.
Este mensaje aparece si el nombre de un control no es una cadena válida en Visual Basic. Visual Basic no cargará el control.
El nombre de control es demasiado largo; truncado a nombre_control.
Este mensaje aparece si Visual Basic encuentra un nombre de control con más de 40 caracteres. Visual Basic carga el control, truncando el nombre.
No se encontró una propiedad de índice y el control nombre_control ya existe. Imposible crear este control.
Este mensaje aparece si Visual Basic encuentra un control sin un índice que tiene el mismo nombre que un control cargado anteriormente. Visual Basic no carga el control.
Imposible cargar el formulario nombre_formulario.
Este mensaje aparece si Visual Basic encuentra inesperadamente el final del archivo o si falta la primera instrucción Begin.
El nombre del formulario o de MDIForm nombre_formulario no es válido; imposible cargar este formulario.
Este mensaje aparece si el nombre de un formulario no es una cadena válida en Visual Basic. Visual Basic no cargará el formulario.
Las cadenas válidas deben empezar con una letra, sólo pueden incluir letras, números y signos de subrayado, y deben tener como máximo 40 caracteres.
El nombre nombre_propiedad de la propiedad del control nombre_control no es válido.
Este mensaje aparece si el nombre de una propiedad no es una cadena válida en Visual Basic o tiene más de 30 caracteres. Visual Basic no establecerá la propiedad.
Imposible cargar la propiedad nombre_propiedad del control nombre_control.
Este mensaje aparece si Visual Basic encuentra una propiedad desconocida. Visual Basic pasa por alto esta propiedad cuando carga el formulario.
Imposible establecer la propiedad nombre_propiedad del control nombre_control.
Este mensaje aparece si Visual Basic no puede establecer la propiedad del control especificado como se indica en la descripción del formulario.
La propiedad nombre_propiedad del control nombre_control tiene un valor no válido.
Este mensaje aparece si Visual Basic encuentra un valor no válido para una propiedad. Visual Basic cambia el valor de la propiedad al valor predeterminado para esa propiedad.
La propiedad nombre_propiedad del control nombre_control tiene una referencia de archivo no válida.
Este mensaje aparece si Visual Basic no pudo usar una referencia de nombre de archivo. Esto ocurrirá si el archivo al que se refiere (probablemente un archivo de datos binario para el formulario) no se encuentra en el directorio especificado.
La propiedad nombre_propiedad del control nombre_control tiene un índice de propiedad no válido.
Este mensaje aparece si Visual Basic encuentra un nombre de propiedad con un índice de propiedad mayor de 255. Por ejemplo:
Prop300 = 5436
Visual Basic pasa por alto la línea de la descripción del formulario que produjo este error.
La propiedad nombre_propiedad del control nombre_control tiene un valor no válido.
Este mensaje aparece si Visual Basic encuentra una propiedad con un valor que no es correcto para ese control. Por ejemplo:
Top = Cahr(22) ' En realidad se deseaba Char(22).
Visual Basic establece la propiedad a su valor predeterminado.
La propiedad nombre_propiedad del control nombre_control debe ser una cadena entre comillas.
Este mensaje aparece si Visual Basic encuentra un valor de propiedad sin comillas que debería aparecer entre comillas. Por ejemplo:
Caption = Comenzar la demostración
Visual Basic pasa por alto la línea de la descripción del formulario que produjo este error.
Error de sintaxis: la propiedad nombre_propiedad del control nombre_control no tiene un '='.
Este mensaje aparece si Visual Basic encuentra un nombre y un valor de propiedad sin un signo igual entre ellos. Por ejemplo:
Text "Comenzar la demostración"
Visual Basic no carga la propiedad.
Formato del archivo de proyecto (.vbp)
Visual Basic siempre guarda los archivos de proyecto (.vbp) en formato ASCII. El archivo de proyecto contiene entradas que reflejan los valores de su proyecto. Entre estos se incluyen los formularios y módulos del proyecto, referencias, opciones varias que ha elegido para controlar la compilación, etc.
Esta es la apariencia que debe tener un archivo .vbp. Este proyecto incluye módulos guardados con los nombres de clase y de archivo que se muestran en la siguiente tabla.
Se agregan entradas al archivo .vbp cuando agrega formularios, módulos, componentes, etc. al proyecto. También se agregan entradas cuando establece opciones para el proyecto. Muchas de estas opciones se establecen mediante el cuadro de diálogo Propiedades del proyecto.
Apéndice B: Convenciones de codificación
Este apéndice presenta un conjunto de convenciones de codificación que sugerimos para los programas de Visual Basic.
Las convenciones de codificación son pautas de programación que no están enfocadas a la lógica del programa, sino a su estructura y apariencia física. Facilitan la lectura, comprensión y mantenimiento del código. Las convenciones de codificación pueden incluir:
· Convenciones de nombres para objetos, variables y procedimientos.
· Formatos estandarizados para etiquetar y comentar el código.
· Instrucciones de espaciado, formato y sangría.
En las secciones siguientes se explica cada una de estas áreas y se dan ejemplos de su uso correcto.
¿Por qué existen las convenciones de codificación?
La razón principal de usar un conjunto coherente de convenciones de código es estandarizar la estructura y el estilo de codificación de una aplicación de forma que el autor y otras personas puedan leer y entender el código fácilmente.
Las convenciones de codificación correctas dan como resultado un código fuente preciso, legible y sin ambigüedad, que es coherente con otras convenciones del lenguaje y lo más intuitivo posible.
Convenciones de codificación mínimas
Un conjunto de convenciones de codificación de propósito general debe definir los requisitos mínimos necesarios para conseguir los objetivos explicados anteriormente, dejando libertad al programador para crear la lógica y el flujo funcional del programa.
El objetivo es hacer que el programa sea fácil de leer y de entender sin obstruir la creatividad natural del programador con imposiciones excesivas y restricciones arbitrarias.
Por tanto, las convenciones sugeridas en este apéndice son breves y sugerentes. No muestran todos los objetos y controles posibles, ni especifican todos los tipos de comentarios informativos que podrían ser útiles. Dependiendo del proyecto y de las necesidades específicas de la organización, quizás desee ampliar estas instrucciones para que incluyan elementos adicionales como:
· Convenciones para objetos específicos y componentes desarrollados internamente o comprados a otros proveedores.
· Variables que describan las actividades comerciales o instalaciones de la organización.
· Cualquier otro elemento que el proyecto o la empresa considere importante para conseguir mayor claridad y legibilidad.
Convenciones de nombres de objetos
Los objetos deben llevar nombres con un prefijo coherente que facilite la identificación del tipo de objeto. A continuación se ofrece una lista de convenciones recomendadas para algunos de los objetos permitidos por Visual Basic.
Prefijos sugeridos para los objetos de acceso a datos (DAO)
Use los prefijos siguientes para indicar Objetos de acceso a datos (DAO).
Algunos ejemplos:
Prefijos sugeridos para menús
Las aplicaciones suelen usar muchos controles de menú, lo que hace útil tener un conjunto único de convenciones de nombres para estos controles. Los prefijos de controles de menús se deben extender más allá de la etiqueta inicial "mnu", agregando un prefijo adicional para cada nivel de anidamiento, con el título del menú final en la última posición de cada nombre. En la tabla siguiente hay algunos ejemplos.
Cuando se usa esta convención de nombres, todos los miembros de un grupo de menús determinado se muestran uno junto a otro en la ventana Propiedades de Visual Basic. Además, los nombres del control de menú documentan claramente los elementos de menú a los que están adjuntos.
Selección de prefijos para otros controles
Para los controles no mostrados arriba, debe intentar establecer un estándar de prefijos únicos de dos o tres caracteres que sean coherentes. Solamente se deben usar más de tres caracteres si proporcionan más claridad.
Para controles derivados o modificados, por ejemplo, amplíe los prefijos anteriores para que no haya dudas sobre qué control se está usando realmente. Para los controles de otros proveedores, se debe agregar al prefijo una abreviatura del nombre del fabricante en minúsculas. Por ejemplo, una instancia de control creada a partir del marco 3D incluido en la Edición profesional de Visual Basic podría llevar el prefijo fra3d para evitar confusiones sobre qué control se está usando realmente.
Convenciones de nombres de constantes y variables
Además de los objetos, las constantes y variables también requieren convenciones de nombres bien compuestas. En esta sección se muestran las convenciones recomendadas para las constantes y variables permitidas por Visual Basic. También se explican cuestiones relacionadas con la identificación del tipo de datos y su alcance.
Las variables se deben definir siempre con el menor alcance posible. Las variables globales (públicas) pueden crear máquinas de estado enormemente complejas y hacer la lógica de una aplicación muy difícil de entender. Las variables globales también hacen mucho más difícil mantener y volver a usar el código.
En Visual Basic las variables pueden tener el alcance siguiente:
En una aplicación de Visual Basic, las variables globales se deben usar sólo cuando no exista ninguna otra forma cómoda de compartir datos entre formularios. Cuando haya que usar variables globales, es conveniente declararlas todas en un único módulo agrupadas por funciones y dar al módulo un nombre significativo que indique su finalidad, como Public.bas.
Una práctica de codificación correcta es escribir código modular siempre que sea posible. Por ejemplo, si la aplicación muestra un cuadro de diálogo, coloque todos los controles y el código necesario para ejecutar la tarea del diálogo en un único formulario. Esto ayuda a tener el código de la aplicación organizado en componentes útiles y minimiza la sobrecarga en tiempo de ejecución.
A excepción de las variables globales (que no se deberían pasar), los procedimientos y funciones deben operar sólo sobre los objetos que se les pasan. Las variables globales que se usan en los procedimientos deben estar identificadas en la sección Declaraciones al principio del procedimiento. Además, los argumentos se deben pasar a los procedimientos Sub y Function mediante ByVal, a menos que sea necesario explícitamente cambiar el valor del argumento que se pasa.
Prefijos de alcance de variables
A medida que aumenta el tamaño del proyecto, también aumenta la utilidad de reconocer rápidamente el alcance de las variables. Esto se consigue escribiendo un prefijo de alcance de una letra delante del tipo de prefijo, sin aumentar demasiado la longitud del nombre de las variables.
Una variable tiene alcance global si se declara como Public en un módulo estándar o en un módulo de formulario. Una variable tiene alcance de nivel de módulo si se declara como Private en un módulo estándar o en un módulo de formulario, respectivamente.
Constantes
El cuerpo del nombre de las constantes se debe escribir en mayúsculas y minúsculas, con la letra inicial de cada palabra en mayúsculas. Aunque las constantes estándar de Visual Basic no incluyen información de tipo de datos y el alcance, los prefijos como i, s, g y m pueden ser muy útiles para entender el valor y el alcance de una constante. Para los nombres de constantes, se deben seguir las mismas normas que para las variables. Por ejemplo:
Variables
Declarar todas las variables ahorra tiempo de programación porque reduce el número de errores debidos a erratas (por ejemplo, aNombreUsuarioTmp frente a sNombreUsuarioTmp frente a sNombreUsuarioTemp). En la ficha Editor del cuadro de diálogo Opciones, active la opción Declaración de variables requerida. La instrucción Option Explicit requiere que declare todas las variables del programa de Visual Basic.
Las variables deben llevar un prefijo para indicar su tipo de datos. Opcionalmente, y en especial para programas largos, el prefijo se puede ampliar para indicar el alcance de la variable.
Tipos de datos de variables
Use los prefijos siguientes para indicar el tipo de datos de una variable
Nombres descriptivos de variables y procedimientos
El cuerpo de un nombre de variable o procedimiento se debe escribir en mayúsculas y minúsculas y debe tener la longitud necesaria para describir su funcionalidad. Además, los nombres de funciones deben empezar con un verbo, como IniciarNombreMatriz o CerrarDiálogo.
Para nombres que se usen con frecuencia o para términos largos, se recomienda usar abreviaturas estándar para que los nombres tengan una longitud razonable. En general, los nombres de variables con más de 32 caracteres pueden ser difíciles de leer en pantallas VGA.
Cuando se usen abreviaturas, hay que asegurarse de que sean coherentes en toda la aplicación. Alternar aleatoriamente entre Cnt y Contar dentro de un proyecto provoca una confusión innecesaria.
Tipos definidos por el usuario
En un proyecto grande con muchos tipos definidos por el usuario, suele ser útil dar a cada uno de estos tipos un prefijo de tres caracteres sólo suyo. Si estos prefijos comienzan con "u", será fácil reconocerlos cuando se esté trabajando con tipos definidos por el usuario. Por ejemplo, "ucli" se podría usar como prefijo para las variables de un tipo Cliente definido por el usuario.
Convenciones de codificación estructurada
Además de las convenciones de nombres, las convenciones de codificación estructurada, como comentarios al código y sangrías coherentes, pueden mejorar mucho la legibilidad del código.
Convenciones de comentarios al código
Todos los procedimientos y funciones deben comenzar con un comentario breve que describa las características funcionales del procedimiento (qué hace). Esta descripción no debe describir los detalles de implementación (cómo lo hace), porque a veces cambian con el tiempo, dando como resultado un trabajo innecesario de mantenimiento de los comentarios o, lo que es peor, comentarios erróneos. El propio código y los comentarios de líneas necesarios describirán la implementación.
Los argumentos que se pasan a un procedimiento se deben describir cuando sus funciones no sean obvias y cuando el procedimiento espera que los argumentos estén en un intervalo específico. También hay que describir, al principio de cada procedimiento, los valores de retorno de funciones y las variables globales que modifica el procedimiento, en especial los modificados a través de argumentos de referencia.
Los bloques del comentario de encabezado del procedimiento deben incluir los siguientes encabezados de sección. En la sección siguiente, "Dar formato al código", hay algunos ejemplos.
Recuerde los puntos siguientes:
· Cada declaración de variable importante debe incluir un comentario de línea que describa el uso de la variable que se está declarando.
· Las variables, controles y procedimientos deben tener un nombre bastante claro para que los comentarios de línea sólo sean necesarios en los detalles de implementación complejos.
· Al principio del módulo .bas que contiene las declaraciones de constantes genéricas de Visual Basic del proyecto, debe incluir un resumen que describa la aplicación, enumerando los principales objetos de datos, procedimientos, algoritmos, cuadros de diálogo, bases de datos y dependencias del sistema. Algunas veces puede ser útil un pseudocódigo que describa el algoritmo.
Dar formato al código
Como muchos programadores usan todavía pantallas VGA, hay que ajustarse al espacio de la pantalla en la medida de lo posible y hacer que el formato del código siga reflejando la estructura lógica y el anidamiento. Estos son algunos indicadores:
· Los bloques anidados estándar, separados por tabuladores, deben llevar una sangría de cuatro espacios (predeterminado).
· El comentario del esquema funcional de un procedimiento debe llevar una sangría de un espacio. Las instrucciones de nivel superior que siguen al comentario del esquema deben llevar una sangría de un tabulador, con cada bloque anidado separado por una sangría de un tabulador adicional. Por ejemplo:
'*****************************************************
' Finalidad: Ubica el primer caso encontrado de un
' usuario especificado en la matriz
' ListaUsuario.
' Entradas:
' strListaUsuario(): lista de usuarios para buscar.
' strUsuarioDest: nombre del usuario buscado.
' Resultados: Índice del primer caso de rsUsuarioDest
' encontrado en la matriz rasListaUsuario.
' Si no se encuentra el usuario de destino, devuelve -1.
'*****************************************************
Function intBuscarUsuario (strListaUsuario() As String, strUsuarioDest As _
String)As Integer
Dim i As Integer ' Contador de bucle.
Dim blnEncontrado As Integer ' Indicador de
' destino encontrado.
intBuscarUsuario = -1
i = 0
While i <= Ubound(strListaUsuario) and Not blnEncontrado
If strListaUsuario(i) = strUsuarioDest Then
blnEncontrado = True
intBuscarUsuario = i
End If
Wend
End Function
Agrupación de constantes
Las variables y constantes definidas se deben agrupar por funciones en lugar de dividirlas en áreas aisladas o archivos especiales. Las constantes genéricas de Visual Basic se deben agrupar en un único módulo para separarlas de las declaraciones específicas de la aplicación.
Operadores & y +
Use siempre el operador & para unir cadenas y el operador + cuando trabaje con valores numéricos. El uso del operador + para concatenar puede causar problemas cuando se opera sobre dos variables Variant. Por ejemplo:
vntVar1 = "10.01"
vntVar2 = 11
vntResult = vntVar1 + vntVar2 'vntResult = 21.01
vntResult = vntVar1 & vntVar2 'vntResult = 10.0111
Crear cadenas para MsgBox, InputBox y consultas SQL
Cuando esté creando una cadena larga, use el carácter de subrayado de continuación de línea para crear múltiples líneas de código, de forma que pueda leer o depurar la cadena fácilmente. Esta técnica es especialmente útil cuando se muestra un cuadro de mensaje (MsgBox) o un cuadro de entrada (InputBox), o cuando se crea una cadena SQL. Por ejemplo:
Dim Msj As String
Msj = "Esto es un párrafo que estará en un" _
& " cuadro de mensajes. El texto está separado en" _
& " varias líneas de código en el código de origen, " _
& "lo que facilita al programador la tarea de leer y depurar."
MsgBox Msj
Dim CTA As String
CTA = "SELECT *" _
& " FROM Título" _
& " WHERE [Fecha de publicación] > 1988"
ConsultaTítulos.SQL = CTA
Visiten Youtube, Programación, Scribd, Taringa, mis paginas
No hay comentarios:
Publicar un comentario