ZWCAD - Bloki dynamiczne i atrybuty


Recommended Posts

Chcę zrobić blok dynamiczny pręta do zbrojenia płyty. Pręt ma określoną długość, którą mogę rozciągać (a więc zmieniać jego długość) a prostopadle do niego mam linię wymiarową określającą jego rozstaw, którą też mogę rozciągać (też mam długość rozkładu). Po środku stoi blok z atrybutami. 

Czy mogę powiązać atrybuty bloku ze zmiennymi atrybutami? Aby blok wiedział, że zmieniła się długość pręta i wciągała do siebie jego wartość?

Macie jakiś pomysł czy można to zautomatyzować?

Link to comment
Share on other sites

Z powodu zastrzeżeń patentowych dotyczących bloków dynamicznych ZWCAD nie ma edytora bloków dynamicznych, więc raczej nie da się stworzyć takiego bloku.

Natomiast jeśli Pan dąży, np. do zestawienia prętów w tabelce, to można na to osiągnąć poprzez polecenie _DATAEXTRACTION

Można utworzyć sobie własny szablon ustawień i szybko utworzyć takie zestawienie.

Link to comment
Share on other sites

Nie nie, nie o to chodzi. 

No dobrze.. a można wczytać wartość długości rozciąganych elementów do VBA?

To znaczy, mam blok dynamiczny, w którym rozciągam dwie prostopadłe linie. Wartości te są edytowalne i można je zmieniać poprzez kliknięcie myszką lub wpisanie wartości. Te wartości są sobie tożsame. Czy można stworzyć makro VBA w którym to klikamy na blok i np. msgbox podaje nam wartości długości tych dwóch linii?

Link to comment
Share on other sites

OK, więc w pliku blok dynamiczny, który posiada parametry rozciągania długości o nazwach Rozstaw i Dlugosc_preta (na zdjęciu w czerwonej ramce), blok będzie posiadał również atrybuty do przechowywania informacji itp. (niebieska ramka), ale o nich proszę nie myśleć - wiem jak się do nich dostać przez VBA.

Teraz pytanie, czy mogę wczytać wartości z czerwonej ramki z pod VBA i wyświetlić je w msgBox, a może mogę je też podmienić?

PS. Na początku chodziło mi o to, żeby któryś z atrybutów (z niebieskiej ramki) podczytywał na żywo po każdej zmianie długości (z czerwonej ramki)

test_blok.png

forum_cad_blok.dwg

Link to comment
Share on other sites

Tak na szybko to odczytać właściwości (z niebieskiej ramki) można tak:

Public Sub test()
    Dim ss As ZcadSelectionSet
    Dim ent As ZcadEntity
    Dim bname As String
    Dim props() As ZcadDynamicBlockReferenceProperty
    Dim pvalue As Variant
    Dim blkref As ZcadBlockReference
    With ThisDrawing.SelectionSets
        While .Count > 0
              .Item(0).Delete
        Wend
        Set ss = .Add("$DynBlocks$")
    End With

    Dim ftype(0 To 1) As Integer
    Dim fdata(0 To 1) As Variant

    ftype(0) = 0: ftype(1) = 66
    fdata(0) = "INSERT": fdata(1) = 1
    ss.SelectOnScreen ftype, fdata
     
    If ss.Count = 0 Then
        MsgBox "Nie wybrano bloku...Kończymy"
        Exit Sub
    End If

    Set blkref = ss.Item(0)
    Dim i As Integer
    props = blkref.GetDynamicBlockProperties
 
    Dim prop As ZcadDynamicBlockReferenceProperty
    For i = LBound(props) To UBound(props)
        Set prop = props(i)
        pvalue = prop.Value
        Dim asTxt As String
        asTxt = CStr(pvalue)
        MsgBox (asTxt)
    Next i

End Sub

Dalej powinno już być łatwo.

Link to comment
Share on other sites

Aha, elegancko.

Teraz jak już mam dostęp do bloku dynamicznego, jego parametrów i atrybutów to chodzi mi po głowie takie makro, które byłoby wczytywane wraz z oknem zwcada i śledziłoby zmianę któregokolwiek parametru (lub atrybutu) bloku o nazwie "Test_blok" i za każdym razem wyrzucałoby Msgbox typu "parametr bloku o współrzędnych x,y został zmieniony" lub "atrybut bloku o współrzędnych x,y został zmieniony". Byłby to blok superdynamiczny, który mógłby reagować na każdą zmianę :)

Jest to w ogóle możliwe? Czy takie makro ciągle działające w tle nie zajmowałoby za dużo zasobów? Co o tym myślicie? 

Link to comment
Share on other sites

Tak na pierwszy rzut oka wygląda na możliwe. Ale jak zwykle diabeł tkwi w szczegółach.

Mechanizm reakcji można zrealizować przy użyciu reaktorów. Tylko nigdy nie używałem ich w VBA, nie jestem pewien czy są dostępne. Jeśliby nie były, to można taki reaktor uruchamiać w LISP a on uruchamiałby odpowiednią funkcję w VBA.

Co do zasobów to raczej byłbym spokojny, choć oczywiście wszystko zależy od stopnia skomplikowania makra i wielkości pliku. Ale to lepiej sprawdzić w boju niż zakładać że będzie zbyt obciążające. Dla każdego użytkownika taki próg bólu może być w innym miejscu.

 

Link to comment
Share on other sites

Witam

kiedyś napisałem taki program który odczytuje parametry bloku dynamicznego:

sub program()

On Error Resume Next

Dim z As Double

Dim x As Double

Dim ent As ZcadEntity

Dim blk1 As ZcadBlockReference

Dim ContextData As Variant

Dim sset1 As ZcadSelectionSet

Dim dynblk As ZcadDynamicBlockReferenceProperty

Set sset1 = ThisDrawing.SelectionSets.Add("grupa1")

ThisDrawing.Utility.Prompt ("wybierz bloki dynamiczne :")
sset1.SelectOnScreen
z = ThisDrawing.Utility.GetInteger("wybierz nr. zmiennej bloku dyn : ")
z = z - 1
For Each ent In sset1
If ent.ObjectName = "AcDbBlockReference" Then
Set blk1 = ent
If blk1.IsDynamicBlock = True Then
ContextData = blk1.GetDynamicBlockProperties
Set dynblk = ContextData(z)
x = x + dynblk.Value
End If
End If
Next

ThisDrawing.Utility.Prompt ("calkowita suma współczynnika (" & dynblk.PropertyName & ") wynosi = " & x)
ThisDrawing.Utility.Prompt (" ")

end sub

teraz wystarczy go tylko przerobić do potrzeb.

zrobiłem też taki blok dynamiczny powiązany z wymiarem z nudów, może taka wersja będzie wystarczająca ??

informacja o długości pręta i rozstawienia jest wyświetlona.

pozdrawiam

 

blok_pret.dwg

Link to comment
Share on other sites

  • 6 months later...

No dobra, pomożecie powalczyć z reaktorem? Plik z blokiem dynamicznym - bohaterem w załączniku

Procedura:

Private Sub ZcadDocument_ObjectModified(ByVal Object As Object)

    Dim ATT As ZcadAttributeReference
    Dim atts As Variant
           
        If TypeOf Object Is ZcadBlockReference Then
            Set blk = Object
            If blk.EffectiveName = "Konstruktor_dozbrojenia" Then
                atts = blk.GetAttributes
                For j = 0 To UBound(atts)
                    Set att = atts(j)
                    If j = 0 Then MsgBox "Udało się" & att.TextString
                Next

            End If
        End If
End Sub

OK, trochę dziwnie wygląda odniesienie się do atrybutu tego bloku, ale działa..  Procedura powoduje wywalenie msgboxa z pokazaniem atrybutu po każdorazowej zmianie bloku.

Zmieniona procedura:

Private Sub ZcadDocument_ObjectModified(ByVal Object As Object)

    Dim att As ZcadAttributeReference
    Dim atts As Variant
           
        If TypeOf Object Is ZcadBlockReference Then
            Set blk = Object
            If blk.EffectiveName = "Konstruktor_dozbrojenia" Then
                atts = blk.GetAttributes
                For j = 0 To UBound(atts)
                    Set att = atts(j)
                    'If i = 0 Then MsgBox "Udało się" & att.TextString
                    
                    
                    
                    
                    
                        Dim ss As ZcadSelectionSet
                        Dim ent As ZcadEntity
                        Dim bname As String
                        Dim props() As ZcadDynamicBlockReferenceProperty
                        Dim pvalue As Variant
                        Dim blkref As ZcadBlockReference
                        With ThisDrawing.SelectionSets
                            While .Count > 0
                                  .item(0).Delete
                            Wend
                            Set ss = .Add("$DynBlocks$")
                        End With
                    
                        Dim ftype(0 To 1) As Integer
                        Dim fdata(0 To 1) As Variant
                    
                        ftype(0) = 0: ftype(1) = 66
                        fdata(0) = "INSERT": fdata(1) = 1
                        ss.SelectOnScreen ftype, fdata
                         
                        If ss.Count = 0 Then
                            MsgBox "Nie wybrano bloku...Kończymy"
                            Exit Sub
                        End If
                    
                        Set blkref = ss.item(0)
                        'Dim i As Integer
                        props = blkref.GetDynamicBlockProperties
                        MsgBox props(0).Value
                        Dim prop As ZcadDynamicBlockReferenceProperty
                        'For i = LBound(props) To UBound(props) - 1
                            Set prop = props(0)
                            pvalue = prop.Value
                            Dim asTxt As String
                            asTxt = CStr(pvalue)
                            MsgBox (asTxt)
                        'Next i
                    

                Next

            End If
        End If
End Sub

Na chama wrzucone to co Kruszynski wymyślił. Tym razem procedura pokazuje długość pręta po każdorazowej zmianie. Niestety mogę się odnieść jedynie do pierwszej długości props(0), wyłączyłem pętle, bo przy props(1) wywala już błąd.

 

CEL: Po zmianie długości pręta lub wymiaru, chcę podmienić atrybut. Czuję, że jestem już blisko, ale działam na ślepo. Pomożecie?

blok.dwg

Link to comment
Share on other sites

Wiem że czegoś tu nie rozumiem, ale też jeszcze nie wiem czego.

Z eksperymentu wyszło mi, że tablica

Dim prop As ZcadDynamicBlockReferenceProperty

Zwraca 8 elementów.
Te o indeksach 1,3,5,7 mają taką samą nazwę "Origin" Nie wiem dlaczego, i nie wnikam,
ale jak zmieniłem pętlę, żeby przechodziła indeksem co 2

For i = LBound(props) To UBound(props) - 1 Step 2
	Set prop = props(i)
	pvalue = prop.Value
	Dim asTxt As String
	asTxt = CStr(pvalue)
	MsgBox (asTxt)
Next i

To wyświetliło poprawnie i kulturalnie 4 wartości.

Link to comment
Share on other sites

A jednak jeszcze trochę głębiej w to wniknąłem i wyszło mi że tam gdzie jest Origin

asTxt = CStr(pvalue)

Wyrzuca błąd

Run-time error '13' :

Type mismatch

w linijce

asTxt = CStr(pvalue)

Co w sumie miałby sens, bo w tym przypadku pvalue jest variantem - tablicą trzyelementową. To chyba jest jakiś punkt, A z takimi CStr może sobie nie poradzić.

Teraz pytanie co dalej z tym ma się dziać. o jeśli maa to być tylko wyświetlone, to pewnie wystarczy odwołać się do każdego elementu variantu, i poskładać to w jeden tekst. Ale to już pozostawiam, powinno być łatwe.

Link to comment
Share on other sites

Tak też o tym myślałem. Tak będę kombinował

Do stworzenia superbloku potrzebne mi jeszcze kilka patentów.

1. Jaka komenda vba poda mi współrzędne zaznaczonego bloku?

2. Czy istnieje możliwość podania współrzędnych w jakiejś funkcji a funkcja zwróci nazwy wszystkich bloków występujących w tym punkcie i je zaznaczy?

3. Czy jest możliwość zaingerowania w blok nie edytując go. Na przykład po spełnieniu określonego warunku wszystko co jest wewnątrz bloku zmieni kolor na żółty.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...