Объектно-ориентированный режим вывода отчетов в Visual FoxPro предлагает неограниченные возможности для вывода отчетов используя объекты ReportListener. Приложение Вывода Отчетов предлагает удобный механизм помощи для совместного использования с другими пользователями средств вывода отчетов.
Этот раздел предлагает некоторые инструкции для соглашения о разработке и распространению объектов, расширяющих систему отчетов.
Соглашение по проектированию расширений системы отчетов
- Определяет, является ли Вашей целью обеспечить новый тип вывода, не доступный из базовых классов, таких как Rich Text или улучшить множество форматов вывода в манере независимости результата вывода.
-
Если целью является улучшение результатов вывода, Ваш объект возможно не должен быть ReportListener, и он не является типом вывода.
Конструкция этого объекта должна поддерживаться как член или вспомогательный объект множества объектов ReportListener. Он должен быть небольших размеров и поддерживать одну цель для эффективности работы. Конструкция ReportListener должна принимать улучшения последовательным добавлением коллекции этих объектов.
В противоположность этому, если Вашей целью является новый тип вывода результата, это должен быть объект, порожденный от класса ReportListener, и таким образом он может быть успешным партнером обработчика отчетов. Он является хорошим кандидатом для механизма цепи ответственности, представленным ReportListener Base Foundation Class. Этот механизм позволяет Вам генерировать множество типов вывода при прогоне отчета.
Замечание Вы можете использовать оба метода совместно. Зарегистрируйте Ваши расширенные объекты для объекта ReportListener и направьте их действие на вывод до посылки событий на приемники. Каждый приемник может назначить какие расширения возможностей могут быть использованы для его типа вывода. Пример включен в этот раздел.
- Определите Вашу стратегию обработки ошибок и опубликуйте Ваши требования к объекту в этом приветствии.
- Объекты ReportListener взаимодействует с обработчиком отчетов (Report Engine) уникальным образом, потому что они обрабатывают коды пользователя в течение одной команды Visual FoxPro. Они также частично взаимодействуют с другим кодом пользователя в методах окружения данных и функциях пользователя (UDFs), включенных в файл отчета или наклейки.
Существуют различные способы обработки команды REPORT FORM, которые не совсем правильны. Смотри Обработка ошибок во время прогона отчета для информации и предложений. Когда Вы выберите стратегию будьте уверены, что пользователи вашего класса ReportListener имеют правильную информацию для обеспечения правильной очистки в случае возникновения ошибки.
- Разместите требуемые временные таблицы объекта ReportListener в специальной сессии для этой цели.
-
Свойство FRXDataSession объекта ReportListener обеспечивает вас информацией, которая Вам необходима для доступа к специальной копии файла описания отчета (.frx) во время прогона отчета. Если Вашему ReportListener требуются для работы дополнительные курсоры, используйте эту защищенную сессию даже тогда, когда сессия данных, содержащая данные, на которых базируется отчет представляется Свойством CurrentDataSession объекта ReportListener . Эта стратегия дает уверенность в том, что Вы не трогаете "реальную" сессию данных пользователя и очищаете эти временные файлы после завершения прогона отчета.
Внимание Убедитесь, что Вы переключились на соответствующую сессию данных во время прогона отчета, когда Вы хотите использовать копию отчета или другие рабочие файлы. Для дополнительной информации см. Команда SET DATASESSION.
Подсказка Например, Объектно-ориентированный отчет, который использует дополнительные курсоры в сессии данных FRXD см. Report XML MemberData Extensions.
- Сделайте различия между Свойством OutputType (Visual FoxPro) объекта ReportListener и Свойством ListenerType в вашем проекте.
- OutputType дает вам значение, с которого Приложение вывода Отчета было вызвано, в то время как ListenerType представляет собственный режим генерации вывода, обеспечиваемый базовым классом ReportListener.
Класс, порожденный от класса ReportListener, может быть зарегистрирован для управления множеством различных значений OutputType в таблице регистрации Приложения Вывода Отчета, тогда как базовый класс ReportListener поддерживает различные значения ListenerType. Однако, один OutputType может также поддерживать различные базовые классы и собственный вывод поддержкой множества значений ListenerType.
Пример: Влияние множества эффектов на множество типов вывода
Этот пример создает класс FXListener, порожденный от класса ReportListener, который увеличивает возможности ReportListener Base Foundation класса по управлению цепью приемника. Этот класс обрабатывает все события класса ReportListener до запроса цепи приемника. Все приемники в цепи получают дополнительные возможности от набора эффектов и обрабатывают результаты всех используемых эффектов по мере возможности использования изменений.
FXListener поддерживает коллекцию объектов "эффект". FXListener требует, чтобы все объекты "эффект" являлись экземплярами классов, порожденных от любых базовых классов Visual FoxPro и устанавливали следующий простой интерфейс:
Копировать код | |
---|---|
DEFINE CLASS FX As Custom && any base class
* Требуемый интерфейс:
PROCEDURE ApplyFX(toListener, tcProgram,;
tP1, tP2, tP3, tP4, tP5, tP6,;
tP7, tP8, tP9, tP10, tP11, tP12)
* FXListener передает ссылку на себя как toListener,
* PROGRAM() как tcProgram и
* все параметры ReportListener как tP1 до tP12,
* для каждого события ReportListener во время прогона.
* Параметры от tP1 до tP12 передаются по ссылке,
* поэтому изменения сделанные объектами effect видны
* классу FXListener и его приемники возвращают из
* этого метода.
ENDPROC
ENDDEFINE |
Вы регистрируете один или более эффектов для прогона отчета, добавляя экземпляры одного или нескольких классов, управляющих эффектами, в коллекцию эффектов объекта, порожденного от класса FXListener. Затем Вы вызываете команду REPORT FORM с выражением OBJECT, ссылающемся на Ваш объект FXListener для получения результата от Ваших эффектов.
Пример ниже включает полный код для класса FXListener и простого класса "effect". Класс "effect" использует функцию UPPER() для всего выводного текста. Пример добавляет экземпляр класса "effect" в коллекцию класса FXListener. Он также назначает два приемника для FXListener (экземпляр ReportListener User Feedback Foundation Class и экземпляр ReportListener HTML Foundation Class) до того, как отчет будет вызван на прогон.
Изменения вывода отчета от использования объектов "effect" отображаются в предварительном просмотре первичного класса ReportListener (экземпляр класса FXListener), также как вывод HTML генерируется объектом приемника класса HTMListener в своей цепи.
Работая одновременно, пользователь, по обратной связи с помощью класса ReportListener User Feedback , объединяет указатели на свойство PrintJobName первичного класса ReportListener, .
Подсказка |
---|
Вывод текста изменяется на верхний регистр в методе Render даже при выполнении события EvaluateContents для лучшей призводительности. Использование Render также дает возможность изменять вывод элементов этикетки (Label layout), также как поле или выражение в отчете. Событие EvaluateContents не появляется для элементов этикетки. |
Если Вы добавили объект "effect", который выполняет изменения фонта атрибутов, используя событие EvaluateContents , Вы увидите результаты этих изменений в предварительном просмотре. Однако, Вы не увидите тот же результат для HTML; класс ReportListener HTML Foundation получает свой фонт атрибутов из элементов, определенных в FRX и не включает динамические изменения, сделанные во время прогона. Хорошо спроектированные классы "effect" учитывают возможности, требования и ограничения различных типов вывода, сгенерированных классом ReportListener.
Для получения других примеров классов "effect" см. Report XML MemberData Extensions.
Копировать код | |
---|---|
#DEFINE FFC_HOME HOME() + "FFC\"
LOCAL loPrimaryRL, loSuccessorRL, loSuccessorRL2
loPrimaryRL = CREATEOBJECT("FXListener")
loSuccessorRL = NEWOBJECT("UpdateListener", ;
FFC_HOME + "_ReportListener.vcx")
loSuccessorRL2 = NEWOBJECT("HTMLListener", ;
FFC_HOME + "_ReportListener.vcx")
WITH loPrimaryRL
.PrintJobName = "Проверка приемника FX (FX Listener Test)"
.QuietMode = .T.
.ListenerType = 1
.FXs.Add(CREATEOBJECT("FXSimple"))
.Successor = loSuccessorRL
ENDWITH
loSuccessorRL.Successor = loSuccessorRL2
loSuccessorRL2.QuietMode = .T.
REPORT FORM ? OBJECT loPrimaryRL
* FXListener,
* "Эффекты использующие класс производный от ReportListener:
DEFINE CLASS FXListener AS _ReportListener OF ;
(FFC_HOME + "_reportListener.vcx")
FXs = NULL
PROCEDURE Init()
THIS.FXs = CREATEOBJECT("Collection")
ENDPROC
PROCEDURE SendFX(tcProgram, ;
tP1, tP2, tP3, tP4, tP5, tP6, tP7, tP8, tP9, tP10, tP11,tP12)
IF (NOT THIS.IsSuccessor) AND THIS.FXs.Count > 0
* Только lead делает эту работу.
* Для того, чтобы
* вызвать этот метод,
* который заканчивается DODEFAULT()
* для каждого события,
* сделайте результаты доступными
* для всех приемников.
LOCAL loFX
FOR EACH loFX IN THIS.FXs FOXOBJECT
loFX.ApplyFX(THIS,tcProgram, ;
@tP1, @tP2, @tP3, @tP4, @tP5, @tP6, ;
@tP7, @tP8, @tP9, @tP10, @tP11, @tP12)
NEXT
ENDIF
ENDPROC
PROCEDURE BeforeReport()
THIS.SendFX(PROGRAM())
NODEFAULT
RETURN DODEFAULT()
ENDPROC
PROCEDURE AfterReport()
THIS.SendFX(PROGRAM())
NODEFAULT
RETURN DODEFAULT()
ENDPROC
PROCEDURE BeforeBand(nBandObjCode, nFRXRecNo)
THIS.SendFX(PROGRAM(),nBandObjCode, nFRXRecNo)
NODEFAULT
RETURN DODEFAULT(nBandObjCode, nFRXRecNo)
ENDPROC
PROCEDURE AfterBand(nBandObjCode, nFRXRecNo)
THIS.SendFX(PROGRAM(),nBandObjCode, nFRXRecNo)
NODEFAULT
RETURN DODEFAULT(nBandObjCode, nFRXRecNo)
ENDPROC
PROCEDURE EvaluateContents(nFRXRecno, oObjProperties)
THIS.SendFX(PROGRAM(),nFRXRecno, oObjProperties)
NODEFAULT
IF (NOT ISNULL(THIS.Successor))
THIS.SetSuccessorDynamicProperties()
THIS.Successor.EvaluateContents(nFRXRecno, oObjProperties)
ENDIF
DODEFAULT(nFRXRecno, oObjProperties)
ENDPROC
PROCEDURE AdjustObjectSize(nFRXRecno, oObjProperties)
THIS.SendFX(PROGRAM(),nFRXRecno, oObjProperties)
NODEFAULT
IF (NOT ISNULL(THIS.Successor))
THIS.SetSuccessorDynamicProperties()
THIS.Successor.AdjustObjectSize(nFRXRecno, oObjProperties)
ENDIF
DODEFAULT(nFRXRecno, oObjProperties)
ENDPROC
PROCEDURE Render(nFRXRecNo,;
nLeft,nTop,nWidth,nHeight,;
nObjectContinuationType, ;
cContentsToBeRendered, GDIPlusImage)
THIS.SendFX(PROGRAM(),nFRXRecNo,;
@nLeft,@nTop,@nWidth,@nHeight,;
@nObjectContinuationType, ;
@cContentsToBeRendered, @GDIPlusImage)
NODEFAULT
RETURN DODEFAULT(nFRXRecNo,;
nLeft,nTop,nWidth,nHeight,;
nObjectContinuationType, ;
cContentsToBeRendered, GDIPlusImage)
ENDPROC
ENDDEFINE
* Пример класса FX, заполняющего контракт на разработку FX
* установкой требуемого интерфейса:
DEFINE CLASS FXSimple AS Custom
PROCEDURE ApplyFX(toListener, tcProgram,;
tP1, tP2, tP3, tP4, tP5, tP6, ;
tP7, tP8, tP9, tP10, tP11, tP12)
IF ATC("Render",tcProgram) > 0
tP7 = UPPER(tP7)
* cContentsToBeRendered
* является 7-ым параметром Render
* Заметьте, что многие изменения свойства
* cContentsToBeRendered в методе Render
* будут требовать использования STRCONV() для
* обеспечения результата в Unicode, хотя это
* простое изменение не требует этого.
ENDIF
ENDPROC
ENDDEFINE
|