Учебно-методическое пособие для студентов экономического факультета Ростов-на-Дону
Вид материала | Учебно-методическое пособие |
- Практикум Учебно-методическое пособие для студентов озо биолого-почвенного факультета, 240.69kb.
- Учебно методическое пособие Ростов-на-Дону 2006 Печатается по решению кафедры «Банковское, 485.3kb.
- Методическое пособие для преподавателей колледжа г. Ростов-на-Дону 2010, 106.95kb.
- Учебно-методическое пособие для самостоятельной работы студентов Ростов -на -дону, 684.39kb.
- В. А. Жернов апитерапия учебно-методическое пособие, 443.6kb.
- А. Ю. Лукьянова И. В. Меркулова М. А. Герасименко Банковский маркетинг Учебно-методическое, 325.81kb.
- Учебно-методическое пособие для студентов агрономического факультета всех форм обучения, 1817.54kb.
- Учебно-методическое пособие Рекомендовано методической комиссией финансового факультета, 556.98kb.
- Учебно-методическое пособие для студентов факультета русской филологии Специальность, 990.29kb.
- Учебно-методическое пособие Ростов-на-Дону 2009 удк 66 Отечественная история: Учебно-методическое, 1490.23kb.
10. Ввод и редактирование данных
10.1. Проектирование макета формы для ввода и редактирования данных
Для ввода и редактирования информации о студентах, сохраняемых в виде записей в файле данных, используется форма, которой дано имя frmInputEdit, она является подчиненной формой для главной формы с меню. Макет формы frmInputEdit показан на рисунке 7. При помощи выносок указаны имена помещенных на форму элементов управления – компонентов (объектов) формы.
Остановимся на тех элементах управления, которые используются на макете данной формы.
Надписи (тип Label) – это объекты с именами, имеющими префикс lbl, используются как подписи элементов формы. Из этих подписей ясно, какие элементы для каких полей данных используются.
Текстовые поля (тип TextBox) – это объекты с именами, имеющими префикс txt: txtFIO – для поля «Фамилия И.О.»; txtM1, txtM2, txtM3, txtM4, txtM5 – группа объектов, которая используется для ввода оценок.
Командные кнопки (тип Button) – это объекты с префиксами cmd, нажатие на кнопку (событие Click), как правило, вызывает определенное действие, связанное с кнопкой.
Элементы управления DateTimePicker, позволяющие достаточно удобно вводить даты: txtDR – для поля «Дата рождения».
Рисунок 7. Форма для ввода и редактирования записей файла данных
Комбинированные поля (тип ComboBox) – они сочетают возможности текстового поля и списка, который может быть раскрывающимся; этот тип элемента управления используется для значения поля «Пол» (ComPol), список значений этого поля задается свойством Items. Свойства элемента «ComPol» зададим следующим образом:
Items = “мужской”
“женский”
Sorted = True
Для заполнения поля «Специальность» (ComSpec) используются данные из файла-справочника, список значений для этого поля формируется во время выполнения программы (код будет приведен ниже).
Флажок (тип CheckBox) – используется для того, чтобы отметить записи, которые будут удалены из файла: Check1.
Элемент управления NumericUpDown, который исполняет роль счетчика: txtKurs – для поля «Курс»; txtGroup – для поля «Группа»; txtKol – для поля «Количество оценок».
Элемент «NumericUpDown» используется для изменения, как в сторону увеличения, так и в сторону уменьшения с заданным шагом, в нашем случае равным 1 (свойство «increment») значений полей «Курс», «Группа» и «Количество оценок». Свойства «minimum» и «maximum» задают нижнюю и верхнюю границы изменения счетчика соответственно.
Для перемещения по записям файла кроме командных кнопок используется также вертикальная полоса прокрутки, которая имеет имя «vscrZap», значения некоторых ее свойств определены следующим образом:
minimum = 1
maxmum = 100
SmallChange = 1
LargeChange = 2
Value = 1
В поле «специальность» при заполнении и просмотре записей основного файла базы данных должны подставляться данные из файла-справочника, для чего были составлены процедуры и функции, приведенные в следующем разделе.
В этом месте необходимо нанести на форму все элементы управления, задать из свойства и протестировать форму в автономном режиме, чтобы сравнить результат проектирования с приведенным образцом. Для автономного тестирования сделайте стартовым объектом форму frmInputEdit.
10.2. Программное обеспечение формы для ввода и редактирования
Программное обеспечение формы – это процедуры обработки событий, связанные с элементами управления формы, и пользовательские процедуры и функции, которые непосредственно с элементами не связаны.
10.2.1. Пользовательские процедуры и функции
Сначала опишем пользовательские процедуры и функции для работы с файлом-справочником. С их помощью выполняется связывание основного файла базы данных с файлом-справочником для поля «специальность».
Пользовательская процедура LoadSprav формирует список, который будет показан в поле ввода комбинированного списка ComSpec, т.е. во время выполнения программы формируется значение свойства Items элемента ComSpec, в список Items загружаются все записи файла-справочника.
Private Sub LoadSprav()
Dim Sp As TSpec = New TSpec()
Dim i As Integer
' очищаем список элемента ComSpec и добавляем в него
' пустую строку
ComSpec.Items.Clear()
ComSpec.Items.Add(" ")
' определяем количество записей в справочнике
Decl.NSpec = F1_sp.Length \ Sp.len
' если есть хотя бы одна запись,
If NSpec <> 0 Then
' то поочередно считываем их из файла и
' добавляем в список элемента ComSpec
For i = 1 To NSpec
Sp.ReadFromFile(F1_sp, i)
ComSpec.Items.Add(Trim(Sp.Number) + _
" - " + Trim(Sp.Name))
Next i
End If
End Sub
Пользовательская функция FindSpecCode, возвращает учетный номер специальности, находящейся в справочнике на указанной позиции, передаваемой в качестве параметра.
Private Function FindSpecCode(ByVal number As Integer) As _
Integer
Dim Sp As TSpec = New TSpec()
Sp.ReadFromFile(F1_sp, number)
FindSpecCode = Sp.code
End Function
Пользовательская функция FindSpecIndex получает на вход учетный номер специальности и возвращает номер записи в файле-справочнике, соответствующие этой специальности.
Public Function FindSpecIndex(ByVal code As Integer) _
As Integer
Dim Sp As TSpec = New TSpec()
Dim i As Integer
Dim temp As Integer
' определяется количество записей в справочнике
NSpec = F1_sp.Length \ Sp.len
temp = 0
For i = 1 To NSpec
' поочередно считываются записи из файла
Sp.ReadFromFile(F1_sp, i)
' и если учетный номер записи совпадает,
If (Sp.Code = code) Then
' то запоминается номер его позиции
temp = i
' и осуществляется выход из цикла проверки
Exit For
End If
Next
' возвращается запомненный номер позиции
FindSpecIndex = temp
End Function
Описав все эти процедуры и функции, мы обеспечили взаимодействие данных основного файла с данными в файле-справочнике, т.е. обеспечили связь между файлами.
Для ввода значений полей новой записи файла данных должна быть активизирована форма, подготовленная для ввода данных, т.е. в ней некоторые поля должны быть очищены, а некоторые должны быть заполнены значениями по умолчанию. Из кнопок, обеспечивающих перемещение, активной должна быть только кнопка «Добавить». Все эти действия предусмотрены в пользовательской процедуре ShowNewZap. Опишем код этой процедуры.
Public Sub ShowNewZap()
' загружаем Файл-справочник специальности, выполняя
' пользовательскую процедуру
Call LoadSprav()
' полоса прокрутки становится неактивной
vscrZap.Enabled = False
' кнопка «Добавить» становится активной
cmdAdd.Enabled = True
' кнопки «Вперед», «Конец», «Изменить» и «Обновить»
' становятся неактивными
cmdForward.Enabled = False
cmdBottom.Enabled = False
cmdPack.Enabled = False
cmdEdit.Enabled = False
' начальное заполнение элементов,
' соответствующих полям записей
txtFIO.Text = ""
txtKurs.Value = 1
txtGroup.Value = 1
txtKol.Value = 2
ComPol.Text = ComPol.Items(1)
ComSpec.SelectedIndex = 0
txtDR.Value = Now
' в начале предоставлена возможность ввода двух оценок
' пользователь может увеличить их количество до пяти
txtM1.Visible = True
txtM2.Visible = True
txtM3.Visible = False
txtM4.Visible = False
txtM5.Visible = False
' очистка значений элементов txtM,
' которые могли остаться после ввода предыдущей записи
txtM1.Text = ""
txtM2.Text = ""
txtM3.Text = ""
txtM4.Text = ""
txtM5.Text = ""
lblZap.Text = "Новая запись"
txtFIO.Focus()
Check1.Visible = False
End Sub
После ввода всех значений новой записи, для внесения ее в базу данных нужно нажать на кнопку «Добавить».
После окончания ввода данных необходимо закрыть форму frmInputEdit. При этом все введенные данные должны сохраниться, поэтому при закрытии формы необходимо запросить у пользователя имя файла, в который должно производиться сохранение. Но поскольку эту форму можно закрыть несколькими способами (например, нажав на кнопку «Выход» или кнопку в правом верхнем углу формы), поэтому необходимо обработать все события, обеспечивающие закрытие формы. А поскольку выходу из формы соответствует одна и та же последовательность действий, то оформим ее в виде пользовательской процедуры ExitFromInputEdit.
Sub ExitFromInputEdit()
Dim PathOld As String
Dim PathOldSpec As String
' если путь к основному файлу равен "c:\untitled.dan", т.е.
' форма открыта в режиме создания,
frmMenu.Text = frmMenu.Text + " В.А."
If LCase(Decl.Path) = PathUntitled Then
' то выводится запрос пользователю о сохранении базы
Button = MsgBox("Сохранить файл?", vbQuestion +_
vbYesNoCancel, "Сохранение файла")
If Button = vbYes Then
' если пользователь подтверждает сохранение, то
' следует запрос имени файла, в который будет
' сохранена база данных
PathOld = Decl.Path
PathSpec = Mid(Decl.Path, 1, Len(Decl.Path) - 4) + _
".spe"
PathOldSpec = PathSpec
With frmMenu.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
' то файлы закрывается и переименовываются
CloseAllFiles()
If Not (Dir(Decl.Path) = "") Then
Kill(Decl.Path)
Kill(PathSpec)
End If
Rename(PathOld, Decl.Path)
Rename(PathOldSpec, Decl.PathSpec)
' затем открываются файлы с
' новыми именами
f1 = New FileStream(Decl.Path, FileMode.OpenOrCreate)
F1_sp = New FileStream(Decl.PathSpec, _
FileMode.OpenOrCreate)
' изменение заголовка формы
Me.Text = "Файл: " + Decl.Path
' все пункты меню становятся активными
frmMenu.mnuView.Enabled = True
frmMenu.mnuQuery.Enabled = True
frmMenu.mnuSort.Enabled = True
frmMenu.mnuFileSaveItem.Enabled = True
frmMenu.mnuFileSaveAsItem.Enabled = True
frmMenu.mnuFileCloseItem.Enabled = True
frmMenu.mnuFileDeleteItem.Enabled = True
frmMenu.mnuSearch.Enabled = True
' форма закрывается
Me.Hide()
' форма frmMenu становится активной
frmMenu.Show()
frmMenu.Enabled = True
frmMenu.Focus()
Else
' иначе считается, что нажата кнопка
' «Отмена»
Decl.Path = PathOld
PathSpec = PathOldSpec
Button = vbCancel
End If
Else
' если пользователь на вопрос о сохранении
' файла нажал кнопку «Нет»
If Button = vbNo Then
Pos = 0
N = 0
' файлы закрываются и удаляются
CloseAllFiles()
Kill(Decl.Path)
Kill(PathSpec)
' пункты меню, которые были неактивными в
' начале работы программы, снова
' становятся неактивными
frmMenu.mnuFileSaveItem.Enabled = False
frmMenu.mnuFileSaveAsItem.Enabled = False
frmMenu.mnuFileCloseItem.Enabled = False
frmMenu.mnuFileDeleteItem.Enabled = False
frmMenu.mnuView.Enabled = False
frmMenu.mnuSort.Enabled = False
frmMenu.mnuQuery.Enabled = False
frmMenu.mnuSearch.Enabled = False
' форма закрывается
Me.Hide()
' форма frmMenu становится активной
frmMenu.Show()
frmMenu.Enabled = True
frmMenu.Focus()
End If
End If
Else
' в случае если форма была открыта в режиме просмотра,
' она закрывается
Me.Hide()
' форма frmMenu становится активной
frmMenu.Show()
frmMenu.Enabled = True
frmMenu.Focus()
End If
End Sub
Теперь, опишем процедуры обработки событий нажатия на кнопку «Выход» или кнопку в правом верхнем углу формы.
Обработка события закрытия формы по нажатию кнопки «Выход»:
Private Sub cmdExit_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles cmdExit.Click
‘ вызов процедуры закрытия формы
ExitFromInputEdit()
End Sub
Обработка события закрытия формы по нажатию кнопки :
Private Sub frmInputEdit_FormClosing(ByVal sender As _
System.Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles _
MyBase.FormClosing
Call ExitFromInputEdit()
‘ в том случае, если нажата кнопка «Отмена», то с формы
' выход не происходит
If Button = vbCancel Then e.Cancel = True
End Sub
Хотя подготовлено еще не все программное обеспечение формы, можно запустить проект, но пока не сохранять данные, так как наверняка будут сделаны ошибки, которые необходимо исправить.
Для работы с данными, а именно для вывода в форму полей очередной просматриваемой записи, предусмотрена процедура ShowZap. Она выполняет загрузку элементов формы значениями полей текущей записи (записи с номером i). Ниже приводится код этой процедуры, параметром ее является номер записи в файле.
Public Sub ShowZap(ByVal i As Integer)
Dim R As TStud = New TStud()
' номер записи не должен быть нулем!
If i <> 0 Then
' максимальное значение полосы прокрутки равно
' количеству записей
vscrZap.Maximum = N + 1
vscrZap.Enabled = True
Check1.Checked = False
txtM1.Text = ""
txtM1.Visible = False
txtM2.Text = ""
txtM2.Visible = False
txtM3.Text = ""
txtM3.Visible = False
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
На этом месте снова необходимо протестировать проект на работоспособность и корректность работы. Особое внимание следует уделить взаимодействию различных компонентов приложения.