If (gdSelected in State) or (gdFocused in State)then — КиберПедия 

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

Опора деревянной одностоечной и способы укрепление угловых опор: Опоры ВЛ - конструкции, предназначен­ные для поддерживания проводов на необходимой высоте над землей, водой...

If (gdSelected in State) or (gdFocused in State)then

2020-06-05 219
If (gdSelected in State) or (gdFocused in State)then 0.00 из 5.00 0 оценок
Заказать работу

Begin

DBGrid1.Canvas.Brush.Color:=clHighLight;

DBGrid1.Canvas.Font.Color:=clWhite;

End

Else

Begin

DBGrid1.Canvas.Brush.Color:=clWhite;

DBGrid1.Canvas.Font.Color:=clBlack;

// Если поле цвета не пустое то использовать цвет из поля

if DataModule1.ADOTable1Color.AsString<>'' then

DBGrid1.Canvas.Font.Color:=

StringToColor(DataModule1.ADOTable1Color.AsString);

end;

// Очищаю ячейку

DBGrid1.Canvas.FillRect(Rect);

// Вывожу текст ячейки

DBGrid1.Canvas.TextOut(Rect.Left, Rect.Top, Field.AsString);

Except

DBGrid1.Canvas.TextOut(Rect.Left, Rect.Top, Field.AsString);

end;

end;

Прежде чем описывать этот код хочу тебя предупредить, что пока что у тебя ничего не  ткомпилируется. Delphi будет ругаться на тип TField. Этот тип описан в модуле db, поэтому добавь его в раздел uses. После этого при компиляции ошибок не должно быть. Теперь рассмотрим параметры, которые мы получили в обработчик. У нашего обработчика события есть следующие параметры: Sender – объект, который сгенерировал это событие. У нас это будет сетка.

Rect – здесь хранятся границы области ячейки, которую надо перерисовать. Границы передаются в виде структуры TRect.

Field – этот параметр имеет тип TField и указывает на поле, которое надо перерисовать.

State – здесь находятся параметры, указывающие на текущее состояние ячейки. Возможны следующие параметры:

gdSelected – ячейка выделена.

gdFocused – ячейка имеет фокус ввода.

gdFixed – ячейка является фиксированной. Такие ячейки используются для названий колонок (сверху сетки) и для индикации текущей строки (слева сетки).

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

В следующей строке я проверяю, если текущая ячейка выделена или имеет фокус ввода, то цвет кисти изменяю на clHighLight (это константа, хранящая цвет, используемый для подсветки). Цвет шрифта я устанавливаю в белый. Если ячейка не выделена, то цвет фона (цвет кисти) делаю белым, а цвет шрифта чёрным. Далее идёт проверка, если поле цвета текущей строки не пустое, то цвет шрифта меняю на тот цвет, который указан в поле цвета. Единственное, что надо учитывать – цвет храниться в виде строки, поэтому я преобразовываю его в цвет с помощью функции StringToColor.

Все приготовления закончены, можно заняться рисованием. Для начала я очищаю старое значение ячейки с помощью вызова метода FillRect холста сетки, который закрашивает указанную область цветом кисти (фона). В качестве единственного параметра я указываю область ячейки в виде структуры TRect, которую получаю через параметры обработчика.

После закраски я рисую текст ячейки. Если произошла какая-то ошибка во время подготовки к рисованию (она может возникнуть только при преобразовании StringToColor, если в поле находиться неправильное значение), то я пытаюсь снова вывести текст в блоке except…end.

 

Создание отчётности в Excel

Первое, с чем мы познакомимся – отчётность в Excel. Потребность в выгрузке данных в Excel может возникнуть у каждого программиста баз данных, ведь Office установлен в нашей стране практически на каждом компьютере. А это значит, что нашу отчётность можно смело переносить между компьютерами и быть уверенным, что её смогут прочитать.

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

Но в начале всё таки ткнём мышкой и добавим на форму одну кнопку, по нажатию которой будет создаваться отчётность. Я ещё добавил к программе пункт меню «Экспорт в Excel» в меню «Файл». Результат можешь увидеть на рисунке 15.1.1.

Вот теперь мышку можно убирать. Переходи в редактор кода и сразу же добавляй в раздел uses модуль ComObj. В этом модуле описаны все необходимые функции для работы с COM объектами (мы о них пока не говорили, но всё ещё впереди).

Рисунок 15.1.1 Кнопка создания отчётности в Excel

Теперь создавай обработчик события для кнопки и укажи его же в качестве обработчика для пункта меню (если ты его создал). В этом обработчике нужно написать следующий код:

Var

XLApp,Sheet,Colum:Variant;

index,i:Integer;

Begin

XLApp:= CreateOleObject('Excel.Application');

XLApp.Visible:=true;

XLApp.Workbooks.Add(-4167);

XLApp.Workbooks[1].WorkSheets[1].Name:='Отчёт ';

Colum:=XLApp.Workbooks[1].WorkSheets['Отчёт '].Columns;

Colum.Columns[1].ColumnWidth:=20;

Colum.Columns[2].ColumnWidth:=20;

Colum.Columns[3].ColumnWidth:=20;

Colum.Columns[4].ColumnWidth:=20;

Colum.Columns[5].ColumnWidth:=20;

Colum:=XLApp.Workbooks[1].WorkSheets['Отчёт '].Rows;

Colum.Rows[2].Font.Bold:=true;

Colum.Rows[1].Font.Bold:=true;

Colum.Rows[1].Font.Color:=clBlue;

Colum.Rows[1].Font.Size:=14;

Sheet:=XLApp.Workbooks[1].WorkSheets['Отчёт '];

Sheet.Cells[1,2]:='Телефонный справочник ';

Sheet.Cells[2,1]:='Фамилия ';

Sheet.Cells[2,2]:='Имя ';

Sheet.Cells[2,3]:='e-mail';

Sheet.Cells[2,4]:='Город ';

Sheet.Cells[2,5]:='Дата рождения ';

index:=3;

DataModule1.BookTable.First;

for i:=0 to DataModule1.BookTable.RecordCount-1 do

Begin

Sheet.Cells[index,1]:=DataModule1.BookTable.Fields.Fields[1].AsString;

Sheet.Cells[index,2]:=DataModule1.BookTable.Fields.Fields[2].AsString;

Sheet.Cells[index,3]:=DataModule1.BookTable.Fields.Fields[3].AsString;

Sheet.Cells[index,4]:=DataModule1.BookTable.Fields.Fields[5].AsString;

Sheet.Cells[index,5]:=FormatDateTime('dddddd',

DataModule1.BookTable.Fields.Fields[6].AsDateTime);

Inc(index);

DataModule1.BookTable.Next;

end;

Первая строка создаёт объект Excel (XLApp:= CreateOleObject(' Excel. Application')), и записывает его в переменную XLApp. Эта переменная типа Variant. Variant - это тип, который может принимать любые значения: строки, числа, указатели и др.

Функцию CreateOleObject я сейчас подробно рассматривать не буду, потому что она не относиться к базам данных или отчётности, и требует отдельного разговора.

Единственное, что я сейчас скажу – она позволяет наладить связь с другим приложением по технологии COM. Через эту связь можно передавать данные в чужие приложения. Для этого программа, к которой мы присоединяемся, должна иметь соответствующие возможности для получения данных из вне (как, например, Excel) и тебе должны быть известны функции с которыми можно работать. Чаще всего такие вещи документируются на сайте разработчиков. Я же не могу описать все возможности всех программ, потому что если это сделать, то «Война и Мир» покажутся детской колыбельной. Я думаю, это никому не нужно. Так что я рассмотрю только Excel, чтобы показать возможности передачи данных между приложениями.

Вторая строка (XLApp.Visible:=true) заставляет запустить сам Excel. Потом я добавляю новую рабочую книгу (XLApp.Workbooks.Add(-4167)). Число в скобках – это константа, которая означает создание книги и её изменять нельзя. Подробнее о всех константах ты можешь почитать в руководстве разработчика на сайте MS или в файле excel97.pas, а я не могу тратить на это место книги, потому что констант предостаточно.

Дальше я даю название созданной книге XLApp. Workbooks[1]. WorkSheets[1]. Name:='Отчёт'. Это действие не обязательно, но я всегда это делаю, потому что меня бесит название по умолчанию " Лист 1 ". Всё должно быть понятно с первого взгляда.

Теперь у нас Excel запущен и создана новая книга. Можно переходить к впечатыванию данных. Но прежде чем это сделать я отформатирую колонки и строки. Для этого я получаю указатель на колонки рабочей книги (Colum:= XLApp. Workbooks[1].

WorkSheets['Отчёт']. Columns), и записываю результат в переменную Colum типа Variant.

Теперь последовательно изменяю ширину колонок (Colum. Columns[1]. ColumnWidth:=

20). На русском эта команда будет звучать так:  К олонки.Колонка[1].ШиринаКолонки:=20.

После этого я в ту же переменную записываю указатель на строки рабочей книги (Colum:= XLApp. Workbooks[1]. WorkSheets['Отчёт ']. Rows). Для украшения строк нашего отчёта, я устанавливаю у первых двух строк жирный шрифт (Colum. Rows[1]. Font. Bold:= true). В квадратных скобках теперь порядковый номер строки. Далее идут две строки, в которых я устанавливаю цвет первой строки в синий и размер шрифта равный 14.

Форматирование окончено, теперь можно выводить данные. Для этого я получаю указатель на лист (Sheet:=XLApp.Workbooks[1].WorkSheets['Отчёт']). Для того, чтобы вывести данные, нужно просто присвоить значение в Sheet.Cells[строка, колонки]. Давай посмотрим на код вывода данных таблицы:

i ndex:=3;

DataModule1.BookTable.First;

for i:=0 to DataModule1.BookTable.RecordCount-1 do

Begin

Sheet.Cells[index,1]:=DataModule1.BookTable.Fields.Fields[1].AsString;

Sheet.Cells[index,2]:=DataModule1.BookTable.Fields.Fields[2].AsString;

Sheet.Cells[index,3]:=DataModule1.BookTable.Fields.Fields[3].AsString;

Sheet.Cells[index,4]:=DataModule1.BookTable.Fields.Fields[5].AsString;

Sheet.Cells[index,5]:=FormatDateTime('dddddd',

DataModule1.BookTable.Fields.Fields[6].AsDateTime);

Inc(index);

DataModule1.BookTable.Next;

end;

Сначала я задаю переменной index значение 3. Эта переменная будет отображать, в какую строку таблицы Excel мы сейчас должны выводить данные. Первые две строки у нас уже заняты заголовками для отчёта, поэтому данные нужно начинать выводить с третей строки.

Обрати внимание, что строки и таблицы в Excel нумеруются начиная с единицы, а не с нуля, как в остальных таблицах и массивах.

 

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

Теперь мы готовы запускать цикл, в котором будут перебираться все строки и информация из них будет попадать в Excel. Цикл я запускаю начиная с 0 и до количества строк в таблицы. Таким образом я переберу все записи.

Почему в качестве цикла я использую именно конструкцию for..to..do? Не знаю, просто иногда удобней так, а иногда я использую цикл while. С циклом while этот код выгладил бы так:

while DataModule1.BookTable.Eof<>true do

Begin

// Вывод данных в Excel

Увеличение переменной index;

Переход на следующею строку;

end;

В принципе, всё то же самое, только используется цикл while. Этот цикл удобнее использовать, когда нужно вывести не всю таблицу, а, например, только начиная с текущей позиции. В этом случае не надо будет перед циклом переходить на первую строку, а достаточно только запустить этот цикл, который будет выполняться, пока DataModule1.BookTable.Eof не станет равным true, т.е. не будет достигнут конец таблицы.

Только не забывай внутри цикла переходить на следующую строку. Если ты забудешь это сделать с циклом for, то у тебя в Excel попадёт столько же строк, сколько и в таблице, но все они будут одинаковыми (равны первой строке таблицы). Ну а при цикле while программа может зависнуть, потому что цикл будет бесконечным, ведь конец таблицы никогда не будет достигнут, если не переходить на следующие строки.

Теперь поговорим о выводе данных. Я последовательно заполняю колонки данными из таблицы, присваивая в Sheet.Cells[index, номер колонки], соответствующие данные.

Данные из базы данных я беру по индексу (до этого мы обращались по имени, но здесь я захотел показать тебе, как это делается по индексу). Для этого используется следующая конструкция:

DataModule1.BookTable.Fields.Fields[Номер поля ].AsString

После вывода данных я увеличиваю переменную Index, чтобы на следующем этапе выводить данные в следующую строку и перехожу на новую строку.

В принципе, это и всё. На последок я дам несколько замечаний и покажу тебе универсальный способ вывод данных из сетки:

for i:=1 to Table.RecordCount do

Begin

for j:=1 to DBGrid.Columns.Count do

Sheet.Cells[Index, j]:=DBGrid.Fields[j-1].AsString;

Inc(Index);

Table.Next;

end;

Это просто общий пример не связанный с нашей программой. Здесь так же запускается цикл по всем строкам таблицы. Но вывод данных происходит по новому. Для этого запускается ещё один цикл от 1 до количества колонок в сетке DBGrid. А внутри этого цикла я присваиваю очередной колонке Excel, значение из такой же колонки сетки DBGrid:

Sheet.Cells[ Номер строки, Номер колонки ]:=

DBGrid.Fields[ Номер колонки в сетке ].AsString;

Этот способ более универсален и может подойти почти всегда, когда надо вывести всё содержимое сетки DBGrid и все данные одного типа. В нашем случае в таблице есть дата, поэтому, чтобы она красиво выгладила я её форматирую с помощью FormatDateTime. Так что прямой перенос для этой колонке был бы не очень удобен, но остальные колонки можно было бы перенести указанным способом.

В процессе вывода данных можно изменять цвет строк Sheet.Rows[строка].Font.Color или колонок Sheet.Columns[колонка]. Font.Color, простым присваиванием (как мы это делали при форматировании). Если нужно изменить цвет отдельной ячейки, то это можно сделать, присвоив новое значение в Sheet.Cells[строка, колонка].Font.Color.

Вот ещё некоторые параметры, которые ты можешь изменить:

Sheet.Cells[строка,колонка].Font.Italic - курсивный шрифт

Sheet.Cells[строка,колонка].Font.Bold - жирный шрифт

Sheet.Cells[строка,колонка].Font.Underline - подчёркнутый шрифт

Sheet.Cells[строка,колонка].Font.Size - размер шрифта

С помощью всего этого, ты сможешь создавать простые, но эффективные отчёты. В Delphi, в директории Lib есть файлик excel97.pas, в нём ты найдёшь все доступные функции Excel. Если что-то не будет ясно, то пока отложи это занятие, чуть позже ты наберёшься навыков для понимания заголовочных файлов.

А у нашей программы остался один недостаток – она выводит данные только из основного справочника, и не учитывает телефоны. Чтобы избавиться от этого недостатка можно написать отдельный SQL запрос, который будет формировать сводную таблице из наших двух. Этот запрос можно поместить в отдельный компонент ADOQuery, выполнить его и брать данные оттуда, а не из таблицы BookTable.

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

SELECT *

FROM Справочник, Телефоны

WHERE Справочник.Key1=Телефоны.LinkKey

Рисунок 15.1.2 Кнопка создания отчётности в Excel

 

Отчётность в Quick Reports

еперь я хочу познакомить тебя с мощным средством создания отчётов, которое входит в поставку Delphi – это Quick Reports. Он не является самым быстрым, и в сети Internet можно найти множество более быстрых, как платных, так и бесплатных генераторов отчётов. Н о Quick Reports очень мощный и уже установлен в Delphi и готов к работе. Именно поэтому мы будем рассматривать его, Где бы ты не сел за Delphi, этот генератор уже будет установленным и его можно использовать.

Все компоненты Quick Reports находятся на закладке QReport палитры компонентов. В Delphi 6 у меня уже 23 компонента, позволяющие создать умопомрачительные документы готовые к печати. Давай сначала посмотрим на головной компонент Quick Reports – TQuickRep. Этот компонент – основа любого отчёта. Он представляет собой холст листа будущего отчёта.

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

Давай посмотрим на объектный инспектор и разберёмся с полями нашего отчёта:

Bands – здесь ты можешь указать, что должен иметь будущий документ, а он может содержать:

HasColumnHeader – Заголовки колонок. Если твой отчёт будет содержать таблицу, то она должна иметь шапку, где будут описаны названия колонок. Вот именно эту шапку создают в этой части документа. Так что если тебе нужна будет таблица, то этому свойству нужно будет присвоить true.

HasDetail – если в отчёте есть таблица, то вид строк делается в этом разделе.

HasPageFooter – в этом разделе создаётся нижний колонтитул.

HasPageHeader – здесь создаётся заголовок документа.

HasSummary –содержимое этого раздела печатается один раз в конце отчёта (на последней странице).

HasTitle – в этом разделе делается заголовок отчёта.

Попробуй создать новый проект и бросить на форму один компонент QuickRep. Теперь включи какие-нибудь разделы и посмотри на результат. На форме должны появиться области очерченные пунктирной линией и внизу этой области должно быть написано её предназначение. Так ты легко можешь отличить их между собой. Любую область можно выделить и растянуть или уменьшить (рисунок 15.2.1).

Рисунок 15.2.1 Вид компонента QuickRep с включенными областями

DataSet – здесь указывается набор данных (таблица) из которой отчёт будет брать данные.

Font – шрифт, который будет использоваться по умолчанию.

Frame – здесь ты указываешь параметры рамки.

Options – здесь тебе доступны три параметра. Если FirstPageHeader равно true, то заголовок печатается только на первой странице отчёта. Если LastPageFooter равен true, то нижний колонтитул печатается только на последней странице отчёта. Если установить свойство Compression в true, то отчёт будет сохраняться в сжатом виде.

Page – здесь тебе доступны все необходимые опции для контроля над бумагой отчёта. Ты можешь установить её размеры, отступы и ориентацию.

PrinterSettings – здесь находятся настройки принтера. С принтером мы уже работали, да и настройки практически не требуют пояснения.

ReportTitle – здесь находится заголовок печатаемого документа.

ShowProgress – если этот параметр равен true то во время печати тебе будет доступен индикатор хода выполнения печати.

SnapToGrid – нужно ли выравнивать компоненты по установленной сетке.

Zoom – масштаб отображения данных.

Если дважды щёлкнуть по компоненту QuickRep, то перед тобой откроется окно, в котором все эти настройки представлены в одном окне и в очень удобном виде. Они достаточно понятны и легко разобраться со всем самостоятельно (смотри рисунок 15.2.2).

Я предпочитаю пользоваться именно этим окном, потому что здесь всегда можно увидеть будущий результат и если что, то все изменения можно отменить нажатием кнопки Cancel.

Рисунок 15.2.2 Окно настроек отчёта.

Пока теории хватит, давай посмотрим, как же действует отчётность. Открой телефонный справочник, созданный в прошлой главе. Добавь на панель кнопку печати, а обработчик его события OnClick мы напишем чуть позже. Сейчас мы будем создавать форму отчёта.

Создай новую форму (назовём её ReportForm) и сохрани в модуле ReportFormUnit. Сразу же подключи к этому модулю, модуль данных (DataModule), где у нас хранятся компоненты доступа к таблицам базы данных. Брось на форму компонент QuickRep. Выдели этот компонент и в объектном инспекторе включи параметры HasTitle и HasDetail свойства Bands.

Теперь нужно в этих секциях расположить компоненты, которые будут отображать нужную нам информацию. На закладке QReport палитры компонентов доступны следующие компоненты, которые можно располагать в этих разделах:

QRLabel – надпись. Этот компонент похож на стандартный компонент TLabel и просто отображает нужные данные.

QRDBText – данные. Этот компонент тоже похож на TLabel, только он предназначен для отображения значения какого либо поля из базы данных. Тип поля базы данных должен быть совместим с текстом, т.е. может быть целым числом, строкой, датой, но не может быть картинкой или бинарными данными.

QRSysData – системная информация. Это опять копия TLabel только с возможностью отображать системную информацию – дату, время, номер страницы, номер строки в таблицы, общее количество страниц и т.д.

QRMemo – набор строк. Этот компонент уже похож на TMemo и способен отображать Memo данные из базы данных.

QRShape – компонент для создания обрамлений. Он чем то похож на стандартный TShape.

QRImage – картинка. Компонент схожий с TImage.

Теперь примемся за оформление отчёта. Выдели область заголовка (Title) и увеличь её размер где-то в два раза. В правый верхний угол области (именно области Title, а не компонента QuickRep) помести один компонент QRSysData. Выдели его и в свойстве дата выбери значение qrsDateTime. Теперь этот компонент будет отображать в правом, верхнем углу дату распечатки документа. Советую всегда это делать, чтобы ты сразу видел, какая версия документа была распечатана последней.

В центре области брось компонент QRLabel, увеличь шрифт в свойстве Font и напиши в свойстве Caption текст «Распечатка строки из базы Телефонов». Слева области можешь установить картинку QRImage, чтобы убедиться, что работа с ней ничем не отличается от работы с компонентом TImage.

Оцени результат!!! Мой результат ты можешь увидеть на рисунке 15.2.3.

Рисунок 15.2.3 Вид заголовка нашего отчёта.

Теперь переходим к области Detail. Здесь давай выстроим с троку пять компонентов QRLabel и дадим им заголовки: Фамилия, Имя, e-mail, Город, Дата рождения. Под ними поставь пять компонентов QRDBText. У всех у них установи свойство DataSet в DataModule1.BookTable, а в свойстве DataField укажи соответствующие поля. У тебя должно получиться что-то похожее на рисунок 15.2.4.

Рисунок 15.2.4 Вид блока Detail.

Теперь переходим в главный модуль и по нажатию кнопки печати пишем следующий код:

procedure TMainForm.PrintButtonClick(Sender: TObject);

Begin

ReportForm.QuickRep1.PreviewModal;

end;

В этом коде я вызываю метод PreviewModal компонента QuickRep. Этот метод модально показывает окно предварительного просмотра созданного нами документа. Попробуй запустить программу, выделить какую-нибудь строку и нажать кнопку печати. Перед тобой откроется окно предварительного просмотра, как на рисунке 15.2.5.

Рисунок 15.2.5 Окно предварительного просмотра.

В этом окне достаточно нажать кнопку печати, и документ будет распечатан на принтере.

 


Поделиться с друзьями:

Организация стока поверхностных вод: Наибольшее количество влаги на земном шаре испаряется с поверхности морей и океанов (88‰)...

Индивидуальные и групповые автопоилки: для животных. Схемы и конструкции...

Папиллярные узоры пальцев рук - маркер спортивных способностей: дерматоглифические признаки формируются на 3-5 месяце беременности, не изменяются в течение жизни...

Общие условия выбора системы дренажа: Система дренажа выбирается в зависимости от характера защищаемого...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.085 с.