Шаг 204.
VBA в MSExcel. Практические приемы программирования на VBA. Тема: периодические выплаты. Построение диаграмм. Практика

    На этом шаге мы рассмотрим основные моменты создания указанного приложения.

    В данном приложении решается задача нахождения размера постоянных платежей по выданной в долг сумме на фиксированный срок под фиксированные проценты. Приложение рассчитывает размер выплат для различных процентных ставок, изменяющихся от начальной до конечной с указанным шагом.

    Кроме того, приложение строит диаграмму, показывающую зависимость величины выплат от процентной ставки. Тип диаграммы можно задать, выбирая переключатель из группы Диаграмма диалогового окна Периодических выплат (рисунок 1).


Рис.1. Диалоговое окно Периодических выплат

    Результат табуляции зависимости размера выплат от процентной ставки выводится в элемент управления ListBox диалогового окна и на рабочий лист (рисунок 2).


Рис.2. Отчет, создаваемый приложением на рабочем листе

    Обсудим, как приведенная ниже программа решает описанную задачу и что в ней происходит.

UserForm_Initialize
  1. Активизирует диалоговое окно.
  2. Назначает клавише Esc функцию кнопки Отмена, а клавише EnterВычислить, а также задает тексты всплывающих подсказок для этих кнопок и кнопки Очистка.
  3. Устанавливает изначально переключатель Гистограмма. Проверяет наличие на диске файла, отображаемого в элементе управления Image при данном выборе переключателя. Если такого файла нет, то информирует об этом пользователя, но тем не менее программа продолжает свою работу без загрузки отсутствующего файла. Если файл есть, изображение, содержащееся в этом файле, выводится в элементе управления Image.

Нажатие кнопки Вычислить запускает на выполнение процедуру CommandButton1_Click
  1. Проверяет, являются ли вводимые данные числами. В случае ошибки отображает соответствующее сообщение.
  2. Проверяет согласованность вводимых данных. В случае ошибки отображает соответствующее сообщение (рисунок 3).


    Рис.3. Пример сообщения о несогласованности данных

  3. Вводит на рабочий лист заголовки записей и их форматирует.
  4. Определяет число точек, в которых будут табулироваться процентные ставки.
  5. Последовательно находит размеры выплат для очередной процентной ставки, меняющейся от начального значения до конечного с указанным шагом. Результаты вычислений выводит на рабочем листе и в двумерный массив ЭлементыСписка, число строк которого равно числу процентных ставок. В первый его столбец выводятся процентные ставки, а во второй - величины соответствующих выплат.
  6. На основе массива ЭлементыСписка заполняется список, предварительно очищенный от ранее введенных в него элементов.
  7. В соответствии с установленным переключателем из группы диаграмма при помощи процедуры График строится выбранная диаграмма.

OptionButton1_Click, OptionButton2_Click и OptionButton3_Click
Выбирает переключатель Гистограмма, График или Круговая группы Диаграмма. Проверяет наличие на диске файла, отображаемого в элементе управления Image при данном выборе переключателя. Если такого файла нет, то информирует об этом пользователя, и программа продолжает свою работу без загрузки отсутствующего файла. Если файл имеется, то изображение, содержащееся в этом файле, выводится в элементе управления Image.

График
Удаляет с рабочего листа все ранее построенные диаграммы. Строит диаграмму на рабочем листе. Аргументами процедуры являются ТипГрафика и его Формат.

    Приведем полный текст приложения.

Private Sub CommandButton1_Click()
  ' Процедура вычисления выплат по ссуде

  Dim p As Double
  Dim i_Hnc As Double
  Dim i_Knc As Double
  Dim i_mar As Double
  Dim k As Integer
  Dim i As Integer
  Dim n As Integer
  Dim m As Integer
  Dim A() As Double
  Dim Проценты() As Double
  Dim ПроцентыФормат() As Variant
  Dim ЭлементыСписка() As Variant
  Dim Area As Object
  ' i_нпc - начальная процентная ставка
  ' i_кпc - конечная процентная ставка
  ' i_mar - шаг процентной ставки
  ' р - ссуда
  ' k - число выплат
  '  А() - динамический массив значений выплат
  ' Проценты() - динамический массив значений процентных ставок
  ' ПроцентыФормат() - динамический массив значений процентных ставок,
  ' отформатированных по процентному формату
  ' ЭлементыСписка() - динамический массив, состоящий из   двух столбцов:
  ' значений процентных ставок и выплат, выводимых в список
  
  ' Проверка: вводятся ли в поля диалогового окна числа
  If IsNumeric(TextBox1.Text) = False Then
    MsgBox "Ошибка в ссуде", vbInformation, "Выплаты"
    TextBox1.SetFocus
    Exit Sub
  End If
  If IsNumeric(TextBox2.Text) = False Then
    MsgBox "Ошибка в числе выплат", vbInformation, "Выплаты"
    TextBox2.SetFocus
    Exit Sub
  End If
  If IsNumeric(TextBox3.Text) = False Then
    MsgBox "Ошибка в начальной процентной ставке", vbInformation, "Выплаты"
    TextBox3.SetFocus
    Exit Sub
  End If
  If IsNumeric(TextBox4.Text) = False Then
    MsgBox "Ошибка в конечной процентной ставке", vbInformation, "Выплаты"
    TextBox4.SetFocus
   Exit Sub
  End If
  If IsNumeric(TextBox5.Text) = False Then
    MsgBox "Ошибка в шаге процентной ставки", vbInformation, "Выплаты"
    TextBox5.SetFocus
    Exit Sub
  End If

  ' Присвоение переменным значений, вводимых в диалоговом окне
  p = CDbl(TextBox1.Text)
  k = CInt(TextBox2.Text)
  i_нпс = CDbl(TextBox3.Text) / 100
  i_кпс = CDbl(TextBox4.Text) / 100
  i_шаг = CDbl(TextBox5.Text) / 100
  ' Проверка согласованности вводимых процентных ставок.
  ' Несогласованность ввода отображается в сообщении
  If i_кпс < i_нпс Then
    MsgBox "Конечная процентная ставка меньше начальной", _
                  vbExclamation, "График"
    TextBox3.SetFocus
    Exit Sub
  End If
  If i_кпс < i_нпс + i_шаг Then
    MsgBox "Шаг слишком большой!" & Chr(13) & _
                  "Табулируется только одно значение.", _
                    vbExclamation, "График"
    TextBox5.SetFocus
    Exit Sub
  End If
  If i_шаг <= 0 Then
    MsgBox "Шаг должен быть положительным!", _
                   vbExclamation, "График"
    TextBox5.SetFocus
    Exit Sub
  End If

  ' Очистка рабочего листа от результатов предыдущих вычислений
  ActiveSheet.Cells.Clear

  ' m - количество процентных ставок
  m = (i_кпс - i_нпс) / i_шаг + 1
   
  ' Установка границ динамических массивов
  ' Проценты, ПроцентыФормат и А
  ReDim A(1 To m)
  ReDim Проценты(1 To m)
  ReDim ПроцентыФормат(1 To m)

  ' Ввод заголовков записей на рабочий лист
  With ActiveSheet
      .Range("A:A").ColumnWidth = 17.6
      .Range("A1").Value = "Процентная ставка"
      .Range("A2").Value = "Размер выплаты"
      .Range("A3").Value = "Ссуда"
      .Range("A4").Value = "Число выплат"
  End With

  ' Форматирование заголовков записей
  ActiveSheet.Range("A1:A4").Select
  With Selection
            .HorizontalAlignment = xlGeneral
            .VerticalAlignment = xlBottom
            .WrapText = False
            .Orientation = 30
            .ShrinkToFit = False
            .MergeCells = False
  End With
  With Selection.Interior
            .ColorIndex = 36
            .Pattern = xlSolid
            .PatternColorIndex = xlAutomatic
  End With

  ' Вывод данных на рабочем листе
  With ActiveSheet
     For i = 1 To m
           Проценты(i) = i_нпс + i_шаг * (i - 1)
           A(i) = Application.Pmt(Проценты(i), k, -p)
           A(i) = Format(A(i), "##")
           ПроцентыФормат(i) = Format(Проценты(i), "#.0%")
           .Cells(1, i + 1).Value = ПроцентыФормат(i)
           .Cells(2, i + 1).Value = A(i)
     Next i
     .Range("B3").Value = p
     .Range("B4").Value = k
  End With

  ' Установка границ динамического массива ЭлементыСписка
  ' Используется для вывода значений процентных ставок и значений
  ' соответствующих выплат в  список
  ReDim ЭлементыСписка(1 To m, 0 To 1)

  ' Поэлементное определение массива ЭлементыСписка
  For i = 1 To m
     ЭлементыСписка(i, 0) = ПроцентыФормат(i)
     ЭлементыСписка(i, 1) = A(i)
  Next i

  ' Заполнение списка с двумя колонками данных
  With ListBox1
      .Clear
      .ColumnCount = 2
      .List = ЭлементыСписка()
      .ListIndex = 0
  End With

  ' Удаление всех графических объектов с активного рабочего листа
  ActiveSheet.ChartObjects.Delete

  ' Определение выбранного
  ' переключателя,задающего тип
  ' диаграммы и
  ' построение выбранной диаграммы
  If OptionButton1.Value = True Then График xlColumn, 6
  If OptionButton2.Value = True Then График xlLine, 10
  If OptionButton3.Value = True Then График xlPie, 7
End Sub

Sub График(ТипГрафика As Integer, Формат As Integer)
  ' Процедура построения графика
  ' ТипГрафика - определяет тип диаграммы на втором шаге мастера диаграмм
  ' Формат - определяет вид диаграммы на третьем шаге мастера диаграмм

  Dim Area As Object
  Dim n As Integer
  
  ' Объектная переменная Area - диапазон, по которому строится диаграмма
  Set Area = ActiveSheet.Cells(1, 2).CurrentRegion

  ' n - число столбцов диапазона Area
  n = Area.Columns.Count

  ' (195, 30, 200, 190) - координаты области, где строится диаграмма
  ActiveSheet.ChartObjects.Add(195, 30, 200, 190).Select

  ' Построение диаграммы
   ActiveChart.ChartWizard Source:= _
        Range(Cells(1, 2), Cells(2, n)), _
        Gallery:=ТипГрафика, Format:=Формат, _
        PlotBy:=xlRows, CategoryLabels:=1, _
        SeriesLabels:=0, HasLegend:=False, _
        Title:="Диаграмма", CategoryTitle:="Ставка", _
        ValueTitle:="Выплаты", ExtraTitle:=""
End Sub

Private Sub CommandButton2_Click()
  ' Процедура закрытия диалогового окна
  UserForm1.Hide
End Sub
Private Sub CommandButton3_Click()
  ' Процедура очистки рабочего листа

  ActiveSheet.ChartObjects.Delete
  ' Очистка ячеек рабочего листа
  ActiveSheet.Cells(1, 1).CurrentRegion.Clear
End Sub
'
Private Sub OptionButton1_Click()
  ' Процедура загрузки файла в элемент управления Image
  ' при выборе переключателя Гистограмма

  On Error GoTo Сообщение1
  Image1.Picture = LoadPicture("VBA3_F1.BMP")
  Exit Sub

  ' В случае отсутствия файла с рисунком отображается сообщение

Сообщение1:
  If Err.Number = 53 Then
     MsgBox "Нет графического файла VBA3_F1.BMP." & Chr(13) & _
                   "Работаем без картинки", vbCritical, "Выплаты"
  End If
  Resume Next
End Sub

Private Sub OptionButton2_Click()
  ' Процедура загрузки файла в элемент
  ' управления Image  при выборе переключателя График

  On Error GoTo Сообщение2
  Image1.Picture = LoadPicture("VBA3_F2.BMP")
  Exit Sub

  ' В случае отсутствия файла с рисунком отображается сообщение
Сообщение2:
  If Err.Number = 53 Then
   MsgBox "Нет  графического файла VBA3_F2.BMP." & Chr(13) & _
                 "Работаем без  картинки", vbCritical, "Выплаты"
  End If
  Resume Next
End Sub

Private Sub OptionButton3_Click()
  ' Процедура загрузки файла в элемент
  ' управления Image  при выборе переключателя Круговая

  On Error GoTo Сообщение3
  Image1.Picture = LoadPicture("VBA3_F3.BMP")
  Exit Sub

  ' В случае отсутствия файла с рисунком отображается сообщение
Сообщение3:
  If Err.Number = 53 Then
     MsgBox "Нет графического файла VBA3_F3.BMP." & Chr(13) & _
                   "Работаем без картинки", vbCritical, "Выплаты"
  End If
  Resume Next
End Sub
Private Sub UserForm_Initialize()
  ' Процедура инициализации и активизации диалогового окна

  ' Первоначальный выбор переключателя Гистограмма
  OptionButton1.Value = True
  ' Назначение клавише <Enter> функции кнопки Вычислить
  With CommandButton1
       .Default = True
       .ControlTipText = "Вычисления и составление отчета на рабочем листе"
  End With
  ' Назначение клавише <Esc> функции кнопки Отмена
  With CommandButton2
      .Cancel = True
      .ControlTipText = "Кнопка отмены"
  End With

  CommandButton3.ControlTipText = "Очистка рабочегo листа"

  On Error GoTo Сообщение0
  With Image1
    ' Установка такого же цвета границы элемента
    ' управления Image, как и его фон
    .BorderColor = .BackColor
    ' Загрузка рисунка соответствующего переключателю Гистограмма
    .Picture = LoadPicture("VBA3_F1.BMP")
  End With
  UserForm1.Show
  Exit Sub

  ' В случае отсутствия файла с рисунком, отображается сообщение
Сообщение0:
  If Err.Number = 53 Then
     MsgBox "Нет графического файла VBA3_F1.BMP." & Chr(13) & _
                   "Работаем без картинки", vbCritical, "Выплаты"
  End If
  Resume Next
End Sub
Текст этого примера можно взять здесь.

    На следующем шаге мы закончим изучение этого вопроса.




Предыдущий шаг Содержание Следующий шаг