Так, нарешті настав час, коли можна описати завдання — і ШІ сам напише код! Майже. Раніше навіть не хотілося братися за подібне завдання, адже для одноразової утиліти доводилося годинами читати посібники, експериментувати, налагоджувати код, шукати правильні підходи й функції. Тепер усе значно простіше. Звісно, поки що це не працює ідеально: потрібно розуміти основи програмування, щоб довести код від ШІ до ладу. Але вже справді більшу частину коду пише саме ШІ! Від програміста потрібне лише розуміння базових речей — умов, циклів, змінних; синтаксис, потрібні функції та деякі прийоми використання може взяти на себе ШІ.
Початкове завдання — створити в Excel щось на кшталт розкресленого календаря з днями тижня, числами та комірками для заповнення по днях. Я сформулював його мовою програмістів, хоча не знав самої мови VBA й того, як нею користуватися в Excel:
Напиши макрос для Excel, який перебирає дати з 01.01.2023 до 31.12.2023 у змінній D. Внутрішній цикл проходить по 7 днях, заповнюючи комірки скороченими назвами днів тижня Пн–Нд відповідно до дати в D, а в комірці нижче — числом місяця. На кожній ітерації збільшуй D на 1. Зовнішній цикл виводить назву місяця в рядку, якщо вона відрізняється від попереднього місяця.
ChatGPT видав загалом робочий код, який одразу запустився без помилок і накреслив щось схоже на календар:
Sub FillCalendar()
Dim startDate As Date
Dim endDate As Date
Dim currentDate As Date
Dim currentMonth As String
Dim previousMonth As String
Dim dayOfWeek As String
' Встановлюємо початкову й кінцеву дати
startDate = DateSerial(2023, 1, 1)
endDate = DateSerial(2023, 12, 31)
' Встановлюємо початкові значення
currentDate = startDate
currentMonth = Format(currentDate, "MMMM")
previousMonth = ""
' Активуємо аркуш
Worksheets("Sheet1").Activate
' Очищаємо попередні дані
Cells.Clear
' Встановлюємо початкову позицію для запису даних
Dim rowPosition As Integer
Dim colPosition As Integer
rowPosition = 1
colPosition = 1
' Зовнішній цикл для обробки місяців
Do While currentDate <= endDate
currentMonth = Format(currentDate, "MMMM")
' Виводимо назву місяця, якщо вона відрізняється від попереднього
If currentMonth <> previousMonth Then
Cells(rowPosition, colPosition).Value = currentMonth
previousMonth = currentMonth
rowPosition = rowPosition + 1
End If
' Внутрішній цикл для обробки днів тижня
For i = 1 To 7
dayOfWeek = Format(currentDate, "ddd")
' Заповнюємо комірку назвою дня тижня
Cells(rowPosition, colPosition).Value = dayOfWeek
' Заповнюємо комірку числом місяця
Cells(rowPosition + 1, colPosition).Value = Format(currentDate, "d")
colPosition = colPosition + 1
currentDate = currentDate + 1
Next i
' Переходимо до наступного рядка
rowPosition = rowPosition + 2
colPosition = 1
Loop
End Sub
Розмітка вийшла трохи хаотичною: тиждень починався не з понеділка, дати наступного місяця потрапляли в кінець тижня попереднього, а підсвічування не було. Але ChatGPT міг вносити зміни до цього коду, тож далі можна було окремо попросити його виправити деякі моменти:
1. Допрацюй код, щоб назви місяців були жирним шрифтом, а дні тижня — сірим. Крім того, додавай порожній рядок під комірками з числами місяця.
2. Нехай назви днів тижня будуть не сірим шрифтом, а на сірому тлі; якщо це Сб або Нд, тло має бути жовтим.
3. Тепер усередині циклу For i = 1 To 7, якщо місяць у currentDate відрізняється від місяця currentMonth, потрібно пропустити весь вміст циклу. А змінну colPosition взагалі прибери й використовуй замість неї i — так буде коротше.
Потім я захотів, щоб тиждень завжди починався з понеділка й пропускав дні, якщо місяць починається з іншого дня. Тут я вже як програміст легко додав ще одну умову, попередньо запитавши ШІ, як у VBA отримати номер дня тижня:
Як у макросі отримати з дати номер дня тижня від 1 до 7?
>Щоб отримати номер дня тижня від 1 до 7 на основі дати, можна скористатися функцієюWeekday.
Для якого дня тижня функція Weekday поверне 1?
>ФункціяWeekdayповерне 1 для неділі (Нд).
А якщо потрібно, щоб для понеділка поверталося 1, а для неділі — 7, як це записати?
>Щоб отримати номер дня тижня від 1 до 7, де 1 відповідає понеділку, а 7 — неділі, використайте функціюWeekdayз параметромvbMonday.
Після цього я додав ще одну перевірку. У підсумку скрипт вийшов таким:
Sub FillCalendar()
Dim startDate As Date
Dim endDate As Date
Dim currentDate As Date
Dim currentMonth As String
Dim previousMonth As String
Dim dayOfWeek As String
' Встановлюємо початкову й кінцеву дати
startDate = DateSerial(2023, 1, 1)
endDate = DateSerial(2023, 12, 31)
' Встановлюємо початкові значення
currentDate = startDate
currentMonth = Format(currentDate, "MMMM")
previousMonth = ""
' Активуємо аркуш
Worksheets("Лист1").Activate
' Очищаємо попередні дані
Cells.Clear
' Встановлюємо початкову позицію для запису даних
Dim rowPosition As Integer
rowPosition = 1
' Зовнішній цикл для обробки місяців
Do While currentDate <= endDate
currentMonth = Format(currentDate, "MMMM")
' Виводимо назву місяця, якщо вона відрізняється від попереднього
If currentMonth <> previousMonth Then
Cells(rowPosition, 1).Value = currentMonth
Cells(rowPosition, 1).Font.Bold = True ' Жирний шрифт
previousMonth = currentMonth
rowPosition = rowPosition + 1
End If
' Внутрішній цикл для обробки днів тижня
For i = 1 To 7
If Format(currentDate, "MMMM") = currentMonth Then
dayOfWeek = Format(currentDate, "ddd")
If i = Weekday(currentDate, vbMonday) Then
' Заповнюємо комірку назвою дня тижня
Cells(rowPosition, i).Value = dayOfWeek
' Перевіряємо, чи це субота (Сб) або неділя (Нд)
If dayOfWeek = "Сб" Or dayOfWeek = "Вс" Then
Cells(rowPosition, i).Interior.Color = RGB(255, 255, 0) ' Жовте тло
Else
Cells(rowPosition, i).Interior.Color = RGB(220, 220, 220) ' Сіре тло
End If
' Заповнюємо комірку числом місяця
Cells(rowPosition + 1, i).Value = Format(currentDate, "d")
currentDate = currentDate + 1
End If
End If
Next i
' Переходимо до наступного рядка
rowPosition = rowPosition + 3
colPosition = 1
Loop
End Sub
Готово! Нижче — результат роботи цього коду:

Підсумки:
Це вже далеко не перша утиліта-скрипт, яку я написав таким способом. Головне — раніше доводилося зважувати витрати на ручну роботу й на вивчення особливостей мови та середовища виконання, щоб вирішити, що буде швидше й простіше. У подібному випадку рішення могло бути не на користь одноразового скрипту. Тепер же зусилля, потрібні для розв’язання таких завдань, зменшуються на порядок!

