Новые подходы к Crystal Reports. Использование Crystal Reports вместе с SQLBase и SQLWindows

Thomas Althammer, Ice Tea Group, LLC

Содержание

В предыдущей статье мы осветили вопросы использования Crystal Reports с SQLWindows. Мы научились вызывать, просматривать и печатать готовые отчеты с помощью Report Designer Component (RDC). Crystal Reports не позволяет непосредственно связываться с SQLBase. В маркетинговых материалах Seagate Software (хотя и под разными именами) описывается единственная возможность связи - только через ODBC. Эта статья дает обзор возможностей бесконфликтного совместного использования указанных средств.

Кое-что об ODBC

Когда вы создаете новый отчет с помощью Seagate Crystal Reports 8, появляется окно просмотра данных, позволяющее вам выбрать источник данных для отчета. Если вы раскроете ветвь ODBC, вы заметите, кроме других, элемент с именем CRGUP (при условии, что Crystal Reports правильно установлен). Этот элемент CRGUP представляет источник данных ODBC для SQLBase, установленный при инсталляции. Вы можете согласиться с тем, что имя несколько устарело, но не тревожьтесь об этом - все остальное достаточно актуально.

В действительности все доступные драйвера ODBC, будь то от Seagate Software или от Centura, происходят от одной компании под именем Merant (раньше Intersolv). Эта компания лицензирует использование своих драйверов ODBC другими компаниями. Для устранения конфликта имен эти драйвера получают уникальное имя для каждого продукта, с которым они поставляются. Если вы инсталлируете драйвер ODBC фирмы Centura, источник данных будет называться "SQLBase", в Crystal Reports его имя будет "CRGUP".

Для более детальной информации откройте контрольную панель и выберите источники данных ODBC. Теперь щелкните на закладке "Drivers" и вы увидите окно, похожее на следующий экранный снимок. Вы можете заметить, что существует четыре подходящих элемента, которые могут иметь дело с SQLBase. Забегая вперед, можно добавить, что имя компании некоторое время назад изменилось с Intersolv на Merant. В списке вы можете увидеть, что за исключением имени компании, CRGUP14.DLL и C2GUP14.DLL кажутся идентичными.

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

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

Источники данных ODBC

ODBC предлагает два режима конфигурирования - системные и пользовательские имена источников данных (DSN - data source name). Первые устанавливаются в реестре машины (в ветви HKEY_LOCAL_MACHINE) и доступны всем пользователям. Вторые - источники данных конкретного пользователя и доступны только пользователю текущего сеанса (они регистрируются в ветви реестра HKEY_CURRENT_USER).

Имя источника данных содержит несколько общих установок и специфические для конкретной базы данных конфигурационные параметры. Запустите Regedit.exe и взгляните на ветвь реестра HKEY_CURRENT_USER\Software\ODBC\ODBC.INI. Здесь присутствуют различные конфигурационные поля. (Когда впервые появились драйвера ODBC, до появления реестра в Windows 95, все установки ODBC управлялись файлами INI, вот почему эта ветвь реестра имеет такое забавное название.)

Использование машинно-зависимых источников данных может стать несколько проблематичным и ограничивающим, если ODBC используется для доступа к базам данных на нескольких клиентских машинах. По меньшей мере, в драйвере SQLBase для каждого соединения с базой данных требуется отдельное имя DSN. Представьте, что вы изменили или добавили базу данных на сервере SQLBase - каждый клиент должен быть сконфигурирован с новыми установками. Это становится совершенно невыполнимым в сети с большим количеством пользователей (без автоматизации).

К счастью, существует третий режим конфигурирования, называемый "файловый DSN", - источник данных не зависящий от конкретных установок реестра. Если вы посмотрите на File DSN в диалоге контрольной панели ODBC, вы заметите стандартный каталог для таких *.dsn файлов. Файл DSN для источника данных SQLBase выглядит примерно так:

[ODBC]
DRIVER=Centura SQLBase 3.5 32-bit Driver -NT & Win95
UID=
DB=ISLAND
SRVR=

Это достаточно похоже на *.ini файлы Windows и содержит ту же информацию, что и источники данных в реестре. Однако этот способ более приемлем, когда речь идет о сопровождении. Такой файл может быть легко распространен простым копированием и может располагаться в разделяемом каталоге на файловом сервере.

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

Распространение DSN при использовании Crystal Reports

Важно не смешивать имена DSN и имена баз данных SQLBase . Если вы используете графический интерфейс Crystal Reports для доступа к разным базам данных, вам будет предложен диалог входа, который позволяет вам указать имя используемой базы - SqlDatabase. Однако программно, во время исполнения, с помощью RDC (описанном в первой части этой статьи) могут быть заданы только имя пользователя и пароль. Я думаю это верно и для других ODBC-совместимых приложений. Это значит, что вам необходимо отдельное имя DSN для каждой из баз данных, к которым вы хотите получить доступ.

Убедитесь, что вы дали разные имена источнику данных ODBC и вашей базе данных SQLBase. По некоторым причинам SQLWindows проверяет источники данных ODBC при вызове SqlConnect( ), что может привести к сообщению об ошибке. Если это случится, будет создан файл GUPTA.INI. Поищите такие файлы на вашем жестком диске и при необходимости - удалите их.

Я использую описательные имена для моих баз данных, даже во время обычного входа в приложение. Например, если пользователь выбирает "Island Outfitters Sales" как имя базы данных из списка выбора, внутренней константе SqlDatabase будет присвоено значение "ISLDSALE" и файл "Island Outfitters Sales.dsn" будет выглядеть примерно так:

[ODBC]
DRIVER=Centura SQLBase 3.5 32-bit Driver -NT & Win95
UID=
DB=ISLDSALE
SRVR=

Если вы или ваш заказчик правильно используете установки защиты Microsoft Windows NT, добавление системных источников данных может стать трудной задачей - администратор должен войти в систему на каждой машине или вам нужно будет искать упрощенное, но все равно сложное, решение для установки системных имен DSN на большом числе компьютеров. Использование пользовательских DSN проще, они персональные и могут быть добавлены без использования администраторских прав. Но вы будете обязаны проверять их существование каждый раз, когда приложение используется для определенной базы данных. Удаление приложения тоже может стать проблемой, так как вы не знаете, сколько источников данных существует на каждой машине (или вы должны проверить это). Если ваше приложение соединяется только с одной конкретной базой данных, вам не нужно беспокоиться об этих проблемах.

Лучшим решением (для меня) будет использование файловых источников данных. Я размещаю файлы DSN на разделяемом сетевом диске в каталоге с именем "ODBC", который находится прямо в каталоге установленного приложения (если оно запускается через сеть). Не нужно устанавливать никаких специальных путей для каждого клиента - на каждой машине должны быть правильно установлены только компоненты ODBC. Вы можете установить полный путь и имя файла DSN, который будет использоваться с Crystal Reports, с помощью RDC. Имя пользователя и пароль не должны храниться в файле DSN. Вместо этого, приложение должно передавать SqlUser и SqlPassword программно, в целях обеспечения безопасности.

Исполнение отчетов

Я определил класс cCrystalReports, который охватывает все функциональные возможности. Он приведен в исходных кодах для того, чтобы вы могли его использовать и расширять. Вызов функции "construct" устанавливает связь с интерфейсом времени исполнения RDC. Так же здесь устанавливается связь с текущей базой данных. Каждый отчет, открываемый с помощью этого класса, может повторно использовать соединение, однократно установленное в конструкторе.

Functional Class: cCrystalReports
Class Variables
Variant: vOpt
Instance Variables
CRAXDRT_Application: oCRApplication
CRAXDRT_Ireport: oCRReport
Functions
Function: construct
Description:
Returns
Boolean:
Parameters
Static Variables
Local variables
Boolean: bOk
Variant: vDatabase
Variant: vUser
Variant: vPassword
Actions
Set bOk = TRUE
!
Set bOk = bOk AND oCRApplication.Init( )
!
Set bOk = bOk AND oCRApplication.SetMatchLogOnInfo( TRUE )
Set bOk = bOk AND vDatabase.SetString( SqlDatabase )
Set bOk = bOk AND vUser.SetString( SqlUser )
Set bOk = bOk AND vPassword.SetString( SqlPassword )
Set bOk = bOk AND oCRApplication.LogOnServer( 'PDSODBC.DLL', m_sODBCDataSource, vDatabase, vUser, vPassword )
!
Return bOk

Как только создание экземпляра успешно завершено, отчет может быть открыт с помощью функции openReport( ). Возвращаемым значением метода, обеспечиваемым CRAXDRT_Application, является oCRReport, которое в свою очередь является переменной экземпляра класса.

Function: openReport
Description:
Returns
Boolean:
Parameters
String: p_sFileName
Static Variables
Local variables
Boolean: bOk
Variant: vOpenMethod
Actions
Set bOk = TRUE
!
! open report
Set bOk = bOk AND vOpenMethod.SetNumber( crOpenReportByTempCopy, VT_I2 )
Set bOk = bOk AND oCRApplication.OpenReport( p_sFileName, vOpenMethod, oCRReport )
! *** To Do ***
! - en/disable parameter prompting
! - do other initialisation tasks
!
Set __sFileName = p_sFileName
!
Return bOk

Фрагмент, отмеченный "*** ToDo ***", может, например, использоваться для назначения или запроса определенных параметров. Иначе Crystal Reports запросит их у вас через свой собственный диалог параметров.

Важное дополнение

Написание кода на основе приведенной выше информации может вызвать следующую проблему: если исполняемый модуль Crystal Reports освобождается с помощью функции destruct( ), вы заметите, что все ваши связи с SQLBase исчезнут. Эта ошибка/проблема существует довольно долгое время. Это связано, скорее всего, с Crystal Reports, или что еще более вероятно, с драйвером ODBC. Судя по всему собственные связи базы данных не учитываются при открытии обработчика связи с базой данных. Отсоединение последнего ODBC приводит к освобождению всех обработчиков освобождаемого процесса. Мне кажется, что это результат своего рода сборки мусора - с ошибкой.

Существует обходной путь, позволяющий вам использовать комбинацию собственных и основанных на ODBC связей с SQLBase в рамках одного процесса.

Перед показом первого отчета, приложение SQLWindows инициализирует обработчик среды ODBC, соединяет его с базой данных и отсоединяет его сразу после этого. Однако обработчик продолжает существовать все время жизни приложения. После отсоединения всех собственных связей SQL, обработчик среды освобождается, что не приводит к некорректности любого из ненужных обработчиков.

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

Function: ODBCConstruct
Description:
Returns
Boolean:
Parameters
Static Variables
Local variables
Boolean: bOk
cRegistry: oReg
String: sValue
Actions
Set bOk = TRUE
!
Set bOk = bOk AND m_oODBC.construct( )
! Check Crystal Reports registry entries
Call oReg.SetRootKey( HKEY_CURRENT_USER )
Set bOk = bOk AND oReg.OpenKey( 'Software/Seagate Software/Crystal Reports/DatabaseOptions/OuterJoin', TRUE )
If bOk AND NOT ( oReg.ReadString( 'PlusEqual', sValue) OR sValue!= '' )
Set bOk = bOk AND oReg.WriteString( 'PlusEqual', 'c2gup12;c2gup13;c2gup14' )
Set bOk = bOk AND oReg.CloseKey( )
!
Return bOk

Function: ODBCDestruct
Description:
Returns
Boolean:
Parameters
Static Variables
Local variables
Actions
Return m_oODBC.destruct( )

Function: ODBCValidateConnect
Description:
Returns
Boolean:
Parameters
Static Variables
Local variables
Boolean: bOk
Actions
Set bOk = TRUE
!
Set bOk = bOk AND m_oODBC.connectFromFileDSN( hWndNULL, m_sODBCDataSource, ODBC_DRIVER_NoPrompt )
Set bOk = bOk AND m_oODBC.disconnect( FALSE )
!
Return bOk

Пример приложения и исходный код

Все файлы, за исключением CrystalReports2.app, могут быть прямо использованы в вашем проекте. Если вы захотите поэкспериментировать с примером приложения, вам с помощью текстового редактора нужно будет изменить номер версии в файле Island Outfitters Sample.dsn.

Параметр в m_oODBC.disconnect( ) заставляет оставаться активным обработчик среды ODBC, хотя соединение с базой данных разорвано. Вы можете захотеть углубиться в детали кода, чтобы разобраться, как это работает.

Постскриптум...

Обратите внимание на функцию ODBCConstruct( ) в прилагаемом примере приложения. Она использует функцию Registry.apl, описанную некоторое время назад в статье Joe Meyer из Centura Pro. Эта функция проверяет/добавляет специфические для драйвера параметры в ветвь реестра для Crystal Reports. Это делается с использованием синтаксиса OuterJoin. Вы можете найти дополнительную информацию об этом по адресу www.support.seagatesoftware.com. Я рекомендую добавить ее в ваше приложение, если вы используете Crystal Reports для проверки, что внешние объединения работают правильно с драйвером ODBC для SQLBase.

Заключение

Это не так просто, как "включил и работай", но, изучив несколько статей, вы сможете создать очень интересную комбинацию Crystal Reports с Centura Team Developer 1.5.x и 2000. Не стесняйтесь использовать опубликованные библиотеки в своих собственных проектах.

Вот список положений, освещенных в данной статье, на которые следует обратить внимание:

  • Убедитесь, что использование файлов DSN упрощает внедрение вашего приложения на основе Crystal Reports.
  • Не смешивайте имена DSN с именами баз данных SQLBase - это разные вещи.
  • Один файл DSN необходим для доступа к каждой базе данных при использовании RDC.
  • Не храните SqlUser и SqlPassword в файле DSN.
  • Убедитесь, что вы используете разные имена для источников данных ODBC и баз данных SQLBase.

Страница сайта http://test.interface.ru
Оригинал находится по адресу http://test.interface.ru/home.asp?artId=4067