Автоматизация Microsoft Access с помощью Visual C #

Аннотация

В этой статье показано, как автоматизировать Microsoft Access с помощью Microsoft Visual C# 2005 или Microsoft Visual C# .NET. В разделах и примере кода показано, как выполнить следующие действия:

  • Откройте базу данных в Access.
  • Печать или предварительный просмотр отчета Access.
  • Отображение и изменение формы Access.
  • Избегайте диалоговых окон при открытии базы данных, защищенной паролем, или при включении безопасности на уровне пользователя.
  • Автоматизировать среду выполнения access.

Автоматизация и ADO.NET

Разработчик может работать с базой данных Microsoft Access из Visual C# 2005 или Visual C# .NET с помощью двух отдельных технологий: автоматизации и Microsoft ADO.NET.

ADO.NET является предпочтительной технологией, если вы хотите работать с объектами данных, такими как таблицы и запросы в базе данных Access. Используйте службу автоматизации только в том случае, если требуются функции, связанные с приложением Microsoft Access, такие как возможность печати или предварительного просмотра отчета Access, отображения формы Access или вызова макросов Access.

В этой статье описывается, как автоматизировать Access. В этой статье не рассматриваются ADO.NET. Чтобы получить сведения о ADO.NET, щелкните приведенные ниже номера статей, чтобы просмотреть статьи в базе знаний Майкрософт:

  • 306636 Как подключиться к базе данных и выполнить команду с помощью ADO 2005 и Visual C# 2005 или с помощью ADO.NET и Visual C# .NET

  • 314145 Как заполнить объект DataSet из базы данных с помощью Visual C# .NET

  • 307587 Как обновить базу данных из объекта DataSet с помощью Visual C# 2005 или Visual C# .NET

Автоматизация — это технология МОДЕЛИ COM. Автоматизация позволяет приложениям, написанным на таких языках, как Visual C# .NET, программно управлять другими приложениями. При автоматизации приложения Microsoft Office вы фактически выполняете экземпляр этого приложения в памяти, а затем вызываете объектную модель приложения для выполнения различных задач в этом приложении. С помощью Access и других приложений Microsoft Office практически все действия, которые можно выполнить вручную с помощью пользовательского интерфейса, также могут выполняться программным способом с помощью автоматизации.

Access предоставляет эту программную функциональность с помощью объектной модели. Объектная модель — это коллекция классов и методов, которые служат аналогами логических компонентов Access. Чтобы получить доступ к объектной модели из Visual C# .NET, можно задать ссылку проекта на библиотеку типов.

Общие задачи автоматизации

Открытие базы данных в Access

При автоматизации Microsoft Access необходимо открыть базу данных, прежде чем выполнять полезные задачи, такие как печать отчетов. Чтобы открыть базу данных в экземпляре Access, который вы автоматизируете, используйте методы OpenCurrentDatabase или OpenAccessProject объекта Application. В Access одновременно может быть открыта только одна база данных. Для работы с другой базой данных можно использовать метод CloseCurrentDatabase перед открытием другой базы данных.

Вы также можете использовать метод System.Runtime.InteropServices.Marshal.BindToMoniker (<путь> к базе данных), чтобы открыть базу данных в экземпляре Access. Если база данных уже открыта в экземпляре Access, BindToMoniker возвращает объект Application этого экземпляра. В противном случае BindToMoniker запускает новый экземпляр Access и открывает указанную базу данных.

OpenCurrentDatabase является предпочтительным методом для открытия базы данных, так как вы указываете экземпляр Access, который вы автоматизируете. Можно также указать аргументы для управления открытием базы данных, например:

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

Чтобы просмотреть или распечатать отчет Access, вызовите метод OpenReport объекта DoCmd. При вызове OpenReport один из передаваемых аргументов определяет, отображается ли отчет на экране или отправляется на принтер:

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

Обратите внимание, что аргумент View определяет, отображается ли отчет в Access или отправляется на принтер. Аргумент WhereCondition может ограничить набор записей отчета, если используется допустимое предложение SQL WHERE (без слова WHERE).) Обратите внимание, что вы можете использовать System.Reflection.Missing.Value, чтобы пропустить необязательные параметры объекта.

При предварительном просмотре отчета обязательно задайте свойство Visible объекта Application, чтобы access был виден на экране. Таким образом, пользователь может просмотреть отчет в окне Access.

Существует другой способ печати отчета или других объектов в базе данных. Используйте метод PrintOut объекта DoCmd. В этом примере вы выбираете отчет с именем Employees в окне базы данных, а затем вызываете PrintOut, чтобы распечатать выбранный объект. Метод PrintOut позволяет указать аргументы, соответствующие диалоговом окне "Печать" в 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
   );

В некоторых случаях для печати отчета может потребоваться использовать методы OpenReport и PrintOut. Предположим, вы хотите распечатать несколько копий отчета "Сотрудники", но только для определенного сотрудника. В этом примере сначала используется OpenReport для открытия отчета "Сотрудники" в режиме предварительной версии с использованием аргумента WhereCondition для ограничения записей определенным сотрудником. Затем printOut используется для печати нескольких копий активного объекта:

// 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 появился объект Printer. Этот объект можно использовать для настройки параметров принтера Access, чем в более ранних версиях Access. В качестве примера использования объекта Printer в Access для печати отчета щелкните номер статьи ниже, чтобы просмотреть статью в базе знаний Майкрософт:

284286 как сбросить изменения объекта Application.Printer

Отображение и изменение формы доступа

Visual C# .NET имеет очень мощные возможности форм. Однако иногда требуется, чтобы пользователь просматривал форму, которая была ранее разработана в Access. Кроме того, у вас может быть форма в базе данных Access, которая предоставляет условия для запроса или отчета, и ее необходимо открыть, прежде чем можно будет просмотреть или распечатать отчет. Чтобы открыть и отобразить форму Access, вызовите метод OpenForm объекта 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
   );

Теперь вы можете изменять элементы управления в форме.

Диалоговые окна "Безопасность доступа"

При автоматизации Access вам может быть предложено ввести имя пользователя или пароль или и то, и другое при попытке открыть базу данных. Если пользователь введет неправильные сведения, в коде произойдет ошибка. Иногда требуется избежать этих диалоговых окон и вместо этого программным способом указать имя пользователя и пароль, чтобы код службы автоматизации не прерывал работу.

В Microsoft Access существует два типа безопасности: базы данных, защищенные паролем, и безопасность на уровне пользователя с помощью файла рабочей группы (System.mdw). Если вы пытаетесь открыть базу данных, защищенную паролем, появится диалоговое окно с запросом на ввод пароля базы данных. Безопасность на уровне пользователя отличается от базы данных, защищенной паролем. При активации безопасности на уровне пользователя в Access отображается диалоговое окно входа с запросом имени пользователя и пароля, прежде чем пользователь сможет открыть любую базу данных в Access.

Диалоговые окна "Предотвращение ввода пароля базы данных"

При открытии базы данных, защищенной паролем, можно избежать этого диалогового окна, указав пароль методу 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
   );

Ниже приведен пример, в котором для oAccess ранее был задан экземпляр Access без открытой базы данных. Этот код предоставляет пароль для базы данных, чтобы избежать диалогового окна:

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 не закрывает базу данных в Access. Он закрывает только подключение DAO к базе данных, выполненной с помощью объекта DBEngine. Подключение DAO больше не требуется после использования метода OpenCurrentDatabase. Обратите внимание на код для освобождения объектов oDB и oDBEngine. Эти объекты необходимо использовать для правильного завершения работы Access после завершения кода.

Диалоговые окна "Предотвращение входа в систему системы безопасности доступа"

Если в Access включена безопасность на уровне пользователя, пользователю будет предложено ввести имя пользователя и пароль в диалоговом окне входа. Имя пользователя и пароль нельзя указать с помощью объектной модели Access. Поэтому, если вы хотите избежать диалогового окна входа в систему при автоматизации Access, необходимо сначала запустить файл Msaccess.exe и указать параметры командной строки /user и /pwd, чтобы указать имя пользователя и пароль. После этого можно использовать GetActiveObject или BindToMoniker для получения объекта Application запущенного экземпляра Access, чтобы затем продолжить работу со службой автоматизации.

Автоматизация среды выполнения доступа

Выпуск Microsoft Office Developer Edition включает средства разработчика Microsoft Office (MOD). С помощью mod разработчики Access могут создавать и распространять приложения Access для пользователей, у которых нет розничной версии Access. Когда пользователь устанавливает приложение Access на компьютере без розничной версии Access, устанавливается версия Access среды выполнения. Среда выполнения Access установлена и зарегистрирована как розничная версия. Исполняемый файл также называется Msaccess.exe. Среда выполнения Access позволяет приложению Access выполняться на клиентском компьютере, но среда выполнения Access не позволяет пользователю разрабатывать новые приложения или изменять проектирование существующих приложений.

Среда выполнения Access должна быть запущена с базой данных. Из-за этого требования, если вы хотите автоматизировать среду выполнения Access, необходимо запустить Msaccess.exe и указать базу данных для открытия. После получения объекта Application с помощью GetActiveObject или BindToMoniker можно автоматизировать среду выполнения Access. Если этот подход не используется при попытке автоматизировать среду выполнения access, при попытке создать экземпляр экземпляра вы получите следующее сообщение об ошибке:

Сбой выполнения сервера System.Runtime.InteropServices.COMException (0x80080005) .

Создание полного примера проекта Visual C# 2005 или Visual C# .NET

Чтобы использовать следующий пошаговый пример, убедитесь, что установлен пример базы данных Northwind. По умолчанию Microsoft Access 2000 устанавливает примеры баз данных по следующему пути:

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

Microsoft Access 2002 использует следующий путь:

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

Microsoft Office Access 2003 использует следующий путь:

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

Чтобы убедиться, что пример базы данных Northwind установлен в Access 2002 или Access 2003, щелкните "Примеры баз данных" в меню "Справка", а затем выберите "Образец базы данных Northwind".

  1. Закройте все запущенные в данный момент экземпляры Access.

  2. Запустите Microsoft Visual Studio .NET.

  3. В меню Файл выберите команду Создать, а затем выберите Проект. Выберите приложение Windows в типах проектов Visual C#. По умолчанию создается Form1.

    Примечание Необходимо изменить код в Visual Studio 2005. По умолчанию Visual C# добавляет одну форму в проект при создании Windows Forms проекта. Форма называется Form1. Два файла, представляющих форму, имеют имена Form1.cs и Form1.designer.cs. Код написан в Файле Form1.cs. Файл Form1.designer.cs — это место, где конструктор Windows Forms записывает код, реализующий все выполняемые действия путем перетаскивания элементов управления с панели элементов.

    Дополнительные сведения о конструкторе Windows Forms в Visual C# 2005 см. на следующем веб-сайте Microsoft Developer Network (MSDN):https://msdn.microsoft.com/en-us/library/ms173077.aspx

  4. Добавьте ссылку на библиотеку объектов Microsoft Access. Для этого выполните следующие действия:

    1. On the Project menu, click Add Reference.
    2. На вкладке COM найдите библиотеку объектов Microsoft Access и нажмите кнопку "Выбрать".

    Примечание В Visual Studio 2005. Не нужно нажать кнопку "Выбрать".

    Примечание Microsoft Office 2003 включает основные сборки взаимодействия (PIA). Microsoft Office XP не включает ЛИЧНЫЕ, но их можно скачать.

  5. В диалоговом окне "Добавление ссылок" нажмите кнопку "ОК", чтобы принять выбранные параметры.

    Примечание Если вы ссылались на библиотеку объектов Access 10.0 и при попытке добавить ссылку вы получаете ошибки.

  6. В меню "Вид" щелкните панель элементов, чтобы отобразить панель элементов.

  7. Добавьте пять элементов управления переключателя и один элемент управления "Кнопка" в Form1.

  8. Выберите все элементы управления переключателя и задайте для свойства Size значение 150,24.

  9. Добавьте обработчики событий для события загрузки формы и события Click элемента управления Button:

    1. В режиме конструктора для Form1.cs дважды щелкните Form1.

      Обработчик события загрузки формы создается и отображается в Файле Form1.cs.

    2. В меню "Вид" щелкните "Конструктор", чтобы перейти в режим конструктора.

    3. Дважды щелкните кнопку Button1.

      Обработчик события Click кнопки создается и отображается в Файле Form1.cs.

  10. В Файле Form1.cs замените приведенный ниже код.

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

    на:

          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. Добавьте следующий код в директивы Using в Form1.cs:

    using System.Runtime.InteropServices;
    using System.Diagnostics;
    using System.Reflection; 
    
  12. Нажмите клавишу F5, чтобы выполнить сборку и запуск программы. Отобразится форма 1.

  13. Нажмите кнопку "Печать отчета" и нажмите кнопку "Перейти!". Процедура Print_Report выводит отчет из базы данных Northwind.

  14. Щелкните "Предварительный просмотр отчета" и нажмите кнопку "Перейти!". Процедура Preview_Report предварительного просмотра отчета из базы данных Northwind. Закройте экземпляр Access, когда будете готовы продолжить.

  15. Нажмите кнопку "Показать форму" и нажмите кнопку "Перейти!". Процедура Show_Form отображает форму диалогового окна "Метки клиента" из базы данных Northwind. Он также задает группу параметров в форме "Конкретная страна" и выбирает "США" в списке. Закройте экземпляр Access, когда будете готовы продолжить.

  16. Нажмите кнопку "Печать отчета (безопасность) и нажмите кнопку "Перейти!". В Print_Report_Security показано, как автоматизировать Access и как избежать появления диалогового окна входа, если включена безопасность на уровне пользователя. В этом примере предположим, что вход по умолчанию задан путем передачи пользователю Администратор с пустым паролем. Затем код выводит отчет в базу данных Northwind.

  17. Щелкните предварительный просмотр отчета (среда выполнения), а затем нажмите кнопку "Перейти!". В Preview_Report_Runtime показано, как автоматизировать среду выполнения Access для предварительного просмотра отчета в базе данных Northwind. Если установлена розничная версия Access, процедура будет работать правильно. Закройте экземпляр Access, когда будете готовы продолжить.

Ссылки

Дополнительные сведения см. на следующем веб-сайте MSDN: Разработка Microsoft Office с помощью Visual Studio https://msdn.microsoft.com/en-us/library/aa188489(office.10).aspxДля получения дополнительных сведений щелкните следующие номера статей, чтобы просмотреть статьи в базе знаний Майкрософт:

317109 Office не завершает работу после автоматизации из клиента Visual Studio .NET

316126 Как использовать Visual C# для автоматизации запущенного экземпляра программы Office