Curso sobre Visual Basic
por Guillermo Llanderas

Segunda Parte


Los temas incluidos:


Bases de datos (métodos y propiedades para el acceso a los datos)


Abrir una base de datos

'Abrir una base de datos:
Set database = workspace.OpenDatabase(dbname[,exclusive[,read-only[,source]]])
  'exclusive -> true para abrirla en modo exclusivo. Por defecto, false
  'read-only -> true para abrirla en modo read-only. Por defecto, false
  'source -> es una cadena que identifica el tipo de base de datos y unos
  ' argumentos en el caso de ODBC. Los tipos soportados son:
  '       access          no necesita
  '       dBASE III       "dBASE III;"
  '       dBASE IV        "dBASE IV;"
  '       Paradox 3.x     "Paradox 3.x;"
  '       Paradox 4.x     "Paradox 4.x;"
  '       Btrieve         "Btrieve;"
  '       FoxPro 2.0      "FoxPro 2.0;"
  '       FoxPro 2.5      "FoxPro 2.5;"
  '       FoxPro 2.6      "FoxPro 2.6;"
  '       Excel 3.0       "Excel 3.0;"
  '       Excel 4.0       "Excel 4.0;"
  '       Excel 5.0       "Excel 5.0;"
  '       Text            "Text;"
  '       ODBC            "ODBC;
  ' los argumentos que se lo pueden pasar a ODBC son (por ejemplo):
  '       DATABASE=defaultdatabase;
  '       UID=user; PWD=password;
  '       DSN=datasourcename
  '       LOGINTIMEOUT=seconds"


Abrir un Recordset perteneciente a una base de datos

'Abre un recordset perteneciente a una base de datos:
Set variable = database.OpenRecordset(source[,type[,options]])
  'source -> el origen del recordset.
  '   si es una tabla, el nombre de la tabla dentro de la base de datos
  '   si es un dynaset, la instrucción SQL de consulta
  'type -> el tipo de recordset a abrir. Puede ser: (por defecto dbOpenTable)
  '       dbOpenTable     para un recordset de tipo tabla
  '       dbOpenDynaset   para un recordset de tipo dynaset
  '       dbOpenSnapshot  para un recordset de tipo snapshot
  'options -> Opciones para modificar el modo de acceso a las tablas
  ' dbDenyWrite       Impide que otros usuarios escriban en el recordset
  '                   (impide tanto modificacar como añadir registros)
  ' dbDenyRead        Impide que otros usuarios lean el recordset mientras
  '                   está abierta (solo para tablas)
  ' dbReadOnly        Se abre en modo lectura. Otros usuarios pueden modificar
  ' dbAppendOnly      Solo puedo añadir nuevos registros (solo para dynasets)
  '                   (impide leer o modificar los existentes)
  ' dbInconsistent    Se permiten actualizaciones inconsistentes (solo dynasets)
  ' dbConsistent      Solo se permiten actualiza. consistentes (solo dynasets)
  ' dbForwardOnly     Permite desplazarse solamente hacia adelante
  ' dbSQLPassThrough  Se evita el procesador de consultas del Jet. La consulta
  '                   especificada se traslada a un servidor de ODBC para su
  '                   procesamiento
  ' dbSeeChanges      Para que genere un runtime error si otro usuario cambia
  '                   los datos que estoy editando.


Establecer índices, filtros y criterios de ordenación

'Establecer índices, filtros y criterios de ordenación

'Propiedad Index: especifica el orden de un conjunto de registros en base al
' valor de uno o más campos. Sólo está disponible para tablas.
recordset.Index [= indexname]
  'indexname -> nombre del índice a usar (debe de estar definido en la tabla)

'Propiedad Filter: limita el ámbito de registros, al especificar los que
' cumplan cierto criterio. Solo disponible para dynasets y snapshots
recordset.Filter [= value]
  'value -> string expression que contiene la clausula WHERE de una consulta
  '         SQL sin la palabra reservada WHERE

'Propiedad Sort: especifica el orden de un conjunto de registros en base al
' valor de uno o más campos. Sólo disponible para dynasets y sanpshots
recordset.Sort [=value]
  'value -> string expression que especifica la cluasula ORDER BY de una
  '         consulta SQL sin la palabra reservada ORDER BY


Consultar datos y Modificar registros de un Recordset

'Consultar datos del recodset
recordset.BOF             'Puntero de registro en el principio del recordset
recordset.EOF             'Puntero de registro al final del recordset
recordset.RecordCount     'Número de registros del recordset
recordset.NoMatch         'Indica si el último método de búsqueda o Seek no
                          ' ha conseguido localizar un registro que coincida
                          ' con el criterio especificado
'Modificar registros en el recordset (no sirven para snapshots)
recordset.AddNew          'Prepara el buffer para añadir un registro nuevo
recordset.Edit            'Prepara el buffer para modificar los datos del
                          ' registro actual
recordset.Update          'Guarda los datos del buffer después de un AddNew
                          ' o de un Update
recordset.Delete          'Borra el registro actual del recordset
{workspace | database}.BeginTrans     'Inicia una transacción y establece el
                                      ' estado inicial de la base de datos
{workspace | database}.RollBack       'Vuelve la base de datos a su estado
                                      ' inicial anterior a la emisión de la
                                      ' instrucción BeginTrans
{workspace | database}.CommitTrans    'Guarda de manera permanente todas las
                                      ' modificaciones hechas a la base de
                                      ' datos desde el último BeginTrans


Moverse por la base de datos

'Para moverse por la base de datos:

'Métodos Move: sirven para cambiar la posición del puntero del registro
' desde el registro en uso hasta otro
recordset.Move rows[, start]
recordset.{MoveFirst | MoveLast | MoveNext | MovePrevious}
  'rows -> signed long que indica el número de columnas que se va a
  '        mover el puntero de la base de datos
  'start -> string que identifica un bookmark a partir del que se va a
  '         desplazar el puntero 'rows' columnas. Si no se especifica,
  '         move empieza desde el registro actual
  ' Método         A donde mueve el puntero de registro
  'MoveFirst      Al primer registro del conjunto de registros abierto
  'MoveNext       Al siguiente registro. Si no hay más, se activa EOF
  'MovePrevious   Al registro anterior. Si no hay, se activa BOF
  'MoveLast       Al último registro del conjunto de registros abierto

'Métodos Find: localizan el siguiente registro que cumpla la condición.
' Estos métodos funcionan con dynaset y snapshot
recordset.{FindFirst | FindLast | FindNext | FindPrevious} criteria
  'criteria -> una string expression (como la cláusula WHERE de una consulta
  '            SQL) usada para localizar el registro.
  '  Método         Empieza en                Dirección de búsqueda
  ' FindFirst      Principio del recordset   Hacia el final del recordset
  ' FindLast       Final del recordset       Hacia el principio del recordset
  ' FindNext       Registro actual           Hacia el final del recordset
  ' FindPrevious   Registro actual           Hacia el principio del recordset
  'Después de usar estos métodos, hay que comprobar el estado de la
  ' propiedad NoMatch. Si es verdadero, el método ha fallado al hallar un
  ' registro que cumpla los criterios. Si es falso, el puntero está situado
  ' en un registro encontrado.

'Métodos Seek: hallan el primer registro de una tabla que cumpla una
' condición. Solo se puede usar en tablas (no en dynasets o snapshots)
table.Seek comparison, key1, key2...
  'comparison -> Una de estas string expressions: "<", "<=", "=", ">=", or ">"
  'key1,key2... -> uno o más valores para los campos del índice
  ' Si el operador de comparación es =, >=, > o <>, empieza por el primer
  '  registro para el índice en uso y explora hacia adelante por todo el
  '  índice para hallar la primera coincidencia. Si el operador es < o <=,
  '  empieza por el último registro de la tabla y explora hacia atrás por
  '  toda la tabla.
  'Después de usar estos métodos, hay que comprobar el estado de la
  ' propiedad NoMatch. Si es verdadero, el método ha fallado al hallar un
  ' registro que cumpla los criterios. Si es falso, el puntero está situado
  ' en un registro encontrado.

'Propiedad Bookmark: Identifica la ubicación de un registro específico
object.Bookmark [= value]
  'value -> una string expression o una variant expression que identifica
  '         un bookmark válido
  'Si no se especifica value, la propiedad bookmark devuelve la marca
  ' identificadora del registro actual. Si es especifica, el puntero de
  ' registro se desplaza al registro caracterizado por ese bookmark

'Metodo Idle: Suspende el proceso de los datos, permitiendo al JET completar
' una tarea pendiente como optimizacion de memoria o desbloqueos de paginas
DBEngine.Idle [dbFreeLocks]
  'dbFreeLocks -> si se especifica esta constante, el proceso se detiene hasta
  '               que todos los bloqueos son liberados

Ejemplos de acceso a bases de datos

' Acceso a los datos:

Dim Ws As Workspace
Dim dbAcuario As Database
Dim tbClientes As Recordset
Dim dnClientes As Recordset
Dim dnCliente1Prov As Dynaset
Dim ssClientes As Recordset
Dim sClientes As String

Private Sub Form_Load()
  Set Ws = DBEngine.Workspaces(0)

  'Abre una DB de tipo Access con opciones predeterminadas de acceso a
  'lectura/escritura de datos y acceso compartido:
  Set dbAcuario = Ws.OpenDatabase("acuario.mdb")

  'Abre una tabla de Access con los parámetros implícitos de uso compartido
  'y modo de uso lectura/escritura:
  Set tbClientes = dbAcuario.OpenRecordset("Clientes", dbOpenTable)
  'Abre un dynaset que consta de todos los registros de la tabla Clientes:
  Set dnClientes = dbAcuario.OpenRecordset("SELECT * FROM Clientes", _
                    dbOpenDynaset)
    'Ahora se puede abrir un dynaset a partir del dynaset anterior aplicando
    'un filtro y un método de ordenación
  dnClientes.Filter = "Provincia = 'Po' AND Ciudad <> 'Tuy'"
  dnClientes.Sort = "Provincia,Ciudad"
  Set dnCliente1Prov = dnClientes.OpenRecordset(dbOpenDynaset)
  'Abre un snapshot que consta de todos los registros de la tabla Clientes:
  Set ssClientes = dbAcuario.OpenRecordset("SELECT * FROM Clientes", _
                    dbOpenSnapshot)

  'Establecer el índice a usar e inicializar los datos en pantalla
  tbClientes.Index = "Nombre"
  MsgBox "Número total de registros = " & Str(tbClientes.RecordCount)
  tbClientes.MoveFirst

  'Poner los controles en condiciones iniciales.
  PbValidaciones.Visible = False
  PbOpciones.Visible = True
  For Indice = 0 To 3
    TbDatos(Indice).Enabled = False
  Next Indice
  Call VisualizarDatos
End Sub

  'Impresión de los campos de la tabla en pantalla (función VisualizarDatos)
Sub VisualizarDatos()
  CbPrimero.Enabled = Not TblDirs.BOF
  CbAnterior.Enabled = Not TblDirs.BOF
  CbSiguiente.Enabled = Not TblDirs.EOF
  CbUltimo.Enabled = Not TblDirs.EOF
  If TblDirs.BOF Then
    TblDirs.MoveFirst
  End If
  If TblDirs.EOF Then
    TblDirs.MoveLast
    CbAnterior.SetFocus
  End If
  TbDatos(0).Text = IIf(IsNull(TblDirs("Nombre")), " ", _
                  TblDirs("Nombre"))
  TbDatos(1).Text = IIf(IsNull(TblDirs("Apellidos")), " ", _
                  TblDirs("Apellidos"))
  TbDatos(2).Text = IIf(IsNull(TblDirs("Direccion")), " ", _
                  TblDirs("Direccion"))
  TbDatos(3).Text = IIf(IsNull(TblDirs("Ciudad")), " ", _
                  TblDirs("Ciudad"))
End Sub

  'Borrar un registro de la tabla
Private Sub CbBorrar_Click()
  If MsgBox("+Borrar este registro?", vbYesNo + vbQuestion, "Borrar registro") = 6 Then
    TblDirs.Delete
    If Not TblDirs.EOF Then
      TblDirs.MoveNext
    Else
      TblDirs.MovePrevious
    End If
    Call VisualizarDatos
  End If
End Sub

  'Moverse por la tabla de datos:
    'Al primer registro
Private Sub CbPrimero_Click()
  TblDirs.MoveFirst
  Call VisualizarDatos
  CbPrimero.Enabled = False
  CbAnterior.Enabled = False
End Sub
  'Al registro anterior
Private Sub CbAnterior_Click()
  TblDirs.MovePrevious
  Call VisualizarDatos
End Sub
  'Al registro siguiente
Private Sub CbSiguiente_Click()
  TblDirs.MoveNext
  Call VisualizarDatos
End Sub
  'Al último registro
Private Sub CbUltimo_Click()
  TblDirs.MoveLast
  Call VisualizarDatos
  CbUltimo.Enabled = False
  CbSiguiente.Enabled = False
  CbAnterior.SetFocus
End Sub

  'Añadir un registro:
Private Sub CbAnadir_Click()
  Nuevo = True
  For Indice = 0 To 3
    TbDatos(Indice).Enabled = True
  Next Indice
  TbDatos(0).SetFocus
  PbValidaciones.Visible = True
  PbOpciones.Visible = False
End Sub
    'Editar los campos y en el procedimiento OK:
Private Sub CbOK_Click()
  For Indice = 0 To 3
    TbDatos(Indice).Enabled = False
  Next Indice
  If Nuevo Then
    TblDirs.AddNew
  Else
    TblDirs.Edit
  End If
  TblDirs("Nombre") = Left(TbDatos(0).Text, 30)
  TblDirs("Apellidos") = Left(TbDatos(1).Text, 30)
  TblDirs("Direccion") = Left(TbDatos(2).Text, 40)
  TblDirs("Ciudad") = Left(TbDatos(3).Text, 30)
  TblDirs.Update
  PbOpciones.Visible = True
  PbValidaciones.Visible = False
  TblDirs.Bookmark = TblDirs.LastModified
  Call VisualizarDatos
End Sub
    'En el procedimiento de Cancel:
Private Sub CbCancelar_Click()
  For Indice = 0 To 3
    TbDatos(Indice).Enabled = False
  Next Indice
  Call VisualizarDatos
  PbOpciones.Visible = True
  PbValidaciones.Visible = False
End Sub

  'Para modificar los datos de un registro:
Private Sub CbModificar_Click()
  Nuevo = False
  For Indice = 0 To 3
    TbDatos(Indice).Enabled = True
  Next Indice
  TbDatos(0).SetFocus
  PbValidaciones.Visible = True
  PbOpciones.Visible = False
End Sub
    'Editar los campos. Los procedimientos OK y Cancel son iguales a Añadir.

  'Al entrar en los campos de datos, poner todo el texto marcado
Private Sub TbDatos_GotFocus(Index As Integer)
  TbDatos(Index).SelStart = 0
  TbDatos(Index).SelLength = Len(TbDatos(Index).Text)
End Sub


  'Buscar un registro en un dynaset o en un snapshot
  Dim FindCrit As String
  FindCrit = "Direccion = 'Camelias'"
    'Busca el primer registro que cumpla esa condición
  dnCliente1Prov.FindFirst FindCrit
  Do While Not dnCliente1Prov.NoMatch
    'Busca los siguientes registros que la cumplan
    dnCliente1Prov.FindNext FindCrit
  Loop
    'O bien, se puede hacer la búsqueda al revés, empezando por el final
  dnCliente1Prov.FindLast FindCrit
  Do While Not dnCliente1Prov.NoMatch
    'Busca los siguientes registros que la cumplan
    dnCliente1Prov.FindPrevious FindCrit
  Loop

  'Buscar un registro usando el método Seek
  tbClientes.Index = "Nombre"
    'Buscar el primer cliente cuyo nombre sea mayor que Perez
  tbClientes.Seek ">", "Perez"
  If tbClientes.NoMatch Then
    MsgBox "No aparece"
  Else
    MsgBox "Apareció"
  End If
    'Para buscar por nombre y apellido con una clave compuesta
  TblCliente.Seek ">=", "Perez", "F"

  'Uso de Bookmark:
    'Guarda en sClientes el Bookmark del registro actual
  sClientes = tbClientes.Bookmark
    'nos movemos a otro registro
  tbClientes.MoveNext
    'y volvemos al registro que hemos marcado
  tbClientes.Bookmark = sClientes
    'Se puede usar un array de bookmarks para marcar una serie de registros
    'y después acceder a ellos.
  ReDim BkMrk(1)
  nmbkmk = 0
  tbClientes.MoveFirst
  Do Until tbClientes.EOF
    If birthday Then
      nmbkmk = nmbkmk + 1
      If nmbkmk > 1 Then
        ReDim BkMrk(1 To nmbkmk)
      End If
      BkMrk(nmbkmk) = tbClientes.Bookmark
    End If
    tbClientes.MoveNext
  Loop
  For I = 1 To nmbkmk
    tbClientes.Bookmark = BkMrk(I)
  Next I

ir al índice