Creación de Aplicaciones multiusuario – 1 Ejecución de Access en red La primera decisión a que tenemos que enfrentarnos cuando creamos una aplicación multiusuario de Access es dónde poner los archivos de la Base de Datos. Podemos elegir instalar de dos formas: 1. Instal Instalar ar la Base de Datos Datos completa completa de Access Access en el servidor servidor,, lo que permit permite e a tod todos os los usuarios ejecutar Access desde su estación de trabajo hacia el servidor. 2. Instalar Instalar la aplicación aplicación de Access Access con tablas tablas vinculada vinculadass en cada estación estación de trabajo trabajo y compartir solamente los datos de la Base de Datos entre los usuarios de la red. Instalación de la aplicación en el servidor
Muchos programadores noveles en las aplicaciones de Access en red eligen instalar Access Access en el servidor, como se indica en la primera p rimera opción. La ejecución de Access en el servidor tiene las ventajas siguientes: • •
Se emplea poco espacio o ninguno en las estaciones de trabajo. El software se actualiza fácilmente, porque solamente es preciso actualizar un conjunto de archivos.
Aunque ésta es la solución más fácil, no es la mejor. Durante la ejecución de Access se producen numerosos accesos al servidor de red. Cuando todos los archivos están situados en el servidor de red, éste acceso constante degrada el rendimiento de la red y ralentiza la aplicación de forma significativa. Sin contar con otros problemas habituales de bloqueo de la aplicación por un uso inadecuado del bloqueo de registros. Instalación de Access en cada estación de trabajo
Para solucionar éste problema de rendimiento en la ejecución de Access en red, se puede ejecutar localmente en cada estación de trabajo, accediendo solamente a los datos compartidos que se almacenan en una Base de Datos en el servidor que contiene solamente las tablas de la Aplicación. Dado que la conexión de red se emplea únicamente para la transmisión de datos y no para cargar y ejecutar Access, el funcionamiento general de la Aplicación es mucho más rápido, más seguro, y sin duda alguna, la forma correcta de instalar la Aplicación en red. La única desventaja real de ésta forma de instalación es el incremento en el tiempo de mantenimiento. Aún así, hay formas de realizarlo que resultan extremadamente sencillas, como más adelante se indicará. Para rea Para realiz lizar ar la ins instal talaci ación ón de Acc Access ess de ésta forma forma siguientes procesos:
se deben deben llevar a cab cabo o los
1. Dividir Dividir la Base de Datos Datos mediante mediante el el asistente asistente de Acces Access, s, de forma forma que en una una Base de Datos – Back End - quedarán las tablas, y en la otra – Front End - el resto, con las consultas, formularios, informes etc. 2. Insta Instalar lar el Backe Backend nd , la parte parte de de las tablas tablas en en el servid servidor or de la red 3. Inst Instal alar ar el Fronte Frontend nd en una de la lass es esta taci cion ones es de tr trab abaj ajo. o. Co Con n el as asis iste tent nte e pa para ra administrar las tablas vinculadas apuntar cuando salga el buscador hacia el Frontend instalado en el servidor.
4. Hacer Hacer una copia copia de éste Fronten Frontend, d, que ya tiene tiene las tablas bien bien vinculadas, vinculadas, e instalar instalar en cada estación de trabajo. Mi hábito personal es renombrar luego cada Frontend para evitar cualquier conflicto de nombres, por ejemplo, MiBase1, MiBase2, etc. Una vez realizados todos los pasos, tenemos ya lista la aplicación para trabajar desde cada puesto de trabajo, con la ventaja de que por la red solamente circularán los datos almacenados en la aplicación. Dividir la Base de Datos
Para poder instalar Access a nivel de estaciones de trabajo tenemos que empezar por dividir las tablas donde se almacenan los datos, de todos los demás objetos de la Base de Datos, de forma que obtengamos dos Bases de Datos para la Aplicación.
DISEÑO
TABLAS
Consultas Formularios Macros
Vinculos con Tablas
Tablas
Informes Módulos
División de los objetos en dos Bases de Datos
Al tener en cada estación de trabajo la parte de formularios, informes, etc, el rendimiento es muy superior a la primera opción que hemos señalado. Imaginemos abrir un formul for mulari ario o com comple plejo, jo, cuy cuyo o dis diseñ eño o tuv tuviér iéramo amoss que pasarlo pasarlo a tra través vés de la re red d par para a cad cada a estaci est ación ón de tra trabaj bajo. o. En poco tie tiempo, mpo, la cap capaci acidad dad de trá tráfic fico o de la red se pod podría ría ver colapsada. De ésta segunda manera, los formularios están en cada estación de trabajo, por lo que su apertura es prácticamente instantánea. Una vez dividida la Base de Datos, el propio asistente genera la vinculación de las tablas.. Per tablas Pero o com como o no norma rmalmen lmente te la div divisi isión ón la re reali alizam zamos os en el pue puesto sto de tra trabaj bajo o del programador de la aplicación, cuando pongamos la base de datos de las tablas en el servidor, el Frontend tendrá un vínculo a las tablas que no es el actual. Para ello, en la Barra de menús de Access, en Herramientas Herramientas > Administrador Administrador de tablas vinculadas tenemos un asistente asistente que nos permite buscar la ubicación actual del backend de las tablas y actualizar los vínculos. v ínculos. En este punto hay que señalar que la división de una base de datos no es solo conveniente por una cuestión de tráfico de red, sino necesario cuando estamos desarrollando la apl aplica icació ción n par para a pod poder er act actual ualiza izarr los cam cambio bioss en el dis diseño eño de con consul sultas tas,, for formul mulari arios, os, informes, código VBA, etc. Si no hemos dividido la Base de Datos y el cliente nos solicita algunos algun os cambios, cambios, ¿qué vamos a hace hacerr si ya está introduci introduciendo endo datos? datos? Si hemos dividido dividido previamente la base de datos, la parte de las tablas seguirá siendo la misma, y podremos cambiar cualquier parte de diseño, simplemente cambiando el frontend de cada estación de trabajo por el Frontend con las nuevas modificaciones. Eso sí, en todo momento vigilando que la vinculación de las tablas sea la correcta.
Actualización de vínculos de las tablas
Con independencia de qué método utilicemos para vincular tablas, ya sea mediante el asistente de Access o mediante código VBA, es preciso capacitar a nuestra aplicación para reparar los vínculos rotas, si no queremos acudir a repararlos personalmente cada vez que un usuario o el administrador de la red mueva la carpeta que contiene la base de datos o cambie el nombre. La forma manual de vincular tablas mediante el asistente de Access ya la hemos explicado. Existe una forma de hacerlo mediante código VBA que nos va a permitir que el usuario disponga de un botón que le permita de forma sencilla actualizar los vínculos. - Detectar cuando se rompe un vínculo
Para ev Para evit itar ar so sorp rpre resa sass al us usua uari rio o po poco co ex expe pert rto o en te tema mass de pr prog ogra rama maci ción ón es conveniente proveer a la aplicación de un sistema que al iniciarse detecte si se ha roto algún vínculo de las tablas. De ésta manera, podemos parar l a ejecución de la aplicación e indicarle al usuario que las tablas no están donde estaban y que hay que decirle al programa dónde se encuentran. Para comprobar la validez de un vínculo, simplemente hay que hacer referencia a una propiedad TableDef de la tabla vinculada y tratar los errores que se produzcan. Supongamos que se produce el error siguiente: Error 3265 – El elemento no se encuentra en ésta colección Este error indica sencillamente que el vínculo se ha perdido. Entonces, para hacer ésta primera comprobación, crearemos una función en la ventana módulos que compruebe si efectivamente hay error o no.
Esta función mira si se produce el error que detecta si el vínculo se ha roto o no. Si se ha roto devuelve False y si no se ha roto devuelve True. Ahora podremos utilizar éste resultado para, primero, avisar al usuario del problema, y después revincular las tablas. Esto lo podemos hacer en un formulario de inicio de la aplicación, que lo abrimos de forma predeterminada, y para ello creamos un procedimiento en el evento Al abrir del formulario Inicio:
Una vez que hayamos determinado que se ha roto un vínculo de las tablas, hay que buscar el nuevo emplazamiento de la base de datos del servidor, la que contiene las tablas. Para ello implantaremos un nuevo módulo que se lo facilitaremos a nuestro cliente.
Creación de Aplicaciones multiusuario – 2 Actualizar vínculos de las tablas Una vez determinado que se ha roto un vínculo, v ínculo, como veíamos en el capítulo anterior, hay que buscar el nuevo emplazamiento de la base de datos de las tablas ubicada en el servidor. Se puede hacer manualmente, mediante el asistente de Access Administrador de tablas tab las vin vincul culada adass que muestra muestra un Arc Archiv hivo… o… bus buscar car.. Per Pero o es esto to es com compli plicar carle le la vid vida a al usuario, que tendrá que ir a la Barra de menús y hacer todo el proceso manualmente. La mejor solución es escribirlo en código VBA para automatizar al máximo posible ésta operación. Actualización de los vínculos
Para reparar el vínculo roto, tenemos que definir la información de conexión a las tablas tabl as re remo mota tas, s, em empl plea eand ndo o la nu nuev eva a ub ubic icac ació ión n y de dese senc ncad aden enan ando do lu lueg ego o el mé méto todo do RefreshLink para volver a vincular la tabla.
Para poner en marcha marcha ésta función, y restablecer el vínculo roto roto hay que llamar a la función pasando tanto la nueva ruta de acceso como la tabla a vincular. Para ello escribimos el siguiente código en un botón del formulario de inicio: Dim resultado as Bolean Resultado = refresca(“Nombredelatabla”,”C:\Carpeta\Subcarpeta\Bases refresca(“Nombredelatabla”,”C:\Carpeta\Subcarpeta\Bases de datos en red.mdb”)
Lo que hace el bucle For … Each … Next es recorrer las tablas una por una, coge su nombre y lo pasa a la base de datos externa para volver a crear el vínculo. De ésta forma, nos aseguramos que todas las tablas tendrán el vínculo actualizado. Algo que debemos tener en cuenta cuando vinculamos tablas es que, aunque aparecen en la ventana de la base de datos, las tablas no residen realmente en la aplicación. Dado que residen en la base de datos externa y no en la aplicación, solamente notaremos que los vínculos están rotos cuando abrimos la tabla , consulta o formulario basado en esa tabla.
Un ejemplo práctico completo A continuación vamos a exponer un ejemplo práctico para poder aplicarlo en nuestra aplicación. Lo primero que debemos hacer es crear un formulario con tres botones y un cuadro de texto, como se indica en la figura.
A continuación vamos a crear las l as funciones que harán funcionar todo este sistema. De forma esquemática necesitamos los siguientes módulos: Un módulo que llamaremos mdTestVinculos Un módulo que llamaremos mdDialogoAbrir
Al final de la exposición de los módulos haremos un resumen del funcionamiento y dónde se utiliza cada módulo. Empe Em peza zare remo moss cr crea eand ndo o un mó módu dulo lo en la Ve Vent ntan ana a de mó módu dulo loss qu que e lla llama mare remo moss mdTestVinculos y que hará una comprobación de las tablas vinculadas. Para ello, copiar y pegar en dicho módulo el siguiente código: Option Compare Database Option Explicit Sub RefreshAllLinks(szNewPath RefreshAllLinks(szNewPath As String) On Error Resume Next Dim db As Database, iCount As Integer Dim tblDef As TableDef Set db = CurrentDb() For iCount = 0 To db.TableDef db.TableDefs.Count s.Count - 1 Set tblDef = db.TableDefs(iCount) If tblDef.Connect <> "" Then tblDef.Connect tblDef.Conn ect = ";DATABASE=" & szNewPath Err = 0 tblDef.RefreshLink If Err <> 0 Then Call RelinkTables If Err = 3011 Then ' si no existe tabla MsgBox "El archivo no contiene la tabla requerida '" & tblDef.SourceTableName & "'", 16, "Refresh Error" ElseIf Err = 3024 Then ' no se encuentra MISDATOS.MDB MsgBox "No se ha encontrado la Base de datos!", 16, "Refresh Error" ElseIf Err = 3051 Then ' Acceso denegado MsgBox "El archivo no se puede abrir (debe ser readonly).", 16, "Refresh Error" ElseIf Err = 3027 Then ' MISDATOS.MDB es read-only MsgBox "Nos se pueden actualizar vinculos. El origin es read-only.", 16, "Refresh Error" End If Exit Sub End If End If Next iCount MsgBox "Todos los vinculos se han refrescado!", 64, "Refresco conseguido" Exit Sub End Sub
Function RefreshTableLink(szTableName As String, szNewPath As String) As Boolean
On Error GoTo RefreshTableLinkErr Dim db As Database Set db = CurrentDb() db.TableDefs(szTableName).Connect = ";DATABASE=" & szNewPath & "" db.TableDefs(szTableNam db.TableDefs (szTableName).RefreshLi e).RefreshLink nk RefreshTableLink = True RefreshTableLink Exit Function
' El refresco se ha realizado, devuelve True
RefreshTableLinkErr: RefreshTableLink RefreshTabl eLink = False ' Se encuentra un error, devueve False Exit Function End Function
Function TestLink(szTableName As String) As Boolean On Error Resume Next Dim db As Database Dim rs As Recordset Set db = CurrentDb() Set rs = db.OpenRecordset(szTableName) If Err = 3024 Then ' No existe el vinculo, devuelve False TestLink = False ElseIf Err = 0 Then ' Existe el vinculo, devuelve True TestLink = True End If End Function
Creación de Aplicaciones multiusuario – 3 Un ejemplo práctico completo - 2 Ahora crearemos el modulo mdDialogoAbrir, de utilidad interna. Copiar y pegar el siguiente código en éste módulo creado: Option Compare Database Option Explicit
' Declaraciones para los procedimient procedimientos os Windows Common Dialogs Private Type CLTAPI_OPENFILE strFilter As String intFilterIndex As Long strInitialDir strInitialDi r As String strInitialFile As String strDialogTitle As String
' ' ' ' '
Cadena de filtro Filtro inicial a mostrar. Directorio inicial al abrir Archivo inicial al abrir. Titulo del cuadro de dialogo
strDefaultExtension strDefaultEx tension As String
' Extensión por defecto, si no se ' especifica una. lngFlags As Long ' Flags (ver lista de constantes). strFullPathReturned strFullPathR eturned As String ' Path complete del archive elegido. strFileNameReturned strFileNameR eturned As String ' Nombre del archive elegido. intFileOffset As Integer ' Offset del path completo '(strFullPathReturned) cuando elnombre del archivo '(strFileNameReturned) '(strFileNam eReturned) empieza. intFileExtension intFileExten sion As Integer ' Offset del path complete '(strFullPathReturned) '(strFullPat hReturned) cuando empieza 'la extension del archivo. End Type Const ALLFILES = "Todos los Archivos" Private Type CLTAPI_WIN CLTAPI_WINOPENFILENAME OPENFILENAME lStructSize As Long hWndOwner As Long hInstance As Long lpstrFilter As String lpstrCustomFilter lpstrCustom Filter As String nMaxCustrFilter nMaxCustrFi lter As Long nFilterIndex As Long lpstrFile As String nMaxFile As Long lpstrFileTitle As String nMaxFileTitle nMaxFileTit le As Long lpstrInitialDir lpstrInitia lDir As String lpstrTitle As String Flags As Long nFileOffset As Integer nFileExtension nFileExtens ion As Integer lpstrDefExt As String lCustrData As Long lpfnHook As Long lpTemplateName As String End Type Const Const Const Const Const Const Const Const Const Const Const Const Const Const
OFN_ALLOWMULTISELECT OFN_ALLOWMULTISEL ECT = &H200 OFN_CREATEPROMPT = &H2000 OFN_CREATEPROMPT OFN_EXPLORER = &H80000 OFN_FILEMUSTEXIST = &H1000 OFN_HIDEREADONLY = &H4 OFN_HIDEREADONLY OFN_NOCHANGEDIR = &H8 OFN_NODEREFERENCELINKS = &H100000 OFN_NODEREFERENCELINKS OFN_NONETWORKBUTTON = &H20000 OFN_NOREADONLYRETURN = &H8000 OFN_NOREADONLYRETURN OFN_NOVALIDATE = &H100 OFN_OVERWRITEPROMPT = &H2 OFN_PATHMUSTEXIST = &H800 OFN_READONLY = &H1 OFN_SHOWHELP = &H10
Declare Function CLTAPI_GetOpenFileName Lib "comdlg32.dll" Alias "GetOpenFileNameA" "GetOpenFile NameA" _ (pOpenfilename As CLTAPI_WINOPENFILENAME) _ As Boolean Declare Function CLTAPI_GetSaveFileName Lib "comdlg32.dll" Alias "GetSaveFileNameA" "GetSaveFile NameA" _ (pOpenfilename As CLTAPI_WINOPENFILENAME) _
As Boolean Declare Sub CLTAPI_ChooseColor Lib "msaccess.exe" Alias "#53" _ (ByVal hwnd As Long, rgb As Long)
Function GetOpenFile_CLT(strInitial GetOpenFile_CLT(strInitialDir Dir As String, strTitle As String) As String ' Commentarios : Simple rutina Archivo Abrir. Para opciones adicionales, usar GetFileOpenEX_CLT() ' Parametros: strInitialDir - path para el dierctorio inicial, o en blanco para el directorio actual ' strTitle – Titulo del cuadro de dialogo ' Devuelve : una cadena del path, nombre y extension del archivo seleccionado ' Dim fOK As Boolean Dim typWinOpen As CLTAPI_WINO CLTAPI_WINOPENFILENAME PENFILENAME Dim typOpenFile As CLTAPI_OPENF CLTAPI_OPENFILE ILE Dim strFilter As String Dim quebusca On Error GoTo PROC_ERR quebusca = "Todos los archivos (*.*)" & "" If strInitialDir <> "" Then typOpenFile.strInitialDir = strInitialDir Else typOpenFile.strInitialDir = CurDir() End If If strTitle <> "" Then typOpenFile.strDialogTi typOpenFile .strDialogTitle tle = strTitle End If typOpenFile.strFilter = strFilter typOpenFile.lngFlags typOpenFile. lngFlags = OFN_HIDEREAD OFN_HIDEREADONLY ONLY Or OFN_SHOWHEL OFN_SHOWHELP P GetOpenFile_CLT = typOpenFile.strFullPathReturned PROC_EXIT: Exit Function PROC_ERR: GetOpenFile_CLT = "" Resume PROC_EXIT End Function
Sub ConvertCLT2Win(CLT_Struct As CLTAPI_OPENFILE, Win_Struct As CLTAPI_WINOPENFILENAME) ' Commentarios : Convierte la estructura CLTAPI pasada a estructura Windows Dim strFile As String * 512 On Error GoTo PROC_ERR Win_Struct.hWndOwner = Application. Win_Struct.hWndOwner Application.hWndAccessA hWndAccessApp pp Win_Struct.hInstance Win_Struct.h Instance = 0
If CLT_Struct.strFilter = "" Then Win_Struct.lpstrFilter Win_Struct. lpstrFilter = ALLFILES & Chr$(0) & "*.*" & Chr$(0) Else Win_Struct.lpstrFilter Win_Struct. lpstrFilter = CLT_Struct. CLT_Struct.strFilter strFilter End If Win_Struct.nFilterIndex = CLT_Struct.intFilterIndex Win_Struct.lpstrFile = String(512, 0) Win_Struct.lpstrFile Win_Struct.nMaxFile = 511 Win_Struct.lpstrFileTitle = String$(512, 0) Win_Struct.nMaxFileTitl Win_Struct.n MaxFileTitle e = 511 Win_Struct.lpstrTitle = CLT_Struct.strDialogTitle Win_Struct.lpstrInitial Win_Struct.l pstrInitialDir Dir = CLT_Struct. CLT_Struct.strInitialDi strInitialDir r Win_Struct.lpstrDefExt Win_Struct.l pstrDefExt = CLT_Struct.s CLT_Struct.strDefaultEx trDefaultExtension tension Win_Struct.Flags Win_Struct.F lags = CLT_Struct.l CLT_Struct.lngFlags ngFlags Win_Struct.lStructSize Win_Struct.l StructSize = Len(Win_Stru Len(Win_Struct) ct) PROC_EXIT: Exit Sub PROC_ERR: Resume PROC_EXIT End Sub
Sub ConvertWin2CLT(Win_Struct As CLTAPI_WINOPENFILENAME, CLT_Struct As CLTAPI_OPENFILE) ' Commentarios : Convierte la estructura CLTAPI pasada a estructura Windows On Error GoTo PROC_ERR CLT_Struct.strFullPathReturned CLT_Struct.strFullPathR eturned = Left(Win_St Left(Win_Struct.lpstrFi ruct.lpstrFile, le, InStr(Win_Struct.lpstrF InStr(Win_St ruct.lpstrFile, ile, vbNullChar) - 1) CLT_Struct.strFileNameR CLT_Struct.s trFileNameReturned eturned = RemoveNulls_CLT(Win_Struct.lpstrFileTitle) CLT_Struct.intFileOffse CLT_Struct.i ntFileOffset t = Win_Struct. Win_Struct.nFileOffset nFileOffset CLT_Struct.intFileExtension = Win_Struct.nFileExtension PROC_EXIT: Exit Sub PROC_ERR: Resume PROC_EXIT End Sub
Function CreateFilterString_CLT(ParamArray varFilt() As Variant) As String ' Commentarios : Construye una cadena en formato Windows para "tipo de archivo" ' Parametros: varFilter – parametros en formato: ' Text, Filter, Text, Filter ...
' Como: ' "Todos los archivos (*.*)", "*.*", "Archivos de texto (*.TXT)", "*.TXT" ' "Bases de datos (*.MDB)", "*.MDB" ' "Excel (*.xls)", "*.xls" Dim strFilter As String Dim intCounter As Integer Dim intParamCount As Integer On Error GoTo PROC_ERR intParamCount = UBound(varFilt) If (intParamCount <> -1) Then ' Hace un bucle para cada parametro For intCounter = 0 To intParamCount strFilter = strFilter & varFilt(intCounter) & Chr$(0) Next ' Comprueba que sea un numero par de parámetros If (intParamCount Mod 2) = 0 Then strFilter = strFilter & "*.*" & Chr$(0) End If End If CreateFilterString_CLT CreateFilter String_CLT = strFilter PROC_EXIT: Exit Function PROC_ERR: CreateFilterString_CLT CreateFilter String_CLT = "" Resume PROC_EXIT End Function
Function RemoveNulls_CLT(strIn As String) As String ' Commentarios : Remueve terminadores de una cadena ' Parametros: strIn – cadena a modificar ' Devuelve : cadena modificada Dim intChr As Integer intChr = InStr(strIn, Chr$(0)) If intChr > 0 Then RemoveNulls_CLT RemoveNulls _CLT = Left$(strIn Left$(strIn, , intChr - 1) Else RemoveNulls_CLT = strIn End If End Function
Bien, con esto ya tenemos las funciones que necesitamos para poner en marcha el sistema. Una vez que tenemos todas las funciones de los módulos en la aplicación, tenemos que activar el código del formulario para que q ue todo esto se ponga en marcha. Lo primero que haremos es abrir el formulario en vista diseño y crear un evento en el botón que comprueba los vínculos.
Abrimos la ventana de depuración y pegamos el siguiente código: Private Sub cmdTestLink_Click() On Error Resume Next If TestLink("AquiNombredeTabla") Then MsgBox "El vinculo es correcto.", 64 Else MsgBox "El vinculo está roto y necesita repararse.” , 64 End If End Sub
A continuación creamos un procedimiento de evento en el botón de comando Archivo Abrir, en éste caso llamado Comando5, que nos permitirá buscar la Base de datos. Para ello, copiar y pegar el siguiente código en el evento del botón Al hacer click: Private Sub Comando5_Click() Me.NewPath = GetOpenFile_CLT("C:\", "Seleccionar el archivo") End Sub
Finalmente hacemos la misma operación para el boton de commando Revincular todas las tablas, que en éste caso lo hemos llamado cmdRefreshAll. Copiar y pegar en el evento Al hacer clic el siguiente código: Private Sub cmdRefreshAll_Click() If IsNull(NewPath) Then MsgBox "Hay que indicar el parh complete y el nombre de la Base de datos donde residen las tables vinculadas.", 64 Exit Sub End If If Dir$(NewPath) = "" Then MsgBox "El path\nombre de archive suministrado no existe.", 64 Exit Sub End If Call RefreshAllLinks(Ne RefreshAllLinks(NewPath) wPath) End Sub
Esto es to Esto todo do lo ne nece cesa sari rio o pa para ra co comp mpro robar bar y ac actu tual aliz izar ar lo loss ví vínc ncul ulos os.. Co Con n és ésta ta herramienta, el usuario usuario de la Base de datos no tendrá más que decir dónde dónde está la base de datos con las tablas, y la aplicación hará el resto. Este sistema puede automatizarse aun más, si en lugar de presentar un formulario, ponemos el test de vínculos en un formulario de inicio, poniendo el código para testear en el procedimiento Al abrir del formulario de inicio. A partir de aquí, si el resultado es que los vínculos están rotos, podemos mostrar un mensaje al usuario, indicándole que busque la ruta de la base de datos de las tablas en el cuadro de diálogo que le vamos a presentar. En cualquiera de las dos maneras, el asunto que evitar que el usuario tenga que actuarr manualmente actua manualmente en una cuestión cuestión que supone debe hacerlo hacerlo el progr programa. ama. El hecho de presentarle un cuadro de diálogo para localizar la base de datos de las tablas le va a resultar en cierto modo agradable, ya que supone una interacción entre la aplicación y él.
Creación de Aplicaciones multiusuario – 4 Control del bloqueo de registros
Puesto que en una Base de Datos multiusuarios se va a originar que varios usuarios puedan acceder simultáneamente a la base de datos y posiblemente en algunos momentos varios usuarios traten de actualizar un registro en el mismo momento, Access deberá saber qué cambio debe aceptar. Para ello Access emplea todo un sistema de control del bloqueo de registros. El blo bloque queo o por página página que utiliza utiliza Ac Acces cesss cr crea ea un bloque bloque de 2048 byt bytes es (2k (2k)) de longitud. En este bloque almacena los datos de uno o varios registros, según su tamaño. Las páginas pueden contener varios registros o un solo registro puede ocupar varias páginas. Cuando se activa el bloqueo de registros por página se bloquean todos los registros contenidos en ella. Si la base de datos contiene cierto número de pequeños registros es posible que un
usuario que edite un registro, puede impedir (bloquear) que otros usuarios editen otros muchos registros. El cuadro de diálogo Opciones permite establecer las opciones multiusuario, así como otras opciones.
Bloqueo predeterminado de registros
Las opciones de la sección bloqueo predeterminado de registros establecen el modo que por defecto Access realizará el bloqueo de registros. Las opciones son: Sin bloquear (predeterminado), Todos los registros y Registro modificado −
−
−
Modo de bloqueo Sin bloquear. Este modo se denomina modo de bloqueo optimista porque el bloqueo solo se lleva a cabo en el momento en que se realiza la actualización de un registro, y tan solo causará error si el mismo registro es modificado por dos personas distintas al mismo tiempo. Modo de bloqueo Todos los registros. Al utilizar este méto método do de bloque bloqueo, o, en esencia se esta estarán rán bloqueando bloqueando todos los registros de un recordset. Esto significa que otros usuarios que intenten acceder a esos mismos registros únicamente podrán leerlos pero no podrán actualizarlos. Al elegir ésta opción además, impide que otros usuarios puedan añadir o borrar registros. Modo de bloqueo Registro modificado. Este modo se denomina bloqueo pesimista. Bloquea la página en cuanto se empiece a editar un registro. Uno de los puntos a favor que tiene este modo de bloqueo es que garantiza que solo un usuario estará modificando el registro en un momento dado. En cuanto presione una tecla para modificar el registro, la página de registros donde éste se halla será bloqueada. La parte negativa es que como Access utiliza el bloqueo por página, es posible que otr otros os reg regist istros ros que qui quier eran an mod modifi ificar car otr otros os usu usuari arios os los enc encuen uentre tren n bloqueados, aun cuando nadie esté en realidad modificándolos.
Utilizar el modo de bloqueo optimista, modo de bloque Sin bloquear, es el mejor desde el punto de vista del rendimiento ya que un desconcertante conflicto de escritura solo le aparecerá al usuario cuando dos usuarios editen el mismo registro e intenten actualizarlo al mismo tiempo. Aunque elegir una de éstas opciones para toda la aplicación puede ser suficiente, un buen desarrollador debe tener en cuenta cada momento, cada circunstancia que puedan provocar los usuarios y utilizar el bloqueo a nivel de los formularios independientes. Para ello, tendremos que disponer de formularios sin origen del registro. Cuando el usuario rellena los campos, no está actualizando nada, ya que el formulario no depende de ninguna tabla. Una vez que haya actualizado todos los campos, tendremos un botón Guardar, que mediante código va pasando los valores y finalmente se agrega un registro a la tabla. Este sis Este sistem tema, a, sin duda es rel relati ativam vament ente e cos costos toso o a la hor hora a de pro progra gramar mar,, per pero o absolutamente efectivo en cuanto a rendimiento de la base de datos. Con todo, las funciones que se generan al hacer el primer formulario sirven de plantilla para otros formularios, por lo que la tarea no va a resultar tan complicada. En el cuadro de Opciones tenemos dos valores que podemos manejar: Intervalo de actualización Numero de intentos de actualización a ctualización − −
Si un usu usuari ario o int intent enta a act actual ualiza izarr un reg regist istro ro blo bloque queado ado,, acc access ess esp espera era el tie tiempo mpo especificado y trata de actualizarlo el número de veces indicado. Si la aplicación va a tener ediciones rápidas de registros se pueden manejar éstos valores para mejorar el rendimiento del bloqueo de registros. Si utilizamos el método de bloqueo Sin bloquear es posible que el intervalo y numeros de actualización sean insuficientes. Podemos reducir el intervalo y aumentar el número de intentos. El intervalo de actualizaciones es el tiempo que Access espera antes de buscar un conjunto de registros de un formulario o tabla abiertos y luego actualizar y mostrar los datos modificados. Por ejemplo, cuando dos usuarios abren un formulario en el mismo registro, si uno aplica y guarda los cambios en el registro, la pantalla del otro usuario se actualiza en el intervalo especificado para reflejar los cambios. En cua cualqu lquier ier cas caso, o, dad dado o que cad cada a apli aplicac cación ión dif difier iere e de otr otra, a, es con conven venien iente te ir probando éstos valores hasta conseguir los más óptimos para cada aplicación.