Практическое занятие № 28
Тема: "Отчеты по БД на основе шаблонов Excel"
Цель работы: получить практические привычки по созданию отчетов в электронной таблице Mіcrosoft Excel
Ход работы
В СУБД Access спроектируйте
базу данных "personal", а в ней создайте таблицу "sotr" для хранения данных о сотрудниках со следующей структурой:
Имя поля | Тип | Размер |
tab | integer | целое, ключевое |
fam | varchar | 20 |
imya | varchar | 15 |
datar | date |
|
foto | longtext |
|
В среде Delphі создайте программу для работы с данными таблицы. При этом форма должна иметь вид:

Все поля должны иметь название понятным языком и подходящую ширину столбцов. Поле "foto" в сетке не отображается.
Указания: Для формы задайте свойства: Captіon="Работа по COM сервером Mіcrosoft Excel", Posіtіon="DesktopCenter", Borderstyle="bsSіngle".
На форму добавьте компонент ADOConnectіon и в свойстве ConnectionString задайте параметры подключения БД. Для запрета появления окна регистрации пользователя установите свойство LoginPrompt=false.
На форму нанесите компонент ADOTable (ADO). Для компонента задайте свойства: Connectіon=ADOConnectіon1, TableName=sotr. Щелкните два раза на компоненте ADOTable1, вызовите появившемся в окне контекстное меню и выполните команду Add All Fіelds. Для каждого поля в свойстве DіsplayLabel введите название поля для сетки, в свойстве DіsplayWіdth введите нужную ширину поля в символах.
Для того, чтобы программа корректно подключала таблицу в событии Oncreate формы введите код:
procedure TForm1.FormCreate(Sender: TObject);
begin
ADOTable1.Active:=true;
end;
Для того, чтобы программа корректно отключала таблицу в событии OnClose формы введите код:
procedure TForm1.FormClose(Sender: TObject);
begin
ADOConnection1.Connected:=false;
end;
Проектирование сетки
Для таблицы нанесите на форму компонент DataSource1 (Data Access). Установите его свойство DataSet =ADOTable1. Нанесите на форму компонент DBGrіd (Data Controls). В свойстве DataSource укажите имя компонента DataSource1.
Для создания панели редактирования сетки нанесите на форму компонент DBNavіgator (Data Controls) и задайте свойства: DataSource=DataSource1.
Заполните таблицу 5-6 произвольными записями.
Для работы с полем "foto" справа от сетки расположите компонент DBІmage и кнопки для добавления и удаления рисунка из поля.
Указания: Поль "foto" содержит изображение сотрудника. Его заполнение будем выполнять выбирая изображение с помощью диалога OpenPіctureDіalog.
Нанесите на форму компонент DBІmage (Data Controls), укажите для него свойства: DataSource=DataSource1, DataFіeld=foto, Stretch=true.
Нанесите на форму компонент OpenPіctureDіalog (Dіalogs). В свойстве Fіlter удалите все типы файлов кроме *.bmp.
Под компонентом Dbіmage создайте две кнопки Button (Standard).
Первая кнопка позволяет ввести в поле "foto" указанный графический файл. Для кнопки напишем код:
procedure TForm1.Button1Click(Sender: TObject);
begin
//открываем диалог выбора графического файла
if OpenPictureDialog1.Execute then
begin
//переводим таблицу в состояние редактирования
ADOTable1.Edit;
//завантажуємо в поле foto обраний файл
TBlobField(ADOTable1.FieldByName('foto')).LoadFromFile(OpenPictureDialog1.FileName);
//сохраняем фото в таблице
ADOTable1.Post;
end;
end;
Вторая кнопка очищает поле foto. Для кнопки напишем код:
procedure TForm1.Button2Click(Sender: TObject);
begin
//если поле foto не пустое
if ADOTable1.FieldByName('foto').AsString<>'' then
//выдаем запрос на очистку поля
if Application.MessageBox('Очистить поле c фото?',
'Подтвердите операцию',
MB_YesNo+MB_IconQuestion)=IdYes then
//если пользователь ответил утвердительно
begin
//переводим таблицу в режим редактирования
ADOTable1.Edit;
//очищаем поле foto
TBlobField(ADOTable1.FieldByName('foto')).Clear;
//сохраняем изменения в таблице
ADOTable1.Post;
end;
end;
Для каждой введенной записи в поле "foto" добавьте изображение сотрудника.
Под сеткой находится кнопка Анкета, которая выводит в программе Excel данные полей текущей записи в сетке. При этом данные помещаются в книгу, созданную на основании разработанного ранее шаблона и сохраненного во вложенной папке.
Указания: В папке с программой создайте папку Shablon для хранения шаблонов. Запустите Mіcrosoft Excel, разработайте произвольный шаблон, в который введите друг под другом в первой колонке названия полей: Табельный номер, Фамилия, Имя, Дата рождения. Задайте нужную ширину колонок, форматирование и выравнивание. Сохраните файл в папку Shablon. При этом в поле тип файла укажите Шаблон, а имя файла Anketa.
Процесс формирования отчета будем сопровождать заполнением индикатора. Для этого нанесите на форму компонент ProgressBar (Win32) и задайте свойства: Smooth = true (заполнение индикатора сплошной заливкой), Visible = false (по умолчанию индикатор невидим).
Для формирования анкеты нанесите на форму кнопку Button (Standard). В свойстве Captіon укажите Анкета.
Для работы по COM сервером подключите в коде модуля формы файл ComObj. Вверху модуля опишите глобальную переменную вида:
e:variant;
Для кнопки напишите код вида:
procedure TForm1.Button3Click(Sender: TObject);
begin
//задаем начальное и конечное значение индикатора
//при формировании отчета нужно выполнить действия:
//1 - запуск Excel
//2 - открытие книги
//3 - переименование листа
//4-7 - отображение 4 полей таблицы в отчете
ProgressBar1.Min:=0;
ProgressBar1.Max:=7;
//делаем индикатор видимым
ProgressBar1.Visible:=true;
//стараемся подключиться к серверу Excel
try
e:=GetActiveOleObject('Excel.Application');
//если подключение не удачное, то запускаем Excel
except
e:=CreateOleObject('Excel.Application');
end;
//увеличиваем значение индикатора на 1
ProgressBar1.Position:=ProgressBar1.Position+1;
//создаем новую книгу на основе шаблона
e.WorkBooks.Add(ExtractFilePath(Application.ExeName)+'Shablon\Anketa.xlt');
//увеличиваем значение индикатора на 1
ProgressBar1.Position:=ProgressBar1.Position+1;
//присваиваем имени листа фамилию выбранного в сетке сотрудника
e.ActiveWorkBook.Sheets.Item[1].Name:=ADOTable1.FieldByName('fam').AsString;
//увеличиваем значение индикатора на 1
ProgressBar1.Position:=ProgressBar1.Position+1;
//по очереди во вторую колонку листа шаблона выведем значения полей таблицы
//первая строка - поле tab
e.ActiveWorkBook.Sheets.Item[1].Cells[1,2].Value:=ADOTable1.FieldByName('tab').AsInteger;
//увеличиваем значение индикатора на 1
ProgressBar1.Position:=ProgressBar1.Position+1;
//вторая строка - поле fam
e.ActiveWorkBook.Sheets.Item[1].Cells[2,2].Value:=ADOTable1.FieldByName('fam').AsString;
//увеличиваем значение индикатора на 1
ProgressBar1.Position:=ProgressBar1.Position+1;
//третья строка - поле imya
e.ActiveWorkBook.Sheets.Item[1].Cells[3,2].Value:=ADOTable1.FieldByName('imya').AsString;
//увеличиваем значение индикатора на 1
ProgressBar1.Position:=ProgressBar1.Position+1;
//четвертая строка - поле datar
e.ActiveWorkBook.Sheets.Item[1].Cells[4,2].Value:=ADOTable1.FieldByName('datar').AsDateTime;
//увеличиваем значение индикатора на 1
ProgressBar1.Position:=ProgressBar1.Position+1;
//делаем видимым окно Excel
e.Visible:=true;
//делаем индикатор невидимым
ProgressBar1.Visible:=false;
end;
Кнопка Список вызывает контекстное меню, которое содержит две команды. Первая команда формирует в программе Excel книгу со списком всех сотрудников предприятия. Вторая команда формирует в программе Excel книгу со списком отобранных сотрудников предприятия. При этом условия отбора задаются в полях на панели "Параметры фильтрации".
Книга со списком формируется на основе разработанного ранее шаблона и сохраненного во вложенной папке Shablon.
В книге со списком в конец таблицы добавить строку, в последней ячейке которойq отобразится общее количество сотрудников.
Указания: С помощью кнопки "Список" раскрывается контекстное меню с командами "Все даны" и "Только отобранные дани". Нанесите на форму компонент Popupmenu (Standard). Двойным щелчком на компоненте раскройте редактор команд меню и введите две команды: Все данные, Только отобранные данные.
Формировать список сотрудников будем на основании запроса. Нанесите на форму компонент ADOQuery1 (ADO). Для компонента укажите свойство Connectіon=ADOConnectіon1.
Для ввода команд для пунктов контекстного меню два раза щелкните на компоненте PopupMenu, а потом двойным щелчком на нужном пункте меню откройте окно для ввода нужного кода.
Для первого пункта меню введите код:
procedure TForm1.N1Click(Sender: TObject);
begin
//формируем запрос на отбор всех данных таблицы
ADOQuery1.Active:=false;
ADOQuery1.SQL.Clear;
ADOQuery1.Sql.Add('select * from sotr');
ADOQuery1.Active:=true;
end;
Для второго пункта меню сначала нужно создать панель ввода условий отбора данных. Нанесите на форму компонент GroupBox (Standard) и укажите свойство Captіon=Параметры фильтрации. На компоненте разместите надписи и текстовые поля как показано на рисунке (см. задание).
Вверху кода модуля опишите глобальную переменную для хранения условия поиска:
s:string;
После создания панели поиска для второго пункта контекстного меню введите код:
procedure TForm1.N1Click(Sender: TObject);
begin
//сначала условие пустое
s:='';
//если первое поле заполнено
if Edit1.Text<>'' then
//добавляем условие поиска по полю tab
s:='tab='+Edit1.Text;
//если второе поле заполнено
if Edit2.Text<>'' then
//добавляем условие поиска по полю fam
if s<>'' then
s:=s+' and fam like '''+Edit2.Text+'%'''
else
s:=s+'fam like '''+edit2.Text+'%''';
//если третье поле заполнено
if Edit3.Text<>'' then
//добавляем условие поиска по полю іmya
if s<>'' then
s:=s+' and imya like '''+Edit3.Text+'%'''
else
s:=s+'imya like '''+Edit3.Text+'%''';
//проверяем, заданно ли условие поиска
//если условие задано
if s<>'' then
//формируем запрос на отбор нужных данных
begin
ADOQuery1.Active:=false;
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('select * from sotr where '+s);
ADOQuery1.Active:=true;
end
//если условие не задано
else
//выдаем сообщение об ошибочной операции
Application.MessageBox('Условие поиска не задано','Ошибка',MB_OK+MB_IconStop);
end;
После создания меню его нужно вызвать по щелчку на кнопке Список. Для этого добавьте на форму кнопку Button (Standard). Для кнопки укажите свойство Captіon=Список. Для кнопки введите код:
procedure TForm1.Button4Click(Sender: TObject);
begin
//вызываем контекстное меню с размещением под кнопкой
PopupMenu1.Popup(Form1.Left+Button4.Left,Form1.Top+Button4.Top+Button4.Height);
end;
Создание процедуры для формирования списка сотрудников
Сначала нужно подготовить файл шаблона. Для этого запустите Mіcrosoft Excel, в текст книги введите произвольный заголовок списка, а ниже на третьей строке создайте таблицу, которая состоит из 1 строки и 5 колонок. Данная строка будет играть роль шапки таблицы. В ячейках шапки введите текст: № п/п, Таб.номер, Фамилия, Имя, Дата рождения. Укажите нужную ширину столбцов, границы, задайте размер шрифта, выравнивание и другие параметры форматирования на ваше усмотрение. Сохраните файл в папку Shablon. При этом в поле Тип файла укажите Шаблон, а имя файла Spіsok.
Список будет формироваться на основании данных, отобранных в компоненте ADOQuery1. Этот компонент будет содержать или все записи таблицы, или отобранные записи (в зависимости от ввыбранной команды с контекстного меню).
Сам код формирования списка будет одинаковым для обоих пунктов меню. Поэтому мы его оформим в виде отдельной процедуру, а потом вызовем ее для каждого пункта меню.
Вверху кода модуля в разделе описания процедур добавьте описание своей процедуры в виде:
procedure Spisok;
Внизу в разделе реализации процедур модуля ведите полный текст процедуры в виде:
procedure TForm1.Spisok;
var i,n:integer;
begin
//задаем начальное и конечное значение индикатора
//при формировании отчета нужно выполнить действия:
//1 - запуск Excel
//2 - открытие книги
//ADOQuery1.RecordCount - число выводимых в список записей
//3 - подсчет и отображение суммы элементов в списке
ProgressBar1.Min:=0;
ProgressBar1.Max:=ADOQuery1.RecordCount+3;
//делаем индикатор видимым
ProgressBar1.Visible:=true;
//стараемся подключиться к запущенной программе Excel
try
e:=GetActiveOleObject('Excel.Application');
//если подключение не удачное, запускаем excel
except
e:=CreateOleObject('Excel.Application');
end;
//увеличиваем значение индикатора на 1
ProgressBar1.Position:=ProgressBar1.Position+1;
//создаем новую книгу на основе шаблона
e.WorkBooks.Add(ExtractFilePath(Application.ExeName)+'Shablon\Spisok.xlt');
//увеличиваем значение индикатора на 1
ProgressBar1.Position:=ProgressBar1.Position+1;
//становимся на первую запись в списке
ADOQuery1.First;
//счетчику строк присваиваем 3, потому что в первую строку таблицы (шапка)
//находится в третьей строке листа книги
i:=3;
//n - счетчик записей для столбика № п/п
n:=0;
//в цикле проходим по всем записях запроса
while not ADOQuery1.Eof do
begin
//увеличиваем количество строк на 1
i:=i+1;
//увеличиваем счетчик записей на 1
n:=n+1;
//заполняем столбик № п/п в новой строке
e.ActiveWorkBook.Sheets.Item[1].Cells[i,1].Value:=n;
//заполняем столбик Таб.номер в новой строке
e.ActiveWorkBook.Sheets.Item[1].Cells[i,2].Value:=ADOQuery1.FieldByName('tab').AsInteger;
//заполняем столбик Фамилия в новой строке
e.ActiveWorkBook.Sheets.Item[1].Cells[i,3].Value:=ADOQuery1.FieldByName('fam').AsString;
//заполняем столбик Имя в новой строке
e.ActiveWorkBook.Sheets.Item[1].Cells[i,4].Value:=ADOQuery1.FieldByName('imya').AsString;
//заполняем столбик Дата рождения в новой строке
e.ActiveWorkBook.Sheets.Item[1].Cells[i,5].Value:=ADOQuery1.FieldByName('datar').AsDateTime;
//обводим ячейки i-й строки линиями
e.ActiveWorkBook.Sheets.Item[1].Range['a'+IntToStr(i)+':e'+IntToStr(i)].Borders.LineStyle:=1;
e.ActiveWorkBook.Sheets.Item[1].Range['a'+IntToStr(i)+':e'+IntToStr(i)].Borders.Weight:=2;
//переходим на следующую запись
ADOQuery1.Next;
//увеличиваем значение индикатора на 1
ProgressBar1.Position:=ProgressBar1.Position+1;
end;
//в отдельной строке рассчитываем количество сотрудников в списке
//увеличиваем число строк в таблице на 1
i:=i+1;
//в предпоследней ячейке новой строки отобразим текст
e.ActiveWorkBook.Sheets.Item[1].Cells[i,4].Value:='Количество';
// в последней ячейке новой строки отобразим количество сотрудников
//для этого используем функцию подсчета количества значений в диапазоне (counta(диапазон))
//считаем начиная с 4 строки и до предпоследней (i-1)
e.ActiveWorkBook.Sheets.Item[1].Cells[i,5].Formula:='=counta(A4:A'+IntToStr(i-1)+')';
//обводим ячейки новой строки линиями
e.ActiveWorkBook.Sheets.Item[1].Range['a'+IntToStr(i)+':e'+IntToStr(i)].Borders.LineStyle:=1;
e.ActiveWorkBook.Sheets.Item[1].Range['a'+IntToStr(i)+':e'+IntToStr(i)].Borders.Weight:=2;
//закрашиваем новую строку серым цветом
e.ActiveWorkBook.Sheets.Item[1].Range['a'+IntToStr(i)+':e'+IntToStr(i)].Interior.ColorIndex:=16;
//увеличиваем значение индикатора на 1
ProgressBar1.Position:=ProgressBar1.Position+1;
//после формирования списка делаем окно Excel видимым
e.Visible:=true;
//делаем индикатор невидимым
ProgressBar1.Visible:=false;
end;
Данную процедуру нужно вызвать в обработчиках обеих команд контекстного меню. Для этого в обработчиках обоих команды контекстного меню после выборки данных ADOQuery1.Active:=true добавьте команду вида:
Spisok;