Тема: Конструкция For Each...Next для акадовских объектов. Что здесь неправильно?

Народ, помогите, пожалуйста! Никак не получается с этим кодом:

Sub CalculateTotalLengthOfConductors()
Dim acLine as AcadLine
Dim singleTotalLength as Single
Dim stringLayerName as String
singleTotalLength = 0
stringLayerName = InputBox("Введите слой, на котором надо посчитать длины отрезков")
For Each acLine In ThisDocument.ModelSpace
       If acLine.Layer = stringLayername Then singleTotalLength = singleTotalLength + acLine.Length
Next acLine
MsgBox("Длина отрезков на слое " & stringLayername & " равна " & singleTotalLength)
End Sub

Надо посчитать длины отрезков прямой (AcadLine), находящихся на определенном слое.
Это ведь можно сделать с помощью конструкции For Each...Next, перебирая объекты типа AcadLine в коллекции ThisDocument.ModelSpace. Правильно? Если да, тогда почему на строчке

Next acLine

выдается ошибка "Type mismatch" ("Несоответствие типов")? Код ошибки времени выполнения - 13.

Re: Конструкция For Each...Next для акадовских объектов. Что здесь неправильно?

Я тут в двух местах оговорился. Вместо ThisDocument читать ThisDrawing (именно так, как исправлено, и написано у меня в коде).

Re: Конструкция For Each...Next для акадовских объектов. Что здесь неправильно?

Function CalculateTotalLengthOfConductors() As Double
Dim objEnt As AcadEntity, dSumLen As Double, sLayerName As String
  sLayerName = InputBox("Введите имя слоя для сложения длин отрезков", _
    "Запрос имени слоя", "*")
  If sLayerName = "" Then sLayerName = "*"
  On Error Resume Next
  For Each objEnt In ThisDrawing.ModelSpace
    If UCase(objEnt.Layer) Like UCase(sLayerName) And _
        UCase(objEnt.ObjectName) = "ACDBLINE" Then
      dSumLen = dSumLen + objnt.Length
    End If
  Next objEnt
  CalculateTotalLengthOfConductors = dSumLen
End Function

Re: Конструкция For Each...Next для акадовских объектов. Что здесь неправильно?

А у этого objEnt нет такого свойства - Length. Ты меня что-то дезинформируешь :).

Re: Конструкция For Each...Next для акадовских объектов. Что здесь неправильно?

Не знаю, может, у нас Автокады разные (у меня пока что установлен 2006-й), но в Автокаде, что установлен на моем компе, у класса AcadEntity, увы, нет свойства Length.

Re: Конструкция For Each...Next для акадовских объектов. Что здесь неправильно?

Function CalculateTotalLengthOfConductors() As Double
  Dim objEnt As AcadEntity, dSumLen As Double, sLayerName As String
  sLayerName = InputBox("Введите имя слоя для сложения длин отрезков", _
    "Запрос имени слоя", "*")
  If sLayerName = "" Then sLayerName = "*"
  On Error Resume Next
  For Each objEnt In ThisDrawing.ModelSpace
    If UCase(objEnt.Layer) Like UCase(sLayerName) And _
        UCase(objEnt.ObjectName) = "ACDBLINE" Then
      Dim line As AcadLine
      Set line = objEnt
      dSumLen = dSumLen + line.Length
    End If
  Next objEnt
  CalculateTotalLengthOfConductors = dSumLen
End Function

А так?

Re: Конструкция For Each...Next для акадовских объектов. Что здесь неправильно?

OS_Winuntu пишет:

А у этого objEnt нет такого свойства — Length. Ты меня что-то дезинформируешь :).

А для Вас это принципиально?)))

Re: Конструкция For Each...Next для акадовских объектов. Что здесь неправильно?

Если выполнится условие:

If UCase(objEnt.ObjectName) = "ACDBLINE" Then

то код просто не имеет права не посчитать
строчку:

dSumLen = dSumLen + objnt.Length

Re: Конструкция For Each...Next для акадовских объектов. Что здесь неправильно?

А вот и ошибочка:

dSumLen = dSumLen + obj[b]E[/b]nt.Length

Re: Конструкция For Each...Next для акадовских объектов. Что здесь неправильно?

А в вашем первоначальном варианте вы перебирали все объекты ModelSpace. И естесственно при указании на следующий объект, не являющийся линией, программа сообщала об ошибке типов.
В этом случае лучше воспользоваться предварительным выбором с фильтрами. Будет работать и быстрее и правильнее.

Re: Конструкция For Each...Next для акадовских объектов. Что здесь неправильно?

> Кулик Алексей aka kpblc
Пардон. Я все понял :).

> Александр Ривилис

> Сидор Лютый
Спасибо огромное, особенно за разъяснения.
Если я правильно понимаю, класс AcadEntity является базовым для AcadLine и благодаря основным принципам ООП (наследование и полиморфизм), когда я запрашиваю свойство Length, класс AcadEntity берет значение этого свойства у классов-наследников и выводит мне?

Re: Конструкция For Each...Next для акадовских объектов. Что здесь неправильно?

> OS_Winuntu
Я все понял
Мне кажется, что не все.
Обратите внимание на строчку:

[b]On Error Resume Next[/b]

Именно благодаря ей, а не благодаря основным принципам ООП и работает код предложенный уважаемыми специалистами.
Я не знаю уровня вашей подготовки, но опять таки, очень советую обратить внимание не дельные и практические советы от Сидора Лютого.
Visual Basic тем и хорош, что избавляет программиста от идеологии пресловутого ООП, а также наследований, полиморфизмов и прочих ... инкапсуляций. Зто не значит, конечно, что вам запрещается туда лезть, но это уже другое кино.

Re: Конструкция For Each...Next для акадовских объектов. Что здесь неправильно?

> LeonidSN
Понятно.
Ну, мой уровень подготовки - самый начальный (хотя про ООП я кое-что знаю :), только пока не применял на практике). Я не профессиональный программист, а любитель. Я просто хочу чуток облегчить свою работу по основной специальности :).

Re: Конструкция For Each...Next для акадовских объектов. Что здесь неправильно?

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

Re: Конструкция For Each...Next для акадовских объектов. Что здесь неправильно?

И еще одно замечание. Для конструкторов точность типа Double - избыточна. Нам не нужно столько знаков после запятой. Тип Single - вполне удовлетворяет нашим требованиям. Я, когда на пробу запустил вышеуказанный код, но с типом Single и MsgBox'ом в конце кода, мне ответ пришел с тремя знаками после запятой, что меня вполне устроило (нам даже нужны результаты с точностью до десятых). И надеюсь, что и моих коллег по работе такое устроит.

Re: Конструкция For Each...Next для акадовских объектов. Что здесь неправильно?

Ну, вообщем, и мои две копейки в это дело:

Sub TotalLength()
    Dim ss As AcadSelectionSet
    Dim lin As AcadLine
    Dim Total As Single
    Dim MyLayer As String
    'MyLayer = "OS_Winuntu"
    MyLayer = "arm053"
    On Error Resume Next
    ThisDrawing.SelectionSets.Item("MySet").Delete
    Set ss = ThisDrawing.SelectionSets.Add("MySet")
    Dim intDXF(3) As Integer
    Dim varVal(3) As Variant
    intDXF(0) = -4: varVal(0) = "<AND"
    intDXF(1) = 0: varVal(1) = "LINE"
    intDXF(2) = 8:    varVal(2) = MyLayer
    intDXF(3) = -4:    varVal(3) = "AND>"
    Dim mode As Integer
    mode = acSelectionSetAll
    ss.Select mode, , , intDXF, varVal
    Total = 0
    For Each lin In ss
        Total = Total + lin.Length
    Next lin
    MsgBox Total
End Sub

Re: Конструкция For Each...Next для акадовских объектов. Что здесь неправильно?

Народ, подскажите, пожалуйста, откуда вы берете такие названия: "ACDBLINE" и т.д. Где об этом можно почитать? А то я облазил всю справку по AutoCAD'у и по программированию в его VBA, а там нигде ничего подобного не нашел.

Re: Конструкция For Each...Next для акадовских объектов. Что здесь неправильно?

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

Sub Test()
    Dim objEnt As AcadEntity
    For Each objEnt In ThisDrawing.ModelSpace
        objEnt.Highlight (True)
        MsgBox ("этот объект называется " & objEnt.ObjectName)
        objEnt.Highlight (False)
    Next
End Sub

Re: Конструкция For Each...Next для акадовских объектов. Что здесь неправильно?

^C^C(ENTGET(CAR(ENTSEL)))
вот это повесить на кнопку и про каждый объект можно посмотреть что и как...