Работа с выполненными задачами на листе «Периодическое»

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

В конечном итоге выглядеть это должно так:

Перемещение выполненных задач со страницы Периодчическое
Готовый вариант автоматизации работы с выполненными задачами на листе "Периодическое"

Также, как и в статье «Перемещение выполненной задачи со страницы «Отложенные» в архив» добавим автоматически появляющуюся кнопку «Выполнено», используя функцию «Если», напротив каждого пункта:

=ЕСЛИ(E3>0;"Выполнено";"")

Для самой кнопки напишем макрос и разместим его в процедуре Private Sub Worksheet_SelectionChange(ByVal Target As Range) на листе «Периодическое»:

' Выполнено
If Cells(ActiveCell.Row, ActiveCell.Column).Value = "Выполнено" And ActiveCell.Column = 11 Then ' запоминаем номер строки, на которой была нажата кнопка "Выполнено"
n_stroki = ActiveCell.Row
n_stroki2 = "B" & n_stroki

With UserForm2
' изменяем содержание Label2 на название нажатой задачи
.Label2 = Workbooks("planero.xlsm").Worksheets("Периодическое").Range(n_stroki2).Value
' показываем форму UserForm2 пользователю
.Show
End With
End If

После в vba создадим форму UserForm2, на которой разместим:

На итог получится форма следующего вида:

Всплывающее окно
Окно, появляющееся при нажатии на кнопку «Выполенно»

Теперь реализуем работоспособность самой формы. И начнём с формирования календаря при запуске формы:

' формируем календарь при запуске формы
Private Sub UserForm_Initialize()
' массив наименований месяцев
aMonth = Array("Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль", "Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь")
Dim tekMonth As Byte' текущий месяц
tekMonth = Month(Date)' получаем порядковый номер текущего месяца
' название текущего месяца
UserForm2.pMonth.Caption = aMonth(tekMonth - 1) & " " & Year(Date)
' если текущий месяц - декабрь - то следующим месяцем будет январь следующего года
If tekMonth = 12 Then UserForm2.tMonth.Caption = aMonth(0) & " " & Year(DateAdd("yyyy", 1, Date))
' если текущий месяц - не декабрь
If tekMonth < 12 Then UserForm2.tMonth.Caption = aMonth(tekMonth) & " " & Year(Date)
' если текущий месяц - декабрь - то следующим месяцем будет январь следующего года
If tekMonth = 11 Then UserForm2.nMonth.Caption = aMonth(0) & " " & Year(DateAdd("yyyy", 1, Date))
' если текущий месяц - не декабрь
If tekMonth < 11 Then UserForm2.nMonth.Caption = aMonth(tekMonth + 1) & " " & Year(Date)

' получаем текущую дату
oneDada = DateAdd("d", (-Day(Date) + 1), Date)
' запускаем функцию формирования дат календаря
Call Module1.calendar(UserForm2, "p", oneDada, 1)
Call Module1.calendar(UserForm2, "t", DateAdd("m", 1, oneDada), 0)
Call Module1.calendar(UserForm2, "n", DateAdd("m", 2, oneDada), 0)
End Sub

Данная процедура запускает выполнение функции calendar для формирования дат месяца, находящейся в Module1:

' функция формирования дат календаря
Function calendar(formN As Object, mylabel, data, n As Byte)
Dim tekMonth As Byte' текущий месяц
tekMonth = Month(Format(data, "dd mm yyyy"))
Dim wd As Byte
wd = Weekday(Format(data, "dd mm yyyy")) - 1

Dim k'количество дней в месяце m года god
Select Case tekMonth
Case 1, 3, 5, 7, 8, 10, 12: k = 31
Case 4, 6, 9, 11: k = 30
Case 2
Select Case Year(Date)
Case Year(Date) Mod 4 = 0
If Year(Date) Mod 400 = 0 Then k = 28 Else k = 29
Case Else: k = 28
End Select
End Select

Dim den As Byte
den = 1
Dim i2, j2 As Byte
For i = 1 To 6
If i > 1 Then wd = 1
For j = wd To 7
formN.Controls(mylabel & "_" & i & "_" & j).Caption = den
If n = 1 Then
If Format(Date, "dd mm yyyy") = Format(den & "." & Month(Date) & "." & Year(Date), "dd mm yyyy") Then
i2 = i
j2 = j
End If
End If
den = den + 1
If den > k Then Exit For
Next j
If den > k Then Exit For
Next i
For i = 1 To 6
For j = 1 To 7
With formN.Controls(mylabel & "_" & i & "_" & j)
.BackColor = RGB(255, 255, 255)
.BorderColor = RGB(255, 255, 255)
.ForeColor = RGB(0, 0, 0)
End With
Next j
Next i
If n = 1 Then
With formN.Controls(mylabel & "_" & i2 & "_" & j2)
.BackColor = RGB(244, 97, 0)
.BorderColor = RGB(244, 97, 0)
.ForeColor = RGB(255, 255, 255)
End With
End If
End Function

В итоге форма преобразится следующим образом (где оранжевым цветом выделена текущая дата):

Всплывающее окно со сформированным календарем

Теперь напишем функцию выбора даты календаря:

' функция выбора даты календаря
Function Set_On_Off(formN As Object, mylabel, i2 As Integer, j2 As Integer, n As Byte)
' если отсутствует число в дате месяца - запрещаем его выбор
If formN.Controls(mylabel & "_" & i2 & "_" & j2).Caption <> True Or formN.Controls(mylabel & "_" & i2 & "_" & j2).Caption <= 0 Then Exit Function

' Очистить все ячейки
For i = 1 To 6
For j = 1 To 7
With formN.Controls("p_" & i & "_" & j)
.BackColor = RGB(255, 255, 255)
.BorderColor = RGB(255, 255, 255)
.ForeColor = RGB(0, 0, 0)
End With
With formN.Controls("t_" & i & "_" & j)
.BackColor = RGB(255, 255, 255)
.BorderColor = RGB(255, 255, 255)
.ForeColor = RGB(0, 0, 0)
End With
With formN.Controls("n_" & i & "_" & j)
.BackColor = RGB(255, 255, 255)
.BorderColor = RGB(255, 255, 255)
.ForeColor = RGB(0, 0, 0)
End With
Next j
Next i

' Выделить текущую ячейку
With formN.Controls(mylabel & "_" & i2 & "_" & j2)
.BackColor = RGB(204, 255, 204)
.BorderColor = RGB(150, 150, 150)
.ForeColor = RGB(0, 0, 0)
End With

' запоминаем выбранную дату в глобальной переменной
new_data = Format(formN.Controls(mylabel & "_" & i2 & "_" & j2).Caption & " " & formN.Controls(mylabel & "Month").Caption, "dd.mm.yyyy")
End Function

И её запуск при нажатии на каждую дату календаря:

Private Sub p_1_1_Click()
Call Set_On_Off(UserForm2, "p", 1, 1, 1)
End Sub

Теперь проработаем вопрос с CheckBox1 и CheckBox2. Если пользователь выбрал «Считать задачу выполненной и переместить в архив»: нужно снять галочку с «Напомнить», скрыть календарь, переместить кнопку и CheckBox2 выше и уменьшить высоту формы. Что и делает нижеприведенный макрос:

' пользователь выбрал checkbox "Напомнить"
Private Sub CheckBox1_Click()
' если пользователь выбрал "Напомнить"
If UserForm2.CheckBox1.Value Then
With UserForm2
' убираем галочку с checkbox "Считать задачу выполненной и переместить в архив"
.CheckBox2.Value = False
' показываем календарь
.Frame1.Visible = True
' перемещаем кнопку "Ок" и checkbox2 вниз
.CheckBox2.Top = 190
.CommandButton1.Top = 186
' увеличиваем размер формы
.Height = 248
End With
End If
End Sub

В случае выбора пользователем пункта «Напомнить»: нужно, наоборот, показать календарь, передвинуть кнопки и увеличить размер формы:

' пользователь выбрал checkbox "Считать задачу выполненной и переместить в архив"
Private Sub CheckBox2_Click()
' если пользователь выбрал "Считать задачу выполненной и переместить в архив"
If UserForm2.CheckBox2.Value Then
With UserForm2
' убираем галочку с checkbox "Напомнить"
.CheckBox1.Value = False
' скрываем календарь
.Frame1.Visible = False
' перемещаем кнопку "Ок" и checkbox2 вверх
.CheckBox2.Top = 80
.CommandButton1.Top = 76
' уменьшаем размер формы
.Height = 140
End With
End If
End Sub

Теперь необходимо реализовать макрос, выполняющий выбранное пользователем действие, либо считать задачу выполненной (в этом случае, задачу перемещаем в архив), либо напомнить о ней через какое-то время (в этом случае, изменяем дату выполнения задачи на дату, выбранную пользователем в календаре). Данный макрос необходимо привязать к нажатию кнопки «Ок»:

' нажатие на кнопку "Ок"
Private Sub CommandButton1_Click()
' ссылка на книгу
Set stran = Workbooks("planero.xlsm")
' если пользователь выбрал "Считать задачу выполненной и переместить в архив"
If UserForm2.CheckBox2.Value Then
' запоминаем номер строки, на которой была нажата кнопка "Выполнено"
n_stroki = ActiveCell.Row
n_stroki2 = "B" & n_stroki
' изменяем кнопку на "Невыполнено"
Cells(ActiveCell.Row, ActiveCell.Column).FormulaLocal = "=ЕСЛИ(E" & ActiveCell.Row & ">0;" & """Невыполнено"";" & """"")"
' вырезаем строку
stran.Worksheets("Периодическое").Rows(n_stroki & ":" & n_stroki).Cut
' переходим на страницу "Архив"
stran.Worksheets("Архив").Select
' вставляем вырезанную строку со страницы "Периодическое" на страницу "Архив"
stran.Worksheets("Архив").Rows("3:3").Insert
' переходим обратно на страницу "Периодическое"
stran.Worksheets("Периодическое").Select
' если пользователь выбрал "Напомнить"
Else
' запоминаем номер строки, на которой была нажата кнопка "Выполнено"
n_stroki = ActiveCell.Row
n_stroki2 = "B" & n_stroki
' если пользователь выбрал новую дату
If new_data > 0 Then
' записываем новую дату напротив выбранной задачи
With stran.Worksheets("Периодическое").Range("E" & n_stroki)
.Value = new_data
.HorizontalAlignment = xlRight
End With
End If
End If
' скрываем форму
Unload UserForm2
' убираем курсор с кнопки "Выполнено"
stran.Worksheets("Периодическое").Cells(ActiveCell.Row, ActiveCell.Column - 10).Select
End Sub

И в заключении предусмотрим снятие активности с кнопки «Выполнено» в случае закрытия диалогового окна с помощью «крестика», для этого необходимо выполнить макрос при закрытии всплывающего окна:

' в случае закрытия формы "крестиком" убираем курсор с кнопки "Выполнено"
Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
Workbooks("planero.xlsm").Worksheets("Периодическое").Cells(ActiveCell.Row, ActiveCell.Column - 10).Select
End Sub

Следующим шагом автоматизируем работу с выполненными задачами и подзадачами на вкладке «Проекты».

Актуальная версия Планеро доступна по ссылке.

Поделись с друзьями:
Комментарии 2

© планеро.ru