Cómo automatizar Microsoft Access mediante Visual C#



Para una versión de Microsoft Visual Basic .NET de este artículo, consulte 317113 .

Resumen

Este artículo demuestra cómo automatizar Microsoft Access mediante Microsoft Visual C# 2005 o Microsoft Visual C#. NET. Los temas y el código de ejemplo muestran cómo hacer lo siguiente:
  • Abrir una base de datos en Access.
  • Imprimir o vista previa de un informe de Access.
  • Mostrar y editar un formulario de Access.
  • Evitar los cuadros de diálogo cuando se abre una base de datos protegida con contraseña o cuando está activada la seguridad a nivel de usuario.
  • Automatizarlos.

Automatización frente a ADO.NET

Un desarrollador puede trabajar con una base de datos de Microsoft Access desde Visual C# 2005 o Visual C# .NET mediante dos tecnologías diferentes: Microsoft ADO.NET y automatización.

ADO.NET es la tecnología recomendada si desea trabajar con objetos de datos, como tablas y consultas en una base de datos de Access. Utilizar la automatización sólo si necesita características específicas de la aplicación de Microsoft Access, como la capacidad para imprimir u obtener una vista previa de un informe de Access, para mostrar un formulario de Access, o llamar a macros.

Este artículo describe cómo automatizar Access. El artículo no describe ADO.NET. Para obtener información acerca de ADO.NET, haga clic en los números de artículo siguientes para verlos en Microsoft Knowledge Base:
306636 cómo conectarse a una base de datos y ejecutar un comando mediante ADO 2005 y Visual C# 2005 o mediante ADO.NET y Visual C#.

314145 cómo llenar un objeto DataSet desde una base de datos mediante Visual C#.

307587 cómo actualizar una base de datos desde un objeto DataSet mediante Visual C# 2005 o Visual .NET C#

La automatización es una tecnología de modelo de objetos componentes (COM). La automatización permite que las aplicaciones escritas en lenguajes como Visual C# .NET controlar otras aplicaciones mediante programación. Cuando se automatiza una aplicación de Microsoft Office, ejecutar realmente una instancia de esa aplicación en la memoria y, a continuación, llamar en el modelo de objetos de la aplicación para realizar diversas tareas en esa aplicación. Con Access y otras aplicaciones de Microsoft Office, prácticamente todas las acciones que puede realizar manualmente mediante la interfaz de usuario pueden también realizarse mediante programación utilizando la automatización.

Access expone esta funcionalidad a través de un modelo de objetos de programación. El modelo de objetos es una colección de clases y métodos que actúan como homólogos de los componentes lógicos de acceso. Para tener acceso al modelo de objetos desde Visual C#., puede establecer una referencia de proyecto a la biblioteca de tipos. Para obtener más información acerca de este proceso, o para obtener más información acerca de la documentación del modelo de objetos de Office, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:
222101 cómo encontrar y usar la documentación del modelo de objetos de Office

Tareas comunes de automatización

Abrir una base de datos en Access

Al automatizar Microsoft Access, debe abrir una base de datos para poder realizar tareas útiles, como la impresión de informes. Para abrir una base de datos en la instancia de Access que esté automatizando, utilice los métodos OpenCurrentDatabase u OpenAccessProject del objeto Application . Puede tener sólo una base de datos abierta en Access a la vez. Para trabajar con una base de datos diferente, puede utilizar el método CloseCurrentDatabase antes de abrirla.

También puede utilizar el método System.Runtime.InteropServices.Marshal.BindToMoniker (< ruta de acceso a la base de datos >) para abrir una base de datos en una instancia de Access. Si la base de datos ya está abierto en una instancia de Access, BindToMoniker devuelve el objeto Application de esa instancia. De lo contrario, BindToMoniker inicia una nueva instancia de Access y abre la base de datos especificada.
OpenCurrentDatabase es el método preferido para abrir una base de datos, ya que permite especificar la instancia de Access que esté automatizando. También puede proporcionar argumentos para controlar cómo se abre la base de datos, por ejemplo:
Access.Application oAccess = null;
// Start a new instance of Access for Automation:
oAccess = new Access.ApplicationClass();

// Open a database in exclusive mode:
oAccess.OpenCurrentDatabase(
"c:\\mydb.mdb", //filepath
true //Exclusive
);

Imprimir o vista previa de un informe de Access

Para obtener una vista previa o imprimir un informe de Access, llame el método OpenReport del objeto DoCmd . Al llamar a OpenReport, uno de los argumentos que se pasan determina si el informe de vista previa en la pantalla o si ha de enviarse a la impresora:
// Preview a report named Sales:oAccess.DoCmd.OpenReport(
"Sales", //ReportName
Access.AcView.acViewPreview, //View
System.Reflection.Missing.Value, //FilterName
System.Reflection.Missing.Value //WhereCondition
);

// Print a report named Sales:
oAccess.DoCmd.OpenReport(
"Sales", //ReportName
Access.AcView.acViewNormal, //View
System.Reflection.Missing.Value, //FilterName
System.Reflection.Missing.Value //WhereCondition
);

Observe que el argumento vista determina si se muestra el informe en Access, o si ha de enviarse a la impresora. El argumento WhereCondition puede limitar el conjunto de registros del informe, si utiliza una cláusula WHERE de SQL válida (sin la palabra donde.) Observe que puede utilizar System.Reflection.Missing.Value para omitir cualquier parámetro de objeto que es opcional.

Si en la vista preliminar de un informe, asegúrese de establecer la propiedad Visible del objeto Application para que Access esté visible en la pantalla. De esta forma, el usuario puede ver el informe en la ventana de Access.

Hay otra forma de imprimir un informe u otros objetos de la base de datos. Utilice el método PrintOut del objeto DoCmd . En este ejemplo, se selecciona el informe Employees en la ventana Base de datos y, a continuación, se llama a PrintOut para imprimir el objeto seleccionado. El método PrintOut permite proporcionar los argumentos correspondientes al cuadro de diálogo Imprimir de la caja en Access:
// Select the Employees report in the database window:oAccess.DoCmd.SelectObject(
Access.AcObjectType.acReport, //ObjectType
"Employees", //ObjectName
true //InDatabaseWindow
);

// Print 2 copies of the selected object:
oAccess.DoCmd.PrintOut(
Access.AcPrintRange.acPrintAll, //PrintRange
System.Reflection.Missing.Value, //PageFrom
System.Reflection.Missing.Value, //PageTo
Access.AcPrintQuality.acHigh, //PrintQuality
2, //Copies
false //CollateCopies
);

O bien, en algunos casos, es aconsejable utilizar el OpenReport y los métodos de impresión para imprimir un informe. Suponga que desea imprimir varias copias del informe Employees, pero sólo para un empleado específico. En este ejemplo primero se utiliza OpenReport para abrir el informe en modo de vista previa, con el argumento WhereCondition para limitar los registros para un empleado específico. A continuación, se utiliza PrintOut para imprimir varias copias del objeto activo:
// Open the report in preview mode using a WhereCondition:oAccess.DoCmd.OpenReport(
"Employees", //ReportName
Access.AcView.acViewPreview, //View
System.Reflection.Missing.Value, //FilterName
"[EmployeeID]=1" //WhereCondition
);

// Print 2 copies of the active object:
oAccess.DoCmd.PrintOut(
Access.AcPrintRange.acPrintAll, //PrintRange
System.Reflection.Missing.Value, //PageFrom
System.Reflection.Missing.Value, //PageTo
Access.AcPrintQuality.acHigh, //PrintQuality
2, //Copies
false //CollateCopies
);

// Close the report preview window:
oAccess.DoCmd.Close(
Access.AcObjectType.acReport, //ObjectType
"Employees", //ObjectName
Access.AcCloseSave.acSaveNo //Save
);

Access 2002 introdujo el objeto Printer . Puede utilizar este objeto para personalizar la configuración de impresora de acceso más fácilmente que en versiones anteriores de Access. Para obtener un ejemplo de uso del objeto Printer de Access para imprimir un informe, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:
284286 cómo restablecer los cambios al objeto Application.Printer

Mostrar y editar un formulario de Access

Visual C# .NET tiene funciones muy potentes para formularios. Sin embargo, puede haber ocasiones cuando desea que el usuario para ver formularios desarrollados en Access. O bien, puede tener un formulario en la base de datos de Access que proporciona criterios para una consulta o un informe y debe abrir dicho formulario antes de que se puede obtener una vista previa o imprimir el informe. Para abrir y mostrar un formulario de Access, llame al método OpenForm del objeto DoCmd :
// Show a form named Employees:oAccess.DoCmd.OpenForm(
"Employees", //FormName
Access.AcFormView.acNormal, //View
System.Reflection.Missing.Value, //FilterName
System.Reflection.Missing.Value, //WhereCondition
Access.AcFormOpenDataMode.acFormPropertySettings, //DataMode
Access.AcWindowMode.acWindowNormal, //WindowMode
System.Reflection.Missing.Value //OpenArgs
);

Ahora puede editar los controles en el formulario.

Cuadros de diálogo de seguridad de acceso

Al automatizar Access, es posible que se deba introducir un nombre de usuario o una contraseña o ambos, cuando intenta abrir una base de datos. Si el usuario introdujera algún valor equivocado, se producirá un error en el código. Puede haber ocasiones cuando desea evitar estos cuadros de diálogo y en su lugar para proporcionar mediante programación el nombre de usuario y la contraseña para que el código de automatización se ejecute sin interrupciones.

Hay dos tipos de seguridad en Microsoft Access: bases de datos protegidas con contraseña y seguridad de nivel de usuario a través de un archivo de grupo de trabajo (System.mdw). Si intenta abrir una base de datos está protegida con contraseña, recibirá un cuadro de diálogo le pide la contraseña de la base de datos. Seguridad de nivel de usuario es diferente de una base de datos protegida con contraseña. Cuando está activada la seguridad de nivel de usuario, Access muestra un cuadro de diálogo de inicio de sesión que le pide un nombre de usuario y la contraseña antes de que el usuario puede abrir cualquier base de datos en Access. Para obtener más información acerca de la seguridad de acceso y el archivo de información de grupo de trabajo, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:

305542 descripción de la función de archivos de información de grupo de trabajo en la seguridad de acceso

Evitar los cuadros de diálogo de contraseña de base de datos

Si está abriendo una base de datos que se ha protegido con una contraseña, podrá evitar el cuadro de diálogo proporcionando la contraseña al método OpenCurrentDatabase :
// Open a password-protected database in shared mode:// Note: The bstrPassword argument is case-sensitive
oAccess.OpenCurrentDatabase(
"c:\\mydb.mdb", //filepath
false, //Exclusive
"MyPassword" //bstrPassword
);


Éste es un ejemplo, donde oAccess se ha establecido previamente en una instancia de Access que no tiene una base de datos abiertos. Este código proporciona la contraseña para la base de datos para evitar un cuadro de diálogo:
string sDBPassword = "MyPassword"; //database passwordDAO._DBEngine oDBEngine = oAccess.DBEngine;
DAO.Database oDB = oDBEngine.OpenDatabase("c:\\mydb.mdb",
false, false, ";PWD=" + sDBPassword);
oAccess.OpenCurrentDatabase("c:\\mydb.mdb", false);
oDB.Close();
System.Runtime.InteropServices.Marshal.ReleaseComObject(oDB);
oDB = null;
System.Runtime.InteropServices.Marshal.ReleaseComObject(oDBEngine);
oDBEngine = null;

El oDB.Close no cierra realmente la base de datos en Access. Sólo cierra la conexión DAO a la base de datos se realizó a través del objeto DBEngine . Esta conexión ya no es necesaria cuando se utiliza el método OpenCurrentDatabase . Observe el código que libera los objetos oDB y oDBEngine. Debe utilizar estos objetos para que Access pueda cerrarse correctamente una vez completado el código.

Para obtener más información, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:
235422 cómo abrir una base de datos protegida con contraseña mediante automatización en Access 2000

Evitar los cuadros de diálogo de inicio de sesión de seguridad de acceso

Si está activada la seguridad de nivel de usuario en Access, se solicita el usuario con un cuadro de diálogo de inicio de sesión, pide un nombre de usuario y una contraseña. Un nombre de usuario y una contraseña no pueden especificarse mediante el modelo de objetos de Access. Por lo tanto, si desea evitar el cuadro de diálogo de inicio de sesión al automatizar Access, primero debe iniciar el archivo Msaccess.exe y proporcionar la /user y /pwd modificadores para especificar el nombre de usuario y la contraseña. Después, puede utilizar GetActiveObject o BindToMoniker para recuperar el objeto Application de la instancia en ejecución de Access, por lo que se puede proceder con la automatización. Para obtener un ejemplo de cómo hacerlo, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:
192919 cómo automatizar una base de datos protegida de access utilizando Visual Basic

Para obtener más información acerca de cómo iniciar Access con modificadores de línea de comandos, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:
209207 cómo utilizar modificadores de línea de comandos en Microsoft Access

Automatizar Access Runtime

El Microsoft Office Developer Edition incluye Microsoft Office Developer Tools (MOD). Con MOD, los programadores de Access pueden crear y distribuir aplicaciones de acceso a los usuarios que no tengan la versión comercial de Access. Cuando el usuario instala la aplicación de Access en un equipo que no tiene la versión comercial de Access, se instala una versión en tiempo de ejecución de Access. El tiempo de ejecución de Access se instala y se registra como la versión comercial. El ejecutable también se denominará Msaccess.exe. El tiempo de ejecución de Access permite que una aplicación de Access ejecutar en un equipo cliente, pero el tiempo de ejecución de Access no permite un usuario para desarrollar nuevas aplicaciones o modificar el diseño de las aplicaciones existentes.

El tiempo de ejecución de Access debe iniciarse con una base de datos. Debido a este requisito, si desea automatizarlos, deberá iniciar Msaccess.exe y especificar una base de datos para abrir. Después de utilizar GetActiveObject o BindToMoniker para recuperar el objeto Application , a continuación, puede automatizar el tiempo de ejecución de Access. Si no utiliza este enfoque al intentar automatizar Access Runtime, recibirá un mensaje de error como el siguiente cuando intenta crear una instancia de la instancia:
System.Runtime.InteropServices.COMException (0x80080005)
Error de ejecución del servidor.
Para obtener más información, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:
295179 mediante automatización provoca un Error de tiempo de ejecución cuando sólo Microsoft Access Runtime está instalado en un equipo

Crear el ejemplo Visual C# 2005 o proyecto .NET de Visual C#

Para utilizar el siguiente ejemplo paso a paso, asegúrese de que está instalada la base de datos de ejemplo Northwind. De forma predeterminada, Microsoft Access 2000 instala las bases de datos de ejemplo en la siguiente ruta:
C:\Program Files\Microsoft Office\Office\Samples
Microsoft Access 2002 utiliza la ruta de acceso siguiente:
C:\Program Files\Microsoft Office\Office10\Samples
Microsoft Office Access 2003 utiliza la ruta de acceso siguiente:
C:\Program Files\Microsoft Office\Office11\Samples
Para asegurarse de que está instalado la base de datos de ejemplo Neptuno en Access 2002 o en Access 2003, haga clic en Bases de datos de ejemplo en el menú Ayuda y, a continuación, haga clic en Base de datos de ejemplo Northwind.
  1. Cierre todas las instancias de Access que se están ejecutando.
  2. Inicie Microsoft Visual Studio. NET.
  3. En el menú archivo , haga clic en nuevo y, a continuación, haga clic en proyecto. Seleccione Aplicación para Windows en los tipos de proyecto de Visual C#. De forma predeterminada, se crea Form1.

    Nota: Debe cambiar el código en Visual Studio 2005. De forma predeterminada, Visual C# agrega un formulario al proyecto cuando se crea un proyecto de formularios Windows Forms. El formulario se denomina Form1. Los dos archivos que lo representan se denominan Form1.cs y Form1.designer.cs. Escriba el código en Form1.cs. El archivo Form1.designer.cs es donde el Diseñador de Windows Forms escribe el código que implementa todas las acciones que realizó arrastrando y colocando controles desde el cuadro de herramientas.

    Para obtener más información acerca de cómo el Diseñador de Windows Forms en Visual C# 2005, visite el siguiente sitio Web de Microsoft Developer Network (MSDN):
  4. Agregue una referencia a la Biblioteca de objetos de Microsoft Access. Para ello, siga estos pasos:
    1. En el menú proyecto , haga clic en Agregar referencia.
    2. En la ficha COM , busque Biblioteca de objetos de Microsoft Accessy, a continuación, haga clic en Seleccionar.

      Nota: En Visual Studio 2005. no tiene que hacer clic en
      Seleccione.

      Nota: Microsoft Office 2003 incluye a ensamblados de interoperabilidad primarios (PIA). Microsoft Office XP no incluye PIA, pero se pueden descargar.
      Para obtener más información acerca de los PIA de Office XP, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:

      328912 ensamblados de interoperabilidad primarios (PIA) de Microsoft Office XP están disponibles para descarga

    3. En el cuadro de diálogo Agregar referencias , haga clic en Aceptar para aceptar sus selecciones.

      Nota: Si hace referencia a la biblioteca de objetos de Access 10.0 y recibe errores al intentar agregar la referencia, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base::
      317157 PRB: errores al hacer referencia a la biblioteca de tipos de Access 10.0 con Visual Studio .NET

  5. En el menú Ver , haga clic en cuadro de herramientas para mostrar el cuadro de herramientas.
  6. Agregue cinco controles de botón de radio y control de un botón a Form1.
  7. Seleccione todos los controles de botón de radio y, a continuación, establezca la propiedad Size en 150,24.
  8. Agregar controladores de eventos para el evento Load del formulario y para el evento Click del control Button:
    1. En la vista Diseño de Form1.cs, haga doble clic en Form1.

      El controlador para el evento Load del formulario se crea y aparece en Form1.cs.
    2. En el menú Ver , haga clic en Diseñador para cambiar a la vista Diseño.
    3. Haga doble clic en Button1.

      El controlador para el evento Click del botón se crea y aparece en Form1.cs.
  9. En Form1.cs, reemplace el código siguiente
    private void Form1_Load(object sender, System.EventArgs e){

    }

    private void button1_Click(object sender, System.EventArgs e)
    {

    }

    con:
          private string msAction = null;      // Commonly-used variable for optional arguments:
    private object moMissing = System.Reflection.Missing.Value;

    private void Form1_Load(object sender, System.EventArgs e)
    {
    radioButton1.Text = "Print report";
    radioButton2.Text = "Preview report";
    radioButton3.Text = "Show form";
    radioButton4.Text = "Print report (Security)";
    radioButton5.Text = "Preview report (Runtime)";
    button1.Text = "Go!";
    radioButton1.Click += new EventHandler(RadioButtons_Click);
    radioButton2.Click += new EventHandler(RadioButtons_Click);
    radioButton3.Click += new EventHandler(RadioButtons_Click);
    radioButton4.Click += new EventHandler(RadioButtons_Click);
    radioButton5.Click += new EventHandler(RadioButtons_Click);
    }

    private void RadioButtons_Click(object sender, System.EventArgs e)
    {
    RadioButton radioBtn = (RadioButton) sender;
    msAction = radioBtn.Text;
    }

    private void button1_Click(object sender, System.EventArgs e)
    {
    // Calls the associated procedure to automate Access, based
    // on the selected radio button on the form.
    switch(msAction)
    {
    case "Print report": Print_Report();
    break;
    case "Preview report": Preview_Report();
    break;
    case "Show form": Show_Form();
    break;
    case "Print report (Security)": Print_Report_Security();
    break;
    case "Preview report (Runtime)": Preview_Report_Runtime();
    break;
    }
    }

    private void NAR(object o)
    {
    // Releases the Automation object.
    try // use try..catch in case o is not set
    {
    Marshal.ReleaseComObject(o);
    }
    catch{}
    }

    private Access.Application ShellGetDB(string sDBPath, string sCmdLine,
    ProcessWindowStyle enuWindowStyle, int iSleepTime)
    {
    //Launches a new instance of Access with a database (sDBPath)
    //using System.Diagnostics.Process.Start. Then, returns the
    //Application object via calling: BindToMoniker(sDBPath). Returns
    //the Application object of the new instance of Access, assuming that
    //sDBPath is not already opened in another instance of Access. To
    //ensure the Application object of the new instance is returned, make
    //sure sDBPath is not already opened in another instance of Access
    //before calling this function.
    //
    //Example:
    //Access.Application oAccess = null;
    //oAccess = ShellGetDB("c:\\mydb.mdb", null,
    // ProcessWindowStyle.Minimized, 1000);

    Access.Application oAccess = null;
    string sAccPath = null; //path to msaccess.exe
    Process p = null;


    // Enable exception handler:
    try
    {
    // Obtain the path to msaccess.exe:
    sAccPath = GetOfficeAppPath("Access.Application", "msaccess.exe");
    if (sAccPath == null)

    {
    MessageBox.Show("Can't determine path to msaccess.exe");
    return null;
    }

    // Make sure specified database (sDBPath) exists:
    if(!System.IO.File.Exists(sDBPath))
    {
    MessageBox.Show("Can't find the file '" + sDBPath + "'");
    return null;
    }

    // Start a new instance of Access passing sDBPath and sCmdLine:
    if(sCmdLine == null)
    sCmdLine = @"""" + sDBPath + @"""";
    else
    sCmdLine = @"""" + sDBPath + @"""" + " " + sCmdLine;
    ProcessStartInfo startInfo = new ProcessStartInfo();
    startInfo.FileName = sAccPath;
    startInfo.Arguments = sCmdLine;
    startInfo.WindowStyle = enuWindowStyle;
    p = Process.Start(startInfo);
    p.WaitForInputIdle(60000); //max 1 minute wait for idle input state

    // Move focus back to this form. This ensures that Access
    // registers itself in the ROT:
    this.Activate();

    // Pause before trying to get Application object:
    System.Threading.Thread.Sleep(iSleepTime);

    // Obtain Application object of the instance of Access
    // that has the database open:
    oAccess = (Access.Application) Marshal.BindToMoniker(sDBPath);
    return oAccess;
    }
    catch(Exception e)
    {
    MessageBox.Show(e.Message);
    // Try to quit Access due to an unexpected error:
    try // use try..catch in case oAccess is not set
    {
    oAccess.Quit(Access.AcQuitOption.acQuitSaveNone);
    }
    catch{}
    NAR(oAccess);
    oAccess = null;
    return null;
    }
    }

    private Access.Application ShellGetApp(string sCmdLine,
    ProcessWindowStyle enuWindowStyle)
    {
    //Launches a new instance of Access using System.Diagnostics.
    //Process.Start then returns the Application object via calling:
    //GetActiveObject("Access.Application"). If an instance of
    //Access is already running before calling this function,
    //the function may return the Application object of a
    //previously running instance of Access. If this is not
    //desired, then make sure Access is not running before
    //calling this function, or use the ShellGetDB()
    //function instead. Approach based on Q316125.
    //
    //Examples:
    //Access.Application oAccess = null;
    //oAccess = ShellGetApp("/nostartup",
    // ProcessWindowStyle.Minimized);
    //
    //-or-
    //
    //Access.Application oAccess = null;
    //string sUser = "Admin";
    //string sPwd = "mypassword";
    //oAccess = ShellGetApp("/nostartup /user " + sUser + "/pwd " + sPwd,
    // ProcessWindowStyle.Minimized);

    Access.Application oAccess = null;
    string sAccPath = null; //path to msaccess.exe
    Process p = null;
    int iMaxTries = 20; //max GetActiveObject attempts before failing
    int iTries = 0; //GetActiveObject attempts made

    // Enable exception handler:
    try
    {
    // Obtain the path to msaccess.exe:
    sAccPath = GetOfficeAppPath("Access.Application", "msaccess.exe");
    if(sAccPath == null)
    {
    MessageBox.Show("Can't determine path to msaccess.exe");
    return null;
    }

    // Start a new instance of Access passing sCmdLine:
    ProcessStartInfo startInfo = new ProcessStartInfo();
    startInfo.FileName = sAccPath;
    startInfo.Arguments = sCmdLine;
    startInfo.WindowStyle = enuWindowStyle;
    p = Process.Start(startInfo);
    p.WaitForInputIdle(60000); //max 1 minute wait for idle input state

    // Move focus back to this form. This ensures that Access
    // registers itself in the ROT:
    this.Activate();

    tryGetActiveObject:
    // Enable exception handler:
    try
    {
    // Attempt to use GetActiveObject to reference a running
    // instance of Access:
    oAccess = (Access.Application)
    Marshal.GetActiveObject("Access.Application");
    }
    catch
    {
    //GetActiveObject may have failed because enough time has not
    //elapsed to find the running Office application. Wait 1/2
    //second and retry the GetActiveObject. If you try iMaxTries
    //times and GetActiveObject still fails, assume some other
    //reason for GetActiveObject failing and exit the procedure.
    iTries++;
    if(iTries < iMaxTries)
    {
    System.Threading.Thread.Sleep(500); //wait 1/2 second
    this.Activate();
    goto tryGetActiveObject;
    }
    MessageBox.Show("Unable to GetActiveObject after " +
    iTries + " tries.");
    return null;
    }

    // Return the Access Application object:
    return oAccess;
    }
    catch(Exception e)
    {
    MessageBox.Show(e.Message);
    // Try to quit Access due to an unexpected error:
    try // use try..catch in case oAccess is not set
    {
    oAccess.Quit(Access.AcQuitOption.acQuitSaveNone);
    }
    catch{}
    NAR(oAccess);
    oAccess = null;
    return null;
    }
    }

    private string GetOfficeAppPath(string sProgId, string sEXE)
    {
    //Returns path of the Office application. e.g.
    //GetOfficeAppPath("Access.Application", "msaccess.exe") returns
    //full path to Microsoft Access. Approach based on Q240794.
    //Returns null if path not found in registry.

    // Enable exception handler:
    try
    {
    Microsoft.Win32.RegistryKey oReg =
    Microsoft.Win32.Registry.LocalMachine;
    Microsoft.Win32.RegistryKey oKey = null;
    string sCLSID = null;
    string sPath = null;
    int iPos = 0;

    // First, get the clsid from the progid from the registry key
    // HKEY_LOCAL_MACHINE\Software\Classes\<PROGID>\CLSID:
    oKey = oReg.OpenSubKey(@"Software\Classes\" + sProgId + @"\CLSID");
    sCLSID = oKey.GetValue("").ToString();
    oKey.Close();

    // Now that we have the CLSID, locate the server path at
    // HKEY_LOCAL_MACHINE\Software\Classes\CLSID\
    // {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx}\LocalServer32:
    oKey = oReg.OpenSubKey(@"Software\Classes\CLSID\" + sCLSID +
    @"\LocalServer32");
    sPath = oKey.GetValue("").ToString();
    oKey.Close();

    // Remove any characters beyond the exe name:
    iPos = sPath.ToUpper().IndexOf(sEXE.ToUpper()); // 0-based position
    sPath = sPath.Substring(0, iPos + sEXE.Length);
    return sPath.Trim();
    }
    catch
    {
    return null;
    }
    }

    private void Print_Report()
    {
    // Prints the "Summary of Sales by Year" report in Northwind.mdb.

    Access.Application oAccess = null;
    string sDBPath = null; //path to Northwind.mdb
    string sReport = null; //name of report to print

    // Enable exception handler:
    try
    {
    sReport = "Summary of Sales by Year";

    // Start a new instance of Access for Automation:
    oAccess = new Access.ApplicationClass();

    // Determine the path to Northwind.mdb:
    sDBPath = oAccess.SysCmd(Access.AcSysCmdAction.acSysCmdAccessDir,
    moMissing, moMissing).ToString();
    sDBPath = sDBPath + @"Samples\Northwind.mdb";

    // Open Northwind.mdb in shared mode:
    oAccess.OpenCurrentDatabase(sDBPath, false, "");
    // If using Access 10.0 object library, use this instead:
    //oAccess.OpenCurrentDatabase(sDBPath, false, null);

    // Select the report name in the database window and give focus
    // to the database window:
    oAccess.DoCmd.SelectObject(Access.AcObjectType.acReport, sReport, true);

    // Print the report:
    oAccess.DoCmd.OpenReport(sReport,
    Access.AcView.acViewNormal, moMissing, moMissing,
    Access.AcWindowMode.acWindowNormal, moMissing);
    // If using Access 10.0 object library, use this instead:
    //oAccess.DoCmd.OpenReport(sReport,
    // Access.AcView.acViewNormal, moMissing, moMissing,
    // Access.AcWindowMode.acWindowNormal, moMissing);
    }
    catch(Exception e)
    {
    MessageBox.Show(e.Message);
    }
    finally
    {
    // Release any Access objects and quit Access:
    try // use try..catch in case oAccess is not set
    {
    oAccess.Quit(Access.AcQuitOption.acQuitSaveNone);
    }
    catch{}
    NAR(oAccess);
    oAccess = null;
    }
    }

    private void Preview_Report()
    {
    // Previews the "Summary of Sales by Year" report in Northwind.mdb.

    Access.Application oAccess = null;
    Access.Form oForm = null;
    string sDBPath = null; //path to Northwind.mdb
    string sReport = null; //name of report to preview

    // Enable exception handler:
    try
    {
    sReport = "Summary of Sales by Year";

    // Start a new instance of Access for Automation:
    oAccess = new Access.ApplicationClass();

    // Make sure Access is visible:
    if(!oAccess.Visible) oAccess.Visible = true;

    // Determine the path to Northwind.mdb:
    sDBPath = oAccess.SysCmd(Access.AcSysCmdAction.acSysCmdAccessDir,
    moMissing, moMissing).ToString();
    sDBPath = sDBPath + @"Samples\Northwind.mdb";

    // Open Northwind.mdb in shared mode:
    oAccess.OpenCurrentDatabase(sDBPath, false, "");
    // If using Access 10.0 object library, use this instead:
    //oAccess.OpenCurrentDatabase(sDBPath, false, null);

    // Close any forms that Northwind may have opened:
    while(oAccess.Forms.Count > 0)
    {
    oForm = oAccess.Forms[0];
    oAccess.DoCmd.Close(Access.AcObjectType.acForm,
    oForm.Name, Access.AcCloseSave.acSaveNo);
    NAR(oForm);
    oForm = null;
    }

    // Select the report name in the database window and give focus
    // to the database window:
    oAccess.DoCmd.SelectObject(Access.AcObjectType.acReport, sReport, true);

    // Maximize the Access window:
    oAccess.RunCommand(Access.AcCommand.acCmdAppMaximize);

    // Preview the report:
    oAccess.DoCmd.OpenReport(sReport,
    Access.AcView.acViewPreview, moMissing, moMissing,
    Access.AcWindowMode.acWindowNormal, moMissing);
    // If using Access 10.0 object library, use this instead:
    //oAccess.DoCmd.OpenReport(sReport,
    // Access.AcView.acViewPreview, moMissing, moMissing,
    // Access.AcWindowMode.acWindowNormal, moMissing);

    // Maximize the report window:
    oAccess.DoCmd.Maximize();

    // Hide Access menu bar:
    oAccess.CommandBars["Menu Bar"].Enabled = false;
    // Also hide NorthWindCustomMenuBar if it is available:
    try
    {
    oAccess.CommandBars["NorthwindCustomMenuBar"].Enabled = false;
    }
    catch{}

    // Hide Report's Print Preview menu bar:
    oAccess.CommandBars["Print Preview"].Enabled = false;

    // Hide Report's right-click popup menu:
    oAccess.CommandBars["Print Preview Popup"].Enabled = false;

    // Release Application object and allow Access to be closed by user:
    if(!oAccess.UserControl) oAccess.UserControl = true;
    NAR(oAccess);
    oAccess = null;
    }
    catch(Exception e)
    {
    MessageBox.Show(e.Message);
    // Release any Access objects and quit Access due to error:
    NAR(oForm);
    oForm = null;
    try // use try..catch in case oAccess is not set
    {
    oAccess.Quit(Access.AcQuitOption.acQuitSaveNone);
    }
    catch{}
    NAR(oAccess);
    oAccess = null;
    }
    }

    private void Show_Form()
    {
    // Shows the "Customer Labels Dialog" form in Northwind.mdb
    // and manipulates controls on the form.

    Access.Application oAccess = null;
    Access.Form oForm = null;
    Access.Controls oCtls = null;
    Access.Control oCtl = null;
    string sDBPath = null; //path to Northwind.mdb
    string sForm = null; //name of form to show

    // Enable exception handler:
    try
    {
    sForm = "Customer Labels Dialog";

    // Start a new instance of Access for Automation:
    oAccess = new Access.ApplicationClass();

    // Make sure Access is visible:
    if(!oAccess.Visible) oAccess.Visible = true;

    // Determine the path to Northwind.mdb:
    sDBPath = oAccess.SysCmd(Access.AcSysCmdAction.acSysCmdAccessDir,
    moMissing, moMissing).ToString();
    sDBPath = sDBPath + @"Samples\Northwind.mdb";

    // Open Northwind.mdb in shared mode:
    oAccess.OpenCurrentDatabase(sDBPath, false, "");
    // If using Access 10.0 object library, use this instead:
    //oAccess.OpenCurrentDatabase(sDBPath, false, null);

    // Close any forms that Northwind may have opened:
    while(oAccess.Forms.Count > 0)
    {
    oForm = oAccess.Forms[0];
    oAccess.DoCmd.Close(Access.AcObjectType.acForm,
    oForm.Name, Access.AcCloseSave.acSaveNo);
    NAR(oForm);
    oForm = null;
    }

    // Select the form name in the database window and give focus
    // to the database window:
    oAccess.DoCmd.SelectObject(Access.AcObjectType.acForm, sForm, true);

    // Show the form:
    oAccess.DoCmd.OpenForm(sForm, Access.AcFormView.acNormal, moMissing,
    moMissing, Access.AcFormOpenDataMode.acFormPropertySettings,
    Access.AcWindowMode.acWindowNormal, moMissing);

    // Use Controls collection to edit the form:

    oForm = oAccess.Forms[sForm];
    oCtls = oForm.Controls;

    // Set PrintLabelsFor option group to Specific Country:

    oCtl = (Access.Control)oCtls["PrintLabelsFor"];
    object[] Parameters = new Object[1];
    Parameters[0] = 2; //second option in option group
    oCtl.GetType().InvokeMember("Value", BindingFlags.SetProperty,
    null, oCtl, Parameters);
    NAR(oCtl);
    oCtl = null;

    // Put USA in the SelectCountry combo box:
    oCtl = (Access.Control)oCtls["SelectCountry"];
    Parameters[0] = true;
    oCtl.GetType().InvokeMember("Enabled", BindingFlags.SetProperty,
    null, oCtl, Parameters);
    oCtl.GetType().InvokeMember("SetFocus", BindingFlags.InvokeMethod,
    null, oCtl, null);
    Parameters[0] = "USA";
    oCtl.GetType().InvokeMember("Value", BindingFlags.SetProperty,
    null, oCtl, Parameters);
    NAR(oCtl);
    oCtl = null;

    // Hide the Database Window:
    oAccess.DoCmd.SelectObject(Access.AcObjectType.acForm, sForm, true);
    oAccess.RunCommand(Access.AcCommand.acCmdWindowHide);

    // Set focus back to the form:
    oForm.SetFocus();

    // Release Controls and Form objects:
    NAR(oCtls);
    oCtls = null;
    NAR(oForm);
    oForm = null;

    // Release Application object and allow Access to be closed by user:
    if(!oAccess.UserControl) oAccess.UserControl = true;
    NAR(oAccess);
    oAccess = null;
    }
    catch(Exception e)
    {
    MessageBox.Show(e.Message);
    // Release any Access objects and quit Access due to error:
    NAR(oCtl);
    oCtl = null;
    NAR(oCtls);
    oCtls = null;
    NAR(oForm);
    oForm = null;
    try // use try..catch in case oAccess is not set
    {
    oAccess.Quit(Access.AcQuitOption.acQuitSaveNone);
    }
    catch{}
    NAR(oAccess);
    oAccess = null;
    }
    }

    private void Print_Report_Security()
    {
    //Shows how to automate Access when user-level
    //security is enabled and you wish to avoid the logon
    //dialog asking for user name and password. In this
    //example we're assuming default security so we simply
    //pass the Admin user with a blank password to print the
    //"Summary of Sales by Year" report in Northwind.mdb.

    Access.Application oAccess = null;
    string sDBPath = null; //path to Northwind.mdb
    string sUser = null; //user name for Access security
    string sPwd = null; //user password for Access security
    string sReport = null; //name of report to print

    // Enable exception handler:
    try
    {
    sReport = "Summary of Sales by Year";

    // Determine the path to Northwind.mdb:
    sDBPath = GetOfficeAppPath("Access.Application", "msaccess.exe");
    if(sDBPath == null)
    {
    MessageBox.Show("Can't determine path to msaccess.exe");
    return;
    }
    sDBPath = sDBPath.Substring(0, sDBPath.Length - "msaccess.exe".Length)
    + @"Samples\Northwind.mdb";
    if(!System.IO.File.Exists(sDBPath))
    {
    MessageBox.Show("Can't find the file '" + sDBPath + "'");
    return;
    }

    // Specify the user name and password for the Access workgroup
    // information file, which is used to implement Access security.
    // Note: If you are not using the system.mdw in the default
    // location, you may include the /wrkgrp command-line switch to
    // point to a different workgroup information file.
    sUser = "Admin";
    sPwd = "";

    // Start a new instance of Access with user name and password:
    oAccess = ShellGetDB(sDBPath, "/user " + sUser + " /pwd " + sPwd,
    ProcessWindowStyle.Minimized, 1000);
    //or
    //oAccess = ShellGetApp(@"""" + sDBPath + @"""" +
    // " /user " + sUser + " /pwd " + sPwd,
    // ProcessWindowStyle.Minimized);

    // Select the report name in the database window and give focus
    // to the database window:
    oAccess.DoCmd.SelectObject(Access.AcObjectType.acReport, sReport, true);

    // Print the report:
    oAccess.DoCmd.OpenReport(sReport,
    Access.AcView.acViewNormal, moMissing, moMissing,
    Access.AcWindowMode.acWindowNormal, moMissing );
    // If using Access 10.0 object library, use this instead:
    //oAccess.DoCmd.OpenReport(sReport,
    // Access.AcView.acViewNormal, moMissing, moMissing,
    // Access.AcWindowMode.acWindowNormal, moMissing);
    }
    catch(Exception e)
    {
    MessageBox.Show(e.Message);
    }
    finally
    {
    // Release any Access objects and quit Access:
    try // use try..catch in case oAccess is not set
    {
    oAccess.Quit(Access.AcQuitOption.acQuitSaveNone);
    }
    catch{}
    NAR(oAccess);
    oAccess = null;
    }
    }

    private void Preview_Report_Runtime()
    {
    //Shows how to automate the Access Runtime to preview
    //the "Summary of Sales by Year" report in Northwind.mdb.

    Access.Application oAccess = null;
    Access.Form oForm = null;
    string sDBPath = null; //path to Northwind.mdb
    string sReport = null; //name of report to preview

    // Enable exception handler:
    try
    {
    sReport = "Summary of Sales by Year";

    // Determine the path to Northwind.mdb:
    sDBPath = GetOfficeAppPath("Access.Application", "msaccess.exe");
    if(sDBPath == null)
    {
    MessageBox.Show("Can't determine path to msaccess.exe");
    return;
    }

    sDBPath = sDBPath.Substring(0, sDBPath.Length - "msaccess.exe".Length)
    + @"Samples\Northwind.mdb";
    if(!System.IO.File.Exists(sDBPath))
    {
    MessageBox.Show("Can't find the file '" + sDBPath + "'");
    return;
    }

    // Start a new instance of Access with a database. If the
    // retail version of Access is not installed, and only the
    // Access Runtime is installed, launches a new instance
    // of the Access Runtime (/runtime switch is optional):
    oAccess = ShellGetDB(sDBPath, "/runtime",
    ProcessWindowStyle.Minimized, 1000);
    //or
    //oAccess = ShellGetApp(@"""" + sDBPath + @"""" + " /runtime",
    // ProcessWindowStyle.Minimized);

    // Make sure Access is visible:
    if(!oAccess.Visible) oAccess.Visible = true;

    // Close any forms that Northwind may have opened:
    while(oAccess.Forms.Count > 0)
    {
    oForm = oAccess.Forms[0];
    oAccess.DoCmd.Close(Access.AcObjectType.acForm,
    oForm.Name, Access.AcCloseSave.acSaveNo);
    NAR(oForm);
    oForm = null;
    }

    // Select the report name in the database window and give focus
    // to the database window:
    oAccess.DoCmd.SelectObject(Access.AcObjectType.acReport, sReport, true);

    // Maximize the Access window:
    oAccess.RunCommand(Access.AcCommand.acCmdAppMaximize);

    // Preview the report:
    oAccess.DoCmd.OpenReport(sReport,
    Access.AcView.acViewPreview, moMissing, moMissing,
    Access.AcWindowMode.acWindowNormal, moMissing );
    // If using Access 10.0 object library, use this instead:
    //oAccess.DoCmd.OpenReport(sReport,
    // Access.AcView.acViewPreview, moMissing, moMissing,
    // Access.AcWindowMode.acWindowNormal, moMissing);

    // Maximize the report window:
    oAccess.DoCmd.Maximize();

    // Hide Access menu bar:
    oAccess.CommandBars["Menu Bar"].Enabled = false;
    // Also hide NorthWindCustomMenuBar if it is available:
    try
    {
    oAccess.CommandBars["NorthwindCustomMenuBar"].Enabled = false;
    }
    catch{}

    // Release Application object and allow Access to be closed by user:
    if(!oAccess.UserControl) oAccess.UserControl = true;
    NAR(oAccess);
    oAccess = null;
    }
    catch(Exception e)
    {
    MessageBox.Show(e.Message);
    // Release any Access objects and quit Access due to error:
    NAR(oForm);
    oForm = null;
    try // use try..catch in case oAccess is not set
    {
    oAccess.Quit(Access.AcQuitOption.acQuitSaveNone);
    }
    catch{}
    NAR(oAccess);
    oAccess = null;
    }
    }

  10. Agregue el código siguiente a las directivas Using de Form1.cs:
    using System.Runtime.InteropServices;using System.Diagnostics;
    using System.Reflection;

  11. Presione F5 para generar y ejecutar el programa. Se muestra Form1.
  12. Haga clic en Imprimir informey, a continuación, haga clic en Ir!. El procedimiento Print_Report imprimirá un informe de la base de datos Northwind.
  13. Haga clic en vista previa del informey, a continuación, haga clic en Ir!. El procedimiento Preview_Report ofrecerá una muestra una vista previa de un informe de la base de datos Northwind. Cierre la instancia de Access cuando esté listo para continuar.
  14. Haga clic en Mostrar el formulario y, a continuación, haga clic en Ir!. El procedimiento Show_Form mostrará el formulario de cuadro de diálogo etiquetas de cliente de la base de datos Northwind. También establece el grupo de opciones del formulario en "País específico" y seleccionará "EE" de la lista. Cierre la instancia de Access cuando esté listo para continuar.
  15. Haga clic en Print report (Security)y, a continuación, haga clic en Ir!. El procedimiento Print_Report_Security muestra cómo automatizar Access y cómo evitar el cuadro de diálogo de inicio de sesión si está activada la seguridad a nivel de usuario. En este ejemplo, se supone el inicio de sesión predeterminado pasando el usuario Admin con una contraseña en blanco. El código, a continuación, imprime un informe en la base de datos Northwind.
  16. Haga clic en Preview report (Runtime)y, a continuación, haga clic en Ir!. El procedimiento Preview_Report_Runtime muestra cómo automatizar Access Runtime para obtener una vista previa de un informe en la base de datos Northwind. Si se instala la versión comercial de Access, el procedimiento funcionará correctamente. Cuando esté listo para continuar, cierre la instancia de Access.

REFERENCIAS

Para obtener más información, visite el siguiente sitio Web de MSDN:
Desarrollo de Microsoft Office con Visual Studio
http://msdn2.microsoft.com/en-us/library/aa188489(office.10).aspx
Para obtener más información, haga clic en los números de artículo siguientes para verlos en Microsoft Knowledge Base:

317157 PRB: errores al hacer referencia a la biblioteca de tipos de Access 10.0 con Visual Studio .NET

317109 aplicación de office no se cierra después de automatización desde cliente de Visual Studio .NET

316126 cómo utilizar Visual C# para automatizar una instancia en ejecución de un programa de Office

316125 PRB: error de Visual .NET C# asociar a la ejecución de la instancia de aplicación de Office

244695 de error: mensaje de Error 2046 llamada AbrirFormulario o AbrirInforme con automatización de acceso

Enlace 302902 para servidores de automatización de Office con Visual C#.

302295 cómo obtener el identificador de ventana para un servidor de automatización de Office mediante Visual C#.

306683 cómo ejecutar macros de Office mediante automatización desde Visual C#.

Propiedades

Id. de artículo: 317114 - Última revisión: 17 ene. 2017 - Revisión: 1

Comentarios