Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Microsoft Access - программирование и готовые решения


Выпуск 16. Access Rapid Start - конструктор приложений в Access

Подписка: "Access 2003/2010 - программирование и готовые решения"
Дата: 20.08.2012
Автор: Парусников Алексей
Сайт: http://www.accessoft.ru под редакцией с http://www.leadersoft.ru
Загрузка: ARS
Получить ключ: Key_ARS

В данном цикле статей рассказывается о работе с конструктором приложений Access - Access Rapid Start. Дополнительные вопросы по этой теме Вы можете задать на форуме. Вы так же можете заказать персональную консультацию или перенос вашего проекта в ARS, связаться с автором для решения вопросов о создании программы на базе ARS - в последнем случае вы кроме готового продукта получите возможность самостоятельно его развивать.


    Данная статья ориентирована на начинающих разработчиков Access, желающих более углубленно изучить возможности программирования в Access и сделать свои приложения более профессиональными.
Особенности проектирования форм в ARS для работы с SQL Server

     Для создания приложений для работы с MS SQL Server существует специальный тип проекта, разработанный Microsoft – ADP. Так же существует мастер, который преобразует mdb приложения в ADP. Однако только в самых простых случаях можно запустив мастера автоматические получить приложение, способное работать с SQL Serever. Дело в том, что принципы работы с данными в SQL Server и Access отличаются и потребуют, как говорят профессиональные разработчики некоторой «перестройки мозгов». Этим мы и займемся в данной статье.

     Хотя существует готовый, «заточенный» под MS SQL Server формат ADP, мы все же применили немного другой подход при создании ARS проектов SQL. Дело в том, что у ADP есть недостатки. Основные из них: жесткая привязка исключительно к MS SQL Server и невозможность создания локальных таблиц на клиенте. Поэтому в ARS используется другой вариант: mdb + ADO, лишенный этих недостатков. Однако разработчик Access и здесь столкнется с трудностями, связанными с тем, что теперь ему придется некоторые вещи, реализуемые ранее в Access «автоматически», делать самому.

     Первое, что нужно четко уяснить начинающему разработчику проектов SQL Server – в запросах придется отказаться от ссылок на объекты приложения, обычно это поля форм или функции общего модуля. Ведь данные теперь жестко отделены от интерфейса и вся обработка происходит на сервере, где нет никаких Forms. Поэтому ссылки в запросах типа:

Where Zak_ID = Forms!frm_Zakaz!Zak_ID

работать не будут. Придется использовать хранимые процедуры с передачей параметров либо собирать строку запроса в VBA. По тем же причинам придется отказаться от автоматического подсчета итогов в примечании форм, используя свойство контрола Данные. То есть теперь запись в нем типа:

=Sum(Kol*CenaTovar)

     так же ничего не будет считать автоматически – это придется делать специальной функцией. Раньше это все работало потому, что в объектной модели DAO и Jet имелись объекты как данных так и приложения, что и позволяло использовать ссылки на то и другое. Ведь Access относится к инструментам быстрого проектирования (Rapid), в котором разработчики постарались максимально облегчить жизнь начинающим, заботливо скрыв от них все нюансы, связанные с разработкой приложений баз данных. Теперь настала пора узнать, что же они скрыли и научиться самому управлять процессом. То есть в принципе это можно воспринимать как переход от езды на автомате на ручную коробку передач. Автомат конечно удобен, но именно потому, что он автомат, он и не даст сделать то, что можно сделать на ручнике. Так что начинаем переучиваться с летчика на вертолетчика.

     Рассмотрим код формы frm_Zakaz и разберем отличия, касаемые работы с ADO. В коде использованы ссылки на SQLVersion только в качестве примера, чтобы показать как «там» и «тут». Вы же при создании своего проекта используйте один из вариантов.

Private Sub Form_Open(Cancel As Integer)
Dim rs As ADODB.Recordset
Dim strSQL As String, KodRec As String

On Error GoTo Err_
     'Вызов класса формы
     Set frm = fcClassCreateForm(Me.Form, _
          "frm_ZakazFind", _
          True, _
          Null, _
     Cancel)

     'Если класс вернул Cancel=-1, то завершаем процедуру
     If Cancel = -1 Then Exit Sub
     'трансформация формы
     Call TransForm(Me)

     If SQLVersion = "mdb_2003" Then
          Me.RecordSource = "tab_Zakaz"
     Else
          KodRec = Split(OpenArgs, "|")(0)
          Set rs = New ADODB.Recordset
          If KodRec = "add" Then

               'Новая запись
               rs.Open "SELECT * FROM tab_Zakaz WHERE(1 = 0)", con, adOpenForwardOnly, adLockOptimistic, adCmdText
          Else

               'Основной рекордсет для формы
               rs.Open "SELECT * FROM tab_Zakaz WHERE (Zak_ID=" & KodRec & ")", con, adOpenStatic, adLockOptimistic, adCmdText
          End If
          Set Me.Recordset = rs
          rs.Close
          Set rs = Nothing
          Set Me!Oprt_ID.Recordset = con.Execute("SELECT User_ID, Login FROM " & sPrefixTabA & "Users ORDER BY Login")
     End If

     If Me.DataEntry Then
          cmd_Apply.Caption = "Добавить"
          Me.Caption = Me.Caption & " - добавление"
     Else
          cmd_Apply.Caption = "Применить"
     End If
Exit Sub

Err_:
     Call ErrorBases(Err)
     Cancel = -1
End Sub

     Поставьте себе за правило ВСЕГДА, во всех функциях и процедурах делать свой обработчик ошибок. В ARS это блок:

On Error GoTo Err_


Exit Sub

Err_:
Call ErrorBases(Err)

     Иначе в случае ошибки компилятор будет сбрасывать все глобальные переменные, в том числе и коннект к серверу (con). Если такое все же случится – просто запустите макрос AutoExec, который обновит подключение.

     Далее обратим внимание, что в зависимости от значения первого параметра KodRec («add» или код записи) мы либо открываем форму на пустой записи, либо на одной, отфильтрованной по коду. Второе делается из соображений оптимизации загрузки. Обычно, начинающие разработчики перейдя на ADP просто цепляют к форме таблицу в конструкторе, как они это делали в mdb проектах, и открывают форму с фильтром в команде открытия Docmd.OpenForm. В итоге при открытии на клиента качается вся таблица, затем фильтруется нужная запись. Если в таблице будет миллион записей – серьезные тормоза обеспечены. Поэтому мы и сделали фильтрацию данных на сервере, а не клиенте.

     Так как линков к таблицам у нас нет, то и цеплять к списку Oprt_ID нечего. Поэтому используется следующий вариант получения для него источника строк:

Set Me!Oprt_ID.Recordset = con.Execute("текст запроса")

     Исходя из тех же соображений оптимизации, подчиненная форма получается свой источник не в виде всей таблицы, а отфильтрованного набора данных. Обычно начинающие разработчики mdb/adp просто цепляют таблицу к подчиненной форме, а затем через ее свойства «Основные/Подчиненные поля» устанавливают фильтр, тем более что таким образом можно не заботиться о заполнении ключевого поля – Access сам это сделает. Однако при таком способе происходит все та же ненужная перекачка/фильтрация данных. Поэтому лучше сделать по другому – присвоить подчиненной фильтрованный источник и значение по умолчанию для ключа.

If SQLVersion = "mdb_2003" Then
     Set frm_sub.Form.Recordset = CurrentDb.OpenRecordset("SELECT * FROM tab_Zakaz_date WHERE Zak_ID=" & Me!Zak_ID, dbOpenDynaset)
Else
     Set rs_Sub = New ADODB.Recordset
     If rs_Sub.State = 1 Then rs_Sub.Close
     rs_Sub.Open "SELECT * FROM tab_Zakaz_date WHERE Zak_ID=" & Me!Zak_ID, con, adOpenForwardOnly, adLockOptimistic, adCmdText
     Set Me.frm_sub.Form.Recordset = rs_Sub
     Me.frm_sub.Form.UniqueTable = "tab_Zakaz_date"
End If

     А вот для ключа подчиненной формы уже можно сдать ссылку (см. поле формы Zak_ID):

=[Формы]![frm_Zakaz]![Zak_ID]

     Этот способ хорош и в Access, и в SQL проектах. Только в Access нужно использовать DAO, а в SQL – ADO подключение. Кроме того, в SQL проекте иногда еще нужно указать уникальную таблицу (UniqueTable), если источник данных формы состоит более чем из одной таблицы, а так же программно делать синхронизацию (Resync) данных между клиентом и сервером. Но это отдельная тема, по которой будет отдельная статья. В данном же случае можно было и не указывать UniqueTable – форма Access автоматически сделает синхронизацию при переходе на следующую запись.

     Теперь заглянем в модуль формы frm_Zakaz_sub – тут тоже есть нюансы, связанные с подключением к серверу через ADO.

     Тут мы видим уже понятную из прежних пояснений привязку источника к списку через con. Но кроме этого есть целый блок, касаемый только приложений SQL:

Function funSumma()
On Error GoTo Err_
     If Me.Recordset Is Nothing Then Exit Function
     Me!SumSumma = Nz(SLookup("Select Sum(ISNULL(KolVo,0)*ISNULL(CenaTovar,0)) From tab_Zakaz_date Where Zak_ID=" & Me.Parent!Zak_ID), 0)
Exit Function

Err_:
     Call ErrorBases(Err)
End Function

Private Sub Form_AfterDelConfirm(Status As Integer)
On Error GoTo Err_
     If SQLVersion <> "mdb_2003" Then
          Call funSumma
     End If
Exit Sub

Err_:
     Call ErrorBases(Err)
End Sub

Private Sub Form_Current()
On Error GoTo Err_
     If SQLVersion <> "mdb_2003" Then
          Call funSumma
     End If
Exit Sub

Err_:
     Call ErrorBases(Err)
End Sub

     Функция funSumma служит для расчета итоговых значений для подчиненной формы. В проектах Access это делалось при помощи свойства контрола Данные. Но так как теперь данные лежат на сервере, то пришлось расчет делать самостоятельно. Причем функцию нужно обязательно повесить на события Текущая запись и После удаления – чтобы итоги оперативно пересчитывались.

     Как видим, пока что ничего особо сложного при создании простых форм в SQL проекте, работающем через ADO нет, за исключением некоторых разобранных выше нюансов. А в поисковой форме править вообще ничего не нужно, разве что запрос-источник (a_QrySource), да и то не всегда. Это связано с особенностями синтаксиса в T-SQL, о которых мы поговорим в одной следующих статей.


Полезные ссылки

Интернет магазин от Leadersoft.ru
В этом магазине Вы можете купить не только готовое программное обеспечение для бизнеса, а также найти компактные решения для самостоятельного проектирования на Microsoft Access, SQL Server или ASP.NET

В избранное