Make a set of blocks in order of an attribute value (trying via safearray)

Make a set of blocks in order of an attribute value (trying via safearray)

Gorra
Advocate Advocate
983 Views
9 Replies
Message 1 of 10

Make a set of blocks in order of an attribute value (trying via safearray)

Gorra
Advocate
Advocate

Hello,

I have a drawings that need a variable number of a single block to be selected and put in numerical order for further processing (The blocks are numbered rectangles representing intended viewports).

I tried getting them as a selection set and then exporting them to another selection set in order, but that didn't work. From what I've been reading it won't work, so I'm trying to order them via a vlax safearray. I'm making slightly more progress, but still isn't getting anywhere fast. 

I'm wondering if I'm just barking up the wrong tree completely.

I've attached the current (unfinished) code, but the relevant subfunctions are here: 

 

(defun SelectBlocks ( / d name n out Blklst Log1)
    (if (setq name "GRIDSHEET_1500"  ;;selecting all dynamic blocks of this name
         Blklst (ssget "_X" '((0 . "INSERT")))
          n -1
          LytSS (ssadd)
    )
    (while (setq Blck (ssname Blklst (setq n (1+ n))))
        (if (= :vlax-true (vla-get-IsDynamicBlock (vlax-ename->vla-object Blck)))
            (if (= (strcase (vla-get-Effectivename (vlax-ename->vla-object Blck))) (strcase name))
            (ssadd Blck LytSS)
             )
        )
    )
  )
 )
 
 (defun Sortblocks ( / first att i ArryIndx x Lb) ; creating an ordered list from the selected blocks
    (setq LytArry (vlax-make-safearray vlax-vbObject '(0 . 50))) ; create array
    (setq ArryIndx 0) ; set index 0
;; __________________________________________________it gets this far then errors out
    (foreach x LytSS ; looking through the sset for the first value
       (setq first (LM:vl-getattributevalue x VTag))
      (if (eq first 3) ; if attribute is 3
          (setq LytArry (vlax-safearray-put-element LytArry ArryIndx x)) ; make first value in array
          (princ)
      )
    )
(setq ArryIndx 1)
(setq Lb 3)
(while (< ArryIndx (sslength LytSS)) ; while current indexs less than the total length
    (foreach i LytSS ; check each block for next attibute value
        (setq SL (ssname LytSS ArryIndx))
        (setq VSL (vlax-ename->vla-object SL)) ; make each entry a vla object
        (setq AVal (LM:vl-getattributevalue VSL VTag)) ; get the sheet number attribute
        (if (eq AVal (+ Lb 1)) ; If sheet number is 1 higher than current Lb
            (progn
                (vlax-safearray-put-element LytArry ArryIndx VSL) ; add the block to the array
                (setq ArryIndx (+ ArryIndx 1)) 
                (setq Lb (+ Lb 1))
                (alert "added to array")
            )
            (progn
                (alert "not added to array")
            )
        ) ; end if
      ) ; end foreach
    ) ;end while
  (setq SrtdLst (vlax-safearray->list LytArry)) ; create list from Array
 )
  

I'm currently getting a bad argument type: consp <Selection set: e5> when I try to get the first foreach loop going. 

Mostly I'm just wondering this approach will work at all before I sink more time into it.

 

Thanks,

Gorra

 

0 Likes
Accepted solutions (1)
984 Views
9 Replies
Replies (9)
Message 2 of 10

Sea-Haven
Mentor
Mentor

For me start again but use some of your code, when you get the dynamic block you add to (ssadd Blck LytSS) so have a selection set of blocks, just look at block and get the attribute value then make a list of (attnum entityname)(attnum entityname)...... just sort the list based on the (car (car value ie sorts on attribute number, you can use this sorted list to make your layouts. 

 

I do something now but rely on creation order but adding the sort would be a good idea where we delete and add a rectang being the mview shape. 

 

Have a look at 

SeaHaven_0-1714628296236.png

 

SeaHaven_1-1714628324769.png

 

0 Likes
Message 3 of 10

komondormrex
Mentor
Mentor
Accepted solution

i would suggest you to operate with lists not selection sets like the following.

select all inserts with block_name and get them as list of vla-objects 

 

(defun selected_blocks_list (block_name / insert_sset)
	(if (setq insert_sset (ssget "_x" '((0 . "insert"))))
		(vl-remove-if '(lambda (insert) (/= (strcase block_name) (strcase (vla-get-effectivename insert))))
					   (mapcar 'vlax-ename->vla-object (vl-remove-if 'listp (mapcar 'cadr (ssnamex insert_sset))))
		)
	)
)
;calling (selected_blocks_list "GRIDSHEET_1500")

 

sort list of above insert_list  (vla-objects) by attribute sort_attribute

(defun sort_insert_list_attribute (insert_list sort_attribute)
	(vl-sort block_list 
			'(lambda (insert_1 insert_2) (< (atoi (getpropertyvalue (vlax-vla-object->ename insert_1) sort_attribute))
											(atoi (getpropertyvalue (vlax-vla-object->ename insert_2) sort_attribute))
										 )
			 )
	)
)

;calling (sort_insert_list_attribute selected_blocks_list "MAPSHTNUM")

use the both like that to get sorted list of inserts vla-objects.

(if (setq to_sort_list (selected_blocks_list "gridsheet_1500")) 
	(setq sorted_list (sort_insert_list_attribute to_sort_list "mapshtnum"))
)

 

0 Likes
Message 4 of 10

Gorra
Advocate
Advocate

@komondormrex Thank you I will also try this and see what I get.

0 Likes
Message 5 of 10

Gorra
Advocate
Advocate

@Sea-Haven Thanks, I will give that a try.

0 Likes
Message 6 of 10

Kent1Cooper
Consultant
Consultant

@Gorra wrote:

... a single block to be selected and put in numerical order for further processing (The blocks are numbered rectangles representing intended viewports).

I tried getting them as a selection set and then exporting them to another selection set in order, but that didn't work. ....

....

;; __________________________________________________it gets this far then errors out
    (foreach x LytSS ; looking through the sset for the first value
....

I'm currently getting a bad argument type: consp <Selection set: e5> ....


That's because (foreach) is for stepping through a list, but LytSS is a selection set.

 

Is there a specific tag name that holds the numbering you want them sorted by?  If so, then you can convert the selection set to a list as already suggested, or you can step through the selection set and directly from there, without any need for VLA-object conversions or looking around for the right tag, build a list of sub-lists, pairing each Block insertion with the value of its numbering tag.  Then it's easy to sort by the number, and then from that sorted list, either extract just the Block insertions into a list of their own in order, or put the Block insertions into another selection set, in sorted order.  Would the "further processing" be better served with a list of entity names, or a selection set?

Kent Cooper, AIA
0 Likes
Message 7 of 10

Gorra
Advocate
Advocate

Hi @Kent1Cooper 

I've gotten komondormrex's suggestion working, whether it works out overall for the vport creations I'll have to see. 

 

Gorra

0 Likes
Message 8 of 10

Sea-Haven
Mentor
Mentor

Once you have the blocks sorted as suggested using entity name then its easy to go to a layout and make a mview that matches the rectang, no reason why not make the list (attnum insertionpt maxpt) make your insertionpoint lower left. 

 

Having done this recently you need to work out how your going to size that block, are you using one title block sheet or different sizes, these questions need to be asked 1st. An updated version allows different scaled rectangs and orientation of sheet landscape v's portrait. 

 

Anyway here is some big hint code mp is midpoint of rectang, ahsc is scale of rectang, ang is rotation angel of rectang. Expects you have made a new layout with correct title block and mview in it.

 

 

(command "mspace")
(command "zoom" "C" mp 500)
(command "UCS" "Z" ang "plan" "")
(command "UCS" "W")
(command "zoom" "C" mp (strcat (rtos ahsc 2 1) "XP") )
(command "Psltscale" 1)
(command "pspace")

 

 

 

 

0 Likes
Message 9 of 10

Gorra
Advocate
Advocate

Thanks @Sea-Haven . The scale and vport size are set by the client so those are easy enough. Your command list is a bit cleaner than mine so I'll probably copy some of that. I had been going with "-view" defined viewports, but the p-space vport size is just a bit larger than the block at the intended scale so I'll need to throw a zoom command in there anyway.

0 Likes
Message 10 of 10

Sea-Haven
Mentor
Mentor

I don't use Views rather set Twistangle of viewport. 

 

; TwistAngle = 5.38670568565608

0 Likes