Хочу обратиться к Вам за помощью. Опираясь на труд Николая, который ежегодно в своем телеграмм-канале присылает нам свой календарь, я сделал свой календарь-ежедневник в Excel. Вот ссылка на файл https://disk.yandex.ru/i/XdXCC7_58gR58w. Поскольку мой файл по идеологии очень близок к файлу Николая, и поскольку я ВООБЩЕ не понимаю как писать макросы, я решил воспользоваться макросом из файла Николая. Естественно немного его подправив. Я указал правильные диапазоны и имена листов. И очень долго мучался, чтобы заставить этот макрос работать... В итоге у меня получилось достичь желаемого результата, но только для 2-х строк "00:00 1 января 2025" и "23:00 31 декабря 2025". Объясните пожалуйста, что не так в макросе??? Почему правильная логика работы достигнута только на указанных двух строках?
Желаемая логика работы ежедневника: 1. На листе "Ежедневник" имеются три области (слева-направо) - календарь, страничка ежедневника, страничка-напоминалка о незавершенных делах. 2. Пользователь заполняет страничку ежедневника на листе "Ежедневник". 3. Сразу после нажатия на Enter на страничке-напоминалке отображается дата записи и сама запись. 4. По мере того, как мероприятия (дела) будут выполняться пользователь, видя на страничке-напоминалке дату, будет кликать мышью на соответствующую дату календаря, чтобы на страничке ежедневника вновь отобразились мероприятия на указанную дату. И затем пользователь в столбце "Статус" из выпадающего списка выбирает, например, "Выполнено". И соответствующая запись исчезает из странички-напоминалки.
Не исключаю, что возможно всю эту логику можно реализовать исключительно макросами (без создания листов "Статус", "Числа" и "Проверка"). И если это возможно, то файл будет "весить" в разы меньше и будет универсальным на годы, а не на один год. Но, к сожалению, мои знания экселя позволяют решить задачу пока только таким способом.
Твёрдо, лаконично, безапелляционно. Не уверен, что способствует получению решения, но, как минимум, внимание к теме привлекает.
Скрытый текст
Код
Option Explicit
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Cells.CountLarge <> 1 Then Exit Sub
Dim flag As Boolean
Dim dt As Date
dt = Target.Value
If IsDate(Target.Value) Then
If Year(dt) = Range("M2") Then
If Not Intersect(Target, Range("C6:Y42")) Is Nothing Then
If IsDate(Target.Cells(1, 0).Value) Then If Month(Target.Cells(1, 0).Value) = Month(dt) Then flag = True
If IsDate(Target.Cells(1, 2).Value) Then If Month(Target.Cells(1, 2).Value) = Month(dt) Then flag = True
End If
If flag = False Then
If Not Intersect(Target, Range("AI4:AI42")) Is Nothing Then flag = True
End If
End If
End If
If flag Then
Application.ScreenUpdating = False
Range("AD2").Value = dt
Dim ys As Long
ys = dt - DateSerial(Year(dt), 1, 1) + 2
Dim arr As Variant
arr = GetDayArr(ys)
Application.EnableEvents = False
Range("AD4").Resize(UBound(arr, 1), UBound(arr, 2)).Value = arr
Application.EnableEvents = True
arr = Empty
Application.ScreenUpdating = True
End If
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
Dim dt As Date, ys As Long
dt = Range("AD2").Value
ys = dt - DateSerial(Year(dt), 1, 1) + 2
Dim rr As Range, needUpdateVypol As Boolean
Set rr = Range("AD4:AD42")
Dim cl As Range
If Not Intersect(Target, rr) Is Nothing Then
For Each cl In Intersect(Target, rr).Cells
Sheets("События").Cells(ys, cl.Row - 2).Value = cl.Value
Next
needUpdateVypol = True
End If
Set rr = rr.Columns(2)
If Not Intersect(Target, rr) Is Nothing Then
For Each cl In Intersect(Target, rr).Cells
Sheets("Статус").Cells(ys, cl.Row - 2).Value = cl.Value
Next
needUpdateVypol = True
End If
If needUpdateVypol Then
UpdateVypol
End If
End Sub
Private Function GetDayArr(ys As Long) As Variant
Dim rr As Range, rp As Range
Set rr = Sheets("События").Cells(ys, 2).Resize(, 39)
Set rp = Sheets("Статус").Cells(ys, 2).Resize(, 39)
GetDayArr = myTranspose(rr, rp)
End Function
Private Function myTranspose(rr As Range, rt As Range) As Variant
Dim arr As Variant, brr As Variant, trr As Variant
arr = rr.Value
trr = rt.Value
ReDim brr(1 To UBound(arr, 2), 1 To 2)
Dim xa As Long
For xa = 1 To UBound(arr, 2)
brr(xa, 1) = arr(1, xa)
brr(xa, 2) = trr(1, xa)
Next
myTranspose = brr
End Function
Private Sub UpdateVypol()
Dim rr As Range, rp As Range
Set rr = Sheets("События").Cells(2, 1).Resize(366, 39)
Set rp = Sheets("Статус").Cells(2, 1).Resize(366, 39)
Dim arr As Variant, prr As Variant
arr = rr.Value
prr = rp.Value
Dim rv As Range
Set rv = Range("AI4:AJ42")
Dim vrr As Variant
ReDim vrr(1 To rv.Rows.Count, 1 To rv.Columns.Count)
Dim ya As Long, xa As Long, yv As Long
For ya = 1 To UBound(arr, 1)
For xa = 2 To UBound(arr, 2)
If Not IsEmpty(arr(ya, xa)) Then
If IsEmpty(prr(ya, xa)) Then
yv = yv + 1
If yv > UBound(vrr, 1) Then GoTo exitFor
vrr(yv, 1) = arr(ya, 1)
vrr(yv, 2) = arr(ya, xa)
End If
End If
Next
Next
exitFor:
rv.Value = vrr
End Sub
Макрос работает должным образом. Под этим выражением подразумевается выполнение 4 пунктов из первоначального задания. Вы бы побороли свою фобию развернутых ответов, и написали бы чуть больше конкретики. Если, конечно, вы заинтересованы в получении решения.
Добрый вечер, уважаемый "МатросНаЗебре"! Я правда очень ценю Ваш труд! Большое спасибо Вам за Ваши усилия в решении данной задачи! Признаться я не думал, что масштаб бедствия настолько велик (если судить по размеру Вашего макроса). Я думал, что если уж первоначальный макрос написал сам Николай Павлов, и мое творение было очень похоже на творение Николая, то я думал, что уже мой макрос очень близок к финальной стадии и в нем нужно подправить, ну... 2-3 строчки. А оказалось, что тут нужно написать целую поэму! Что касается "Макрос работает должным образом" - это не так! Я скопировал Ваш макрос и вставил ровно в тот файл, что я выложил на яндекс диске. (Если что у меня office 2019). И макрос вроде бы работает, но... Во-первых, при определенных кликах мышью появляется сообщение об ошибке, которое, по идее, появляться не должно. Во-вторых, изменение ячейки в строке "23:00" абсолютно ни к чему не приводит ни в каком месяце. Наверно нужно просто подправить диапазон (кстати, я проверил все диапазоны - вроде бы все правильно, но макрос последнюю строчку все равно "не видит"). На самом деле я максимально четко изложил суть задачи, и судя по тому как работает Ваш макрос - условие задачи Вы поняли абсолютно правильно. Но сам макрос работает не 100% корректно. С учетом всего вышесказанного прошу Вас помочь мне и подправить макрос. И еще один вопрос - где можно научиться программировать на языке VBA? Можете посоветовать какую-нибудь умную книгу, где простым языком объясняется как это делать?! Наверно лучшая книга была бы та, которую написал Николай Павлов, но он еще не написал книгу по VBA, к сожалению...
Option Explicit
'v2
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Cells.CountLarge <> 1 Then Exit Sub
Dim flag As Boolean
Dim dt As Date
If IsDate(Target.Value) Then
dt = Target.Value
If Year(dt) = Range("M2") Then
If Not Intersect(Target, Range("C6:Y42")) Is Nothing Then
If IsDate(Target.Cells(1, 0).Value) Then If Month(Target.Cells(1, 0).Value) = Month(dt) Then flag = True
If IsDate(Target.Cells(1, 2).Value) Then If Month(Target.Cells(1, 2).Value) = Month(dt) Then flag = True
End If
If flag = False Then
If Not Intersect(Target, Range("AI4:AI42")) Is Nothing Then flag = True
End If
End If
End If
If flag Then
Application.ScreenUpdating = False
Dim ys As Long
ys = dt - DateSerial(Year(dt), 1, 1) + 2
Dim arr As Variant
arr = GetDayArr(ys)
Application.EnableEvents = False
Range("AD2").Value = dt
Range("AD4").Resize(UBound(arr, 1), UBound(arr, 2)).Value = arr
Application.EnableEvents = True
arr = Empty
Application.ScreenUpdating = True
End If
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
Dim dt As Date, ys As Long
dt = Range("AD2").Value
ys = dt - DateSerial(Year(dt), 1, 1) + 2
Dim rr As Range, needUpdateVypol As Boolean
Set rr = Range("AD4:AD42")
Dim cl As Range
If Not Intersect(Target, rr) Is Nothing Then
For Each cl In Intersect(Target, rr).Cells
Sheets("События").Cells(ys, cl.Row - 2).Value = cl.Value
Next
needUpdateVypol = True
End If
Set rr = rr.Columns(2)
If Not Intersect(Target, rr) Is Nothing Then
For Each cl In Intersect(Target, rr).Cells
Sheets("Статус").Cells(ys, cl.Row - 2).Value = cl.Value
Next
needUpdateVypol = True
End If
If needUpdateVypol Then
UpdateVypol
End If
End Sub
Private Function GetDayArr(ys As Long) As Variant
Dim rr As Range, rp As Range
Set rr = Sheets("События").Cells(ys, 2).Resize(, 39)
Set rp = Sheets("Статус").Cells(ys, 2).Resize(, 39)
GetDayArr = myTranspose(rr, rp)
End Function
Private Function myTranspose(rr As Range, rt As Range) As Variant
Dim arr As Variant, brr As Variant, trr As Variant
arr = rr.Value
trr = rt.Value
ReDim brr(1 To UBound(arr, 2), 1 To 2)
Dim xa As Long
For xa = 1 To UBound(arr, 2)
brr(xa, 1) = arr(1, xa)
brr(xa, 2) = trr(1, xa)
Next
myTranspose = brr
End Function
Private Sub UpdateVypol()
Dim rr As Range, rp As Range
Set rr = Sheets("События").Cells(2, 1).Resize(366, 40)
Set rp = Sheets("Статус").Cells(2, 1).Resize(366, 40)
Dim arr As Variant, prr As Variant
arr = rr.Value
prr = rp.Value
Dim rv As Range
Set rv = Range("AI4:AJ42")
Dim vrr As Variant
ReDim vrr(1 To rv.Rows.Count, 1 To rv.Columns.Count)
Dim ya As Long, xa As Long, yv As Long
For ya = 1 To UBound(arr, 1)
For xa = 2 To UBound(arr, 2)
If Not IsEmpty(arr(ya, xa)) Then
If IsEmpty(prr(ya, xa)) Then
yv = yv + 1
If yv > UBound(vrr, 1) Then GoTo exitFor
vrr(yv, 1) = arr(ya, 1)
vrr(yv, 2) = arr(ya, xa)
End If
End If
Next
Next
exitFor:
rv.Value = vrr
End Sub
Цитата
написал: при определенных кликах мышью появляется сообщение об ошибке
изменение ячейки в строке "23:00" абсолютно ни к чему не приводит
Вечер добрый! Да, теперь макрос работает отлично! Большое Вам спасибо, МатросНаЗебре! Книгу сейчас закажу. Судя по оглавлению - книга серьезная! Спасибо)))