El búho este, en un dia de otoño, lloviendo en su Valladolid Natal, escribió
en el foro de Microsoft Access:
--------------------------------
Cuando hablamos de 'abrir' una base de datos para hacer 'algo' sobre esa
base de datos, hay que diferenciar bien lo que deseamos decir por 'ABRIR'
No es lo mismo
(A) 'abrir' la propia MDB para recuperar una serie de registros de una tabla
(B) 'abrir' otra MDB diferente a la que ejecuta el codigo para recuperar
unos registros
(C)'abrir' la propia MDB para borrar una serie de objetos
(D)'abrir' otra MDB para borrar una serie de objetos
(E)'abrir' otra MDB para copiar objetos pertenecientes a la MDB que corre el
codigo
(F)'Abrir' otra instancia de Access con otra MDB y cerrar la MDB que corre
el codigo
Joer, parece un galimatías, pero no, no lo es.
Y cuando veas los ejemplos estara mas claro. No pienses que es una clase
magistral de nada, es mas que nada para clarificar esto de ABRIR una base de
datos, que por lo menos a mi, siempre me creo una cierta confusion (Y Juan
M. Afan sabe muy bien de esto, pues al final copio un mensaje antiguo
publicado en este foro hace meses ya)
CASO (A)
Aquí hay dos metodos de hacerlo, uno el nuevo que nos ofrece Access a partir
de las nuevas versiones o el que se venía utilizando anteriormente, que
vista una exposicion que hice ayer, esta desaconsejada para bases de datos
en entorno multiusario
Primer metodo del ejemplo (A), el mas comun y el recomendado
Dim MiMdb As Database
set MiMdb=CurrentDb
de esta forma coloco en codigo una copia de la MDB activa para poder actuar
sobre ella, abriendo Recordset etc sin interferir para nada en otras
acciones multiusario de la propia MDB
Segundo Metodo ejemplo (A), el NO recomendado:
Dim MiMdb as Database
DBEngine.Workspaces(0).Databases(0)
CASO B
Pues tenemos la sencillita, la de siempre:
Dim MiMDB as Database
Set MiMdb = OpenDatabase("C:\RUTA\Datos.Mdb")
o
Dim MiMDB as database
Set wrkJet = CreateWorkspace("", "admin", "", dbUseJet)
' Abre para uso en modo excluxivo
Set MiMdb = wrkJet.OpenDatabase("C:\RUTA\Datos.Mdb", True)
para ver las diferencias, mete OPENDATABASE en la ayuda de Access o de VB
CASO C
Bueno, en realidad no hace falta abrir nada, pues con el objeto DOCMD access
lo pone muy facil.
En el caso que te ocupaba a ti, pues sería:
DoCmd.DeleteObject acQuery, "Hola"
incluso, ojo, para otro caso,que sería copiar un objeto de la actual MDB a
otra MDB, en este caso no hace falta 'abrir' dicha segunda MDB, bastaría:
DoCmd.CopyObject "C:\Ruta\Otra.Mdb", NombreReporte, acReport, NombreReporte
CASO D
Los explicados por Juan y por mi en la exposicion anterior, que a la postre,
con declaraciones un poco diferentes, hacen lo mismo
Si te das cuenta (Explicado en el caso (C)...) cuando desees copiar objetos
de MDB1 a MDB2, estando corriendo el codigo en MDB1, no hace falta 'abrir'
MDB2.
Ja ja, me río,por que ahora se nos podría presentar este otro caso.
Estoy en MDB1 y deseo copiar objetos de MDB2 que esta cerrada a MDB3 que
esta cerrada.
¿Como lo hago?
Function CopiaTabla_desdeDB1_DeDB2_aDB3()
On Error GoTo errRollback
Dim dbs As New Access.Application
dbs.OpenCurrentDatabase "C:\Ruta\Dsystem.Mdb", False
dbs.DoCmd.CopyObject "C:\Ruta\Datos.Mdb", , acTable, "Clientes"
dbs.CloseCurrentDatabase
Set dbs = Nothing
Exit Function
errRollback:
MsgBox Err.Number & " " & Err.Description
End Function
No ha sido rizar el rizo, pero estando en una MDB cualquiera, hemos copiado
una tabla de Dystem.Mdb a Datos.Mdb
Y para finalizar, si queremos abrir otra instancia de Access, fisicamente,
con ottra MDB, es decir, tener 'dos Access' abiertos simultaneamente, pues
es facil,
Estando en la primera MDB, creamos por ejemplo un boton de comando, donde en
la propiedad 'Direccion de Hipervinculo' ponemos por ejemplo
c:\twpac\datos.mdb, al picar sobre ese botón de comando, se nos abrira una
segunda instancia de Access, con Datos.Mdb, manteniendo tambien abierta la
instancia de la primera MDB que realizo la llamada.
Y si deseamos hacer lo mismo, pero, que se cierre la primera instancia, no
hay mas que poner en el evento Click del boton mencionado DoCmd.Quit
En este caso, se abre la segunda MDB y se cierra la que esta ejecutando el
codigo.
(En este caso, es decir, cerrar la MDB que corre el codigo y abrir otra
instancia de Access con otra MDB, hay otra forma de hacerlo, pera ya pasa
por una pequeña llamada a la API, tengo un ejemplo en la Web)
Esta era la otra forma:
'Esto ene un modulo
Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
Public Const SW_SHOW = 1
'Esto en cualquier boton de comando de un formulario
Dim FrmVentaActiva As Form
Set FrmVentaActiva = Me
ShellExecute FrmVentaActiva.hwnd, "open", "C:\Ruta\DATOS.MDB", "", "", SW_SHOW
DoCmd.Quit
Un poco rebuscada pero funciona.
Bueno....pues aqui va el 'hilo' mantenido en su dia con Juan. M Afan de
Ribera.
COPIA
======
Hola Juan......sobre aperturas de bases de datos, bla bla bla.....
......................
Dim wrk As Workspace
Dim dbs1 As Database
Set wrk = DBEngine.CreateWorkspace("", "Admin", "")
Set dbs1 = wrk.OpenDatabase("RutaDestinoBase)
Esta es la primera forma. Bien...¿Cuando se emplea?
¿Cuando es conveniente abrirla así?
OTRA
Dim BaseDestino As New Access.Application
Set BaseDestino = New Access.Application
BaseDestino.OpenCurrentDatabase "Destino"
BaseDestino.CloseCurrentDatabase
Set BaseDestino = Nothing
¿Esta forma anterior cuando y por qué?
¿Diferencias y analogías con la anterior?
OTRA
Dim obj As AccessObject, dbs As Object
Set dbs = Application.CurrentProject
'Aplicacion de esta, por ejemplo:
' Busca objetos AccessObject abiertos en la colección AllReports..
For Each obj In dbs.AllReports
msgbox obj.Name
Next obj
Tengo un poco de lío al respecto.
¿Me puedes aclarar un poco el tema?
RESPUESTA DE JUAN
=================
Hola Paco,
Tú dices:
"Me planteo el siguiente caso:
Desde MDB1 deseo comprobar que en MDB2 existe un Reporte XXX
¿Como recorro los nombres de los objeto Reports de dicha MDB2?..."
respuesta:
Function VerReportes(BDatos As String)
Dim objAcc As New Access.Application
Dim rpt As AccessObject
objAcc.OpenCurrentDatabase BDatos
With objAcc
For Each rpt In .CurrentProject.AllReports
Debug.Print rpt.Name
Next
End With
objAcc.CloseCurrentDatabase
Set objAcc = Nothing
End Function
Tú preguntas:
"Dim wrk As Workspace
Dim dbs1 As Database
Set wrk = DBEngine.CreateWorkspace("", "Admin", "")
Set dbs1 = wrk.OpenDatabase("RutaDestinoBase)
Esta es la primera forma. Bien...¿Cuando se emplea?
¿Cuando es conveniente abrirla así?... "
Respuesta:
De esta manera estás abriendo la base de datos a través de la librería DAO y
accederás a toda la jerarquía DAO (empezando con DBEngine, Workspace,
Database, etc.) y todas sus propiedades, métodos y colecciones).
Tú preguntas:
"Dim BaseDestino As New Access.Application
Set BaseDestino = New Access.Application
BaseDestino.OpenCurrentDatabase "Destino"
BaseDestino.CloseCurrentDatabase
Set BaseDestino = Nothing
¿Esta forma anterior cuando y por qué?
¿Diferencias y analogías con la anterior?..."
Respuesta:
De esta otra forma abres una base de datos desde el objeto application, es
decir, desde el mismo programa de Access, es como si tuvieras una ventana
con la base de datos abierta (puedes tenerla o no, según quieras). De esta
manera accederás a todos las colecciones, métodos, propiedades y objetos que
posee el objeto application (que no son los mismos que con DAO). Tú decides
en cada momento, cuál de las dos formas de abrir la base de datos te
proporcionará la funcionalidad que necesitas. En el caso concreto que
preguntabas es méjor acceder a la colección AllForms de CurrentProject del
objeto Application, ya que contiene TODOS los informes (estén abiertos o
no).
Tú preguntas:
"OTRA
Dim obj As AccessObject, dbs As Object
Set dbs = Application.CurrentProject
'Aplicacion de esta, por ejemplo:
' Busca objetos AccessObject abiertos en la colección AllReports..
For Each obj In dbs.AllReports
msgbox obj.Name
Next obj..."
Respuesta:
Aquí lo único que se diferencia de la primera es que no declaras dbs como
AccessObject (que sería lo correcto), y lo declaras como Object (es decir,
cualquier tipo de Objeto).
Aprovechando que tiene que ver con esto último, te comento algo que ya le
comenté a McPegasus el otro día. Es un detalle tonto, pero creo que muy
útil.
Imagínate que quieres hacer una rutina para rellenar un documento de Word o
de Excel, desde Access. Lo normal es que empezaras declarando una variable
tipo Word.Application o Excel.Application. Bien. De esta manera, podrás usar
a través de esta variable la librería de objetos de Word o Excel (previa
señalización en el cuadro referencias, claro). La cosa vendría a ser algo
así:
Dim appWord as New Word.Application
appWord.open Documents = "C:\doc1.doc" (o algo así, que no me acuerdo)
... ...
Pequeño truco:
Para escribir el código, hazlo como indico arriba. Será fácil y documentado
por el examinador de objetos con el operador "." (punto). Una vez probado
que todo funcione correctamente, rehaz la declaración de variables y añade
una nueva línea al código:
Dim appWord as Object
Set appWord = CreateObject("Word.Application")
haciendo esto, puedes quitar la referencia a la librería de objetos de Word,
ahorrando una referencia al programa (se abrirá una referencia implícita
sólo cuando uses esa rutina), y sin embargo todo funcionará correctamente.
Creo que esta es una de las utilidades de usar variables Object (génericas).
En el resto de los casos, lo mejor es declarar las variables con su tipo
correcto. Puede que hayan casos en que de lo mismo, pero es más que nada
como buena costumbre de programación
Saludos desde BCN
happy
               (
geocities.com/es/ensolva/Descargas)                   (
geocities.com/es/ensolva)                   (
geocities.com/es)