. Последнее обновление сайта было в 02:37

Добавление отчетов профессионального качества в приложение

(07:38) 16.07.2004
 +
шрифт
 -

Для понимания статьи требуется знание среды Visual Studio .NET.
Загрузка примеров кодов для этой статьи: Crystal.exe (391KB)

Аннотация

Генератор отчетов Crystal Reports for Visual Studio .NET предлагает комплексное решение по организации отчетности для .NET-разработчиков, которое полностью интегрируется с такими операционными средами, как Visual Studio .NET IDE и .NET Framework. Crystal Reports поддерживает технологии ADO.NET и XML Web Services, серверные ASP.NET элементы управления и кэширования. Он "бесшовно" интегрируется с Visual Studio .NET Server Explorer, набором инструментальных средств и средой разработки. Crystal Reports имеет богатую модель программирования и располагает гибкими возможностями настройки и развертывания отчетов. Перечисленные основные возможности Crystal Reports, как и другие, рассматриваемые здесь, позволяют выполнять сложную рутинную работу над представлением данных в приложениях пользователя.

Используя технологии Microsoft, разработчики долго и тесно сотрудничали с Crystal Reports еще во время внедрения Visual Basic 1.0. Теперь, с появлением платформы .NET и Visual Studio .NET, Crystal Reports снова установил стандарт для интеграции сторонних программных продуктов с инструментальными средствами Microsoft. Генератор отчетов Crystal Reports for Visual Studio .NET был разработан совместно с инженерами Microsoft с целью наиболее полной интеграции Crystal Reports с операционными средами .NET Framework и Visual Studio .NET. Он выполняет функции встроенного разработчика, позволяющего создавать новые отчеты, импортировать любые существующие отчеты Crystal Reports (или отчеты данных на языке Visual Basic 6.0) в формате .rpt, а также предоставляет ряд других возможностей, которые будут описаны ниже.

В этой статье я сначала рассмотрю процедуру создания приложения Windows Forms, затем технологию ASP.NET Web Service и построение клиентского приложения ASP.NET. Попутно я расскажу о некоторых полезных приемах программирования для решения таких задач, как создание документов Acrobat (PDF) из имеющихся отчетов, формирование отчетов на базе параметризованных хранимых процедур SQL Server передача отчетов с помощью учетных данных текущего пользователя базы данных. Загружаемый пример программы для этой статьи включает приложения Windows Forms, ASP.NET Web Forms и ASP.NET Web Services.

Простой отчет

Начнем с чего-нибудь простого. Я создам отчет из таблицы Customers (Клиенты) базы данных SQL Server Northwind и открою его в приложении Windows Forms. Для этого нужно создать новое приложение для Windows в Visual Studio .NET. (Я буду работать с языком Visual Basic, хотя эта концепция переносима на любой язык .NET.) После того, как приложение будет создано, щелкните правой кнопкой мыши по имени проекта в окне Solution Explorer и выберите в контекстном меню Add | Add New Item (Добавить | Добавить новый элемент). Затем в списке шаблонов Templates диалогового окна Add New Item выберите Crystal Report, укажите в строке Name отчет CustomersBasic.rpt и щелкните по кнопке Open (см. рис. 1).

Рис. 1. Создание простого отчета

После того, как откроется диалоговое окно Crystal Report Gallery, вы можете принять настройки по умолчанию (радиокнопка Using the Report Expert и строка Standard) и щелкнуть по кнопке OK. Когда откроется диалоговое окно Report Expert, перейдите к ветке OLE DB (ADO) древовидного списка на вкладке Data. В появившемся диалоговом окне OLE DB (ADO) выберите Microsoft OLE DB Provider for SQL Server, укажите сервер SQL Server и информацию для входа в этот сервер, затем выберите базу данных Northwind и щелкните по кнопке Finish. Вернитесь к диалоговому окну Standard Report Expert, открыв узел Northwind иерархического дерева, перейдите к узлу Tables, затем дважды щелкните по узлу Customers. На вкладке Fields щелкните по кнопке Add All, чтобы добавить в отчет все поля таблицы Customers. Далее, убедитесь в том, что на вкладке Style для создаваемого отчета указан соответствующий заголовок в поле Title и выбран стиль в списке Style, затем щелкните по кнопке Finish.

После этого активируется разработчик Crystal Reports for Visual Studio .NET и появится созданный отчет. Также появится окно Field Explorer, состыкованное с окнами Server Explorer и Toolbox. В последнем из них находится палитра Crystal Reports. Кроме того, в левом верхнем углу панели инструментов Visual Studio .NET появится панель инструментов Crystal Reports.

Я воспользуюсь этим отчетом для иллюстрации примеров, содержащихся в этой статье. В качестве первого примера рассмотрим отображение отчета в окне. Выполнить это довольно легко. Просто перенесите CrystalReportViewer из палитры Windows Forms окна Toolbox в среду разработчика для формы по умолчанию в проекте и установите для атрибута Name значение cvwMain, для атрибута Dock значение Fill, для атрибута ReportSource - мой отчет (используя опцию Browse) и затем запустите приложение. После того, как я спроектирую отчет, войдя в базу данных с пустым паролем, этот отчет сразу появится на экране. При наличии непустого пароля для отображения отчета потребуется снова войти в базу данных. Далее я покажу, как написать небольшую программу, автоматизирующую вход в базу данных, с помощью которой пользователи, уже прошедшие процедуру аутентификации, не будут повторно входить в базу данных для запуска отчетов.

Строго типизированные отчеты

Теперь, когда я кратко изложил основные принципы создания простых отчетов, давайте перейдем к более сложным вопросам. Подобно тому, как создаются строго типизированные наборы DataSets со своими атрибутами и методами, можно создать строго типизированные отчеты. По своему существу все отчеты, созданные с помощью Crystal Reports и Visual Studio .NET, составляют класс строго типизированных отчетов в качестве побочного продукта самого процесса разработки. Чтобы в этом убедиться, щелкните по кнопке Show All Files (Показать все файлы) в Solution Explorer, перейдите по иерархическому дереву к CustomersBasic.rpt и убедитесь в существовании файла класса, созданного Visual Studio .NET. Я могу создать экземпляр этого класса в программе и назначить его атрибуту ReportSource объекта CrystalReportViewer, содержащегося в моей форме. Для этого я добавлю следующую строку текста программы к событию формы Load (установив атрибут ReportSource формы cvwMain в None в первом окне Properties).

cvwMain.ReportSource = New CustomersBasic()

Подобно строго типизированным наборам DataSets, которые используют разработчик компонентов DataSet, строго типизированные отчеты также имеют соответствующий разработчик компонентов. Если щелкнуть по палитре компонентов Components окна Toolbox в Visual Studio .NET, появится объект под названием ReportDocument. Перетащив его на свою форму, вы увидите имя класса вашего отчета в раскрывающемся списке Name диалогового окна Choose a ReportDocument. Выберите его и щелкните по кнопке OK. Вы получите исполняемый доступный экземпляр класса вашего отчета. Переименуйте этот объект в cbsMain (cbs является префиксом CustomersBasic) и замените следующей строкой текста программы в событии формы Load:

cvwMain.ReportSource = cbsMain

Если вы сейчас снова запустите приложение, то ваш отчет запустится, как и прежде. Этот запуск отличается от предыдущего тем, что, не ссылаясь на конкретный файл, находящийся в конкретном физическом месте, ReportViewer обращается непосредственно к объекту, который может выступать в качестве экземпляра, полученного из соответствующего класса в сборке приложения, внешней сборке или, как вы увидите далее, в XML Web Service.

Как я уже упоминал, если вы для создания отчета предоставили информацию о подключении с идентификатором пользователя и пустым паролем, то этот отчет после своего создания будет открыт немедленно. В любых других случаях генератор отчетов Crystal Reports for Visual Studio .NET предложит вам зарегистрироваться, поскольку вся информация о подключении, кроме пароля, сохраняется отчетом. Если вам потребуется предоставить пароль во время выполнения программы или другой набор информации о подключении, кроме той, которая уже была предоставлена во время создания отчета (что случается довольно часто), используйте программу, приведенную на рисунке 2 перед установкой cvwMain.ReportSource.

Dim tbCurrent As CrystalDecisions.CrystalReports.Engine.Table
Dim tliCurrent As CrystalDecisions.Shared.TableLogOnInfo

For Each tbCurrent In cbsMain.Database.Tables
tliCurrent = tbCurrent.LogOnInfo
With tliCurrent.ConnectionInfo
.ServerName = "localhost"
.UserID = "ReportUser"
.Password = "msdn"
.DatabaseName = "Northwind"
End With
tbCurrent.ApplyLogOnInfo(tliCurrent)
Next tbCurrent

Рис. 2. Запись Crystal Reports в базу данных

В программе на рисунке 2 я произвольно задал сервер, идентификатор пользователя и пароль, т.е. localhost, ReportUser и msdn соответственно. В большинстве приложений вам, вероятно, придется использовать глобальные переменные или атрибуты класса, или даже переменные сеанса в случае приложения ASP.NET, чтобы в любой момент можно было предъявить имя базы данных и учетные данные пользователя вашего приложения, введенные при первоначальной регистрации. Обратите внимание на цикл For Each в программе. Поскольку в моем отчете содержится только одна таблица, этот цикл по большому счету необязателен (я мог бы просто сделать ссылку на cbsMain.Database.Tables(0)), однако, эта программа будет работать с любым отчетом Crystal Reports for Visual Studio .NET, поэтому я предпочел его оставить, сделав программу более функциональной.

Server Explorer

Теперь рассмотрим другие способы конфигурации элементов управления объекта CrystalReportViewer. Одним из таких способов на этапе разработки является использование проводника Server Explorer. В связи с последними изменениями в .NET Framework данная функция генератора отчетов Crystal Reports for Visual Studio .NET некорректно устанавливается инсталлятором Visual Studio. Чтобы ее настроить и продолжить выполнение следующих шагов, описанных в статье, убедитесь, что все права доступа для папки Crystal Reports в каталоге Visual Studio .NET установлены и осуществляется полное управление пользовательской средой ASPNET. (Кстати, по умолчанию эта папка находится в C:\Program Files\Microsoft Visual Studio .NET\Crystal Reports). Проверить права доступа можно с помощью вкладки Security в окне свойств папки. Чтобы открыть вкладку Security, пользователи Windows XP должны выбрать пункт меню Tools | Folder Options в окне Explorer, щелкнуть по вкладке View и снять флажок "Use simple file sharing", который является последним пунктом в списке Advanced settings. После выполнения этих шагов все последующие шаги должны выполняться корректно.

Щелкните по узлу Servers иерархического дерева, затем по узлу с именем вашего локального компьютера, далее по расположенному под ним Crystal Services и, наконец, по Server Files. Под этим узлом появятся две папки, в каждой из которых будут содержаться несколько файлов отчетов (см. рис.3). Любой из этих .rpt-файлов можно перетащить в среду разработчика формы, который завершит создание объекта разработчика компонентов ServerFileReport, указывающего на правильный .rpt-файл. Теперь нашим следующим шагом будет установление связи между этим объектом и вашим отчетом.

Рис. 3. Server Explorer

Таким образом, все папки и файлы отчетов, отображаемые в этом разделе Server Explorer, будут расположены в отдельном каталоге на жестком диске сервера. По умолчанию эта папка содержится в подкаталоге Samples\Reports основной папки Crystal Reports, о которой я уже говорил. Две упомянутые прежде папки являются подкаталогами основной папки Crystal Reports и в них физически содержатся все персональные .rpt-файлы.

Чтобы ваш отчет появился в Server Explorer, скопируйте его в родительскую папку, либо в одну из его дочерних папок, либо в вашу собственную. Например, в папке Samples\Reports вы можете создать папку MSDN и скопировать в нее CustomersBasic.rpt. Затем, если вы щелкните правой кнопкой мыши по узлу Server Files в Server Explorer и выберите Refresh в контекстном меню, то появится папка MSDN с дочерним узлом для CustomersBasic.rpt. Перетащите его на вашу форму и переименуйте конечный объект sfrCustomersBasic. В окне Properties задайте атрибут ReportSource формы cvwMain, указав на этот объект. Закомментируйте каждую строку программы в событии формы Load и запустите приложение, после чего на экране появится ваш отчет.

Создание отчетов из DataSets

Позднее я расскажу о дополнительных возможностях разработчика компонентов ServerFileReport, а сейчас нам нужно рассмотреть следующий шаг, который заключается в модифицировании отчета с целью получения данных посредством поставщика DB OLE из ADO.NET DataSet, а не из физической базы данных. Сначала создадим строго типизированный набор DataSet на основе таблицы Customers базы данных Northwind. Для этого используем наиболее простой способ, добавим в проект пустой набор DataSet и присвоим ему имя DataSet dsNorthwind.xsd, открыв диалоговое окно Add New Item (см. рис.4).

Рис.4. Добавление DataSet

Откройте дизайнер компонентов DataSet, дважды щелкнув по соответствующему узлу в Solution Explorer. Перетащите таблицу Customers из Server Explorer на плоскость разработки DataSet и сохраните файл. Затем откройте отчет, щелкните правой кнопкой мыши по его плоскости разработки, чтобы открыть контекстное меню, и выберите Database и Set Location. В диалоговом окне Set Location разверните узлы Project Data, ADO.NET DataSets и узел для вашего набора DataSet, затем выберите таблицу Customers. Наконец, в раскрывающемся списке Current Data Source выберите Customers и щелкните по кнопке Replace. После этого отчет будет обращаться к вашему строго типизированному набору DataSet для получения метаданных и будет запускаться при привязке к экземпляру этого набора. Для продолжения щелкните по кнопке Close.

Теперь, когда я модифицировал отчет для работы с экземпляром dsNorthwind, нужно создать его в моей форме и задать в атрибуте ReportSource объекта CrystalReportViewer. Для этого перетащите таблицу Customers из Server Explorer на плоскость разработки формы, тем самым добавив в нее объекты SQLConnection и SQLDataAdapter, указывающих на базу данных Northwind и на таблицу Customers этой базы данных соответственно. Переименуйте эти объекты в scnNorthwind и sdaCustomers и измените атрибут ConnectionString объекта scnNorthwind, включив в него идентификатор пользователя и пароль. Затем щелкните правой кнопкой мыши по sdaCustomers и выберите Generate Dataset. В разделе "Choose a dataset" выберите радиокнопку Existing, а в правом от нее раскрывающемся списке имя класса вашего строго типизированного набора DataSet (такой выбор наиболее соответствует настройкам по умолчанию). На рисунке 5 это показано достаточно ясно.

Рис. 5. Создание DataSet

Щелкните по кнопке OK, переименуйте новый объект DataSet в "ndsMain" и замените код события Load на следующий фрагмент:

sdaCustomers.Fill(ndsMain)
cbsMain.SetDataSource(ndsMain)
cvwMain.ReportSource = cbsMain

Обратите внимание, что в данном фрагменте фигурирует созданный мною объект "ndsMain", который является экземпляром класса dsNorthwind строго типизированного набора DataSet. Далее, этот фрагмент программы задает атрибуту DataSource объекта "cbsMain" (экземпляр класса строго типизированных отчетов CustomersBasic) значение "ndsMain". И, наконец, как и в предыдущих примерах, атрибуту ReportSource формы cvwMain (мой объект CrystalReportViewer) я задаю значение "cbsMain".

Запустите свое приложение и убедитесь, что отчет выполняется и отображается на экране так же, как и в других случаях. Этот пример отличается тем, что в нем данные поступают не из базы данных, а от изолированного объекта DataSet. В моем случае заполнение объекта DataSet осуществлялось с помощью прямого запроса к таблице Customers. (Чтобы увидеть фактический текст запроса, в объекте sdaCustomer выберите SelectCommand и затем CommandText.) Я мог бы построить этот объект DataSet из любого источника данных или из нескольких выбранных мною источников, поскольку построенный набор данных зависим от структуры ndsNorthwind.

Создание отчетов из хранимых процедур

Чтобы проиллюстрировать эту тему, сначала создадим параметризованную хранимую процедуру для работы с таблицей базы данных Customers, имеющей имя spCustomers. Эта хранимая процедура забирает параметр строки, который должен использоваться в операторе WHERE для ограничения количества возвращаемых записей. После этого в тексте программы я построю объект набора данных DataSet для этой процедуры и свяжу отчет с этим набором данных. Вот текст хранимой процедуры.

CREATE PROCEDURE dbo.spCustomers
(
@CustPattern nVarChar(40)
)
AS
select * from Customers Where CompanyName Like @CustPattern + '%'
RETURN

Вы можете создать хранимую процедуру любым удобным способом; например, с помощью Visual Studio .NET, как это показано на рисунке 6.

Рис. 6. Создание хранимой процедуры с помощью Visual Studio .NET

Чтобы создать отчет из хранимой процедуры (присвоив параметру @CustPattern произвольное значение "A"), я изменил текст события формы Load (см. пример на рисунке 7).

Private Sub frmViewReport_Load(ByVal sender As Object, ByVal e As _
System.EventArgs) Handles MyBase.Load

Dim scmCustomersSP As New SqlClient.SqlCommand("spCustomers", _
scnNorthwind)
scmCustomersSP.CommandType = CommandType.StoredProcedure
scmCustomersSP.Parameters.Add("@CustPattern", "A")

Dim sdaCustomersSP As New SqlClient.SqlDataAdapter(scmCustomersSP)
Dim dsReport As New DataSet()
sdaCustomersSP.Fill(dsReport, "Customers")

cbsMain.SetDataSource(dsReport)
cvwMain.ReportSource = cbsMain

End Sub

Рис. 7. Модифицированный OnLoad Event

В этой программе не используется ни один из тех объектов, которые были созданы на этапе разработки, за исключением объекта scnNorthwind. Существенно и то, что в этой программе также не используется экземпляр dsNorthwind строго типизированного набора DataSet в качестве источника данных для отчета. Вместо него я применил объект ADO.NET DataSet без контроля типов и с именем dsReport. Это чрезвычайно важно несмотря на то, что этот отчет разработан для строго типизированного набора DataSet. Во время запуска отчета в качестве источника данных будет задан универсальный объект DataSet без контроля типов, структура которого соответствует структуре экземпляра dsNorthwind. Когда потребуется вызвать метод Fill объекта DataAdapter, я буду использовать переопределяемую версию, которая должна принять некое табличное имя. Чтобы гарантировать структурное соответствие dsReport и dsNorthwind, я задам для этого табличного имени имя Customers. Если я этого не сделаю, то на экране появится отчет без каких-либо данных.

Отчет можно создать не только на основе таблицы базы данных, как это было продемонстрировано в первом примере, но и на основе хранимой процедуры. Для установки значения параметра в программе требуется определенная команда, затрагивающая объекты, атрибуты и методы в разных пространствах имен генератора отчетов Crystal Reports for Visual Studio .NET. Рассмотрим это более подробно.

Чтобы хранимые процедуры можно было выбирать в качестве источников данных, требуется настроить генератор отчетов Crystal Reports for Visual Studio .NET. Для этого щелкните правой кнопкой мыши по пустой области в плоскости разработки отчета и выберите в контекстном меню пункт Designer | Default Settings. В диалоговом окне Default Settings откройте вкладку Database, проверьте, установлен ли флажок Stored Procedures в разделе Show, и щелкните по кнопке OK.

Затем щелкните правой кнопкой мыши по плоскости разработки отчета и выберите в контекстном меню пункт Database | Set Location. Спуститесь по иерархическому дереву Replace With к узлу OLE DB (ADO), еще раз щелкните правой кнопкой мыши, чтобы открылось диалоговое окно OLE DB (ADO), и введите всю необходимую информацию для подключения к вашей копии базы данных SQL Server Northwind. Вернувшись к диалоговому окну Set Location, разверните узел Northwind, затем узел Stored Procedures и выберите узел spCustomers;1. В комбинированном списке Current Data Source укажите Customers, щелкните по кнопке Replace и затем по кнопке Close.

Теперь, когда вы настроили этот отчет - который был первоначально разработан на основе таблицы Customers базы данных Northwind и преобразован для использования строго типизированного набора данных в качестве источника данных - вы можете использовать для получения данных хранимую процедуру spCustomers. Поскольку spCustomers является параметризированной хранимой процедурой, генератор отчетов Crystal Reports for Visual Studio .NET автоматически добавит в ваш отчет поле для параметров Crystal Reports с именем параметра хранимой процедуры. Чтобы в этом убедиться, разверните в окне Field Explorer узел Parameter Fields. Справа под ним вы увидите поле с параметром @CustPattern (см. рис.8).

Рис. 8. Параметры

Теперь вы можете установить cvwMain.ReportSource как на этапе разработки, так и в самой программе, указав на rpt-файл или на экземпляр cbsMain разработчика компонентов ReportDocument. При запуске приложения генератор отчетов Crystal Reports for Visual Studio .NET автоматически откроет диалоговое окно, запрашивающее значение параметра @CustPattern. Введите любую понравившуюся вам строку, чтобы генератор отчетов подключал только тех клиентов, у которых значение поля CompanyName будет начинаться с этой строки.

Не смотря на то, что генератор отчетов Crystal Reports for Visual Studio .NET может запросить значения параметров и запустить отчет без написания программного кода, в большинстве случаев желательно, чтобы эти значения запрашивались у приложений и передавались в отчет программным путем. На рисунке 9 приведена программа, необходимая для программного присваивания значений параметров с помощью объектной модели Crystal Reports. В этой программе я снова использовал произвольное значение "A", присвоив его параметру pdvCustPattern.

Private Sub frmViewReport_Load(ByVal sender As Object, ByVal e As _
System.EventArgs) Handles MyBase.Load

Dim pvCustPattern As New CrystalDecisions.Shared.ParameterValues()
Dim pdvCustPattern As New _
CrystalDecisions.Shared.ParameterDiscreteValue()

pdvCustPattern.Value = "A"
pvCustPattern.Add(pdvCustPattern)
cbsMain.DataDefinition.ParameterFields _
("@CustPattern").ApplyCurrentValues(pvCustPattern)

cvwMain.ReportSource = cbsMain

End Sub

Рис. 9. Назначение параметров

Относительно этой программы необходимо сделать ряд замечаний. Мне не совсем понятно, почему параметрам T-SQL можно присвоить только одно значение, в то время как полям параметров генератора отчетов Crystal Reports for Visual Studio .NET присваивается совокупность значений. Учитывая этот факт, я построил такую совокупность значений, которая состоит только из одного элемента, и присвоил ему значение "A". В результате эта программа создает не только pvCustPattern, экземпляр объекта CrystalDecisions.Shared.ParameterValues, который допускает использование нескольких значений, но и pdvCustPattern, экземпляр класса CrystalDecisions.Shared.ParameterDiscreteValue, который допускает использование только одного значения. Программа присваивает строку "A" атрибуту Value для pdvCustPattern и загружает его в pvCustPattern посредством метода суммирования. Затем pvCustPattern присваивается полю параметра @CustPattern посредством метода ApplyCurrentValues, а экземпляр CustomersBasic присваивается атрибуту ReportSource в средстве отображения отчетов. Хотя эта программа может показаться несколько скомканной, она, тем не менее, работает.

Web-службы для XML-отчетов

Теперь можно рассмотреть, как используется технология XML Web Services в Crystal Reports for Visual Studio .NET. Значительным достижением в этой области является удачная разработка достаточно сложных функций с легко реализуемыми преимуществами; например, отчеты могут публиковаться как Web-службы и использоваться в качестве ReportSource для элемента управления CrystalReportViewer.

Чтобы создать Web-службу для XML-отчетов из файла CustomersBasic.rpt, откройте Visual Studio .NET и создайте новый проект ASP.NET Web Service под именем MSDNCrystalWebService. Удалите файл Service1.asmx, который добавляется к проекту по умолчанию, и вместо него добавьте CustomersBasic.rpt. Затем щелкните правой кнопкой мыши по CustomersBasic.rpt в Solution Explorer и выберите в контекстном меню пункт Publish as Web Service (см. Рисунок 10).

Рис. 10.

В результате в проект будет добавлен файл Web-службы, CustomersBasicService.asmx. Теперь будем компоновать проект. Вернитесь в приложение Windows Forms и установите для cvwMain.ReportSource URL-адрес Report Web Service согласно следующей строке текста программы:

cvwMain.ReportSource = "http://localhost/MSDNCrystalWebService/" _
& "CustomersBasicService.asmx"

В качестве альтернативы вы можете добавить веб-ссылку для этого asmx-файла в проекте и затем указать cvwMain.ReportSource в экземпляре класса Web Service.

cvwMain.ReportSource = New localhost.stomersBasicService()

Можно ли создать интерфейс XML Web Services в Crystal Reports так же легко, как и Web-службу? Внимательно изучите программу файла класса, который расположен с небольшим отступом под файлом CustomersBasic.rpt (чтобы увидеть файл, щелкните по кнопке Show All Files в Solution Explorer). В программе этого файла содержатся два класса: CustomersBasic и CachedCustomersBasic.

CustomersBasic является первичным классом, который необходим для реализации строго типизированного отчета; если вы посмотрите на процедуры атрибутов этого отчета, то увидите его со всеми разделами, которые наследуются из ReportClass и охватывают элементы коллекции ReportDefinition.Sections. В свою очередь, CachedCustomersBasic реализует интерфейс IcachedReports для создания кешированного отчета и в своем методе CreateReport создает экземпляр CustomersBasic (первый класс). С помощью интерфейса, подобного интерфейсу IcachedReports и использующего WebMethods, можно вывести отчет в виде XML Web Service.

Теперь взгляните на программу файла класса, который расположен под файлом CustomersBasicService.asmx. Этот файл также содержит два класса, но, в отличие от предыдущего файла, в нем один класс вложен в другой. CustomersBasicService наследуется из класса ReportServiceBase, который, в свою очередь, открывает веб-методы, необходимые для публикации отчета в виде XML Web Service. CustomersBasicService содержит класс CachedWebCustomersBasic, который, по своему существу, имеет точно такую же реализацию, что и уже рассмотренный класс CachedCustomersBasic. Различие можно найти в конструкторе:

Public Sub New(ByVal webServiceParam As CustomersBasicService)
Me.webService = webServiceParam
End Sub

Этот конструктор вызывается из конструктора CustomersBasicService, чтобы указать в нем атрибут webService кешированного отчета:

Public Sub New()
Me.ReportSource = New CachedWebCustomersBasic(Me)
End Sub

Подведем итоги: ReportClass в Crystal Report создает возможные строго типизированные отчеты; интерфейс IcachedReports позволяет создавать кешированные экземпляры ReportClass; и, наконец, ReportServiceBase создает интерфейс Web Services для строго типизированных отчетов, который благодаря атрибуту webService совместим с интерфейсом IcachedReports.

Кстати, вы не забыли о компоненте ServerFileReport, который я создал, перетащив из Server Explorer? В нем также задействуется технология Web Services. Если вы вернетесь в проект Windows Form, то заметите, что у sfrCustomersBasic имеется атрибут WebServiceURL указывающий на .asmx-файл общего вида. Адрес URL будет выглядеть примерно следующим образом: localhost/crystalreportwebformviewer/ServerFileReportService.asmx. Несмотря на то, что этот URL-адрес стандартен, атрибут ReportPathProperty класса sfrCustomersBasic, указывая на \MSDN\ CustomersBasic.rpt, задает относительный путь и имя отчета, который требуется запустить.

С первого взгляда кажется странным, что компонент ServerFileReport требует запуска отчета через соединение HTTP/SOAP с локальным компьютером. Однако, благодаря этому вы можете легко запустить отчеты Crystal Reports for Visual Studio .NET, существующие на удаленном компьютере: просто щелкните правой кнопки мыши по узлу Servers в окне Server Explorer и выберите Add Server, затем подключитесь к любому серверу в ваших сетях LAN/WAN и запустите на удаленном компьютере требуемые отчеты Crystal Reports for Visual Studio .NET. Данная возможность позволяет легко развертывать отчеты по всему предприятию: для этого установите среду Visual Studio .NET на сервере и скопируйте rpt-файлы в соответствующую папку, после чего эти rpt-файлы без какой-либо специальной программы станут доступны для всей организации (по протоколу SOAP). В этом случае вам даже не потребуется такой относительно простой процесс, как выбор пункта "Publish as Web Service", который выполняется после щелчка правой кнопки мыши по отчету в проекте ASP.NET, поскольку все, что вам будет нужно сделать, так это скопировать файл в соответствующую папку.

Недостаток использования операции перетаскивания объектов в Server Explorer заключается в том, что в нем можно просматривать только те объекты сервера, которые постоянно находятся в сетях LAN/WAN разработчика, а не за брандмауэром. Но тут есть одна хитрость: пока известны адрес URL и значение атрибута ReportPath при подключенном к сети Internet сервере (с брандмауэром или нет), вы сможете создать новый экземпляр CrystalDecisions.ReportSource.ServerFileReport и задать в нем значения этих атрибутов, указав их в программе.

Интерфейс SOAP так удобен и прост, что Crystal Reports for Visual Studio .NET применяет его в качестве оболочки программ сортировки для своего более раннего продукта, сервера Crystal Enterprise. Узел Crystal Enterprise под Crystal Services в Server Explorer можно использовать для просмотра отчетов, содержащихся на любом сервере Crystal Enterprise в сети LAN/WAN, а также для использования этих отчетов в качестве допустимых значений ReportSources для элемента управления CrystalReportViewer при повторном применении SOAP. В этом случае отчеты Crystal Enterprise будут доступны для любых подключенных к сети Internet генераторов отчетов Crystal Reports for Visual Studio .NET с правильным адресом URL и идентификатором объекта.

Построение отчетности в клиентских приложениях ASP.NET

До сих пор все, что я сделал на клиентском компьютере, было выполнено в приложении Windows Forms, однако отчеты можно также представлять и в веб-приложениях ASP.NET. К счастью, Crystal Reports for Visual Studio .NET поддерживает технологию ASP.NET. Теперь я покажу, как представлять отчеты в виде документов HTML или документов Acrobat (PDF), используя элемент управления ASP.NET Web Forms CrystalReportViewer. Кроме того, я рассмотрю кэширование и использование кешированных данных.

Поскольку Web Forms CrystalReportViewer работает аналогично Windows Forms, изложение основных операций займет не слишком много времени. Для начала создайте в среде Visual Studio .NET новое веб-приложение ASP.NET Web Application и, используя функцию Add Existing Item, добавьте в проект CustomersBasic.rpt. Затем задайте местоположение данных для отчетов, вернувшись к таблице Customers, и в целях тестирования используйте вход с пустым паролем. Переименуйте WebForm по умолчанию в ViewReport.aspx и добавьте к нему элемент управления Web Forms CrystalReportViewer, задав для его атрибута ID значение cvwMain. Поскольку на этапе разработки элемент управления Web Forms CrystalReportViewer не имеет атрибута ReportSource, следует задать этот атрибут в событии Page_Load в ViewReport.aspx следующим образом:

cvwMain.ReportSource = Server.MapPath("CustomersBasic.rpt")

Запустив приложение, убедитесь в эффективности данной процедуры. Этот отчет является чистым HTML-документом несмотря на то, что в нем поддерживаются функции поиска, навигации, масштабирования и других элементов управления просмотром (кроме печати - об этом речь пойдет позже), хотя и с помощью переадресации (postback). Можно попробовать и другие способы загрузки отчета, которые я уже рассматривал: создание отчета из строго типизированного набора DataSet или из набора DataSet без контроля типов, из хранимой процедуры с помощью ReportDocument или разработчика компонентов ServerFileReport и т.п. Можно скопировать в событие Page_Load в ViewReport.aspx программу, которую я уже использовал для настройки учетной информации отчета и значений параметров, а также для манипулирования объектами ADO.NET. Это аналогично тому, что я уже делал, и я не буду повторяться, хотя опция ReportDocument требует некоторого объяснения.

Кешированные ReportDocuments

Теперь давайте рассмотрим функции Crystal Reports for Visual Studio .NET для кешированных отчетов. Перетащите разработчик компонентов ReportDocument на плоскость разработки ViewReport.aspx и выберите ProjectName.CustomersBasic из Name: комбинированного списка в диалоговом окне Choose a ReportDocument, не нажимая кнопку OK. Обратите внимание на флажок "Generate cached strongly typed report" ("Создать кешированный строго типизированный отчет") (см. рис.11).

Рис. 11 Функция кешированных отчетов

Установите этот флажок. Щелкните по кнопке OK и назовите созданный компонент как ccbMain. Затем, свяжите элемент управления просмотра с этим объектом в событии Page_Load с помощью следующей строки программы:

cvwMain.ReportSource = ccbMain

Перетащите элементы управления Data Time и Print Time в раздел заголовка страницы отчета. Эти элементы управления можно найти в окне Field Explorer под узлом Special Fields. Затем запустите приложение и просмотрите отчет. Когда вы его запустите в первый раз, элементы управления Data Time и Print Time должны быть одинаковыми (или же очень похожими). Но если вы обновите страницу, то увидите, что Print Time продолжает обновляться, а Data Time остается одним и тем же. Теперь скопируйте текущий адрес URL обозревателя в буфер обмена и закройте обозреватель. Откройте окно нового обозревателя и вставьте в него указанный адрес URL для просмотра отчета в новом сеансе (без перестройки сборки из Visual Studio .NET). Вы увидите, что исходная временная метка будет отображаться в Data Time.

Теперь закройте обозреватель и вернитесь в Visual Studio .NET. Снова перетащите дизайнер компонентов ReportDocument на плоскость разработки ViewReport.aspx и выберите ProjectName.CustomersBasic, сняв флажок "Generate cached strongly typed report". Щелкните по кнопке OK и назовите созданный компонент как "cbsMain". После завершения данной операции свяжите элемент управления просмотра с созданным объектом в событии Page_Load, внеся в программу имя нового компонента:

cvwMain.ReportSource = cbsMain

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

Когда вы используете атрибуты DataDefinition или Database объекта cbsMain (экземпляр моего некешированного ReportDocument) для задания значений параметров или атрибутов входа в таблицы, обратите внимание, что ccbMain (экземпляр кешированного ReportDocument) не имеет таких атрибутов. Как использовать кешированные отчеты по отношению к защищенным таблицам и параметризованным хранимым процедурам? Ключ лежит в программе, расположенной позади строго типизированного отчета. Снова щелкните по кнопке Show All Files (Показать все файлы) в Solution Explorer, перейдите к CustomersBasic.rpt и откройте позади него файл программы. Вы уже были здесь, но сейчас вам следует открыть программу для класса CachedCustomersBasic, содержащуюся в этом файле.

Обратите внимание, что программа создает новый экземпляр некешированного класса CustomersBasic для своего метода CreateReport, поскольку CachedCustomersBasic в действительности содержит CustomersBasic. Таким образом, я могу написать настраиваемую программу в этом общедоступном методе, чтобы иметь доступ к атрибутам Database и DataDefinition как созданного экземпляра класса CustomersBasic, так и интерфейса с защищенными объектами базы данных и параметризованными хранимыми процедурами. Если я применяю этот метод, то при создании нового экземпляра кешированного отчета будет создаваться соответствующий сконфигурированный экземпляр некешированного строго типизированного отчета.

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

Если вы убрали из программы комментарии, то специальная функция BuildCompleteCacheKey сгенерирует уникальный ключ для конкретного отчета. Раскомментированная программа, которая во всем остальном оставлена без изменений, выполняется так же как программа с комментариями. Если этот ключ не модифицируется, то Crystal Reports неявно использует алгоритм BuildCompleteCacheKey для создания вашего ключа. Это подходит для многих случаев. Но что делать, если вам требуется модифицировать ключ? Предположим, вы узнали, что в какой-то момент времени ваши данные значительно изменились. Тогда вы могли бы приписать к ключу кеша свою строку, чтобы обеспечить его изменение в этот момент времени или после него. Приведем тривиальный пример: раскомментируйте программу в GetCustomizedCacheKey и вставьте перед оператором Return следующую строку:

key &= DatePart(DateInterval.Minute, Now())

Эта строка прозволяет генерировать новый ключ кеша в тот момент, когда текущее время изменяется на одну минуту. В событии Page_Load класса ViewReport.aspx укажите ccbMain для cvwMain.ReportSource, затем запустите приложение и обновите несколько раз страницу. При этом вы увидите изменение в Data Time, которые происходят, когда минутный отсчет фактического времени увеличивается на единицу. Подобным образом можно приписать к ключу кеша значения различных параметров и другие детали, связанные с данными, чтобы избежать обработки одних и тех же кешированных данных при прогонах отчета. Можно создать собственный ключ, не просто прибавляя кое-какие строки к ключу кеша по умолчанию, но написав его целиком с самого начала; но этот метод я не буду рекомендовать хотя бы потому, что это все равно, что изобретать колесо.

Конечно, эти изменения в классе строго типизированных отчетов весьма полезны, но они связаны с некоторым риском, поскольку при обновлении отчета Visual Studio .NET попытается переписать файл класса этого отчета и, если не принять соответствующих мер, то вы потеряете внесенные изменения. Чтобы этого избежать, вам следует создать собственный класс, реализующий IcachedReport с программой из класса CachedCustomersBasic. После этого вы сможете создать в ViewReport.aspx, а именно в событии Page_Load, экземпляр этого класса и указать на него в cvwMain.ReportSource. На Figure 12 показана программа для данного класса (включая программу, использующую объект ASP.NET Request для задания значения поля параметра отчета и для добавления этого значения в ключ кеша), а также программа (см. ниже), демонстрирующая код события Page_Load, который требуется для ее использования.

Private Sub Page_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load

Dim mcrMain As New cMSDNCachedReport()
McrMain.ASPRequest = Request
CvwMain.ReportSource = mcrMain
End Sub

Преобразование в формат PDF

Сильная сторона элемента управления Web Forms CrystalReportViewer заключается в том, что он представляет отчеты в виде документов HTML, но в этом и его слабость. С одной стороны, такое представление отчетов содействует максимальной совместимости Crystal Reports for Visual Studio .NET и клиентских обозревателей; с другой, язык HTML не предусматривает точное постраничное разбиение при выводе на печать.

Чтобы обойти проблемы, связанные с печатью, следует преобразовать отчет в формат Adobe Acrobat (PDF). Вы можете написать довольно простую программу ASP.NET, которая позволила бы программным способом преобразовать отчет в формат PDF и затем перенаправила бы ваш обозреватель на этот файл. Таким образом, пользователь может запросить отчет через событие Postback и получить адрес PDF-версии отчета, которую он будет печатать. На Figure 13 показана программа, позволяющая выполнить эту операцию. Для простоты я использую некешированный объект cbsMain компонента ReportDocument для генерирования отчета.

Если вы для представления отчетов собираетесь использовать PDF-файлы, вам следует узнать о недостатках этого метода. Во-первых, чтобы удовлетворить многочисленным пользователям, вы должны дать уникальные имена созданным PDF-файлам; программа на Figure 13 использует постоянную текстовую строку, поэтому она годится только для демонстрации предлагаемого метода. Во-вторых, в какой-то момент времени PDF-файлы должны быть окончательно отредактированы, и, в зависимости от количества готовых отчетов на вашем приложении, весь файловый ввод-вывод, связанный с созданием и доводкой PDF-файлов, может при неправильном управлении и настройке значительно замедлить функцию масштабируемости. При создании приложений ASP.NET с помощью Crystal Reports for Visual Studio .NET рекомендуется изучить программу просмотра со стороны клиента и составить стратегию печати, поскольку у каждой опции имеется свой набор значимых аргументов "за" и "против".

Заключение

В этой статье я подробно рассмотрел возможности генератора отчетов Crystal Reports for Visual Studio .NET, хотя за ее рамками осталось много интересного материала, требующего отдельного исследования. Ничего более не желая, я рассчитываю на то, что вы после ее прочтения осознаете богатство предоставляемых возможностей и прекрасную интеграцию этого инструмента с .NET Framework и Visual Studio .NET.


Код для вставки в блог:


Оставьте свой комментарий

Чтобы оставлять комментарии, Вам нужно ВОЙТИ или ЗАРЕГИСТРИРОВАТЬСЯ

Новостная лента