VBA. Пишем макрос для Excel

Сегодня мы будем изучать написание макросов для Microsoft Excel и попробуем применить их на конкретном примере.

Начнём с матчасти. Нам понадобится: Microsoft Excel, одна голова и пара рук. Эксель "из коробки" обладает встроенным компилятором VBA, поэтому устанавливать его дополнительно не требуется.

Итак, начнём с простого: создадим первую пользовательскую функцию. Чтобы войти в редактор кода, нажмите Alt+F11. Вы увидите среду разработки Visual Basic, а слева - менеджер проектов. В нём нажмите на корне дерева правой кнопкой нажмите Insert -> Module. Теперь мы видим окно для редактирования кода. Создадим в нём функцию, возвращающую универсальную газовую постоянную:

Function RUG() As Double
RUG = 8.314472            
End Function

Теперь мы можем вставить эту функцию в любое место книги.

Теперь попробуем создать функцию с параметрами.

Function sum(a, b) As Double
sum = a + b
End Function

Как видите, использование функций в VBA похоже на использование функций в других языках. А теперь закончим наш Hello World и перейдём к рассмотрению реального примера. В качестве примера решим дифференциальное уравнение методом Рунге-Кутты 4 порядка.

Исходные данные:

Для решения нам необходимо объявить 5 функций.

Первая функция будет непосредственно вычислять значение производной по формуле, которая дана по условию задачи. Функция выглядит так:

Function func(a As Double, f_k As Double, x As Double, t As Double) As Double
func = 1 + a * x * Sin(t) - f_k * x * x
End Function

Здесь а и f_k - параметры уравнения, x - координата, t - шаг по времени.

Метод Рунге-Кутты предполагает расчёт четырёх коэффициентов: k1, k2, k3, k4. Обратите внимание: мы не можем объявлять функцию k1 напрямую - возникнет конфликт с номером ячейки таблицы. Поэтому воспользуемся префиксом.

Function f_k1(h As Double, a As Double, f_k As Double, x As Double, t As Double) As Double
f_k1 = h * func(a, f_k, x, t)
End Function
 
Function f_k2(h As Double, a As Double, f_k As Double, x As Double, t As Double) As Double
f_k2 = h * func(a, f_k, x + 0.5 * h, y + 0.5 * f_k1(h, a, f_k, x, t))
End Function
 
Function f_k3(h As Double, a As Double, f_k As Double, x As Double, t As Double) As Double
f_k3 = h * func(a, f_k, x + 0.5 * h, t + 0.5 * f_k2(h, a, f_k, x, t))
End Function
 
Function f_k4(h As Double, a As Double, f_k As Double, x As Double, t As Double) As Double
f_k4 = h * func(a, f_k, x + h, f_k3(h, a, f_k, x, t))
End Function

Здесь h - шаг сетки. Остальные параметры имеют то же назначение, что и в первой функции. Вычисления производятся чисто по схеме Рунге-Кутты.

Теперь нам осталось лишь применить наши функции и решить дифференциальное уравнение. Для этого нам понадобится начальное условие. Его мы можем выбрать любое, в данном случае x(0)=0.

Кому лень разбираться, расшифровываю формулу:

Теперь растягиваем нашу формулу на весь интервал и получаем численное решение.

Для наглядности построим график:

Здесь синей линией показан график найденной функции, коричневой - её аппроксимация методом наименьших квадратов. Этот метод я описывать не буду, просто скажу, что в итоге мы получили уравнение x=-0.65t2+1.2664t-0.01992. Если вам интересна реализация этого метода, можете посмотреть его во вложенном файле.

Darth_Vaider,

vr-online.ru

Версия для печатиВерсия для печати

Рубрики: 

  • 1
  • 2
  • 3
  • 4
  • 5
Всего голосов: 0
Заметили ошибку? Выделите ее мышкой и нажмите Ctrl+Enter!

Комментарии

Аватар пользователя mike

Как нехватает спойлеров! В них удобно упрятывать код. Как-то давно я написал целую библиотку для Билдера, позволяющую делать с Экселом всё, что угодно. Косвенно подтолкнула к этому статья в "Вестях", называлась она "Суперфункции". Конечно, была и рабочая потребность. Выложил бы кое-что, но не постить же код! Визивиговые спойлеры пригодились бы.