ZWCAD - Bloki dynamiczne i atrybuty


Rekomendowane odpowiedzi

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ć?

Odnośnik do komentarza
Udostępnij na innych stronach

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.

Odnośnik do komentarza
Udostępnij na innych stronach

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?

Odnośnik do komentarza
Udostępnij na innych stronach

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

Odnośnik do komentarza
Udostępnij na innych stronach

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.

Odnośnik do komentarza
Udostępnij na innych stronach

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? 

Odnośnik do komentarza
Udostępnij na innych stronach

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.

 

Odnośnik do komentarza
Udostępnij na innych stronach

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

Odnośnik do komentarza
Udostępnij na innych stronach

  • 6 miesięcy temu...

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

Odnośnik do komentarza
Udostępnij na innych stronach

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.

Odnośnik do komentarza
Udostępnij na innych stronach

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.

Odnośnik do komentarza
Udostępnij na innych stronach

Chyba najłatwiej tak:

Dim attribs As Variant
attribs = blkref.GetAttributes
; tu trzeba wybrać odpowiedni atrybut wybierając w pętli po TagString

For i = LBound(props) To UBound(props) - 1
	Set prop = props(i)
    If prop.PropertyName = "Rozstaw" Then
    	; a tu ustawić wartość (TextString) atrybutu
    End If
Next i

 

 

Odnośnik do komentarza
Udostępnij na innych stronach

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.

Odnośnik do komentarza
Udostępnij na innych stronach

Dołącz do dyskusji

Możesz dodać zawartość już teraz a zarejestrować się później. Jeśli posiadasz już konto, zaloguj się aby dodać zawartość za jego pomocą.

Gość
Dodaj odpowiedź do tematu...

×   Wklejono zawartość z formatowaniem.   Usuń formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Odnośnik został automatycznie osadzony.   Przywróć wyświetlanie jako odnośnik

×   Przywrócono poprzednią zawartość.   Wyczyść edytor

×   Nie możesz bezpośrednio wkleić grafiki. Dodaj lub załącz grafiki z adresu URL.

Ładowanie