В этой статье мы рассмотрим создание автоматизированной книги, которая позволит организовать участок работы, связанный с кадровым учетом в организации. На рис. 3.23 показан один из листов этой книги, содержащий штатное расписание. Здесь каждая строка информирует сотрудника кадровой службы о конкретной должности в определенном подразделении. Например, в пятой строке указана должность одного переводчика в административном отделе. Третий столбец на листе содержит информацию о количестве ставок.
Учитывая постановку задачи, нам в дальнейшем понадобится учитывать уже занятые ставки, чтобы отличить их от вакантных. Для этого мы воспользуемся шестым столбцом на листе Штатное расписание. Его мы будем программно использовать для фиксации занятости ставок. Скажем, если на место секретаря в административный отдел будет принят один человек, то в шестом столбце данной строки это будет отмечено цифрой 1. Наоборот, при переводе или увольнении сотрудника единица будет вычитаться из соответствующей ячейки. Разумеется, нам в процессе работы понадобится справочный лист, который представлен на рис. 3.24. Видно, что здесь в каждом столбце листа содержится перечень данных, который будет программно использоваться для подстановки в различные списки для исключения неоднозначности выбора.

Рис. 3.23. Лист Штатное расписание
Лист Основной (рис. 3.25) будет играть роль регистра текущих данных. На этом листе мы будем фиксировать всю информацию о конкретных сотрудниках. Все данные на рис. 3.25 не видны, поэтому приведем названия тех столбцов, которые скрыты:
Разумеется, ручное заполнение листа Основной не предусматривается (или не является основным в процессе работы), и мы специально разработаем удобный интерфейс, который позволит с листа Управление (рис. 3.26) воспользоваться специально разработанными формами ввода.

Рис. 3.24. Содержание справочного листа книги

Рис. 3.25. Организация листа с информацией по сотрудникам
На листе Управление три кнопки, каждая из которых реализует определенное функциональное действие. Значения свойства Name у этих элементов управления относительно варианта «по умолчанию» мы изменим, и они (слева направо) выглядят следующим образом:

Рис. 3.26. Организация листа Управление
Наша задача заключается в том, чтобы последовательно рассмотреть функциональные действия, связанные с каждой из трех данных кнопок. Первая цель — обеспечить зачисление нового сотрудника щелчком на кнопке Принять. В этом случае будет открываться форма, показанная на рис. 3.27.

Рис. 3.27. Форма Включение нового сотрудника
В плане программирования первая процедура, которая нам понадобится, вызывается щелчком на кнопке Принять на листе Управление. Ее программный код состоит из единственной строки (листинг 3.19).
1 2 3 4 | ' Листинг 3.19. Процедура, выполняемая при щелчке на кнопке Принять Private Sub Add_People_Click() AddNewSotr.Show End Sub |
Таким образом, перед пользователем открывается форма, представленная на рис. 3.27. После ее заполнения щелчком на кнопке Записать информация переносится на лист с названием Основной. Перед дальнейшими программными процедурами приведем в табл. 3.2 значения свойства Name элементов управления.
| Тип элемента управления | Подпись | Name |
|---|---|---|
| TextBox | Табельный номер | TabNum |
| TextBox | Дата приема | DatePriem |
| TextBox | Фамилия | Fam |
| TextBox | Имя | Ima |
| TextBox | Отчество | Otch |
| ComboBox | Подразделение | Podrazdel |
| ComboBox | Должность | Dolznost |
| ComboBox | Вид работы | VidRab |
| ComboBox | Пол | Pol |
| ComboBox | Вид договора | VidDog |
| TextBox | Дата приказа | DatePrikaz |
| TextBox | Номер приказа | NumPrikaz |
| TextBox | Оклад | Oklad |
| CommandButton | Записать | OK |
Пять полей со списками должны при открытии формы должны быть заполнены данными с листа Справочный. Для этого процедуру UserForm_Activate необходимо оформить в соответствии с листингом 3.20.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | ' Листинг 3.20. Процедура, выполняемая при активизации формы AddNewSotr Private Sub Userform_Activate() ' Подсчет и заполнение списка подразделений N = 0 While Worksheets("SPRAV").Cells(N + 2, 4).Value <> "" N = N + 1 Wend Podrazdel.Clear For i = 1 To N Podrazdel.AddItem Worksheets("SPRAV").Cells(i + 1, 4).Value Next ' Очистка списка должностей Dolznost.Clear ' Подсчет и заполнение списка вариантов работы N = 0 While Worksheets("Справочный").Cells(N + 2, 2).Value <> "" N = N + 1 Wend VidRab.Clear For i = 1 To N VidRab.AddItem Worksheets("Справочный").Cells(i + 1, 2).Value Next N = 0 While Worksheets("Справочный").Cells(N + 2, 1).Value <> "" N = N + 1 Wend ' Заполнение списка указания пола Pol.Clear For i = 1 To N Pol.AddItem Worksheets("Справочный").Cells(i + 1, 1).Value Next N = 0 While Worksheets("Справочный").Cells(N + 2, 3).Value <> "" N = N + 1 Wend ' Подсчет и заполнение списка вариантов договора VidDog.Clear For i = 1 To N VidDog.AddItem Worksheets("Справочный").Cells(i + 1, 3).Value Next ' Подсчет числа сотрудников на основном листе N = 0 While Worksheets("Основной").Cells(N + 2, 1).Value <> "" N = N + 1 Wend ' Извлечение табельного номера последней записи Kod = Worksheets("Основной").Cells(N + 1, 1).Value If N <> 0 Then ' Внесение значения нового табельного номера TabNum.Text = Kod + 1 End If End Sub |
Кроме заполнения полей со списками, процедура, представленная в листинге 3.20, позволяет выполнить еще одно функциональное действие. Поле Табельный номер на рис. 3.27, разумеется, должно быть при открытии формы автоматически заполнено исходя из табельного номера предыдущего сотрудника. Для этого мы в строке Kod = Worksheets("Основной").Cells(N + 1, 1).Value извлекли значение из первого столбца последней заполненной строки. После этого увеличили на единицу извлеченное значение и внесли результат в текстовое окно TabNum.
Наоборот, при увольнении единица вычитается (тем самым показывается освобождение ставки).
Перейдем теперь к рассмотрению действий пользователя при работе с формой. Так, после выбора подразделения в элементе управления Podrazdel элемент управления Dolznost должен заполняться только должностями из штатного расписания (для каждого подразделения они свои). В листинге 3.21 показана необходимая для этого процедура.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | ' Листинг 3.21. Обработка щелчка на поле со списком подразделений Private Sub Podrazdel_Click() Dolznost.Clear ' Подсчет числа записей в штатном расписании N = 0 While Worksheets("Штатное расписание").Cells(N + 2, 1).Value <> "" N = N + 1 Wend Next For i = 1 To N If Podrazdel.Text = Worksheets("Штатное расписание").Cells(i + 1, 1).Value Then ' Если подразделение совпадает с указанным, то ' должность заносится в список Dolznost.AddItem Worksheets("Штатное расписание").Cells(i + 1, 2).Value End If Next End Sub |
Заполнив остальные поля на рис. 3.27, пользователь может щелчком на кнопке Записать внести информацию на лист Основной. Текст необходимой для этого программной процедуры представлен в листинге 3.22.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | ' Листинг 3.22. Обработка щелчка на кнопке Записать на форме Private Sub OK_Click() ' Подсчет числа записей на листе Основной N = 0 While Worksheets("Основной").Cells(N + 2, 1).Value <> "" N = N + 1 Wend Worksheets("Основной").Cells(N + 2, 1).Value = TabNum.Text Worksheets("Основной").Cells(N + 2, 2).Value = Fam.Text Worksheets("Основной").Cells(N + 2, 3).Value = Ima.Text Worksheets("Основной").Cells(N + 2, 4).Value = Otch.Text Worksheets("Основной").Cells(N + 2, 5).Value = DatePriem.Text Worksheets("Основной").Cells(N + 2, 6).Value = Dolznost.Text Worksheets("Основной").Cells(N + 2, 7).Value = Podrazdel.Text Worksheets("Основной").Cells(N + 2, 8).Value = Pol.Text Worksheets("Основной").Cells(N + 2, 9).Value = VidRab.Text Worksheets("Основной").Cells(N + 2, 10).Value = NumPrikaz.Text Worksheets("Основной").Cells(N + 2, 11).Value = DatePrikaz.Text Worksheets("Основной").Cells(N + 2, 12).Value = Oklad.Text ' Фрагмент коррекции штатного расписания N = 0 While Worksheets("Штатное расписание").Cells(N + 2, 1).Value <> "" N = N + 1 Wend For i = 1 To N If Podrazdel.Text = Worksheets("Штатное расписание").Cells(i + 1, 1).Value _ And Worksheets("Штатное расписание").Cells(i + 1, 2).Value = _ Dolznost.Text Then ' Шестой столбец листа используется для учета занятых должностей Worksheets("Штатное расписание").Cells(i + 1, 6).Value = _ CInt(Worksheets("Штатное расписание").Cells(i + 1, 6).Value) + 1 End If Next MsgBox ("Информация внесена") Hide End Sub |
Кроме внесения новой информации на лист Основной, процедура, представленная в листинге 3.22, отмечает заполнение ставки на листе Штатное расписание. Для этого используется шестой столбец листа Штатное расписание. И при принятии нового человека на конкретную должность в определенной строке шестого столбца производится добавление единицы. Результат продемонстрирован на рис. 3.28.

Рис. 3.28. Отметка занятых должностей
Учитывая рассмотренную возможность учета занятых ставок, следует скорректировать процедуру (см. листинг 3.21), выполняемую по щелчку на поле со списком подразделений. Этот модернизированный вариант представлен в листинге 3.23, и он позволяет исключать уже занятые должности (в списке остаются только вакантные ставки).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | ' Листинг 3.23. Обработка щелчка на списке подразделений на форме (вариант 2) Private Sub Podrazdel_Click() Dolznost.Clear N = 0 While Worksheets("Штатное расписание").Cells(N + 2, 1).Value <> "" N = N + 1 Wend For i = 1 To N If Podrazdel.Text = Worksheets("Штатное расписание").Cells(i + 1, 1).Value _ And (Worksheets("Штатное расписание").Cells(i + 1, 3).Value) - _ CInt(Worksheets("Штатное расписание").Cells(i + 1, 6)) > 0 Then Dolznost.AddItem Worksheets("Штатное расписание").Cells(i + 1, 2).Value End If Next End Sub |
Здесь вместе с проверкой подразделения еще проверяется условие наличия ставки в указанном подразделении:
1 2 | (Worksheets("Штатное расписание").Cells(i + 1, 3).Value) - _ CInt(Worksheets("Штатное расписание").Cells(i + 1, 6)) > 0 |
Таким образом, необходимый «функционал» для внесения новых сотрудников обеспечен; перейдем к другой форме, Yvolnenie (рис. 3.29), которая позволит производить необходимые технические действия для увольнения сотрудников.

Рис. 3.29. Форма для реализации удаления сотрудников
Технически форма для увольнения открывается по щелчку на кнопке Уволить, расположенной на листе Управление. В этом случае необходимо оформить процедуру Del_People_Click() в виде, представленном в листинге 8.24.
1 2 3 4 | ' Листинг 3.24. Обработка щелчка на кнопке Уволить на листе Управление Private Sub Del_People_Click() Yvolnenie.Show End Sub |
На форме (рис. 3.29) расположено семь элементов управления, при этом два из них являются чисто пояснительными и представляют надписи (Label). В верхней части формы расположено поле со списком (Name — Spk), в которое заносятся все имеющиеся сотрудники. Пользователю после выбора конкретного специалиста требуется указать в текстовых окнах номер приказа на увольнение (Name — NumPrikaz) и его дату (Name — DatePrikaz). После этого щелчком на кнопке Внести информацию (Name — OK) на листе Основной фиксируется факт увольнения. Также изменения производятся и на листе Штатное расписание — одна из должностей переходит в категорию вакантных. В плане рассмотрения описанных функциональных действий первая процедура, которая нам понадобится, выполняется при активизации формы (листинг 3.25).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | ' Листинг 3.25. Процедура, выполняемая при активизации формы на рис. 3.29 Private Sub UserForm_Activate() N = 0 While Worksheets("Основной").Cells(N + 2, 1).Value <> "" N = N + 1 Wend Spk.Clear For i = 1 To N ' Извлечение фамилии, имени и отчества сотрудника a = Worksheets("Основной").Cells(i + 1, 2).Value + " " + _ Worksheets("Основной").Cells(i + 1, 3).Value + " " + _ Worksheets("Основной").Cells(i + 1, 4).Value ' Добавление ФИО в список Spk.AddItem a Next End Sub |
Теперь сотрудник, работающий с данной разработкой, может щелчком на поле со списком выбрать одного из сотрудников и далее внести номер и дату приказа.
Технический момент связан с тем, что мы можем таким образом выбрать уже ранее уволенного сотрудника (его данные не пропадают из базы). Здесь можно предложить несколько вариантов программной реализации для исключения подобной ситуации. Мы используем один из наиболее несложных. Так, мы обеспечим, чтобы при выборе фамилии сотрудника в поле со списком в текстовые поля NumPrikaz и DatePrikaz заносилась информация из 13-го и 14-го столбцов листа Основной. В этих столбцах и размещается информация об увольнении. В листинге 3.26 приведена процедура, необходимая для выполнения данного функционального действия.
1 2 3 4 5 | ' Листинг 3.26. Обработка щелчка на поле со списком на рис. 3.29 Private Sub Spk_Click() NumPrikaz.Text = Worksheets("Основной").Cells(Spk.ListIndex + 2, 13).Value DatePrikaz.Text = Worksheets("Основной").Cells(Spk.ListIndex + 2, 14).Value End Sub |
Теперь при попытке повторного увольнения сотрудника мы это увидим — увидим номер и дату приказа об увольнении. На данном листе осталось разработать процедуру, которая позволила бы вносить информацию об увольнении на лист Основной, а также корректировать штатное расписание (листинг 3.27).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | ' Листинг 3.27. Обработка щелчка на кнопке Внести информацию Private Sub OK_Click() ' Вычисляется номер строки, где расположена информация о сотруднике NomStr = Spk.ListIndex + 2 ' Внесение информации о номере приказа и дате увольнения Worksheets("Основной").Cells(NomStr, 14).Value = DatePrikaz.Text Worksheets("Основной").Cells(NomStr, 13).Value = NumPrikaz.Text ' Извлечение информации о подразделении и должности сотрудника Podrazdelenie = Worksheets("Основной").Cells(NomStr, 7).Value Dolznost = Worksheets("Основной").Cells(NomStr, 6).Value ' Подсчет числа записей в штатном расписании N = 0 While Worksheets("Штатное расписание").Cells(N + 2, 1).Value <> "" N = N + 1 Wend For i = 1 To N If Podrazdelenie = Worksheets("Штатное расписание").Cells(i + 1, 1).Value _ And Worksheets("Штатное расписание").Cells(i + 1, 2).Value = _ Dolznost Then ' Коррекция штатного расписания Worksheets("Штатное расписание").Cells(i + 1, 6).Value = _ CInt(Worksheets("Штатное расписание").Cells(i + 1, 6).Value) - 1 End If Next MsgBox ("Информация введена") End Sub |
Во второй части процедуры OK_Click() производится коррекция штатного расписания. На рис. 3.28 это отражено в уменьшении на единицу количества занятых должностей.

Рис. 3.30. Форма Perevod для перевода сотрудников
Таким образом, мы обеспечили прием и увольнение с работы. На листе Управление последним нерассмотренным сервисом является перевод сотрудников с одной должности на другую. Для этого мы разработаем форму, представленную на рис. 3.30. Отображение ее на экране обеспечивает процедура (листинг 3.28) обработки щелчка на кнопке Перевод на листе Управление.
1 2 3 4 | ' Листинг 3.28. Обработка щелчка на кнопке Перевод листа Управление Private Sub Tr_People_Click() Perevod.Show End Sub |
На форме Perevod три элемента управления типа ComboBox (поле со списком) с соответствующими надписями (элементы Label). Два элемента управления типа Label используются в дальнейших программных процедурах. Они выделены более светлым оттенком и снабжены соответствующими надписями (которые также представляют элементы типа Label). И еще один элемент управления — CommandButton. В табл. 3.3 приведены значения свойства Name данных элементов на форме. Первая процедура, которую мы рассмотрим, выполняется при активизации формы. Ее действия сводятся к заполнению полей со списками, а сам текст приведен в листинге 3.29.
| Тип элемента управления | Подпись | Name |
|---|---|---|
| ComboBox | ФИО | Spk |
| ComboBox | Новое подразделение | NewPodrazdel |
| ComboBox | Новая должность | NewDolznost |
| Label | Подразделение | StPodr |
| Label | Должность | StDolznost |
| CommandButton | Перевести | OK |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | ' Листинг 3.29. Процедура, выполняемая при активизации формы Private Sub UserForm_Activate() ' Подсчет числа сотрудников N = 0 While Worksheets("Основной").Cells(N + 2, 1).Value <> "" N = N + 1 Wend ' Очистка и последующее заполнение списка сотрудников Spk.Clear For i = 1 To N a = Worksheets("Основной").Cells(i + 1, 2).Value + " " + _ Worksheets("Основной").Cells(i + 1, 3).Value + " " + _ Worksheets("Основной").Cells(i + 1, 4).Value Spk.AddItem a Next ' Заполнение списка подразделений N = 0 While Worksheets("Справочный").Cells(N + 2, 4).Value <> "" N = N + 1 Wend NewPodrazdel.Clear For i = 1 To N NewPodrazdel.AddItem Worksheets("Справочный").Cells(i + 1, 4).Value Next ' Заполнение списка должностей While Worksheets("Справочный").Cells(N + 2, 5).Value <> "" N = N + 1 Wend NewDolznost.Clear For i = 1 To N NewDolznost.AddItem Worksheets("Справочный").Cells(i + 1, 5).Value Next End Sub |
Таким образом, при открытии формы перевода элементы управления «Поле со списком» заполнены. Пользователь, работающий с данной книгой, должен выбрать в поле со списком интересующего его сотрудника. Выполняемая при этом процедура осуществляет внесение информации о подразделении и должности сотрудника в элементы управления на форме. Если же сотрудник уволен, то сообщение об этом факте выводится в надпись, предназначенную для подразделения. Необходимый программный код данной процедуры представлен в листинге 3.30.
1 2 3 4 5 6 7 8 9 10 11 | ' Листинг 3.30. Обработка щелчка на поле со списком сотрудников Private Sub Spk_Click() If Worksheets("Основной").Cells(Spk.ListIndex + 2, 14).Value = "" Then ' Внесение информации о старом подразделении StPodr.Caption = Worksheets("Основной").Cells(ListIndex + 2, 7).Value ' Внесение информации о старой должности StDolznost.Caption = Worksheets("Основной").Cells(Spk.ListIndex + 2, 6).Value Else StPodr.Caption = "Уволен" End If End Sub |
Следующая процедура (листинг 3.31) позволяет внести в поле со списком NewDolznost только вакантные должности в указанном подразделении.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | ' Листинг 3.31. Обработка щелчка на поле со списком подразделений Private Sub NewPodrazdel_Click() ' Очистка поля со списком должностей NewDolznost.Clear ' podschet N = 0 While Worksheets("Штатное расписание").Cells(N + 2, 1).Value <> "" N = N + 1 Wend For i = 1 To N If NewPodrazdel.Text = Worksheets("Штатное расписание").Cells(i + 1, 1).Value _ And (Worksheets("Штатное расписание").Cells(i + 1, 3).Value - _ CInt(Worksheets("Штатное расписание").Cells(i + 1, 6).Value)) > 0 Then ' Добавление в список вакантной должности NewDolznost.AddItem Worksheets("Штатное расписание").Cells(i + 1, 2).Value End If Next End Sub |
На рис. 3.31 продемонстрирован вариант заполнения формы благодаря разработанным процедурам.

Рис. 3.31. Заполненная форма перевода сотрудника
Теперь ключевая процедура (листинг 3.32), которая выполняется по щелчку на кнопке Перевести. Она производит изменения на листах Основной и Штатное расписание.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | ' Листинг 3.32. Обработка щелчка на кнопке Перевести на рис. 3.31 Private Sub OK_Click() ' Вычисление номера строки, где располагается информация по сотруднику Nom = Spk.ListIndex + 2 ' Подсчет числа записей на листе Основной N = 0 While Worksheets("Основной").Cells(N + 2, 1).Value <> "" N = N + 1 Wend ' Внесение информации о новых должности и подразделении Worksheets("Основной").Cells(Nom, 6).Value = NewDolznost.Text Worksheets("Основной").Cells(Nom + 2, 7).Value = NewPodrazdel.Text ' Подсчет числа строк в штатном расписании NN = 0 While Worksheets("Штатное расписание").Cells(NN + 2, 1).Value <> "" NN = NN + 1 Wend For i = 1 To NN If StPodr.Caption = Worksheets("Штатное расписание").Cells(i + 1, 1).Value _ And Worksheets("Штатное расписание").Cells(i + 1, 2).Value = _ StDolznost.Caption Then ' Фиксирование освобождаемой должности Worksheets("Штатное расписание").Cells(i + 1, 6).Value = _ CInt(Worksheets("Штатное расписание").Cells(i + 1, 6).Value) - 1 Exit For End If Next For i = 1 To NN If NewPodrazdel.Text = Worksheets("Штатное расписание").Cells(i + 1, 1).Value _ And Worksheets("SHTAT").Cells(i + 1, 2).Value = NewDolznost.Text Then ' Фиксирование занимаемой должности Worksheets("Штатное расписание").Cells(i + 1, 6).Value = _ CInt(Worksheets("Штатное расписание").Cells(i + 1, 6).Value) + 1 Oklad = Worksheets("Штатное расписание").Cells(i + 1, 4).Value Worksheets("Основной").Cells(Nom, 12).Value = Oklad Exit For End If Next MsgBox ("Перевод выполнен") End Sub |
Результат работы рассмотренных процедур показан на рис. 3.32.

Рис. 3.32. Результат изменений в штатном расписании
Управление Excel из других офисных программ пакета Microsoft Office
Как отправлять электронные сообщения Microsoft Outlook прямо из вашего листа таблицы Excel с помощью VBA
Очень простой пример управления Word из Excel с помощью VBA
О. А. Сдвижков — Непараметрическая статистика в MS Excel и VBA
С. Роман — Использование макросов в Excel
Как обеспечить вывод значений выпадающего списка с двоеточием, как в бухгалтерских программах?
Как при помощи инструментов Excel решить задачу о коробке максимального объема
Построение графика функции одной переменной средствами Excel
Как правильно вводить, редактировать и копировать формулы в таблицах Excel
Как в Excel обойтись без подстановки шрифтов при применении малых кеглей