Logo CitForum CITForum на CD Форумы Газета Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

22.05.2012

Google
WWW CITForum.ru
2004 г.

Проблемы отчетов в ACCESS

Сергей Гущенко, Издательский Дом "КОМИЗДАТ"

Важным элементом программ работы с базами данных является механизм "отчетов". Так как структура баз может быть достаточно сложной, для реализации таких программ недостаточно знать основные возможности "конструктора отчетов". Может потребоваться знание ряда слабо документированных функций и технологических приемов

Выходные документы в СУБД проектируются с помощью механизма отчетов. В MS Access этот механизм имеет массу возможностей, позволяющих создавать выходные документы без обращения к программированию на встроенном языке VBA. Однако не все задачи можно решить таким путем.

Рассмотрим пример. Допустим, есть таблица "TELEFKOD" телефонных кодов с 528-ю записями, начало которой имеет следующий вид:

NPP GOROD KOD_TEL OBLAST
1 Авдеевка 06236 Донецкая
2 Акимовка 06131 Запорожская
3 Александрия 05235 Кировоградская
4 Александровка 06269 Донецкая
5 Александровка 05269 Кировоградская
6 Алушта 06560 Крым

Рис. 1. Вид отчета в Конструкторе

Причем поле "NPP" имеет тип Счетчик (Длинное целое), особенность которого состоит в следующем: при удалении записи в этом поле удаляется и значение, которое больше повторяться не будет. В результате перечень порядковых номеров может не совпасть с перечнем значений в этом поле.

В качестве выходного документа для этой таблицы подготовлен несложный отчет, вид которого в Конструкторе представлен на рис. 1.

Рис. 2. Вид окна свойств Примечания отчета

В этом отчете названия колонок (шапка таблицы) размещены в верхнем колонтитуле, в качестве номера по порядку используется поле "NPP", в нижнем колонтитуле указывается номер страницы и добавлено Примечание отчета с количеством выводимых записей и примером подписей. Модуль класса пустой (то есть никаких программных кодов на языке VBA нет). Распечатывается такой отчет без проблем. Но могут возникнуть претензии к размещению Примечания. По умолчанию его свойство Не разрывать имеет значение "Да". (рис. 2).

Это означает: если всё Примечание не помещается на последней странице строк с данными, то оно будет целиком перенесено на следующую. Но не всегда такое решение допустимо - особенно если печатается финансовый документ. Поэтому можно поменять значение этого свойства на "Нет" - тогда Примечание будет начинаться сразу после вывода последней записи. Это решает рассматриваемую проблему, но не до конца. Может возникнуть ситуация, когда одна подпись (например, Директора) окажется на одной странице (последней с данными), а другая перенесется на следующую,- тоже плохо. Более приемлемым решением в этом случае - с небольшой высотой Примечания - было бы его размещение полностью на отдельной странице, но так, чтобы к нему сверху автоматически добавлялись несколько последних строк с данными. И вот тут без обращения к VBA уже не обойтись. Вариантом решения этой задачи может оказаться следующий текст Модуля класса с кодами обработки событий:

Option Compare Database
Option Explicit
Dim I1 As Integer, KolZap As Integer, KolZ As Integer
Dim dd As Database, zap As Recordset,

Private Sub Report_NoData (Cancel As Integer)
MsgBox (" А нету записей!")
Cancel = True
End Sub

Private Sub Report_Open (Cancel As Integer)
Set dd = CurrentDb
Set zap = dd. OpenRecordset (" TELEFKOD", dbOpenDynaset)
If Not zap. BOF Then
zap. MoveLast
KolZap = zap. RecordCount
End If
zap. Close
KolZ = 0
End Sub

Private Sub ВерхнийКолонтитул_Format 
            (Cancel As Integer, FormatCount As Integer)
Me![EndStr1]. Visible = False
I1 = 0
End Sub

Private Sub ОбластьДанных_Format 
            (Cancel As Integer, FormatCount As Integer)
I1 = I1 + 1
KolZ = Me. CurrentRecord
If I1 > 39 Then
If KolZap - KolZ < 3 Then
Me![EndStr1]. Visible = True
End If
End If
End Sub

Во-первых, здесь по ходу дела задействовано интересное свойство Report_NoData - обработка ситуации, когда в таблице-источнике данных нет записей. Текст процедуры почти стандартен, строка Cancel = True приводит к прекращению печати отчета.

Рис. 3. Размещение элемента управления Конец страницы в Области данных

Во-вторых, в Области данных установлен элемент управления Конец страницы (рис. 3), действие которого контролируется в модуле класса.

При форматировании каждой новой страницы его "видимость" отключается (Me![EndStr1]. Visible = False). Включается же при форматировании Области данных - при наступлении определенного условия, которое состоит из двух частей. Первая контролирует область листа, на котором Примечание уже не может разместиться полностью. В данном отчете опытным путем определено, что такой момент возникает после печати 39-й строки (If I1 > 39 Then). Целочисленной переменной, в которой учитывается номер печатаемой строки, является I1. Рис. 4. Пример вывода Примечания отчета на новой странице вместе с несколькими (двумя) последними строками данных При форматировании верхнего колонтитула она обнуляется, а при форматировании каждой новой строки данных ее значение увеличивается на 1. Но этого мало - требуется еще определить, что выводятся последние строки. Это делается через две другие переменные: KolZ, в которую заносится номер текущей записи в печатаемой таблице (KolZ = Me. CurrentRecord) и KolZap, в которой хранится общее количество записей, рассчитываемое при открытии отчета (KolZap = zap. RecordCount). В конечном итоге, если возникает ситуация печати последних двух записей в зоне листа, где уже не может полностью разместиться Примечание, то они печатаются вместе с ним на следующей странице (рис. 4).

Рис. 5. Настройка в "Конструкторе" поля для отображения порядкового номера Рис. 6. Результат отображения "Отчета" (рис. 5) при просмотре

Но в этом примере есть и ошибка - итоговое поле для подсчета количества записей в Примечании отчета насчитало 528 записей. А последний Номер по порядку значится как "529". Такая ситуация возможна в случае, если в качестве номера по порядку выводится поле, имеющее тип Счетчик, а в процессе заполнения таблицы были выполнены удаления записей (в примере была удалена одна запись). Поэтому в качестве поля порядкового номера в отчете лучше использовать свободное поле, не связанное с исходной таблицей. В качестве данных для такого поля надо установить значение "=1" и указать вариант Для всего в параметре Сумма с накоплением (рис. 5 - вид в Конструкторе и рис. 6 - при предварительном просмотре).

Рис. 7. Добавление поля порядкового номера на странице (в Конструкторе)

Может возникнуть необходимость нумерации не только в границах всего отчета, но и постранично. Это также делается через свободное поле (рис. 7), но его заполнение выполняется в модуле класса. Под него объявляется новая переменная, например: Dim NStrP As Integer. Она должна обнуляться при форматировании верхнего колонтитула и заполняться при форматировании области данных, например:



Private Sub ВерхнийКолонтитул_Format 
            (Cancel As Integer, FormatCount As Integer)
…..
NStrP = 0
End Sub

Private Sub ОбластьДанных_Format 
            (Cancel As Integer, FormatCount As Integer)
…..
NStrP = NStrP + 1
Me![NSTR1] = NStrP
End Sub
Рис. 8. Вид диалогового окна Сортировка и группировка Рис. 9. Вид Отчета с группировкой по областям и с сортировкой по городам внутри "группы"

Последним вариантом учета строк рассмотрим нумерацию в группе. Access позволяет сортировать и группировать данные прямо при выводе. Эти настройки выполняются в Конструкторе через диалоговое окно Сортировка и группировка (вызывается по команде меню Вид) - рис. 8. Для создания группировки по какому-либо полю этого окна, его (поле) надо выбрать в списке (в примере - поле OBLAST) и указать "Да" в параметре Заголовок группы. Здесь же можно установить сортировку для других полей без группировки по ним (в примере - по полю GOROD). Вывод порядкового номера в группе производится в "свободном" поле, в параметре Данные которого указано "=1", но Сумма с накоплением установлена Для группы. Фрагмент результата показан на рис. 9.

Следующей проблемой может оказаться размещение в нижнем колонтитуле промежуточных сумм по какому-либо полю. Такая ситуация часто возникает в финансовых документах - например, при распечатке ведомости на зарплату. На первый взгляд, сделать это можно по технологии, рассмотренной ранее: объявляется переменная, обнуляется при форматировании верхнего колонтитула и заполняется при форматировании области данных. Но поскольку результат должен быть занесен в "свободное" поле, размещенное в другом разделе (в Нижнем колонтитуле), сумма окажется неправильной - ведь процесс форматирования некоторых разделов "отчетов" в Access может повторяться!!! Это является особенностью технологии подготовки "отчетов" - нужно помнить об этом при программировании. В частности, в рассматриваемом примере заполнение переменной для промежуточной суммы (SumStr) можно выполнять не при форматировании области данных, а при отработке свойства печати области данных (ОбластьДанных_Print), в которой можно проконтролировать ситуацию - будет печататься лист с этими данными или нет. И именно в зависимости от результатов контроля должно быть заполнено поле, расположенное в нижнем колонтитуле. Допустим, оно имеет имя SumS, а переменная, в которой накапливается значение на странице,- SumStr. Тогда текст кода подобной процедуры будет иметь следующий вид:

Private Sub ОбластьДанных_Print 
            (Cancel As Integer, PrintCount As Integer)
'PrintCount = 0 - страница не печатается, 
'           = 1 - будет печататься

SumStr = SumStr + NStrP
If PrintCount = 1 Then Me![SumS] = SumStr
End Sub
Рис. 10. Пример вывода Отчета с Подчиненным отчетом в разделе Примечания отчета (и с неправильным заполнением поля № строки на странице в Подчиненном отчете - значения "55, 56 и т.д.")

Подобная же ситуация может возникнуть при попытке использовать Подчиненный отчет, который чаще всего вставляется в Примечание отчета или в Примечание группы. Если в нем требуется указывать какое-то расчетное значение (например, тот же номер на странице), то оно может оказаться неправильным, так как такой отчет будет форматироваться несколько раз (рис. 10).

Для решения проблемы команду заполнения поля № строки на странице Подчиненного отчета надо переместить из обработки события Форматирования в обработку события Печать раздела Область данных, например:

Private Sub ОбластьДанных_Print 
            (Cancel As Integer, PrintCount As Integer)
NStrP = NStrP + 1
Me![NSTR1] = NStrP
SumStr = SumStr + NStrP
If PrintCount = 1 Then Me![SumS] = SumStr
End Sub

Подписка на новости CITForum.ru

Новые публикации:

7 июля

  • Управление параллелизмом с низкими накладными расходами для разделенных баз данных в основной памяти

  • Рекурсивные запросы в Oracle

  • Жесткий диск WD10EARS с сектором 4 КБ. Подготовка к эксплуатации в Linux.

    Обзоры журнала Computer:

    Газета:

  • Московские пробки - исследование IBM

  • От Osborne до iPad: эволюция портативных компьютеров

    19 мая

  • Прозрачный механизм удаленного обслуживания системных вызовов

  • Система моделирования Grid: реализация и возможности применения

    Газета:

    Майкл Стоунбрейкер:

  • Ошибки в системах баз данных, согласованность "в конечном счете" и теорема CAP

  • Дискуссия по поводу "NoSQL" не имеет никакого отношения к SQL

    29 апреля

  • Материалы конференции "Корпоративные Базы Данных-2010"

  • Разные облики технологии баз данных (отчет о конференции)

    14 апреля

  • MapReduce: внутри, снаружи или сбоку от параллельных СУБД?

  • Научные вызовы технологиям СУБД

    Обзоры журнала Computer:

    31 марта

  • Рационализация согласованности в "облаках": не платите за то, что вам не требуется

  • Взаимные блокировки в Oracle

  • Архитектура среды тестирования на основе моделей, построенная на базе компонентных технологий

  • Объектное представление XML-документов

    Газета:

  • Microsoft для российских разработчиков: практика с элементами фундаментальности

    10 марта

  • HadoopDB: архитектурный гибрид технологий MapReduce и СУБД для аналитических рабочих нагрузок

  • Классификация OLAP-систем вида xOLAP

  • BGP. Три внешних канала. Балансировка исходящего и входящего трафиков

    Газета:

  • Что мы знаем об iPhone 4G?

    17 февраля

  • MapReduce и параллельные СУБД: друзья или враги?

  • Объектно-ориентированное программирование в ограничениях: новый подход на основе декларативных языков моделирования данных

  • Системологический подход к декомпозиции в объектно-ориентированном анализе и проектировании программного обеспечения

    Газета:

  • Эволюция Wine

    3 февраля

  • Дом на песке

  • Реальное переосмысление "формальных методов"

  • Интервью с Найджелом Пендзом

    Газета:

  • iPad. Первый взгляд на долгожданный планшет от Apple

  • Я не верю в iPad

    20 января

  • SQL/MapReduce: практический подход к поддержке самоописываемых, полиморфных и параллелизуемых функций, определяемых пользователями

  • Данные на лету: как технология потокового SQL помогает преодолеть кризис

    Обзоры журнала Computer:

    2 декабря

  • Сергей Кузнецов. Год эпохи перемен в технологии баз данных

    18 ноября

  • Генерация тестовых программ для подсистемы управления памятью микропроцессора

  • Сравнительный анализ современных технологий разработки тестов для моделей аппаратного обеспечения

    Все публикации >>>


  • IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

    Информация для рекламодателей PR-акции, размещение рекламы — тел. +7 495 6608306, ICQ 232284597 Пресс-релизы — pr@citforum.ru
    Послать комментарий
    Информация для авторов

    Редакция раздаёт котят!

    Rambler's Top100 TopList liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня This Web server launched on February 24, 1997
    Copyright © 1997-2000 CIT, © 2001-2009 CIT Forum
    Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...