Raptorgrrr писал(а):Проблема таже - не выходит из рекурсии, валиться с ошибкой
Run-error 9
Subscript out range? т.е. выход за пределы диапазона.
Еще бы! В FindEx имеется:
- Код: Выделить всё
For i = 0 To Units.Count
Что естественно неправильно. Правильный вариант:
- Код: Выделить всё
For i = 0 To Units.Count - 1
Далее, вылезала ошибка, вопящая о том, что ключ уже существует. Я так понимаю, что это опечатка на странице Excel. Поправил, стало работать нормально. Общее мнение по коду - "черт те что, и с боку бантик". При полном отсутствии комментариев, дальнейший разбор полетов невозможен. Останаовлюсь лишь на одной процедуре.
- Код: Выделить всё
Private Function CreateUnit(Name As String, Level As Long, Optional Mach As Boolean, Optional CCode As String, _
Optional UID As Long, Optional ParentID) As CSubdivision
Dim Unit As New CSubdivision
Set CreateUnit = Nothing
If (Name <> vbNullString) And (Level > 0) Then
Unit.Name = CStr(Name)
Unit.Level = CLng(Level)
If IsMissing(CCode) Then Unit.CCode = CCode
Unit.UID = IIf(IsMissing(UID), 0, CLng(UID))
Unit.ParentID = IIf(IsMissing(ParentID), 0, CLng(ParentID))
Unit.Mach = IIf(IsMissing(Mach), False, CBool(Mach))
Set CreateUnit = Unit
End If
End Function
Во-первых, все входные параметры должны быть
ByVal. Во-вторых,
Optional-параметры должны бы иметь значение по умолчанию. В принципе, если они не заданы, то для
Boolean будет
False, а для
Long - 0. В-третьих,
ParentID имеет тип
Variant, почему? Логика подсказывает, что это должен быть
Long. Далее, идем в текст процедуры.
- Код: Выделить всё
Set CreateUnit = Nothing
Нафига? Возвращаемое значение функции и так
Nothing изначально.
- Код: Выделить всё
If (Name <> vbNullString) And (Level > 0) Then
Очередной раз возникает желание бить по голове. Если хочется выяснить, не пустая ли строка, проверь ее длину, ну или срfвни с нулем указатель на нее.
- Код: Выделить всё
If Len(Name) Then
или
- Код: Выделить всё
If StrPtr(Name) Then
Еще один нюанс. Вариант
- Код: Выделить всё
If Len(Name) Then
If Level > 0 Then
End If
End If
Будет работать несколько шустрее, чем
- Код: Выделить всё
If Len(Name) And Level > 0 Then
End If
Идем дальше
- Код: Выделить всё
Unit.Name = CStr(Name)
Ну вот нафига преобразовывать строку в строку, тем более дважды, поскольку далее в процедуре присвоения свойств опять же торчит
CStr? Следующая строка аналогично, но с
CLng. Далее
- Код: Выделить всё
If IsMissing(CCode) Then Unit.CCode = CCode
Бред в квадрате. Во-первых,
IsMissing сработает только для необязательных параметров типа
Variant, для всех остальных всегда будет использовано значение по по умолчанию и
IsMissing заведомо
False, и никакое значение
Unit.CCode присвоено не будет. Но даже, если будет
True, то плучается, что мы присваиваем пропущенное значение? Может наоборот? Следующие строки.
- Код: Выделить всё
Unit.UID = IIf(IsMissing(UID), 0, CLng(UID))
IsMissing не сработает, всегда будет использоваться
CLng(UID). Если бы вдруг сработало, то присваивали бы 0, а 0 и так значение по умолчанию, зачем огород городить? Таким образом, после прикладывания мозга к этой процедуре, она становится такой:
- Код: Выделить всё
Private Function CreateUnit(ByVal Name As String, ByVal Level As Long, Optional ByVal Mach As Boolean = False, Optional ByVal CCode As String = vbNullString, _
Optional ByVal UID As Long = 0, Optional ByVal ParentID As Long = 0) As CSubdivision
If Len(Name) Then
If Level > 0 Then
Set CreateUnit = New CSubdivision
With CreateUnit
.Name = Name
.Level = Level
.CCode = CCode
.UID = UID
.ParentID = ParentID
.Mach = Mach
End With
End If
End If
End Function