Страницы

четверг, 20 февраля 2014 г.

Пользовательская лента меню Access 2007

Оформление пользовательской ленты меню в MS Access 2007 - задача не такая простая, как в Access 2003. Примеры из руководства к Office на сайте Microsoft содержат ошибки и не срабатывают. Создадим ленту на примере демонстрационной базы данных.



В демо-базе находятся пока одна таблица и одна форма. Тематика – медицина (учет пациентов в больнице). Перейдем к формированию ленты.
1. Путь первый. Создаем ленту с системными рисунками.
Настройки ленты будут храниться в системной таблице – USysRibbons. По умолчанию, системные объекты не видны. Чтобы их включить, переходим Пуск -> Параметры Access -> Текущая база данных. Спускаемся в раздел Переходы и нажимаем кнопку «Параметры переходов». Устанавливаем галочку «Показывать системные объекты».


Сохраняем, закрываем. Создаем новую таблицу с полями:


Необходимо проверить, чтобы имена полей точно совпадали с указанными на рисунке. Поле ID – ключевое.
Сохраняем таблицу под именем USysRibbons.
Вот такая получилась база данных.


Что как бы подразумевается в этой базе. Справочник пациентов, справочник МКБ (это международная классификация болезней), документы госпитализации и выписки, отчет по статистике. На каждый объект (справочник и документ) должна быть форма. На каждую форму и отчет должен быть макрос (или функция в модуле). Создать макрос легко – в разделе «Создание» нажать кнопку «Макрос» выбрать из выпадающего меню «ОткрытьФорму» или «ОткрытьОтчет», затем в аргументах выбрать название формы или отчета.
Заполним таблицу с настройками ленты. В поле RibbonName запишем название нашей будущей ленты, допустим, MedStat.
В поле RibbonXml введем текст:
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
  <ribbon startFromScratch="true">
    <tabs>
       <tab id="tab1" label="Статистика" visible="true">
        <group id="db1" label="Справочники">
          <button id="frm1" size="large" label="Пациенты" screentip="Пациенты" supertip="Пациенты" 
imageMso="RecordsMoreRecordsMenu" onAction="mPatient" />
<button id="frm2" size="large" label="Справочник МКБ" screentip="Справочник МКБ" supertip="Справочник 
МКБ" imageMso="SourceControlShowHistory" onAction="mMKB" />
        </group>
<group id="db2" label="Документы">
<button id="frm3" size="large" label="Госпитализация" screentip="Госпитализация" supertip="Госпитализация" 
imageMso="AccessListContacts" onAction="mHosp" />
<button id="frm4" size="large" label="Выписка" screentip="Выписка" supertip="Выписка" 
imageMso="ViewsReportView" onAction="mRecovery" />
                </group>
<group id="db3" label="Отчеты">
<button id="frm5" size="large" label="Статистика" screentip="Статистика" supertip="Статистика" 
imageMso="FilePrintPreview" onAction="mStatistics" />
                </group>
      </tab>
    </tabs>
  </ribbon>
</customUI>
Пояснения по тексту:
Строчка ribbon startFromScratch="true" показывает, что мы создаем свою ленту «с нуля», то есть остальных акцессовских менюшек не будет.
Затем описываем вкладки “tabs”. У каждой пишем название и id. Затем идут группы кнопок – Справочники, Документы и Отчеты. Затем описываем каждую кнопку, в параметре OnAction пишем название макроса, отвечающего за это действие. imageMso – это рисунок на кнопке. В этом варианте мы берем системные рисунки. Их можно посмотреть, если открыть Пуск -> Параметры Access -> Настройка. Видим список команд, выбираем из поля со списком пункт «Все команды» и ищем подходящий по смыслу значок. Если на строчку навести курсор, то всплывет строчка, в которой видно название рисунка (imageMso)


Вот его и указываем.
После ввода данных идем в параметры Access -> Текущая база данных и в параметрах ленты указываем нашу ленту


Если ее в списке нет, то базу нужно закрыть, снова открыть и выбрать ленту. И еще не забываем убрать галочку «Область переходов». Затем снова закрываем и открываем базу. Результат


2. Путь второй. Лента с пользовательскими рисунками
Как быть, если хочется, чтобы рисунки на кнопках были свои, подходящие к теме?
Скачаем набор иконок (или нарисуем) для своей базы. Все картинки нужно перевести в формат bmp, а то в итоге получится ошибка 481 – invalid picture, короче, неверный формат рисунка.
Закрываем базу, зажимаем кнопку Shift и, держа ее нажатой, запускаем базу снова. Появляется стандартное меню Access.
Здесь у нас опять распутье – можно загружать рисунки из папки на диске, можно хранить в базе данных. Первый способ предполагает постоянное расположение рисунков в одном месте и копирование их вместе с базой. Вместо ImageMso=”идентификатор” нужно писать
 getImage="onGetImage"
И еще нужно создать функцию VBA
Function onGetImage(control As IRibbonControl, ByRef image)         
    Select Case control.ID
    Case "myControl":
        Set image = LoadPicture("c:\images\MyImage.bmp")
    End Select
End Function
Лучше выбрать второй способ и хранить рисунки в базе данных. Но тут необходимо создать еще три объекта – таблицу для хранения рисунков, форму для их выбора и функцию VBA.
Есть два варианта хранения рисунков – в одной записи все рисунки и в каждой записи по рисунку. В первом случае код проще, но масштабируемость хуже. Если в базе много рисунков, возникнут сложности. Поэтому сразу выбираем второй вариант, потому что код все равно готовый и придумывать не нужно.
Создаем системную таблицу USysRibbonImages с полями:
ControlId – текстовое (идентификатор рисунка) – ключевое.
Images – вложение (Attachment) – один или несколько рисунков
Description – текстовое (описание).
Сейчас создаем форму. Выделяем эту таблицу, переходим на вкладку Создание и нажимаем кнопку «Форма». Сохраняем форму с тем же именем.
Вносим все нужные картинки, записывая для каждой уникальный идентификатор (такой же, как и идентификатор кнопки, например, frm1, если взять мой пример).
Создаем модуль в редакторе Visual Basic, в модуле пишем функцию
Public Function OnGetImage(control As IRibbonControl, ByRef image)
    Static frmRibbonImages As Form
    Static rsForm As DAO.Recordset2
    Dim rsAttachments As DAO.Recordset2
    If frmRibbonImages Is Nothing Then
        DoCmd.OpenForm "USysRibbonImages", WindowMode:=acHidden
        Set frmRibbonImages = Forms("USysRibbonImages")
        Set rsForm = frmRibbonImages.Recordset
    End If
   
    rsForm.FindFirst "ControlId='" & control.Id & "'"
    If rsForm.NoMatch Then
        ' No image found
        Set image = Nothing
    Else
        Set image = frmRibbonImages.Images.PictureDisp
    End If
End Function
Пояснение. Скрыто открывается форма с рисунками,  определяется ее RecordSet. В этом RS по полю идентификатора ищется нужный рисунок. Если такой рисунок найден, то он присваивается по ссылке параметру Images.
Если приложение выдает ошибку, что какой-то объект not defined, то, возможно, не подключена библиотека с компонентом IRibbonControl. Нужно зайти в меню Tools -> References и поставить там галочку в строке Microsoft Office


Сохраняем. Сейчас нужно изменить таблицу с параметрами ленты. В поле RibbonXml вместо ImageMso пишем
getImage="OnGetImage"
То есть, например, получится такая строчка для первой кнопки:
button id="frm1" size="large" label="Пациенты" screentip="Пациенты" supertip="Пациенты" getImage="OnGetImage" onAction="mPatient" />
Сохраняем, перезапускаем базу. Если все нормально, то нужно еще загрузиться с шифтом и убрать из доступа системные объекты, а то мало ли пользователь доберется.
Вот итоговый результат:


Ну, офисные рисунки выглядят получше, да еще их довольно много, так что можно обойтись и первым способом. Тут и делать полегче, и база меньше весит. Но можно подготовить хорошие иконки, необычные, под свою базу, будет оригинально во втором варианте. В общем, кому что нравится.
С лентой можно связать кучу всяких функций, будет лучше, чем кнопочная форма. Или можно запускать отчет с параметрами прямо из ленты, без дополнительной формы.
Есть к чему стремиться.