Automatizace aplikace Microsoft Access pomocí jazyka Visual C #

Souhrn

Tento článek ukazuje, jak automatizovat aplikaci Microsoft Access pomocí jazyka Microsoft Visual C# 2005 nebo Microsoft Visual C# .NET. Témata a ukázkový kód ukazují, jak postupovat takto:

  • Otevřete databázi v Accessu.
  • Tisk nebo zobrazení náhledu accessové sestavy
  • Umožňuje zobrazit a upravit formulář aplikace Access.
  • Vyhněte se dialogovým oknům při otevření databáze chráněné heslem nebo při zapnutém zabezpečení na úrovni uživatele.
  • Automatizujte accessový modul runtime.

Automatizace vs. ADO.NET

Vývojář může pracovat s databází Microsoft Accessu z Visual C# 2005 nebo Visual C# .NET pomocí dvou samostatných technologií: Automation a Microsoft ADO.NET.

ADO.NET je upřednostňovaná technologie, pokud chcete pracovat s datovými objekty, jako jsou tabulky a dotazy v accessové databázi. Automatizaci použijte jenom v případě, že potřebujete funkce specifické pro aplikaci Microsoft Access, jako je možnost tisku nebo zobrazení náhledu accessové sestavy, zobrazení formuláře Accessu nebo volání maker Accessu.

Tento článek popisuje, jak automatizovat Access. Tento článek ADO.NET nepojednává. Informace týkající se ADO.NET získáte v následujících článcích znalostní báze Microsoft Knowledge Base:

  • 306636 Jak se připojit k databázi a spustit příkaz pomocí ADO 2005 a Visual C# 2005 nebo pomocí ADO.NET a Visual C# .NET

  • 314145 Jak naplnit objekt DataSet z databáze pomocí jazyka Visual C# .NET

  • 307587 Jak aktualizovat databázi z objektu DataSet pomocí Visual C# 2005 nebo Visual C# .NET

Automatizace je technologie modelu COM (Component Object Model). Automatizace umožňuje aplikacím napsaným v jazycích, jako je Visual C# .NET, programově řídit jiné aplikace. Když automatizujete aplikaci Microsoft Office, spustíte instanci této aplikace v paměti a potom zavoláte objektový model aplikace, abyste mohli v této aplikaci provádět různé úlohy. S Aplikací Access a dalšími aplikacemi Microsoft Office je možné prostřednictvím služby Automation provádět prakticky všechny akce, které můžete provádět ručně prostřednictvím uživatelského rozhraní.

Access zpřístupňuje tuto programovou funkci prostřednictvím objektového modelu. Objektový model je kolekce tříd a metod, které slouží jako protějšky logických komponent Accessu. Pokud chcete získat přístup k objektového modelu z Visual C# .NET, můžete nastavit odkaz na projekt na knihovnu typů.

Běžné úlohy automatizace

Otevření databáze v Accessu

Při automatizaci aplikace Microsoft Access je nutné otevřít databázi před provedením užitečných úloh, jako je tisk sestav. K otevření databáze v instanci aplikace Access, kterou automatizujete, použijete metody OpenCurrentDatabase nebo OpenAccessProject objektu Application. V Accessu můžete mít současně otevřenou jenom jednu databázi. Pokud chcete pracovat s jinou databází, můžete použít metodu CloseCurrentDatabase před otevřením jiné databáze.

Můžete také použít metodu System.Runtime.InteropServices.Marshal.BindToMoniker(<cesta k databázi>) k otevření databáze v instanci accessu. Pokud je databáze již otevřena v instanci aplikace Access, vrátí funkce BindToMoniker objekt Application této instance. Jinak BindToMoniker spustí novou instanci Accessu a otevře zadanou databázi.

OpenCurrentDatabase je upřednostňovaná metoda pro otevření databáze, protože zadáváte instanci Accessu, kterou automatizujete. Můžete také zadat argumenty pro řízení způsobu otevření databáze, například:

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

Chcete-li zobrazit náhled nebo vytisknout sestavu aplikace Access, zavolejte metodu OpenReport objektu DoCmd. Při volání OpenReport jeden z argumentů, které předáte určuje, zda je sestava zobrazena v náhledu na obrazovce nebo zda je odeslána do tiskárny:

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

Všimněte si, že argument Zobrazení určuje, jestli se sestava zobrazí v Accessu nebo jestli se odešle do tiskárny. Argument WhereCondition může omezit sadu záznamů sestavy, pokud použijete platnou klauzuli WHERE jazyka SQL (bez slova WHERE).) Všimněte si, že můžete použít System.Reflection.Missing.Value přeskočit všechny parametry objektu, které jsou volitelné.

Pokud náhled sestavy zobrazujete, nezapomeňte nastavit vlastnost Visible objektu Application tak, aby byl Access viditelný na obrazovce. Tímto způsobem může uživatel sestavu zobrazit v okně Accessu.

Existuje další způsob, jak vytisknout sestavu nebo jiné objekty v databázi. Použití PrintOut metodu DoCmd objektu. V tomto příkladu vyberete sestavu s názvem Zaměstnanci v okně Databáze a potom zavoláte výtisk pro tisk vybraného objektu. Metoda umožňuje zadat argumenty, které odpovídají tisk dialogové okno v Accessu:

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

Nebo v některých případech můžete chtít k tisku sestavy použít metody OpenReport i PrintOut. Předpokládejme, že chcete vytisknout více kopií sestavy Zaměstnanci, ale pouze pro konkrétního zaměstnance. Tento příklad nejprve používá OpenReport k otevření sestavy Zaměstnanci v režimu náhledu pomocí argumentu WhereCondition k omezení záznamů na konkrétního zaměstnance. Výtisk se pak použije k tisku více kopií aktivního objektu:

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

Aplikace Access 2002 zavedla objekt tiskárny. Tento objekt můžete použít k jednoduššímu přizpůsobení nastavení tiskárny v Accessu než v dřívějších verzích Accessu. Příklad použití objektu tiskárny v aplikaci Access k tisku sestavy klepněte na článek číslo článku databáze Microsoft Knowledge Base:

284286 Jak obnovit změny objektu Application.Printer

Zobrazení a úprava formuláře aplikace Access

Visual C# .NET má velmi výkonné možnosti formuláře. Může však nastat situace, kdy chcete, aby uživatel zobrazil formulář, který byl dříve vyvinut v Accessu. Nebo můžete mít formulář v accessové databázi, který poskytuje kritéria pro dotaz nebo sestavu, a před zobrazením náhledu nebo tiskem sestavy je nutné tento formulář otevřít. Pokud chcete otevřít a zobrazit formulář Accessu, zavoláte metodu OpenForm objektu 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
   );

Teď můžete upravit ovládací prvky ve formuláři.

Dialogová okna Zabezpečení přístupu

Při automatizaci Accessu se může při pokusu o otevření databáze zobrazit výzva k zadání uživatelského jména, hesla nebo obojího. Pokud uživatel zadá nesprávné informace, v kódu dojde k chybě. Může nastat situace, kdy se chcete těmto dialogovým oknům vyhnout a místo toho programově zadat uživatelské jméno a heslo, aby se váš kód Automation spouštěl bez přerušení.

V Microsoft Accessu existují dva typy zabezpečení: databáze chráněné heslem a zabezpečení na úrovni uživatele prostřednictvím souboru pracovní skupiny (System.mdw). Pokud se pokoušíte otevřít databázi chráněnou heslem, zobrazí se dialogové okno s výzvou k zadání hesla databáze. Zabezpečení na úrovni uživatele se liší od databáze chráněné heslem. Když je aktivováno zabezpečení na úrovni uživatele, access zobrazí přihlašovací dialogové okno s výzvou k zadání uživatelského jména i hesla před tím, než uživatel může otevřít libovolnou databázi v Accessu.

Jak se vyhnout dialogům s heslem databáze

Pokud otevíráte databázi chráněnou heslem, můžete se tomuto dialogovému oknu vyhnout zadáním hesla metodě 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
   );

Tady je příklad, kdy byla oAccess dříve nastavená na instanci Accessu, která nemá otevřenou databázi. Tento kód poskytuje databázi heslo, aby se zabránilo dialogovému oknu:

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;

Soubor oDB.Close ve skutečnosti nezavře databázi v Accessu. Zavře pouze připojení DAO k databázi vytvořené prostřednictvím objektu DBEngine. Připojení DAO už není po použití metody OpenCurrentDatabase nutné. Všimněte si kódu pro uvolnění objektů oDB a oDBEngine. Tyto objekty musíte použít, aby se Access po dokončení kódu správně ukončil.

Zabránění přihlášení k zabezpečení přístupu – dialogová okna

Pokud je v Accessu zapnuté zabezpečení na úrovni uživatele, zobrazí se uživateli výzva k přihlášení s výzvou k zadání uživatelského jména i hesla. Uživatelské jméno a heslo nelze zadat pomocí objektového modelu accessu. Proto pokud se chcete při automatizaci Accessu vyhnout přihlašovacímu dialogovému oknu, musíte nejprve spustit Msaccess.exe soubor a zadat přepínače příkazového řádku /user a /pwd pro zadání uživatelského jména a hesla. Potom můžete použít GetActiveObject nebo BindToMoniker k načtení objektu Application spuštěné instance Accessu, abyste mohli pokračovat ve službě Automation.

Automatizace modulu Access Runtime

Microsoft Office Developer Edition obsahuje Microsoft Office Developer Tools (MOD). Pomocí modu můžou vývojáři Accessu vytvářet a distribuovat aplikace pro Access uživatelům, kteří nemají prodejní verzi Accessu. Když uživatel nainstaluje aplikaci Access na počítač, který nemá prodejní verzi Accessu, nainstaluje se verze Accessu za běhu. Modul Access Runtime je nainstalovaný a je zaregistrovaný jako maloobchodní verze. Spustitelný soubor se také nazývá Msaccess.exe. Access Runtime umožňuje aplikaci accessu běžet na klientském počítači, ale accessový modul runtime neumožňuje uživateli vyvíjet nové aplikace ani upravovat návrh stávajících aplikací.

Access Runtime musí být spuštěný s databází. Z důvodu tohoto požadavku, pokud chcete automatizovat Access Runtime, musíte spustit Msaccess.exe a zadat databázi, která se má otevřít. Poté, co použijete GetActiveObject nebo BindToMoniker k načtení objektu aplikace, můžete pak automatizovat Access Runtime. Pokud tento přístup nepoužijete při pokusu o automatizaci accessového modulu runtime, při pokusu o vytvoření instance se zobrazí chybová zpráva, například následující:

Spuštění serveru System.Runtime.InteropServices.COMException (0x80080005) se nezdařilo.

Vytvoření kompletního ukázkového projektu Visual C# 2005 nebo Visual C# .NET

Pokud chcete použít následující ukázku krok za krokem, ujistěte se, že je nainstalovaná ukázková databáze Northwind. Ve výchozím nastavení aplikace Microsoft Access 2000 nainstaluje ukázkové databáze v následující cestě:

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

Microsoft Access 2002 používá následující cestu:

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

Microsoft Office Access 2003 používá následující cestu:

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

Chcete-li se ujistit, zda je ukázková databáze Northwind nainstalována v aplikaci Access 2002 nebo Access 2003, klepněte v nabídce Nápověda na příkaz Ukázkové databáze Northwind.

  1. Zavřete všechny instance Accessu, které jsou aktuálně spuštěné.

  2. Spusťte Microsoft Visual Studio .NET.

  3. V nabídce Soubor klikněte na Nový a potom klikněte na Project. V typech projektů Visual C# vyberte aplikaci pro Windows. Ve výchozím nastavení je vytvořen Formulář1.

    Poznámka Musíte změnit kód v sadě Visual Studio 2005. Visual C# ve výchozím nastavení přidá jeden formulář do projektu při vytváření projektu model Windows Forms. Formulář má název Form1. Dva soubory, které představují formulář, mají název Form1.cs a Form1.designer.cs. Kód napíšete v Souboru Form1.cs. Soubor Form1.designer.cs je místo, kde návrhář model Windows Forms zapíše kód, který implementuje všechny akce, které jste provedli přetažením ovládacích prvků z panelu nástrojů.

    Další informace o model Windows Forms Designer v jazyce Visual C# 2005 naleznete na následujícím webu Microsoft Developer Network (MSDN):https://msdn.microsoft.com/en-us/library/ms173077.aspx

  4. Přidejte odkaz na knihovnu objektů aplikace Microsoft Access. Postupujte takto:

    1. V nabídce Projekt klikněte na Přidat odkaz.
    2. Na kartě COM vyhledejte Microsoft Access Object Library a klepněte na tlačítko Vybrat.

    Poznámka V sadě Visual Studio 2005. nemusíte kliknout na Vybrat.

    Poznámka Microsoft Office 2003 obsahuje primární sestavení vzájemné spolupráce (PIA). Sada Microsoft Office XP neobsahuje osobní údaje, ale je možné je stáhnout.

  5. V dialogovém okně Přidat odkazy potvrďte výběr kliknutím na tlačítko OK.

    Poznámka Pokud odkazujete na knihovnu objektů Accessu 10.0 a při pokusu o přidání odkazu se zobrazí chyby.

  6. V zobrazení nabídky, klepněte na tlačítko Sada nástrojů zobrazíte sadu nástrojů.

  7. Přidejte pět ovládacích prvků přepínačů a jeden ovládací prvek tlačítka do formuláře Form1.

  8. Vyberte všechny ovládací prvky přepínačů a pak nastavte vlastnost Velikost na 150 24.

  9. Přidejte obslužné rutiny událostí pro událost načtení formuláře a pro událost Click ovládacího prvku Tlačítko:

    1. V návrhovém zobrazení pro Form1.cs poklikáte na Form1.

      Obslužná rutina události Load formuláře se vytvoří a zobrazí v Souboru Form1.cs.

    2. V zobrazení nabídky, klepněte na tlačítko Návrhář přepnout do návrhového zobrazení.

    3. Poklikáte na Tlačítko1.

      Obslužná rutina události Click tlačítka se vytvoří a zobrazí v Souboru Form1.cs.

  10. V Souboru Form1.cs nahraďte následující kód.

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

    S:

          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. Do direktiv Using v Form1.cs přidejte následující kód:

    using System.Runtime.InteropServices;
    using System.Diagnostics;
    using System.Reflection; 
    
  12. Stisknutím klávesy F5 sestavte a spusťte program. Zobrazí se formulář1.

  13. Klikněte na Tisk sestavy a potom klikněte na Přejít!. Procedura Print_Report vytiskne sestavu z databáze Northwind.

  14. Klikněte na náhled sestavy a potom klikněte na Přejít!. Procedura Preview_Report zobrazí náhled sestavy z databáze Northwind. Až budete připraveni pokračovat, zavřete instanci Accessu.

  15. Klepněte na tlačítko Zobrazit formulář a potom klepněte na tlačítko Přejít!. Procedura Show_Form zobrazí formulář dialogového okna Popisky zákazníků z databáze Northwind. Nastaví také skupinu možností ve formuláři na "Konkrétní země" a ze seznamu vybere "USA". Až budete připraveni pokračovat, zavřete instanci Accessu.

  16. Klepněte na tlačítko Tisk sestavy (zabezpečení) a potom klepněte na tlačítko Přejít!. Postup Print_Report_Security ukazuje, jak automatizovat Access a jak se vyhnout přihlašovacímu dialogovému oknu, pokud je zapnuté zabezpečení na úrovni uživatele. V tomto příkladu předpokládejte výchozí přihlášení předáním uživatelského Správa s prázdným heslem. Kód pak vytiskne sestavu v databázi Northwind.

  17. Klikněte na náhled sestavy (runtime) a potom klikněte na Go!. Postup Preview_Report_Runtime ukazuje, jak automatizovat modul Access Runtime pro zobrazení náhledu sestavy v databázi Northwind. Pokud je nainstalovaná maloobchodní verze Accessu, bude postup fungovat správně. Až budete připraveni pokračovat, zavřete instanci Accessu.

Odkazy

Další informace naleznete na následujícím webu MSDN: Microsoft Office Development with Visual Studio https://msdn.microsoft.com/en-us/library/aa188489(office.10).aspxDalší informace získáte v následujících článcích znalostní báze Microsoft Knowledge Base:

317109 aplikace Office se po automatizaci z klienta Visual Studio .NET neukončí

316126 Jak pomocí jazyka Visual C# automatizovat spuštěnou instanci aplikace Office