Практическое занятие № 15

Тема: Отчеты по БД на основе шаблонов Excel

Цель работы: получить практические навыки по формированию отчетов в программе Microsoft Excel

 

Ход работы

 

Пусть в СУБД Access спроектирована база данных (скачать). База защищена паролем "rpo" и имеет две таблицы.

 

Таблица "students", состоит из полей:

 

Имя поля Тип Размер
id_stud Счетчик Ключевое
fam Текстовый 15
imya Текстовый 15
otch Текстовый 15
finance Текстовый 10 (Госзаказ, Контракт)
datar Дата/время  
srbal Числовой Одинарной точности с плавающей точкой. Значение по умолчанию - 0
foto Поле OLE  
id_grup Числовой Внешний ключ для связи с таблицей groups

 

Таблица "groups", состоит из полей:

 

Имя поля

Тип

Размер

id_grup Счетчик Ключевое
grupa

Текстовый

30

 

В программе на C# выполните подключение базы данных

 

Указания: на панели "Источники данных" щелкните на кнопке "Добавить новый источник данных" (если панель не отображается, то выбери команду меню "Данные - Показать источники данных"). Запуститься мастер создания подключения к БД. В окне выберите значение "База данных", затем значение "Набор данных". На следующем шаге щелкните на кнопке "Создать подключение". В новом окне Вам будет предложено подключить файлы БД SQL Server. Щелкните на кнопке "Изменить" и выберите формат БД "Microsoft Access". После этого укажите нужный файл БД (путь к файлу не удаляйте, среда C# самостоятельно скопирует указанный файл в папку проекта и скорректирует путь к нему). Так как база защищена паролем, то щелкните на кнопке "Дополнительно" и в строке "Jet OLEDB: DataBase Password" укажите пароль "rpo". Для проверки соединения щелкните на кнопке "Проверить подключение". После задания всех параметров мастер предложит выбрать способ сохранения пароля к БД: не включать в строку подключения или включать в строку подключения. Выберите первый вариант для безопасности.

После задания параметров БД при переходе на следующий шаг мастера появится запрос на копирование файла БД в папку с проектом, подтвердите эту операцию.

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

На следующем шаге выберите обе таблицы students и groups, с которыми планируете работать в проекте, и щелкните "Готово".

Сразу нужно настроить поведение полей-счетчиков в таблицахВ окне "Источники данных" щелкните на кнопке "Изменить набор данных в конструкторе". Отобразится структура таблиц. Выделите поле id_stud в таблице students и измените свойства: AutoIncrementSeed = 1AutoIncrementStep = 1Выделите поле id_grup в таблице groups и измените свойства: AutoIncrementSeed = 1, AutoIncrementStep = 1.

 

Отображение данных из связанных таблиц

При выводе отчета о студентах одной из колонок будет колонка "Название группы", которой соответствует поле grupa из таблицы groups. Следовательно, нам нужно получать данные из двух связанных таблиц в одном наборе данных. Для этого создадим новый TableAdapter.

Щелкните правой кнопкой на пустом месте окна с таблицами и выберите команду "Добавить - Table Adapter". Введите текст запроса для связанного набора данных:

 

//отбираем все поля из таблицы stud и поле grupa из таблицы groups

SELECT students.*, groups.grupa FROM groups INNER JOIN students ON groups.id_grup = students.id_grup

 

Переименуйте созданную новую таблицу: Name = StudReport. В результате автоматически переименуется и связанный с таблицей TableAdapter в studReportTableAdapter.

 

Создайте программу для работы c БД:

 

 

Все поля в сетке назвать по-русски. Сетка заблокирована для ввода.

 

Указания: для формы задайте свойства: Caption=Поиск данных в БД, Position=DesktopCenter, Borderstyle=bsSingle (нерастягиваемая форма), MiximizeBox = false (нет кнопки разворачивания окна).

Для подключения связанного набора данных SotrReport нанесите на форму компонент DataRowView. Появится окно, в котором нужно указать подключаемую таблицу SotrReport. На форме появятся дополнительные компоненты для работы с таблицей: bazaDataSet - для доступа к подключению, studReportBindingSource - для работы со связанным  набором данных, studReportTableAdapter - для работы с копией таблицы БД. Фамилии студентов будем отображать в алфавитном порядке. Для этого для компонента sotrReportBindingSource задайте свойство Sort = fam (имя поля для сортировки).

Для сетки задайте свойства: AllowUserToAddRows = false (запрет добавления новых строк в сетке), AllowUserToDeleteRows = false (запрет на удаление данных в сетке без подтверждения), AlternatingRowsDefaultCellStyle - BackColor = серый (цвет фона четных строк сетки), AutoSizeColumnsMode=Fill (ширина колонок подстраивается под размер сетки). Для настройки параметров колонок сетки откройте ее свойство Columns. Вы увидите список всех ее колонок. Колонки id_stud, id_grup, foto сделайте невидимыми (Visible=false), для остальных колонок в свойстве HeaderText укажите названия как на рисунке. Колонку "Группа" переместите так, как показано на рисунке.

 

Если запустить программу на выполнение, то сетка будет пустой, потому что в строке соединения мы не сохранили пароль к БД и подключение не установлено.

Для формы откройте событие Load. В этом событии будут находится вызов метода  Fill(), загружающий копию связанного набора данных в компонент TableAdapter. Над этой командой добавьте команду подстановки пароля в строку соединения:

Properties.Settings.Default["BazaConnectionString"] += ";Jet OLEDB:Database Password=rpo";

 

Фото будем заполнять с помощью диалога выбора графического файла при щелчке на кнопке "+". Кнопка "-" очищает поле Фото.

 

Указания: добавьте компонент PictureBox.

 

Для связывания компонента с полем таблицы нужно в событии Load формы добавить команду:

 

pictureBox1.DataBindings.Add(new Binding("Image", studReportBindingSource, "foto", true));

 

Фото будем заполнять с помощью диалога. Нанесите на форму компонент OpenFileDialog и в свойстве Filter укажите допустимые форматы графических файлов:

 

Графические файлы|*.jpg;*.gif;*.bmp;*.png

 

Для кнопки "+" напишите код добавления фотографии:

 

void Button1Click(object sender, EventArgs e)

{

    //если файл в диалоге выбран

    if (openFileDialog1.ShowDialog()==DialogResult.OK)

    {

        //записываем файл в переменную

        Bitmap pict = new Bitmap(openFileDialog1.FileName);

        //в поле pictureBox отображаем переменную

        pictureBox1.Image = (Image)pict;

    }

}

 

Для кнопки "-" напишем код очистки фотографии:

 

void Button2Click(object sender, EventArgs e)

{

    pictureBox1.Image=null;

}

 

Кнопка Анкета формирует отчет по текущей записи на основании созданного шаблона.

 

Указания: в папке с программой создайте папку "Templates" для хранения шаблонов. Запустите Mіcrosoft Excel, в первую колонку листа введите в разные ячейки подписи к данным: Фамилия, Имя, Отчество, Группа, Финансирование, Дата рождения, Средний балл. Сохраните файл в папку "Templates". При этом в поле "Тип файла" укажите "Шаблон Excel 97-2003", а имя файла "Anketa".

Для формирования анкеты нанесите на форму кнопку Button. В свойстве Text укажите "Анкета".

Для работы с программой Microsoft Excel вверху кода формы подключите пространства имен:

 

using System.IO;

using Excel = Microsoft.Office.Interop.Excel;

using System.Reflection;

using System.Runtime.InteropServices;

 

Кроме этого нужно подключить COM библиотеку программы Microsoft Excel. В контекстном меню проекта выберите команду "Добавить ссылку". В новом окне перейдите на закладку COM и выберите элемент с именем "Microsoft Excel XX Object Library", где ХХ - номер версии Excel (на разных компьютерах может быть разным).

 

Также вверху класса формы опишите глобальную переменную:

 

Excel.Application ex;

 

Для кнопки напишите код вида:

 

void Button3Click(object sender, EventArgs e)

{

    //пытаемся подключиться к запущенному Excel

    try

    {

        ex = Marshal.GetActiveObject ("Excel.Application") as Excel.Application;

    }

    //если Excel на запущен, запускаем его

    catch (COMException err)

    {

        ex = new Excel.Application();

    }

 

    //создаем новую книгу на основе шаблона

    ex.Workbooks.Add(Application.StartupPath + "\\Templates\\Anketa.xlt");

 

    //во вторую колонку листа напротив введенных названий отобразим значения полей таблицы

    //в первую колонку первой строки листа отображаем второе поле таблицы

    (ex.ActiveWorkbook.Sheets[1] as Excel.Worksheet).Cells[1,2]=

        (studReportBindingSource.Current as DataRowView)["fam"];
        //во вторую колонку второй строки листа отображаем третье поле поле таблицы и т.д.

    (ex.ActiveWorkbook.Sheets[1] as Excel.Worksheet).Cells[2,2]=

        (studReportBindingSource.Current as DataRowView)["imya"];
        (ex.ActiveWorkbook.Sheets[1] as Excel.Worksheet).Cells[3,2]=

        (studReportBindingSource.Current as DataRowView)["otch"];
        (ex.ActiveWorkbook.Sheets[1] as Excel.Worksheet).Cells[4,2]=

        (studReportBindingSource.Current as DataRowView)["grup"];
        (ex.ActiveWorkbook.Sheets[1] as Excel.Worksheet).Cells[5,2]=

        (studReportBindingSource.Current as DataRowView)["finance"];
        (ex.ActiveWorkbook.Sheets[1] as Excel.Worksheet).Cells[6,2]=

        (studReportBindingSource.Current as DataRowView)["datar"];
        (ex.ActiveWorkbook.Sheets[1] as Excel.Worksheet).Cells[7,2]=

        (studReportBindingSource.Current as DataRowView)["srbal"].ToString();

 

    //делаем окно Excel видимым   

    ex.Visible=true;

}

 

Кнопка "Список" формирует в программе Microsoft Excel документ со списком отобранных записей. При этом условия отбора задаются в полях внизу формы. Если условие не задано, то отчет формируется по всей таблице.

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

Документ со списком формируется на основе разработанного ранее шаблона и сохраненного во вложенной папке "Templates".

 

Указания: отчет будет формироваться по шаблону. Запустите Mіcrosoft Excel, на листе введите произвольный заголовок списка, а ниже создайте таблицу, которая состоит из 1 строки и 9 колонок. Данная строка будет играть роль шапки таблицы.

В ячейках шапки введите текст: № п/п, Фамилия, Имя, Отчество, Группа, Финансирование, Дата рожд., Средний балл. Если колонок много разверните лист в альбомную ориентацию. Укажите нужную ширину столбцов, задайте размер шрифта, выравнивание и другие параметры форматирования на ваше усмотрение. Сохраните файл в папку "Templates". При этом в поле "Тип файла укажите "Шаблон Excel 97-2003", а имя файла "List".

Проектирование панели для задания условия фильтрации

Для задания условий поиска нанесите на форму 3 текстовых поля TextBox.

 

Для отображения на форме процесса постройки отчета нанесите на форму компонент ProgressBar и задайте свойство Visible=false, Style = Continuous (плавное заполнение индикатора).

Нанесите на форму кнопку и задайте для нее свойство Text = Список. Для кнопки введите код:

 

void Button4Click(object sender, EventArgs e)

{

    //вначале условие не задано

    string s = "";

    //если первое поле не пустое, добавляем к условию

    if (textBox1.Text != "")

        s += "fam like '" + textBox1.Text + "%'";

   

    //если второе поле не пустое, добавляем к условию

    if (textBox2.Text != "")

        if (s != "")

            s += " and imya like '" + textBox2.Text + "%'";

        else

            s += "imya like '" + textBox2.Text + "%'";

   

    //если третье поле не пустое, добавляем к условию

    if (textBox3.Text != "")

        if (s != "")

            s += " and otch like '" + textBox3.Text + "%'";

        else

            s += "otch like '" + textBox3.Text + "%'";

 

    //если условие задано

    if (s != "")

        //к набору данных из сетки применяем условие фильтрации

        studReportBindingSource.Filter = s;

    //если условие не задано

    else

        //у набора данных из сетки отключаем фильтр

        studReportBindingSource.Filter = null;

 

    //начинаем строить отчет

    //настраиваем начальные параметры индикатора

    //начальное значение 0

    progressBar1.Value = 0;

    //максимальное значение равно количество записей в наборе + 2

    //(запуск Excel + подсчет итоговых показателей по таблице)

    progressBar1.Maximum = studReportBindingSource.Count+2;

    //делаем индикатор видимым

    progressBar1.Visible = true;

  

    //пытаемся подключиться к запущенному Excel

    try

    {

        ex = Marshal.GetActiveObject("Excel.Application") as Excel.Application;

    }

    //если Excel на запущен, запускаем его

    catch (COMException err)

    {

        ex = new Excel.Application();

    }

 

    //создаем новую книгу на основе шаблона   

    ex.Workbooks.Add(Application.StartupPath + "\\Templates\\List.xlt");

   

    //увеличиваем индикатор на 1

    progressBar1.Value++;

 

    //счетчик строк в таблице начинается с 2

    //(у нас в шаблоне две строки листа заняты: заголовок + шапка)

    int i = 2;

 

    //в цикле проходим по набору данных StudReport

    foreach (DataRowView row in studReportBindingSource)

    {

        //наращиваем количество строк

        i++;

        //в каждую ячейку i-й строки таблицы записываем значения поля запроса

        //в первую колонку выводи значение № п/п

        (ex.ActiveWorkbook.Sheets[1] as Excel.Worksheet).Cells[i, 1] = i-2;

        //в остальные колонки выводим значения полей текущей записи

        (ex.ActiveWorkbook.Sheets[1] as Excel.Worksheet).Cells[i, 2] = row["fam"];

        (ex.ActiveWorkbook.Sheets[1] as Excel.Worksheet).Cells[i, 3] = row["imya"];

        (ex.ActiveWorkbook.Sheets[1] as Excel.Worksheet).Cells[i, 4] = row["otch"];

        (ex.ActiveWorkbook.Sheets[1] as Excel.Worksheet).Cells[i, 5] = row["grupa"];

        (ex.ActiveWorkbook.Sheets[1] as Excel.Worksheet).Cells[i, 6] = row["finance"];

        (ex.ActiveWorkbook.Sheets[1] as Excel.Worksheet).Cells[i, 7] = row["datar"];

        (ex.ActiveWorkbook.Sheets[1] as Excel.Worksheet).Cells[i, 8] = row["srbal"];

        //увеличиваем индикатор на 1

        progressBar1.Value++;

    }

 

    //под таблицей отобразим общее число записей и средний балл по всему списку

    //наращиваем число строк для вывода расчетных данных

    i++;

    //в первой ячейке i-й строки отображаем текст "Всего"

    (ex.ActiveWorkbook.Sheets[1] as Excel.Worksheet).Cells[i, 1] = "Всего";

    //во второй ячейке i-й строки вводим формулу

    //функция counta() считает число непустых значений в диапазоне

    //диапазон зададим по колонке A3:A(i-1)

    (ex.ActiveWorkbook.Sheets[1] as Excel.Worksheet).Cells[i, 2].Formula = "=counta(A3:A" + (i - 1).ToString() + ")";

    //в третьей ячейке i-й строки отображаем текст "Средний балл"

    (ex.ActiveWorkbook.Sheets[1] as Excel.Worksheet).Cells[i, 3] = "Средний балл";

    //в четвертой ячейке i-й строки вводим формулу

    //функция average() считает среднее по ячейкам диапазона

    //диапазон зададим по колонке со средним баллом H3:H(i-1)

    (ex.ActiveWorkbook.Sheets[1] as Excel.Worksheet).Cells[i, 4].Formula = "=average(H3:H" + (i - 1).ToString() + ")";

 

    //увеличиваем индикатор на 1

    progressBar1.Value++;

 

    //обводим ячейки таблицы линией

    //таблица находится в диапазоне A2:Hi

    //задаем тип линии

    (ex.ActiveWorkbook.Sheets[1] as Excel.Worksheet).Cells.get_Range("A2:H" + i.ToString()).Borders.LineStyle = Excel.XlLineStyle.xlContinuous;

    //задаем толщину линии

    (ex.ActiveWorkbook.Sheets[1] as Excel.Worksheet).Cells.get_Range("A2:H" + i.ToString()).Borders.Weight = Excel.XlBorderWeight.xlThin;

 

    //для последней строки с расчетными данными задаем цвет фона

    //строка задается диапазоном Ai:Hi

    (ex.ActiveWorkbook.Sheets[1] as Excel.Worksheet).Cells.get_Range("A" + i.ToString() + ":H" + i.ToString()).Interior.Color =
Color.LightGray;

 

    //индикатор скрываем

    progressBar1.Visible = false;

    //делаем окно Excel видимым

    ex.Visible = true;

}