Какую роль играют модули в написании кода, который требует меньше памяти? - PullRequest
1 голос
/ 03 мая 2019

На работе я погружаюсь в мир VBA, чтобы попытаться создать шаблон электронной таблицы, который будет запускать отчет при нажатии кнопки команды.

Несколько раз я сталкивался с ошибкой во время выполнения «Недостаточно памяти», которая была легко исправлена ​​путем фальсификации кода с использованием комбинаций предложений других пользователей на этом сайте!

Однако мне сейчас интересно узнать, как сделать коды менее ресурсоемкими. В частности, помогают ли модули сделать код менее ресурсоемким, и если да, то как мне эффективно использовать их в этом отношении? Например, я должен назначить Sub каждому модулю или это будет излишним?

Я новичок в VBA, поэтому любая помощь и критика приветствуются!

1 Ответ

0 голосов
/ 03 мая 2019

Краткий ответ: нет вообще.


Ошибка «нехватка памяти» имеет много причин, ни одна из которых не связана с тем, сколько модулей содержит ваш код. Потому что это все модули: организационный инструмент в вашем распоряжении.

Совершенно невозможно диагностировать ошибку «недостаточно памяти», не зная ничего о том, что делает код: <meta> вам придется сузить проблему доКонкретный фрагмент кода, прежде чем вы сможете спросить об этом на этом сайте (сброс всего модуля и вопрос «что не так с этим кодом?» не сработает) </meta>

Ищите очень, очень большие массивы, возможно операции с буфером обмена.Может быть, вы запускаете цикл, который пытается создать и сохранить большие объекты размером в 101 млн. Баджиллионов - это может быть почти что угодно ... только не количество модулей.


следует ли присваивать Sub каждому модулю или это будет излишним?

Как и во многих других случаях, ответ «зависит».Как только вы ознакомитесь с языком и начнете изучать объектно-ориентированное программирование (ООП), вы столкнетесь с руководящими принципами и принципами проектирования, которые настоятельно рекомендуют сделать общедоступные интерфейсы максимально простыми: придерживаться интерфейса Принцип сегрегации («Я» в «SOLID») означает, что это совершенно полный и приемлемый модуль класса, имеющий:

'@Interface IComparable
'@ModuleDescription("Defines a generalized type-specific comparison method that a class implements to order or sort its instances.")
Option Explicit

'@Description("Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes (-1), follows (1), or occurs in the same position in the sort order (0) as the other object.")
Public Function CompareTo(ByVal other As Object) As Integer
End Function

Но это далеко за рамки концепций процедурного программирования начального уровня.

[...], который будет запускать отчет при нажатии кнопки команды.

Эта кнопка может быть кнопкой ActiveX илиShape объект, который прикреплен к макросу.Предполагая, что это ActiveX, код программы может выглядеть следующим образом:

Option Explicit

Private Sub RunSalesReportButton_Click()
    SalesReportMacro.CreateWeeklyReport
End Sub

И тогда вы можете иметь стандартный модуль SalesReportMacro, который может начинаться так:

'@ModuleDescription("A macro that generates the weekly sales report.")
Option Explicit
Option Private Module

'@Descrition("Generates the weekly sales report.")
Public Sub CreateWeeklyReport()
    If Not RefreshSalesData Then Exit Sub
    CreatePivotReport
End Sub

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

Private Function RefreshSalesData() As Boolean
    Dim reportWeek As String
    reportWeek = PromptForReportWeek
    If Not IsNumeric(reportWeek) Then Exit Function

    On Error GoTo CleanFail
    AdjustDataConnectionCommand reportWeek
    RefreshSalesData = True

CleanExit:
    Exit Function
CleanFail:
    MsgBox "Could not refresh the data for week " & reportWeek & ".", vbExclamation
    Resume CleanExit
End Function

И чем глубже вы идете, тем ниже становится уровень абстракции:

Private Function PromptForReportWeek() As String
    Dim currentWeek As Integer
    currentWeek = GetCurrentWeekNumber
    PromptForReportWeek = InputBox("Please specify week#", "Generate Report", currentWeek)
End Function

Private Function GetCurrentWeekNumber()
    GetCurrentWeekNumber = 42 'todo
End Function

Private Sub AdjustDataConnectionCommand(ByVal weekNumber As String)
    With ThisWorkbook.Connections(1).OLEDBConnection
        .CommandText = "dbo.WeeklySalesReport " & weekNumber
        .Refresh
    End With
End Sub

Private Sub CreatePivotReport()
    'todo
End Sub

Процедуры (Sub,Function и другие, которые вы обнаружите в свое время) должны иметь одну цель и должны быть как можно более краткими и сосредоточенными на этой одной задаче.Сделав это, вы упростите последующий рефакторинг вашего кода - скажем, через 2 месяца вам нужно добавить еще одну кнопку ActiveX для нового макроса CreateWeeklyInventoryReport: есть хороший шанс, что этот новый отчет также потребуетсяна PromptForReportWeek - если эта функциональность уже абстрагирована в свою собственную область, вы можете легко удалить / вырезать ее из этого модуля, добавить новый модуль CalendarParameterPrompt (который ... может закончиться только с эту процедуру на некоторое время ... пока вам не понадобится подходящее место для размещения аналогичной функции PromptForReportMonth), добавьте / вставьте ее туда, сделайте ее Public и вызовите ее из любого другого макроса / модуля.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...