Использование средств Visual Basic.net в создании информационных систем

Проектирование информационной системы. Использование различных моделей для проектирования концептуальной схемы информационной структуры программного обеспечения. Реализация информационной системы "Студенты", процесс создания и пользовательские модули.

Рубрика Программирование, компьютеры и кибернетика
Вид учебное пособие
Язык русский
Дата добавления 17.11.2015
Размер файла 571,4 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

txtM4.Text = ""

txtM4.Visible = False

txtM5.Text = ""

txtM5.Visible = False

' производится чтение записи и заполнение элементов

' формы, соответствующих полям записи

R.ReadFromFile(f1, Ind(i))

txtFIO.Text = R.FIO

ComPol.SelectedIndex = R.Pol

txtKurs.Text = CStr(R.Kurs)

txtGroup.Text = CStr(R.Group)

txtKol.Text = CStr(R.Kol)

ComSpec.SelectedIndex = FindSpecIndex(R.Spec)

txtDR.Value = R.DataR

If R.Kol > 0 Then

txtM1.Visible = True

txtM1.Text = CStr(R.M(0))

End If

If R.Kol > 1 Then

txtM2.Visible = True

txtM2.Text = CStr(R.M(1))

End If

If R.Kol > 2 Then

txtM3.Visible = True

txtM3.Text = CStr(R.M(2))

End If

If R.Kol > 3 Then

txtM4.Visible = True

txtM4.Text = CStr(R.M(3))

End If

If R.Kol > 4 Then

txtM5.Visible = True

txtM5.Text = CStr(R.M(4))

End If

' вывод номера записи и отметки об ее удалении

lblZap.Text = CStr(i) + "из" + CStr(N)

Check1.Visible = True

Check1.Checked = Del(Ind(i))

' значение полосы прокрутки полагается равным

' номеру записи

vscrZap.Value = i

End If

End Sub

10.2.2 Процедуры обработки событий

Для работы пользователя с файлом справочником на форму были помещены кнопки cmdAddSpec, cmdEditSpec и cmdDelSpec, соответственно, для добавления, изменения и удаления записей в файле справочнике. Опишем процедуры обработки событий нажатия на эти кнопки.

Процедура обработки события для добавления записи в файл-справочник.

Private Sub cmdAddSpec_Click(ByVal sender As System.Object,_

ByVal e As System.EventArgs) Handles cmdAddSpec.Click

Dim TempStr As String

Dim Sp As TSpec = New TSpec()

Dim tempIndex As Integer

' текущая форма становится неактивной

Me.Enabled = False

' до тех пор пока пользователь не введет число, происходит

' запрос учетного номера новой специальности

TempStr = InputBox("Введите учетный номер специальности", _

"Ввод данных")

Do While Not (IsNumeric(TempStr))

If (TempStr = "") Then

Me.Enabled = True

Exit Sub

End If

MsgBox("Ошибка ввода", vbOKOnly + vbExclamation, _

"Ошибка")

TempStr = InputBox("Введите учетный номер" + _

" специальности", "Ввод данных")

Loop

' учетный номер записывается в структуру Sp

Sp.Code = CByte(TempStr)

' запрос кода специальности

TempStr = InputBox("Введите код сциальности (6 цифр)", _

"Ввод данных")

' код записывается в структуру Sp

Sp.Number = TempStr

' запрос названия новой специальности

TempStr = InputBox("Введите название специальности", _

"Ввод данных")

' название записывается в структуру Sp

Sp.Name = TempStr

' проверяется попытка повторного использования учетного

' номера специальности в файле справочнике

tempIndex = FindSpecIndex(Sp.Code)

' если такой номер уже есть,

If 0 <> tempIndex Then

' то выводится сообщение о возможности изменения данных

If (vbYes = MsgBox("Такой учетный номер уже есть! " _

+ " Перезаписать?", vbYesNo + vbExclamation, _

"Предупреждение")) Then

' изменение данных записи

Sp.writeToFile(F1_sp, tempIndex)

End If

Else

' добавление новой записи в справочник

Sp.writeToFile(F1_sp, NSpec + 1)

End If

' вызов пользовательской процедуры загрузки записей

' справочника в элемент ComSpec

Call LoadSprav()

' текущая форма становится активной

Me.Enabled = True

End Sub

Процедура обработки события изменения записи в файле-справочнике.

Private Sub cmdEditSpec_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles cmdEditSpec.Click

Dim Sp As TSpec = New TSpec()

Dim i As Integer

' текущая форма становится неактивной

Me.Enabled = False

' чтение текущей записи из файла-справочника

i = ComSpec.SelectedIndex

Sp.ReadFromFile(F1_sp, i)

' запрос на изменение кода специальности

If (vbNo = MsgBox("Код специальности оставить без" + _

" изменения?", vbYesNo + vbExclamation, "Вопрос:")) Then

Sp.Number = InputBox("Введите новый код " + _

"специальности (6 цифр)", "Ввод данных")

End If

' запрос на изменение кода специальности

If (vbNo = MsgBox("Название специальности оставить " + _

"без изменения?", vbYesNo + vbExclamation, _

"Вопрос:")) Then

Sp.Name = InputBox("Введите новое название " + _

"специальности", "Ввод данных")

End If

' запись обновленных данных

Sp.writeToFile(F1_sp, i)

' вызов пользовательской процедуры загрузки записей

' справочника в элемент ComSpec

Call LoadSprav()

' текущая форма становится активной

Me.Enabled = True

End Sub

Процедура обработки события удаления записи из файла-справочника.

Private Sub cmdDelSpec_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles cmdDelSpec.Click

Dim i As Integer

Dim j As Integer

Dim ListIndex As Integer

Dim Sp As TSpec = New TSpec()

Dim R As TStud = New TStud()

Dim TempFile As FileStream

' текущая форма становится неактивной

Me.Enabled = False

' сообщение о возможности удаления записей

' из основного файла

If (vbNo = MsgBox("Внимание!!! Все данные, " + _

"содержащие удаляемую информацию будут уничтожены!" + _

" Продолжить?", vbYesNo + vbExclamation, _

"Предупреждение:")) Then

' если была нажата кнопка «Нет», то выход из процедуры

' и текущая форма становится неактивной

Me.Enabled = True

Exit Sub

End If

' отметка на удаление всех записей основного файла базы,

' в которых содержится информация об удаляемой спец-ности

ListIndex = ComSpec.SelectedIndex

If ListIndex <> 0 Then

Sp.ReadFromFile(F1_sp, ListIndex)

For i = 1 To N

R.ReadFromFile(f1, i)

If R.Spec = Sp.Code Then

Del(i) = 1

End If

Next i

End If

' запись во временный файл всех данных, за исключением

' данных об удаляемой специальности

TempFile = New FileStream (PathTemp, FileMode.Create)

j = 1

For i = 1 To NSpec

Sp.ReadFromFile(F1_sp, i)

If i <> ListIndex Then

Sp.writeToFile(TempFile, j)

j = j + 1

End If

Next i

F1_sp.Close()

TempFile.Close()

' перезапись измененного файла-справочника

Kill(PathSpec)

Rename(PathTemp, PathSpec)

' загрузка обновленного файла-справочника

F1_sp = New FileStream(PathSpec, FileMode.Open)

' вызов пользовательской процедуры загрузки записей

' справочника в элемент ComSpec

Call LoadSprav()

' текущая форма становится активной

Me.Enabled = True

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

' основного файла данных

cmdPack_Click(sender, e)

End Sub

В этом месте снова запустите проект для проверки взаимодействия основного файла базы данных с файлом-справочником, но сохранять записи также пока невозможно, так как не реализована кнопка «Добавить». Не забывайте регулярно сохранять проект.

Процедура обработки события нажатия на кнопку «Добавить» обеспечивает добавление записи в файл базы данных и подготовку к вводу полей новой записи.

Private Sub cmdAdd_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles cmdAdd.Click

Dim R As TStud = New TStud()

Dim Sp As TSpec = New TSpec()

' заполнение полей записи

R.FIO = txtFIO.Text

R.Kurs = CByte(txtKurs.Text)

R.Group = CByte(txtGroup.Text)

R.Kol = CByte(txtKol.Text)

R.Pol = CByte(ComPol.SelectedIndex)

R.Spec = FindSpecCode(ComSpec.SelectedIndex)

R.DataR = txtDR.Value

' проверка корректности введенных данных в поле

' специальности

If R.Spec = 0 Then

MsgBox("Неверное значение поля специальность!")

Exit Sub

End If

' проверка непустоты полей оценок

If (txtM1.Text = "") Or (txtM2.Text = "") Or _

(R.Kol > 2) And (txtM3.Text = "") Or _

(R.Kol > 3) And (txtM4.Text = "") Or _

(R.Kol > 4) And (txtM5.Text = "") Then

MsgBox("Введены не все оценки!")

Exit Sub

End If

R.M(0) = CByte(txtM1.Text)

R.M(1) = CByte(txtM2.Text)

If R.Kol > 2 Then R.M(2) = CByte(txtM3.Text)

If R.Kol > 3 Then R.M(3) = CByte(txtM4.Text)

If R.Kol > 4 Then R.M(4) = CByte(txtM5.Text)

' позиция передвигается,

Pos = N + 1

' количество записей увеличивается

N = N + 1

' запись вносится в файл

R.writeToFile(f1, Pos)

' кнопки «Начало» и «Назад» становятся активными

cmdTop.Enabled = True

cmdBackUp.Enabled = True

cmdExit.Focus()

' вызов процедуры для заполнения новой записи

Call ShowNewZap()

End Sub

А теперь попытайтесь заполнить файл данными (1-2 записи) и закрыть форму frmInputEdit с сохранением файлов.

Заметим, что количество видимых на форме элементов txtM«i», предназначенных для ввода оценок прямо зависит от содержимого элемента txtKol. Таким образом, скрытие лишних видимых элементов и показ нужных невидимых элементов txtM«i» должны зависеть от изменения содержимого txtKol, т.е. далее необходимо обработать событие изменения содержимого элемента txtKol. Приведем код процедуры обработки этого события.

Private Sub txtKol_ValueChanged(ByVal sender As System.Object,_

ByVal e As System.EventArgs) Handles txtKol.ValueChanged

Dim i As Integer = txtKol.Value

' все элементы, соответствующие оценкам скрываются

txtM1.Visible = False

txtM2.Visible = False

txtM3.Visible = False

txtM4.Visible = False

txtM5.Visible = False

' открываются первые несколько элементов

' их количество зависит от значения элемента txtKol

If i > 0 Then txtM1.Visible = True

If i > 1 Then txtM2.Visible = True

If i > 2 Then txtM3.Visible = True

If i > 3 Then txtM4.Visible = True

If i > 4 Then txtM5.Visible = True

End Sub

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

Кроме этого необходимо предусмотреть проверку корректности вводимых данных в поля, соответствующие оценкам. Это можно сделать с помощью следующей обработки события изменения содержимого элементов txtM.

Private Sub txtM_TextChanged(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles txtM5.TextChanged, _

txtM4.TextChanged, txtM3.TextChanged, txtM2.TextChanged, _

txtM1.TextChanged

Dim txtM As TextBox = sender

' если содержимое элемента txtM(Index) является числом

If IsNumeric(txtM.Text) = True Then

' и не находится в пределах от 2 до 5,

If CByte(txtM.Text) < 2 Or CByte(txtM.Text) > 5 Then

' пользователь получает предупреждение об ошибке

MsgBox("Неверная оценка", vbExclamation + vbOKOnly, _

"Ошибка")

End If

ElseIf txtM.Text <> "" Then

' если содержимое не является цифрой,

' пользователь получает предупреждение об ошибке

MsgBox("Оценка должна являться цифрой!", vbOKOnly + _

vbExclamation, "Ошибка")

End If

End Sub

В этом месте нужно выполнить полное тестирование формы frmInputEdit, для этого необходимо заполнить файл данными (4-5 записей) и сохранить его.

Кроме ввода новых данных форма frmInputEdit должна позволять просматривать и редактировать существующие данные, для этого необходимо описать перемещение по записям нашей базы данных. Для перемещения по записям будем использовать кнопки «Начало» (cmdTop), «Конец» (cmdBottom), «Назад» (cmdBackUp) и «Вперед» (cmdForward). Опишем обработку событий нажатия для каждой кнопки:

Private Sub cmdTop_Click(ByVal sender As System.Object,_

ByVal e As System.EventArgs) Handles cmdTop.Click

' вывод первой записи данных

Pos = 1

Call ShowZap(Pos)

' кнопки перемещения по записям становятся активными

frmMenu.Text = frmMenu.Text + " Авт"

cmdTop.Enabled = True

cmdBottom.Enabled = True

cmdForward.Enabled = True

cmdBackUp.Enabled = True

' кнопки «Изменить» и «Обновить» становятся активными

cmdEdit.Enabled = True

cmdPack.Enabled = True

' кнопка «Добавить» становится неактивной

frmMenu.Text = frmMenu.Text + "ор: "

cmdAdd.Enabled = False

' фокус передается на кнопку «Выход»

cmdExit.Focus()

End Sub

Private Sub cmdBottom_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles cmdBottom.Click

' вывод последней записи данных

Pos = N

Call ShowZap(Pos)

' кнопки перемещения по записям становятся активными

frmMenu.Text = frmMenu.Text + "дов "

cmdTop.Enabled = True

cmdBottom.Enabled = True

cmdForward.Enabled = True

cmdBackUp.Enabled = True

' кнопки «Изменить» и «Обновить» становятся активными

cmdEdit.Enabled = True

cmdPack.Enabled = True

' кнопка «Добавить» становится неактивной

cmdAdd.Enabled = False

' фокус передается на кнопку «Выход»

cmdExit.Focus()

End Sub

Private Sub cmdBackUp_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles cmdBackUp.Click

' переход на предыдущую позицию

Pos = Pos - 1

' все кнопки становятся активными

frmMenu.Text = frmMenu.Text + "рохо"

cmdTop.Enabled = True

cmdBottom.Enabled = True

cmdForward.Enabled = True

cmdEdit.Enabled = True

cmdPack.Enabled = True

' если запись первая, то кнопка «Назад»

' становится неактивной

If Pos <= 1 Then

cmdBackUp.Enabled = False

Pos = 1

End If

' вывод записи с номером Pos

Call ShowZap(Pos)

End Sub

Private Sub cmdForward_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles cmdForward.Click

' переход на следующую позицию

frmMenu.Text = frmMenu.Text + "Ско"

Pos = Pos + 1

' если была не последняя запись,

If Pos <= N Then

' то переход на следующую запись

vscrZap.Value = Pos

Call ShowZap(Pos)

cmdBackUp.Enabled = True

cmdExit.Focus()

Else

' иначе вызов процедуры для заполнения новой записи

Call ShowNewZap()

End If

End Sub

Для перемещения по записям базы данных можно использовать полосу прокрутки (элемент управления VscrZap). При помощи полосы прокрутки можно перемещаться на одну или несколько записей в базе. Процедура обработки события изменения значения имеет вид:

Private Sub vscrZap_Scroll(ByVal sender As System.Object, _

ByVal e As System.Windows.Forms.ScrollEventArgs) _

Handles vscrZap.Scroll

` максимальное значение полосы прокрутки равно

` количеству записей

VScrZap.Maximum = N

` перемещение на запись по значению полосы прокрутки

Pos = VScrZap.Value

Call ShowZap(Pos)

End Sub

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

Новый этап тестирования проекта для проверки возможности перемещения по записям базы данных с использованием описанных возможностей.

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

Для очередного этапа тестирования проекта необходимо подготовить тестовый файл, в котором должно быть 15-20 записей с разными значениями курсов (2-3 курса), для каждого значения курса должно быть несколько групп (2-3 группы), в каждой группе должно быть несколько студентов (3-4 студента).

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

11. Работа с существующим файлом

11.1 Открытие файла

Для открытия файла необходимо выполнить команду «Файл Открыть». Ей соответствует процедура обработки события, приведенная ниже.

Private Sub mnuFileOpenItem_Click(ByVal sender As _

System.Object, ByVal e As System.EventArgs) _

Handles mnuFileOpenItem.Click

Dim R As TStud = New TStud()

Dim Sp As TSpec = New TSpec()

Dim i As Integer

Decl.Path = PathUntitled

' запрос имени файла базы данных

With OpenFileDialog1

.FileName = ""

.Filter = "Все файлы (*.*)|*.*|" + _

"текстовые файлы(*.txt)|*.txt|" + _

"файлы исх. данных(*.dan)|*.dan|" + _

"файлы результата (*.rez)|*.rez"

.FilterIndex = 3

.ShowDialog()

Decl.Path = .FileName

If Decl.Path <> "" Then

PathSpec = Mid(Decl.Path, 1, Len(Decl.Path) - 4) + _

".spe"

End If

End With

' если имя файла не пусто

If Decl.Path <> "" Then

' файл открывается

f1 = New FileStream(Decl.Path, FileMode.Open)

' определяется количество записей базы данных

N = f1.Length \ R.len

' аналогично открываем файл справочник для

' специальности

F1_sp = New FileStream(PathSpec, FileMode.Open)

NSpec = F1_sp.Length \ Sp.len

Pos = 1

frmInputEdit.Text = "Файл: " + Decl.Path

' все пункты меню становятся активными

mnuView.Enabled = True

mnuSort.Enabled = True

mnuSearch.Enabled = True

mnuQuery.Enabled = True

mnuFileSaveItem.Enabled = True

mnuFileSaveAsItem.Enabled = True

mnuFileCloseItem.Enabled = True

mnuFileDeleteItem.Enabled = True

End If

' инициализация индексного массива Ind, который будет

' использоваться для сортировки данных, и массива Del

' для пометки удаляемых записей

For i = 1 To Nmax

Ind(i) = i

Del(i) = 0

Next i

End Sub

При выборе пункта меню «Файл Открыть» появится диалоговое окно, в котором пользователь может выбрать файл, который нужно открыть. Полное имя файла будет записано в переменную Path модуля Declar и в том случае, если путь существует, производится чтение из выбранного файла. Файл-справочник для специальности имеет то же самое имя, что и основной файл. Отличие состоит только в расширениях этих файлов. Кроме этого, все пункты пользовательского меню становятся доступными. Для того чтобы просмотреть содержимое файла базы данных, нужно в строке меню выбрать пункт меню «Просмотр» и в нем один из возможных вариантов просмотра.

11.2 Просмотр файла базы данных

Файл базы данных можно просмотреть, используя форму frmInputEdit. Для этого необходимо написать еще одну пользовательскую процедуру для данной формы (не забудьте для этого перейти в окно кода формы frmInputEdit). Это процедура с именем View_Form, которая должна загрузить данные и вывести первую запись в уже известном нам виде на форме frmInputEdit. Ниже приведен код этой процедуры.

Public Sub view_form()

Dim R As TStud = New TStud()

' загрузка формы frmInputEdit

frmMenu.Enabled = False

Me.Enabled = True

Me.Show()

' загрузка Файла-справочника по специальности, выполнение

' пользовательской процедуры

Call LoadSprav()

' определение количества записей в основном файле базы

N = f1.Length \ R.len

' если записей нет, то вызов процедуры для заполнения

' новой записи

If N = 0 Then

Call ShowNewZap()

cmdAdd.Enabled = True

Else

' иначе производится загрузка и вывод первой записи

Pos = 1

vscrZap.Value = Pos

Call ShowZap(Pos)

' кнопки перемещения по записям становятся активными

cmdTop.Enabled = True

cmdBottom.Enabled = True

cmdForward.Enabled = True

cmdBackUp.Enabled = True

' кнопки «Изменить» и «Обновить» становятся активными

cmdEdit.Enabled = True

cmdPack.Enabled = True

' кнопка «Добавить» становится неактивной

cmdAdd.Enabled = False

' фокус передается на кнопку «Выход»

cmdExit.Focus()

End If

End Sub

В данной процедуре открытый файл проверяется на пустоту и если он пуст (т.е. файл существует, но в нем нет ни одной записи данных), то вызывается процедура создания нового файла-базы данных (процедура ShowNewZap). Если файл не является пустым, то вызывается процедура ShowZap для вывода в форму первой записи, а так же делаются активными кнопки, позволяющие перемещаться по записям базы данных.

Для просмотра файла базы данных с использованием формы frmInputEdit необходимо в форме frmMenu написать процедуру обработки события выбора команды меню «Просмотр Форма», которая содержит вызов пользовательской процедуры View_Form, принадлежащей форме frmInputEdit:

Private Sub mnuViewFormItem_Click(ByVal sender As _

System.Object, ByVal e As System.EventArgs) _

Handles mnuViewFormItem.Click

` вызов процедуры загрузки формы

frmInputEdit.View_Form

End Sub

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

Для вывода данных в виде таблицы добавим в проект еще одну форму, дадим этой форме имя frmTableReadOnly и поместим на нее элемент для отображения данных в виде таблицы (DataGridView), переименуем этот элемент, задав его имя, GridView1.

Процедура обработки события выбора пункта меню «Просмотр Таблица» имеет вид:

Private Sub mnuViewTableItem_Click(ByVal sender As _

System.Object, ByVal e As System.EventArgs) _

Handles mnuViewTableItem.Click

Dim i As Integer

Dim j As Integer

Dim R As TStud = New TStud()

Dim sp As TSpec = New TSpec()

With frmTableReadOnly.GridView1

' установка количества строк таблицы и ширины столбцов

.ColumnCount = 12

' запись названий столбцов в таблицу

.Columns(0).Name = "Номер"

.Columns(1).Name = "Курс"

.Columns(2).Name = "Группа"

.Columns(3).Name = "Специальность"

.Columns(4).Name = "ФИО"

.Columns(5).Name = "Пол"

.Columns(6).Name = "Кол-во оценок"

For j = 1 To 5

.Columns(j + 6).Name = "Оц.№ " + CStr(j)

Next j

' чтение очередной записи и загрузка ее полей

' в таблицу

For i = 1 To N

R.ReadFromFile(f1, Ind(i))

' чтение специальности по ее коду

j = frmInputEdit.FindSpecIndex(R.Spec)

sp.ReadFromFile(F1_sp, j)

' загрузка новой строки в таблицу

Dim row As String() = New String() _

{CStr(i), R.Kurs, R.Group, _

Trim(sp.Number) + " - " + Trim(sp.Name), Trim(R.FIO), _

R.Pol, R.Kol, R.M(0), R.M(1), R.M(2), R.M(3), R.M(4)}

.Rows.Add(row)

Next i

End With

' изменение заголовка формы

frmTableReadOnly.Text = "Просмотр файла: " + Decl.Path

' загрузка формы frmTableReadOnly

frmTableReadOnly.Show()

End Sub

На этом месте рекомендуется протестировать создаваемый проект. Особое внимание следует уделить корректности чтения записей из файла и вывода их в таблицу и элементы формы.

11.3 Изменение и удаление записей в файле базы данных

Эти действия предусмотрены в форме для ввода и редактирования (форма frmInputEdit) и для их выполнения используются кнопки «Изменить» (cmdEdit) и «Обновить» (cmdPack).

Для корректировки содержимого полей текущей записи используется кнопка «Изменить». Отредактировав нужные поля некоторой записи, нажимаем кнопку «Изменить» и все изменения для текущей записи вносятся в базу данных. Обработка события нажатия на кнопку «Изменить»:

Private Sub cmdEdit_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles cmdEdit.Click

Dim R As TStud = New TStud()

' производится заполнение всех полей записи,

' включая измененные

R.FIO = txtFIO.Text

R.Kurs = CByte(txtKurs.Text)

R.Group = CByte(txtGroup.Text)

R.Kol = CByte(txtKol.Text)

R.Pol = ComPol.SelectedIndex

R.Spec = FindSpecCode(ComSpec.SelectedIndex)

R.DataR = txtDR.Value

R.M(0) = CByte(txtM1.Text)

R.M(1) = CByte(txtM2.Text)

If R.Kol > 2 Then

If txtM3.Text <> "" Then

R.M(2) = CByte(txtM3.Text)

Else

MsgBox("Оценка №3 должна являться цифрой!", vbOKOnly + _

vbExclamation, "Ошибка")

Exit Sub

End If

End If

If R.Kol > 3 Then

If txtM4.Text <> "" Then

R.M(3) = CByte(txtM4.Text)

Else

MsgBox("Оценка №4 должна являться цифрой!", vbOKOnly + _

vbExclamation, "Ошибка")

Exit Sub

End If

End If

If R.Kol > 4 Then

If txtM5.Text <> "" Then

R.M(4) = CByte(txtM5.Text)

Else

MsgBox("Оценка №5 должна являться цифрой!", vbOKOnly + _

vbExclamation, "Ошибка")

Exit Sub

End If

End If

' запись вносится в файл на то место,

' на котором находилась старая запись

R.writeToFile(f1, Pos)

MsgBox("Изменение выполнено успешно!")

End Sub

С файлом исходных данных связан массив Del, который по умолчанию заполнен нулями. Удаляемым записям соответствует значение, равное единице. Для того чтобы удалить некоторые записи, необходимо отметить их на форме frmInputEdit, используя флажок-переключатель Check1, затем нажать на кнопку «Обновить». Для элемента Check1 и кнопки «Обновить» процедуры обработки события Click - щелчка левой кнопки мыши на этих объектах имеют вид:

Private Sub Check1_CheckedChanged(ByVal sender As _

System.Object, ByVal e As System.EventArgs) _

Handles Check1.CheckedChanged

' отмечается на удаление запись с номером Pos

If Check1.Checked Then

Del(Ind(Pos)) = 1

Else

Del(Ind(Pos)) = 0

End If

End Sub

Private Sub cmdPack_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles cmdPack.Click

Dim i As Integer

Dim j As Integer = 1

Dim R As TStud = New TStud()

' открывается вспомогательный файл

F2 = New FileStream(PathTemp, FileMode.Create)

' из основного файла во вспомогательный переписываются

' записи, которые не нужно удалять

For i = 1 To N

R.ReadFromFile(f1, i)

If Del(i) = 0 Then

R.writeToFile(F2, j)

j = j + 1

End If

Next i

' закрываются файлы, и происходит сохранение

' вспомогательного файла под именем основного

' файла базы данных

f1.Close()

F2.Close()

Kill(Decl.Path)

Rename(PathTemp, Decl.Path)

' открывается новый основной (рабочий файл) базы

f1 = New FileStream(Decl.Path, FileMode.Open)

N = f1.Length \ R.len

' возвращение исходных значений массивам Ind и Del

For i = 1 To Nmax

Ind(i) = i

Del(i) = 0

Next i

' вывод первой записи данных

Pos = 1

If N = 0 Then

Call ShowNewZap()

Else

Call ShowZap(Pos)

End If

MsgBox("Обновление выполнено успешно!")

End Sub

Таким образом, для удаления записей используется временный файл, куда переносятся все те записи, которые не должны быть удалены (для них значение Del(i) равно нулю), затем исходный файл удаляется, а временный файл переименовывается.

Новый этап тестирования проекта с целью проверки его работоспособности при добавленных возможностях.

11.4 Сохранение и удаление файлов

Мы описали возможности ввода, просмотра и редактирования данных. Добавим несколько процедур, обрабатывающие события выбора следующих пунктов меню: «Файл Сохранить как», «Файл Закрыть» и «Файл Удалить».

При выборе данного пункта меню «Файл Сохранить как» основной файл базы (файл с данными) должен быть сохранен под новым именем, а затем, должно быть открыто это новое сохранение.

Private Sub mnuFileSaveAsItem_Click(ByVal sender As _

System.Object, ByVal e As System.EventArgs) _

Handles mnuFileSaveAsItem.Click

Dim R As TStud = New TStud()

Dim Sp As TSpec = New TSpec()

Dim PathOld As String

Dim PathOldSpec As String

' запоминаются имена основного файла базы данных и

' Файла-справочника

PathOld = Decl.Path

PathSpec = Mid(Decl.Path, 1, Len(Decl.Path) - 4) + ".spe"

PathOldSpec = PathSpec

' запрос имени нового файла базы

With Me.SaveFileDialog1

.FileName = ""

.Filter = "Все файлы (*.*)|*.*|" + _

"Текстовые файлы. (*.txt)|*.txt|" + _

"Файлы исходных данных (*.dan)|*.dan|" + _

"Файлы результатов (*.rez)|*.rez"

.FilterIndex = 3

.ShowDialog()

Decl.Path = .FileName

If Decl.Path <> "" Then

PathSpec = Mid(Decl.Path, 1, Len(Decl.Path) - 4) + _

".spe"

End If

End With

' если имя нового основного файла пусто, то рабочие файлы

' остаются прежними и производится выход из процедуры

If Decl.Path = "" Then

Decl.Path = PathOld

PathSpec = PathOldSpec

Exit Sub

End If

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

' рабочих файлов

Close()

If Not (Dir(Decl.Path) = "") Then

Kill(Decl.Path)

Kill(PathSpec)

End If

FileCopy(PathOld, Decl.Path)

FileCopy(PathOldSpec, PathSpec)

' после копирования открываются новые файлы

f1 = New FileStream(Decl.Path, FileMode.Open)

F1_sp = New FileStream(PathSpec, FileMode.Open)

frmInputEdit.Text = "Файл: " + Decl.Path

End Sub

При выборе пункта меню «Файл Закрыть» все открытые файлы должны быть закрыты и все пункты меню, недоступные в начале работы снова должны снова стать недоступными.

Private Sub mnuFileCloseItem_Click(ByVal sender As _

System.Object, ByVal e As System.EventArgs) _

Handles mnuFileCloseItem.Click

' закрываются все файлы, открытые в процессе работы

CloseAllFiles()

' пункты меню, которые были неактивными в начале

' работы программы, снова становятся неактивными

mnuFileSaveItem.Enabled = False

mnuFileSaveAsItem.Enabled = False

mnuFileCloseItem.Enabled = False

mnuFileDeleteItem.Enabled = False

mnuView.Enabled = False

mnuSort.Enabled = False

mnuQuery.Enabled = False

mnuSearch.Enabled = False

End Sub

При выборе пункта меню «Файл Удалить» основной файл базы (файл с данными) должен быть удален, и все пункты меню, недоступные в начале работы снова должны снова стать недоступными.

Private Sub mnuFileDeleteItem_Click(ByVal sender As _

System.Object, ByVal e As System.EventArgs) _

Handles mnuFileDeleteItem.Click

Dim Button As Integer

' запрос подтверждения на удаление

Button = MsgBox("Действительно удалить?", vbYesNo + _

vbQuestion, "Удаление файла")

' в случае подтверждения вызывается процедура закрытия

' и удаляется основной файл базы данных

If Button = vbYes Then

Call mnuFileCloseItem_Click(sender, e)

Kill(Decl.Path)

Kill(PathSpec)

End If

End Sub

На этом месте снова необходимо протестировать проект на работоспособность и корректность работы. Особое внимание следует уделить взаимодействию различных компонентов приложения.

12. Сортировка данных

Сортировка данных в данной информационной системе производится при помощи индексного массива Ind, описанного в модуле Declar. В этом случае результатом сортировки будет не отсортированный файл, а вспомогательный массив номеров (индексов) Ind, показывающий в каком порядке следует выбирать записи файла, чтобы они образовывали отсортированную последовательность.

Алгоритмы сортировки опишем в стандартном модуле, который необходимо добавить в проект под именем Sorting. Для сортировки данных будем использовать алгоритм сортировки обменом (метод «пузырьковой» сортировки).

Приведем код процедуры сортировки по числовым полям.

Public Sub Sort(Key() As Single, N As Integer, Ind() As Integer)

Dim i As Integer

Dim j As Integer

Dim k As Integer

For j = 1 To N - 1

For i = 1 To N - j

If Key(Ind(i)) > Key(Ind(i + 1)) Then

k = Ind(i)

Ind(i) = Ind(i + 1)

Ind(i + 1) = k

End If

Next i

Next j

End Sub

Перед обращением к этой процедуре необходимо инициализировать массив Ind и занести элементы ключевого поля сортируемого файла во вспомогательный массив Key. Благодаря описанию массива Key как вещественного в него можно записывать числовые данные любого типа: как Single, так и Integer и Byte.

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

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

Заголовок процедуры сортировки по строковым полям имеет вид:

Public Sub SortStr(Key() As String , N As Integer, _

Ind() As Integer)

Заголовок процедуры сортировки по полям типа даты имеет вид:

Public Sub SortDate(Key() As Date, N As Integer, _

Ind() As Integer)

Опишем теперь работу с указанными процедурами сортировки. Т.е. опишем процедуры обработки событий выбора пунктов меню «Сортировка По курсу», «Сортировка По группе», «Сортировка По ФИО» и «Сортировка Исходный порядок». При этом необходимо предусмотреть корректное выполнение вложенных сортировок.

Выбор пункта меню «Сортировка По курсу»

Private Sub mnuSortKursItem_Click(ByVal sender As _

System.Object, ByVal e As System.EventArgs) _

Handles mnuSortKursItem.Click

Dim i As Integer

Dim KeyK(Nmax) As Single

Dim R As TStud = New TStud()

' подготовка к сортировке

For i = 1 To N

R.ReadFromFile(f1, i)

KeyK(i) = R.Kurs

Next i

' вызов процедуры сортировки

Sort(KeyK, N, Ind)

End Sub

Выбор пункта меню «Сортировка По группе»

Private Sub mnuSortGroupItem_Click(ByVal sender As _

System.Object, ByVal e As System.EventArgs) _

Handles mnuSortGroupItem.Click

Dim i As Integer

Dim KeyK(Nmax) As Single

Dim R As TStud = New TStud()

' подготовка к сортировке

For i = 1 To N

R.ReadFromFile(f1, i)

KeyK(i) = R.Group

Next i

' вызов процедуры сортировки

Sort(KeyK, N, Ind)

End Sub

Выбор пункта меню «Сортировка По ФИО»

Private Sub mnuSortFIOItem_Click(ByVal sender As System.Object,_

ByVal e As System.EventArgs) Handles mnuSortFIOItem.Click

Dim i As Integer

Dim KeyK(Nmax) As String

Dim R As TStud = New TStud()

' подготовка к сортировке

For i = 1 To N

R.ReadFromFile(f1, i)

KeyK(i) = Trim(R.FIO)

Next i

' вызов процедуры сортировки

SortStr(KeyK, N, Ind)

End Sub

Выбор пункта меню «Сортировка Исходный порядок»

Private Sub mnuSortUnsorted_Click(ByVal sender As _

System.Object, ByVal e As System.EventArgs) _

Handles mnuSortUnsorted.Click

Dim i As Integer

' возвращение исходных значений массивам Ind и Del

For i = 1 To Nmax

Ind(i) = i

Del(i) = 0

Next i

End Sub

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

В команды меню «Сортировка» вынесены сортировки по одному полю (ключу) данных. А если необходимо выполнить сортировку по набору ключей, т.е. представить данные о студентах так, что сначала идут записи по возрастанию номера курса, записи в пределах одного курса - по возрастанию номера группы, а записи в пределах одной группы - по фамилиям в алфавитном порядке. Здесь мы встречаемся с сортировкой по набору ключей.

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

Допустим, нужно выполнить сортировку по набору ключей: «Курс», «Группа», «Фамилия И.О.». Предположим, что исходный файл отсортирован по последнему ключу (в нашем случае по полю «Фамилия И.О.). Сортируя полученный файл по предшествующему ключу (по полю «Группа»), мы можем быть уверены, что в пределах одного значения данного ключа записи сохраняют упорядоченность по последнему ключу (это следует из свойства устойчивости алгоритма). Т.е. данные будут отсортированы по полю «Группа», а внутри каждой группы - по полю «Фамилия И.О.». Повторяя процесс сортировки по всем ключам от последнего к первому (т.е. в порядке, обратном требуемому), мы получим файл, отсортированный по набору ключей. Опять же напомним, что файл на самом деле не сортируется, а сортируется индексный массив. Подчеркнем, что в описанном процессе индексный массив, являющийся результатом сортировки по некоторому ключу, является исходным для сортировки по очередному ключу.

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

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

Заметим, однако, что при удалении записи в отсортированных данных (это возможно только в режиме просмотра в виде формы) порядок следования записей нарушается, возвращаясь к исходному виду.

На этом месте снова следует протестировать проект на работоспособность и корректность работы. Проверка правильности работы сортировок может быть осуществлена при помощи просмотра данных в виде таблицы. Особое внимание уделить корректности правки и удаления отсортированных записей.

13. Задачи, решаемые в информационной системе

В техническом задании запланировано решение следующих задач:

1. Вывод списков групп по запросам для одной группы и для всех групп.

2. Вычисление среднего балла для каждого студента.

3. Для каждой учебной группы вычисление количества студентов и среднего балла в группе.

Результаты решения задач оформляются в виде отчетов, вывод которых вызывается командами пункта меню «Отчеты» в строке меню главной формы.

Заметим, что первый пункт - это фактически два различных отчета: списки всех групп и список одной, указанной группы. Из-за этого мы при создании пунктов меню поставили в соответствие этому отчету два пункта меню: «Отчеты Списки групп Все группы» и «Отчеты Списки групп Одна группа».

Отчеты будем генерировать в виде текстовых файлов. Для их просмотра используем компонент RichTextBox.

Поместим этот элемент на форму frmMenu, задав ему следующие свойства:

Name = RichTextBox1

Системное имя

Font = Courier New

Шрифт

ReadOnly = True

Запрет редактирования

ScrollBars = Vertical

Вертикальная полоса прокрутки

Visible = False

Объект невидим

Кроме этого элемента поместим на форму еще и кнопку (Name = cmdSaveOtch, Visible = False), при нажатии которой будем сохранять просматриваемый отчет. Таким образом, макет формы frmMenu , доработанный для вывода результатов имеет вид, представленный на рисунке 8.

По нажатию кнопки «Сохранить отчет» текущий отчет (т.е. отчет, который просматривается в данный момент) должен быть сохранен. Таким образом, поскольку мы генерируем отчеты в текстовый файл с заранее заданным именем, то по нажатию кнопки должна быть сделана копия файла с отчетом.

Рисунок 8. Макет главной формы в режиме конструктора

Приведем код процедуры обработки события нажатия на кнопку «Сохранить отчет».

Private Sub cmdSaveOtch_Click(ByVal sender As System.Object,_

ByVal e As System.EventArgs) Handles cmdSaveOtch.Click

' запрос имени файла для сохранения

With SaveFileDialog1

.FileName = ""

.Filter = "Все файлы (*.*)|*.*|" + _

"Текстовые файлы. (*.txt)|*.txt|" + _

"Файлы исходных данных (*.dan)|*.dan|" + _

"Файлы результатов (*.rez)|*.rez"

.FilterIndex = 2

.ShowDialog()

End With

' если имя файла не пусто и не равно имени

' просматриваемого файла,

If SaveFileDialog1.FileName <> "" And _

richName <> SaveFileDialog1.FileName Then

' то производится копирование просматриваемого файла,

FileCopy(richName, SaveFileDialog1.FileName)

' его удаление

Kill(richName)

' и вывод в RichTextBox1 нового файла

richName = SaveFileDialog1.FileName

RichTextBox1.LoadFile(richName, _

RichTextBoxStreamType.PlainText)

' сообщение об успешном завершении сохранения отчета

MsgBox("Отчет сохранен", vbOKOnly + vbInformation, _

"Сохранение")

End If

End Sub

13.1 Вывод списков групп

Вывод списков групп реализован в процедуре обработки события выбора пункта меню «Отчеты Списки групп Все группы».

Прежде чем привести код этой процедуры, обсудим алгоритм, реализованный в ней. Идея алгоритма состоит в следующем: сначала файл с данными о студентах должен быть «отсортирован» по курсу, группе и фамилии; результатом чего станет индексный массив Ind, который позволит просматривать записи файла в отсортированном виде именно таким образом. Такая упорядоченность записей файла фактически представляет его разбитым на группы записей, самая внутренняя группа имеет одинаковые значения для курса и группы и упорядочена в алфавитном порядке фамилий. Поэтому в самом внешнем цикле перебираются курсы, во вложенном в него цикле перебираются номера групп, и в следующем по уровню вложенности цикле (для одинаковых значений курса и группы во всех записях) выбираются и выводятся в текстовый файл фамилии студентов. Код процедуры снабжен подробными комментариями.

Private Sub mnuQueryListAllItem_Click(ByVal sender As _

System.Object, ByVal e As System.EventArgs) _

Handles mnuQueryListAllItem.Click

Dim i As Integer

Dim Ind(Nmax) As Integer

Dim NK As Byte

Dim NG As Byte

Dim NPP As Integer

Dim KeyK(Nmax) As Single

Dim KeyG(Nmax) As Single

Dim KeyFIO(Nmax) As String

Dim R As TStud = New TStud()

' открывается временный вспомогательный файл otch.ist,

' находящийся в той же папке, что и работающий проект

Path2 = CurDir() + "\otch.txt"

F4 = FreeFile()

FileOpen(F4, Path2, OpenMode.Output)

' подготовка данных для сортировки по курсу, группе и ФИО

For i = 1 To N

R.ReadFromFile(f1, i)

KeyK(i) = R.Kurs

KeyG(i) = R.Group

KeyFIO(i) = R.FIO

Ind(i) = i

Next i

' сортировка данных

Call SortStr(KeyFIO, N, Ind)

Call Sort(KeyG, N, Ind)

Call Sort(KeyK, N, Ind)

' чтение первой записи в отсортированном списке

i = 1

R.ReadFromFile(f1, Ind(i))

Do While i <= N

' фиксирование и запись в файл номера текущего курса

NK = R.Kurs

PrintLine(F4, "Курс " + CStr(NK))

Do While NK = R.Kurs And i <= N

' фиксирование и запись в файл номера

' текущей группы

NG = R.Group

PrintLine(F4, vbTab + "Группа " + CStr(NG))

' порядковый номер студентов в группе

' начинается с единицы

NPP = 1

Do While NK = R.Kurs And NG = R.Group

' запись в файл ФИО студента

PrintLine(F4, vbTab + vbTab + CStr(NPP) + "." + _

vbTab + R.FIO)

NPP = NPP + 1

i = i + 1

' если еще есть записи, то считываем

' следующую, иначе выходим из цикла

If i <= N Then

R.ReadFromFile(f1, Ind(i))

Else

Exit Do

End If

Loop

' пропуск строки между списками различных групп

PrintLine(F4, "")

Loop

Loop

' файла отчета закрывается

FileClose(F4)

' загрузка только что созданного файла в RichTextBox1

RichTextBox1.LoadFile(Path2, _

RichTextBoxStreamType.PlainText)

richName = Path2

' показ элемента RichTextBox1 и кнопки «Сохранить отчет»

RichTextBox1.Visible = True

cmdSaveOtch.Visible = True

End Sub

Вывод списка одной группы реализован в процедуре обработки события выбора пункта меню «Отчеты Списки групп Одна группа»

В этой задаче у пользователя сначала запрашиваются значения для курса и группы, и проверяется корректность введенных значений. Затем файл исходных данных упорядочивается по полю «Фамилия» в алфавитном порядке; после чего он просматривается, из него выбираются и выводятся в текстовый файл записи, в которых значения курса и группы совпадают со значениями, введенными пользователем.

Private Sub mnuQueryListOneItem_Click(ByVal sender As _

System.Object, ByVal e As System.EventArgs) _

Handles mnuQueryListOneItem.Click

Dim i As Integer

Dim Ind(Nmax) As Integer

Dim NK As Byte

Dim NG As Byte

Dim NPP As Integer

Dim TempStr As String

Dim KeyFIO(Nmax) As String

Dim R As TStud = New TStud()

' открывается файл otch.ist, находящийся в той же папке,

' что и работающий проект

Path2 = CurDir() + "\otch.ist"

F4 = FreeFile()

FileOpen(F4, Path2, OpenMode.Output)

' запрос у пользователя интересующего его курса

TempStr = InputBox("Введите курс", "Ввод курса")

Do While Not IsNumeric(TempStr)

'если введенный курс не является числом,

' но является пустым значением

If (TempStr = "") Then

' то файл закрывается и осуществляется выход

' из процедуры

FileClose(F4)

Exit Sub

End If

' если введенный курс не является числом,

' то еще раз производится запрос номера курса

MsgBox("Курс - число", vbOKOnly + vbExclamation, _

"Ошибка")

TempStr = InputBox("Введите курс", "Ввод курса")

Loop

' перевод введенного курса в числовое значение

NK = CByte(TempStr)

' запрос у пользователя интересующей его группы

TempStr = InputBox("Введите группу", "Ввод группы")

Do While Not IsNumeric(TempStr)

'если введенная группа не является числом,

' но является пустым значением

If (TempStr = "") Then

' то файл закрывается и осуществляется выход

' из процедуры

FileClose(F4)

Exit Sub

End If

' если введенная группа не является числом,

' то еще раз производится запрос номера группы

MsgBox("Группа-число", vbOKOnly + vbExclamation, _

"Ошибка")

TempStr = InputBox("Введите группу", "Ввод группы")

Loop

' перевод введенной группы в числовое значение

NG = CByte(TempStr)

' подготовка данных для сортировки по полю ФИО

For i = 1 To N

R.ReadFromFile(f1, i)

KeyFIO(i) = R.FIO

Ind(i) = i

Next i

' сортировка данных

Call SortStr(KeyFIO, N, Ind)

' запись в файл информации о курсе и группы

PrintLine(F4, "Курс " + CStr(NK) + ", Группа " + CStr(NG))

' порядковый номер студентов в группе

' начинается с единицы

NPP = 1

For i = 1 To N

' считывание следующей записи и если курс и группа

' соответствуют, то производится вывод в файл отчета

R.ReadFromFile(f1, Ind(i))

If R.Kurs = NK And R.Group = NG Then

PrintLine(F4, vbTab + CStr(NPP) + "." + vbTab + R.FIO)

NPP = NPP + 1

End If

Next i

' файл отчета закрывается

FileClose(F4)

' загрузка только что созданного файла в RichTextBox1

RichTextBox1.LoadFile(Path2, _

RichTextBoxStreamType.PlainText)

richName = Path2

' показ элемента RichTextBox1 и кнопки «Сохранить отчет»

RichTextBox1.Visible = True

cmdSaveOtch.Visible = True

End Sub

13.2 Количество студентов и средний балл в группах

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

Private Sub AverageBallCreate()

Dim i As Integer

Dim j As Integer

Dim KeyK(Nmax) As Single

Dim KeyG(Nmax) As Single

Dim KeyFIO(Nmax) As String

Dim KeyB(Nmax) As Single

Dim R As TStud = New TStud()

Dim S As TBall = New TBall()

' открывается вспомогательный файл Ball.avg, находящийся в

' той же папке, что и работающий проект

Path1 = CurDir + "\Ball.avg"

F3 = New FileStream(Path1, FileMode.Create)

' читается следующая запись из основного файла базы данных

' вычисляется средний балл и созданная запись о среднем

' балле выводится во вспомогательный файл

For i = 1 To N

R.ReadFromFile(f1, i)

S.Sb = 0

For j = 1 To R.Kol

S.Sb = S.Sb + R.M(j - 1)

Next j

S.Sb = S.Sb / R.Kol

S.Kurs = R.Kurs

S.Group = R.Group

S.FIO = R.FIO

S.writeToFile(F3, i)

Next i

' вспомогательный файл закрывается

F3.Close()

End Sub

Вычисление количества студентов и среднего балла для каждой учебной группы реализовано в процедуре обработки события выбора команды меню «Отчеты Количество и средний балл».

В файле исходных данных содержатся только оценки, поэтому в этой процедуре, сначала формируется вспомогательный файл с данными о студентах (курс, группа, ФИО, средний балл). Затем вспомогательный файл упорядочивается по курсу и группе. После этого вычисляется количество записей в группе с одинаковыми значениями курса и группы, а также средний балл в этой же группе.

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

Private Sub mnuQueryKolItem_Click(ByVal sender As _

System.Object, ByVal e As System.EventArgs) _

Handles mnuQueryBallItem.Click

Dim Sum As Double

Dim k As Integer

Dim i As Integer

Dim Ind(Nmax) As Integer

Dim KeyK(Nmax) As Single

Dim KeyG(Nmax) As Single

Dim NK As Byte

Dim NG As Byte

Dim S As TBall = New TBall()

' вызов процедуры создания вспомогательного файла,

' содержащего информацию о среднем балле каждого студента

AverageBallCreate()

' открывается созданный вспомогательный файл

F3 = New FileStream(Path1, FileMode.Open)

' открывается вспомогательный файл kol.avg, находящийся в

' той же папке, что и работающий проект

Path2 = CurDir() + "\kol.avg"

F4 = FreeFile()

FileOpen(F4, Path2, OpenMode.Output)

' подготовка данных для сортировки по курсу и группе

For i = 1 To N

S.ReadFromFile(F3, i)

KeyK(i) = S.Kurs

KeyG(i) = S.Group

Ind(i) = i

Next i

' сортировка данных

Call Sort(KeyG, N, Ind)

Call Sort(KeyK, N, Ind)

' вывод заголовка таблицы отчета

PrintLine(F4, "Курс" + vbTab + "Группа" + vbTab + _

"Кол-во студ." + vbTab + "Сред-ний балл")

' чтение первой записи в отсортированном списке

i = 1

S.ReadFromFile(F3, Ind(i))

Do While i <= N

' фиксирование номера текущего курса

NK = S.Kurs

Do While NK = S.Kurs And i <= N

' фиксирование номера текущей группы

NG = S.Group

' начальные количество и сумма равны нулю

k = 0

Sum = 0

' вычисление количества студентов и суммы их

' средних баллов

Do While NK = S.Kurs And NG = S.Group

k = k + 1

Sum = Sum + S.Sb

i = i + 1

If i <= N Then

S.ReadFromFile(F3, Ind(i))

Else

Exit Do

End If

Loop

' вывод в файл номера курса, номера группы,

' количества студентов и среднего балла группы

PrintLine(F4, CStr(NK) + vbTab + CStr(NG) + vbTab _

+ vbTab + vbTab + CStr(k) + vbTab + vbTab _

+ vbTab + CStr(Format(Sum / k, "#0.00")))

Loop

Loop

' вспомогательные файлы закрываются

F3.Close()

FileClose(F4)

' загрузка только что созданного файла в RichTextBox1

RichTextBox1.LoadFile(Path2, _

RichTextBoxStreamType.PlainText)

richName = Path2

' показ элемента RichTextBox1 и кнопки «Сохранить отчет»

RichTextBox1.Visible = True

cmdSaveOtch.Visible = True

End Sub

13.3 Вычисление среднего балла для каждого студента

Вычисление среднего балла для каждого студента реализовано в процедуре обработки события выбора команды меню «Отчеты Вычисление среднего балла».

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

Добавим в проект форму, дадим форме имя frmTableRez и поместим на нее элемент для отображения данных в виде таблицы (DataGridView), переименуем этот элемент, задав его имя, GridView1.

Также поместим на форму кнопку с системным именем cmdSaveOtch для сохранения отчета в виде текстового файла.

Процедура обработки события нажатия на кнопку «Сохранить отчет» имеет вид:

Private Sub cmdSaveOtch_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles cmdSaveOtch.Click

Dim i As Integer

Dim j As Integer

' запрос имени файла для сохранения отчета

With frmMenu.SaveFileDialog1

.FileName = ""

.Filter = "Все файлы (*.*)|*.*|" + _

"Текстовые файлы. (*.txt)|*.txt|" + _

"Файлы исходных данных (*.dan)|*.dan|" + _

"Файлы результатов (*.rez)|*.rez"

.FilterIndex = 2

.ShowDialog()

End With

' если имя файла не пусто,

If frmMenu.SaveFileDialog1.FileName <> "" Then

' то файл открывается

F4 = FreeFile()

FileOpen(f4, frmMenu.SaveFileDialog1.FileName, _

OpenMode.Output)

' и в него выводятся все ячейки таблицы

With GridView1

For i = 0 To .ColumnCount - 1

Print(F4, .Columns(i).Name + vbTab)

Next i

PrintLine(F4, "")

For j = 0 To .RowCount - 1

For i = 0 To .ColumnCount - 1

Print(F4, CStr(.Rows(j).Cells(i).Value) + vbTab)

Next i

PrintLine(F4, "")

Next j

End With

' файл отчета закрывается

FileClose(F4)

' сообщение об успешном завершении сохранения отчета

MsgBox("Отчет сохранен", vbOKOnly + vbInformation, _

"Сохранение")

End If

End Sub

А теперь приведем код процедуры обработки события, соответствующего выбору пункта меню «Отчеты Вычисление среднего балла». В этой процедуре предусмотрены две возможности вывода результатов: в виде, упорядоченном по курсу, группе и фамилиям студентов; или в виде, упорядоченном по курсу, группе и убыванию среднего балла. Код процедуры снабжен подробными комментариями.

Private Sub mnuQueryBallItem_Click(ByVal sender As _

System.Object, ByVal e As System.EventArgs) _

Handles mnuQueryKolItem.Click

Dim i As Integer

Dim Ind(Nmax) As Integer

Dim KeyK(Nmax) As Single

Dim KeyG(Nmax) As Single

Dim KeyFIO(Nmax) As String

Dim KeyB(Nmax) As Single

Dim S As TBall = New TBall()

Dim Button As Integer

' вызов процедуры создания вспомогательного файла,

' содержащего информацию о среднем балле каждого студента

AverageBallCreate()

' открывается созданный вспомогательный файл

F3 = New FileStream(Path1, FileMode.Open)

' подготовка данных для сортировок

For i = 1 To N

S.ReadFromFile(F3, i)

KeyK(i) = S.Kurs

KeyG(i) = S.Group

KeyFIO(i) = S.FIO

KeyB(i) = -S.Sb ' для сортировки по убыванию

Ind(i) = i

Next i

' запрос о порядке вывода отчета

Button = MsgBox("Вывод по убыванию среднего балла?", _

vbQuestion + vbYesNo, "Вывод результата")

' сортировка данных производится по курсу, группе и либо по

' ФИО, либо по среднему баллу, в зависимости ответа

' пользователя на запрос

If Button = vbYes Then

Call Sort(KeyB, N, Ind)

...

Подобные документы

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.