Excel VBA: ошибка переполнения из-за слишком большого количества неразрушенных объектов? - PullRequest
1 голос
/ 18 апреля 2011

при выполнении задач оптимизации для большого набора данных время от времени я получаю сообщение об ошибке переполнения 6 (обычно через 1 час или 2). Ошибка исчезает, когда я перезагружаю свой макрос с того места, где он остановился, то есть снова запускаю макрос с того места, где произошла ошибка. Может ли ошибка переполнения быть связана с некоторой проблемой создания слишком большого количества объектов, которые не были должным образом уничтожены после использования?

Вот (упрощенная версия) моего класса контейнера, который используется уничтоженным (через Set ... = none) и реконструированным (через Set ... = New) тысячи раз.

'CG_data_point custom collection class
    Public data_points As Collection
Private Sub Class_Initialize()
    Set data_points = New Collection
End Sub

Public Sub AddDataPoint(mydate as date, price as double)
    Dim new_data_point As CG_data_point
    Set new_data_point = New CG_data_point
    new_data_point.EnterData mydate, price
    data_points.Add new_data_point
    Set new_data_point = Nothing 'I assume this one could also be skipped
End Sub

Public Sub RMSE(X as double) as double
...
End Sub

Private Sub Class_Terminate()
    Dim data_point As CG_data_point
    For Each data_point In data_points  'destruct each data point individually
        Set data_point = Nothing
    Next data_point
    Set data_points = Nothing
End Sub

'Main module
dim global_container as CG_data_container

sub do_optimizations()
    Do
          set global_container= new CG_data_container
           .... do something with the data, have in call to global function RMSE_UDF as a cell formula for Solver
          set global_container= nothing
    While (...)
end sub

'worksheet function
function RMSE_UDF(X as double)
     global_container.RMSE(X)
end function

Контейнерная переменная global_container должна быть глобальной, потому что она должна вызываться из UDF рабочего листа (RMSE_UDF); Насколько мне известно, формула рабочего листа не может иметь объект в качестве аргумента, например "= RMSE (MyContainer, ...)". Минимизация среднеквадратических ошибок (RMSE) выполняется с помощью Excel Solver.

Ответы [ 2 ]

1 голос
/ 19 апреля 2011

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

Сравните и сопоставьте эти две части вашего кода:

С AddDataPoint

data_points.Add new_data_point
Set new_data_point = Nothing

Здесь мы добавляем объект, на который ссылается временная переменная new_data_point, в коллекцию. Затем мы устанавливаем new_data_point в Nothing, чтобы удалить ссылку на объект, на который он ссылался. Очевидно, что коллекция будет по-прежнему иметь ссылку на этот объект

С Class_Terminate

For Each data_point In data_points  'destruct each data point individually
    Set data_point = Nothing
Next data_point

Здесь мы по очереди читаем каждый элемент из коллекции во временную переменную с именем data_point. Затем мы устанавливаем data_point в Nothing, чтобы удалить ссылку на объект, на который он ссылался. (Может быть, не совсем так), очевидно, коллекция будет по-прежнему иметь ссылку на этот объект.

Чтобы удалить каждый объект из коллекции, попробуйте несколько раз удалить первый объект в коллекции, пока коллекция не станет пустой:

Do Until (data_points.Count < 1)
    data_points.Remove 1
Loop
0 голосов
/ 18 апреля 2011

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

Другая возможность - это размер самой коллекции, поскольку она индексируется с помощью long. Это довольно большое число, однако, вы должны превысить 2 147 483 647 записей.

...