Comment automatiser Microsoft Access à l’aide de Visual C #

Résumé

Cet article montre comment automatiser Microsoft Access à l’aide de Microsoft Visual C# 2005 ou Microsoft Visual C# .NET. Les rubriques et l’exemple de code vous montrent comment effectuer les opérations suivantes :

  • Ouvrez une base de données dans Access.
  • Imprimer ou afficher un aperçu d’un rapport Access.
  • Afficher et modifier un formulaire Access.
  • Évitez les boîtes de dialogue lorsque vous ouvrez une base de données protégée par mot de passe ou lorsque la sécurité au niveau de l’utilisateur est activée.
  • Automatiser le runtime d’accès.

Automation et ADO.NET

Un développeur peut utiliser une base de données Microsoft Access à partir de Visual C# 2005 ou Visual C# .NET à l’aide de deux technologies distinctes : Automation et Microsoft ADO.NET.

ADO.NET est la technologie préférée si vous souhaitez utiliser des objets de données, tels que des tables et des requêtes dans une base de données Access. Utilisez Automation uniquement si vous avez besoin de fonctionnalités spécifiques à l’application Microsoft Access, telles que la possibilité d’imprimer ou d’afficher un aperçu d’un rapport Access, d’afficher un formulaire Access ou d’appeler des macros Access.

Cet article explique comment automatiser Access. L’article ne traite pas de ADO.NET. Pour plus d’informations sur ADO.NET, cliquez sur les numéros d’article ci-dessous pour afficher les articles de la Base de connaissances Microsoft :

  • 306636 Comment se connecter à une base de données et exécuter une commande à l’aide d’ADO 2005 et de Visual C# 2005 ou à l’aide de ADO.NET et Visual C# .NET

  • 314145 Comment remplir un objet DataSet à partir d’une base de données à l’aide de Visual C# .NET

  • 307587 Comment mettre à jour une base de données à partir d’un objet DataSet à l’aide de Visual C# 2005 ou Visual C# .NET

Automation est une technologie COM (Component Object Model). Automation permet aux applications écrites dans des langages tels que Visual C# .NET de contrôler par programmation d’autres applications. Quand vous automatiser une application Microsoft Office, vous exécutez une instance de cette application en mémoire, puis appelez le modèle objet de l’application pour effectuer différentes tâches dans cette application. Avec Access et d’autres applications Microsoft Office, pratiquement toutes les actions que vous pouvez effectuer manuellement via l’interface utilisateur peuvent également être effectuées par programmation à l’aide d’Automation.

Access expose cette fonctionnalité par programmation via un modèle objet. Le modèle objet est une collection de classes et de méthodes qui servent d’équivalents aux composants logiques d’Access. Pour accéder au modèle objet à partir de Visual C# .NET, vous pouvez définir une référence de projet à la bibliothèque de types.

Tâches d’automatisation courantes

Ouvrir une base de données dans Access

Lorsque vous automatisez Microsoft Access, vous devez ouvrir une base de données avant de pouvoir effectuer des tâches utiles, telles que l’impression de rapports. Pour ouvrir une base de données dans l’instance d’Access que vous automatisez, vous utilisez les méthodes OpenCurrentDatabase ou OpenAccessProject de l’objet Application. Vous ne pouvez ouvrir qu’une seule base de données dans Access à la fois. Pour utiliser une autre base de données, vous pouvez utiliser la méthode CloseCurrentDatabase avant d’en ouvrir une autre.

Vous pouvez également utiliser la méthode System.Runtime.InteropServices.Marshal.BindToMoniker(<path to database>) pour ouvrir une base de données dans une instance d’Access. Si la base de données est déjà ouverte dans une instance d’Access, BindToMoniker retourne l’objet Application de cette instance. Sinon, BindToMoniker démarre une nouvelle instance d’Access et ouvre la base de données spécifiée.

OpenCurrentDatabase est la méthode par défaut pour ouvrir une base de données, car vous spécifiez l’instance d’Access que vous automatisez. Vous pouvez également fournir des arguments pour contrôler la façon dont la base de données est ouverte, par exemple :

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
   );

Pour afficher un aperçu ou imprimer un rapport Access, vous appelez la méthode OpenReport de l’objet DoCmd. Lorsque vous appelez OpenReport, l’un des arguments que vous transmettez détermine si le rapport est affiché en préversion à l’écran ou s’il est envoyé à l’imprimante :

// 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
   );

Notez que l’argument Affichage détermine si le rapport est affiché dans Access ou s’il est envoyé à l’imprimante. L’argument WhereCondition peut limiter l’ensemble d’enregistrements du rapport, si vous utilisez une clause SQL WHERE valide (sans le mot WHERE).) Notez que vous pouvez utiliser System.Reflection.Missing.Value pour ignorer les paramètres d’objet facultatifs.

Si vous affichez un aperçu d’un rapport, veillez à définir la propriété Visible de l’objet Application afin qu’Access soit visible à l’écran. De cette façon, l’utilisateur peut afficher le rapport dans la fenêtre Access.

Il existe une autre façon d’imprimer un rapport ou d’autres objets dans la base de données. Utilisez la méthode PrintOut de l’objet DoCmd. Dans cet exemple, vous sélectionnez un rapport nommé Employés dans la fenêtre Base de données, puis vous appelez PrintOut pour imprimer l’objet sélectionné. La méthode PrintOut vous permet de fournir des arguments qui correspondent à la boîte de dialogue Imprimer dans 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
   );

Ou, dans certains cas, vous pouvez utiliser les méthodes OpenReport et PrintOut pour imprimer un rapport. Supposons que vous souhaitez imprimer plusieurs copies du rapport Employés, mais uniquement pour un employé spécifique. Cet exemple utilise d’abord OpenReport pour ouvrir le rapport Employees en mode aperçu, à l’aide de l’argument WhereCondition pour limiter les enregistrements à un employé spécifique. Ensuite, PrintOut est utilisé pour imprimer plusieurs copies de l’objet actif :

// 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 a introduit l’objet Printer. Vous pouvez utiliser cet objet pour personnaliser les paramètres de l’imprimante Access plus facilement que dans les versions antérieures d’Access. Pour obtenir un exemple d’utilisation de l’objet Printer dans Access pour imprimer un rapport, cliquez sur le numéro d’article ci-dessous pour afficher l’article dans la Base de connaissances Microsoft :

284286 Comment réinitialiser les modifications apportées à l’objet Application.Printer

Afficher et modifier un formulaire d’accès

Visual C# .NET offre des fonctionnalités de forme très puissantes. Toutefois, il peut arriver que vous souhaitiez que l’utilisateur affiche un formulaire précédemment développé dans Access. Vous pouvez également avoir un formulaire dans votre base de données Access qui fournit des critères pour une requête ou un rapport, et vous devez ouvrir ce formulaire avant de pouvoir afficher un aperçu ou imprimer le rapport. Pour ouvrir et afficher un formulaire Access, vous appelez la méthode OpenForm de l’objet 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
   );

Vous pouvez maintenant modifier les contrôles du formulaire.

Boîtes de dialogue Sécurité d’accès

Lorsque vous automatisez Access, vous pouvez être invité à entrer un nom d’utilisateur ou un mot de passe, ou les deux, lorsque vous essayez d’ouvrir une base de données. Si l’utilisateur entre les informations incorrectes, une erreur se produit dans votre code. Il peut arriver que vous souhaitiez éviter ces boîtes de dialogue et fournir par programmation le nom d’utilisateur et le mot de passe afin que votre code Automation s’exécute sans interruption.

Il existe deux types de sécurité dans Microsoft Access : les bases de données protégées par mot de passe et la sécurité au niveau de l’utilisateur via un fichier de groupe de travail (System.mdw). Si vous essayez d’ouvrir une base de données protégée par mot de passe, vous recevrez une boîte de dialogue vous invitant à entrer le mot de passe de la base de données. La sécurité au niveau de l’utilisateur est différente d’une base de données protégée par mot de passe. Lorsque la sécurité au niveau de l’utilisateur est activée, Access affiche une boîte de dialogue d’ouverture de session pour demander à la fois un nom d’utilisateur et un mot de passe avant que l’utilisateur puisse ouvrir une base de données dans Access.

Éviter les boîtes de dialogue de mot de passe de base de données

Si vous ouvrez une base de données protégée par un mot de passe, vous pouvez éviter la boîte de dialogue en fournissant le mot de passe à la méthode 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
   );

Voici un exemple, où oAccess a été précédemment défini sur une instance d’Access qui n’a pas de base de données ouverte. Ce code fournit le mot de passe à la base de données pour éviter une boîte de dialogue :

string sDBPassword = "MyPassword"; //database password
DAO._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;

ODB.Close ne ferme pas réellement la base de données dans Access. Il ferme uniquement la connexion DAO à la base de données qui a été effectuée via l’objet DBEngine. La connexion DAO n’est plus nécessaire après l’utilisation de la méthode OpenCurrentDatabase. Notez le code permettant de libérer les objets oDB et oDBEngine. Vous devez utiliser ces objets pour que Access quitte correctement une fois le code terminé.

Éviter les boîtes de dialogue d’ouverture de session sécurité d’accès

Si la sécurité au niveau de l’utilisateur est activée dans Access, l’utilisateur est invité à ouvrir une boîte de dialogue d’ouverture de session, en indiquant à la fois un nom d’utilisateur et un mot de passe. Un nom d’utilisateur et un mot de passe ne peuvent pas être spécifiés à l’aide du modèle objet Access. Par conséquent, si vous souhaitez éviter la boîte de dialogue d’ouverture de session lors de l’automatisation d’Access, vous devez d’abord démarrer le fichier Msaccess.exe et fournir les commutateurs de ligne de commande /user et /pwd pour spécifier le nom d’utilisateur et le mot de passe. Ensuite, vous pouvez utiliser GetActiveObject ou BindToMoniker pour récupérer l’objet Application de l’instance en cours d’exécution d’Access, afin de pouvoir continuer avec Automation.

Automatisation du runtime d’accès

Microsoft Office Developer Edition inclut les outils de développement Microsoft Office (MOD). À l’aide du mod, les développeurs Access peuvent créer et distribuer des applications Access aux utilisateurs qui n’ont pas la version commerciale d’Access. Lorsque l’utilisateur installe l’application Access sur un ordinateur qui n’a pas la version commerciale d’Access, une version runtime d’Access est installée. Access Runtime est installé et inscrit comme la version commerciale. L’exécutable est également appelé Msaccess.exe. Access Runtime permet à une application Access de s’exécuter sur un ordinateur client, mais access runtime ne permet pas à un utilisateur de développer de nouvelles applications ou de modifier la conception d’applications existantes.

Le runtime d’accès doit être démarré avec une base de données. En raison de cette exigence, si vous souhaitez automatiser le runtime d’accès, vous devez démarrer le Msaccess.exe et spécifier une base de données à ouvrir. Après avoir utilisé GetActiveObject ou BindToMoniker pour récupérer l’objet Application, vous pouvez automatiser access runtime. Si vous n’utilisez pas cette approche lorsque vous essayez d’automatiser le runtime Access, vous recevez un message d’erreur tel que le suivant lorsque vous essayez d’instancier l’instance :

Échec de l’exécution du serveur System.Runtime.InteropServices.COMException (0x80080005).

Créer l’exemple complet de projet Visual C# 2005 ou Visual C# .NET

Pour utiliser l’exemple étape par étape suivant, assurez-vous que l’exemple de base de données Northwind est installé. Par défaut, Microsoft Access 2000 installe les exemples de bases de données dans le chemin suivant :

C:\Program Files\Microsoft Office\Office\Samples

Microsoft Access 2002 utilise le chemin suivant :

C:\Program Files\Microsoft Office\Office10\Samples

Microsoft Office Access 2003 utilise le chemin d’accès suivant :

C:\Program Files\Microsoft\Office\Office11\Samples

Pour vous assurer que l’exemple de base de données Northwind est installé sur Access 2002 ou Access 2003, cliquez sur Exemples de base de données dans le menu Aide, puis cliquez sur Exemple de base de données Northwind.

  1. Fermez toutes les instances d’Access en cours d’exécution.

  2. Démarrez Microsoft Visual Studio .NET.

  3. Dans le menu Fichier, cliquez sur Nouveau, puis sur Projet. Sélectionnez Application Windows dans les types de projet Visual C#. Par défaut, Form1 est créé.

    Note Vous devez modifier le code dans Visual Studio 2005. Par défaut, Visual C# ajoute un formulaire au projet lorsque vous créez un projet Windows Forms. Le formulaire est nommé Form1. Les deux fichiers qui représentent le formulaire sont nommés Form1.cs et Form1.designer.cs. Vous écrivez le code dans Form1.cs. Le fichier Form1.designer.cs est l’endroit où le concepteur Windows Forms écrit le code qui implémente toutes les actions que vous avez effectuées en faisant glisser et en supprimant des contrôles de la boîte à outils.

    Pour plus d’informations sur le concepteur Windows Forms dans Visual C# 2005, visitez le site web Microsoft Developer Network (MSDN) suivant :https://msdn.microsoft.com/en-us/library/ms173077.aspx

  4. Ajoutez une référence à la bibliothèque d’objets Microsoft Access. Pour cela, procédez comme suit :

    1. Dans le menu Projet, cliquez sur Ajouter une référence.
    2. Sous l’onglet COM, recherchez la bibliothèque d’objets Microsoft Access, puis cliquez sur Sélectionner.

    Note Dans Visual Studio 2005. vous n’avez pas besoin de cliquer sur Sélectionner.

    Note Microsoft Office 2003 inclut des assemblys PIA (Primary Interop Assemblies). Microsoft Office XP n’inclut pas de codes confidentiels, mais ils peuvent être téléchargés.

  5. Dans la boîte de dialogue Ajouter des références, cliquez sur OK pour accepter vos sélections.

    Note Si vous référencez la bibliothèque d’objets Access 10.0 et que vous recevez des erreurs lorsque vous essayez d’ajouter la référence.

  6. Dans le menu Affichage, cliquez sur Boîte à outils pour afficher la boîte à outils.

  7. Ajoutez cinq contrôles de case d’option et un contrôle de bouton à Form1.

  8. Sélectionnez tous les contrôles de case d’option, puis définissez la propriété Size sur 150,24.

  9. Ajoutez des gestionnaires d’événements pour l’événement De chargement de formulaire et pour l’événement Click du contrôle Button :

    1. En mode Création pour Form1.cs, double-cliquez sur Form1.

      Le gestionnaire de l’événement de chargement du formulaire est créé et affiché dans Form1.cs.

    2. Dans le menu Affichage, cliquez sur Concepteur pour basculer en mode Création.

    3. Double-cliquez sur Button1.

      Le gestionnaire de l’événement Click du bouton est créé et affiché dans Form1.cs.

  10. Dans Form1.cs, remplacez le code suivant

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

    avec :

          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;
             }
          }
    
    
  11. Ajoutez le code suivant aux directives Using dans Form1.cs :

    using System.Runtime.InteropServices;
    using System.Diagnostics;
    using System.Reflection; 
    
  12. Appuyez sur F5 pour générer et exécuter le programme. Form1 s’affiche.

  13. Cliquez sur Imprimer le rapport, puis sur Go!. La procédure Print_Report imprime un rapport à partir de la base de données Northwind.

  14. Cliquez sur Aperçu du rapport, puis sur Go!. La procédure Preview_Report affiche un aperçu d’un rapport à partir de la base de données Northwind. Fermez l’instance Access lorsque vous êtes prêt à continuer.

  15. Cliquez sur Afficher le formulaire, puis sur Go!. La procédure Show_Form affiche le formulaire de boîte de dialogue Étiquettes client de la base de données Northwind. Il définit également le groupe d’options sur le formulaire sur « Pays spécifique » et sélectionne « USA » dans la liste. Fermez l’instance Access lorsque vous êtes prêt à continuer.

  16. Cliquez sur Imprimer le rapport (Sécurité), puis sur Go!. La procédure Print_Report_Security vous montre comment automatiser Access et comment éviter la boîte de dialogue d’ouverture de session si la sécurité au niveau de l’utilisateur est activée. Dans cet exemple, supposons l’ouverture de session par défaut en passant l’utilisateur Administration avec un mot de passe vide. Le code imprime ensuite un rapport dans la base de données Northwind.

  17. Cliquez sur Aperçu du rapport (Runtime), puis sur Go!. La procédure Preview_Report_Runtime vous montre comment automatiser access runtime pour afficher un aperçu d’un rapport dans la base de données Northwind. Si la version commerciale d’Access est installée, la procédure fonctionne toujours correctement. Fermez l’instance d’Access lorsque vous êtes prêt à continuer.

References

Pour plus d’informations, visitez le site web MSDN suivant : Développement Microsoft Office avec Visual Studio https://msdn.microsoft.com/en-us/library/aa188489(office.10).aspxPour plus d’informations, cliquez sur les numéros d’article suivants pour afficher les articles de la Base de connaissances Microsoft :

317109 application Office ne quitte pas après l’automatisation à partir du client Visual Studio .NET

316126 Comment utiliser Visual C# pour automatiser une instance en cours d’exécution d’un programme Office