Author Topic: Count Specific Block Name and Insert Block to Coords Depending on Block Count  (Read 2041 times)

0 Members and 1 Guest are viewing this topic.

Kylaughlan

  • Guest
Hi there,

I'm looking for a Lisp routine that can count the number of one specific nested block (it will always have the same name) within a single layout, and then automatically insert the same block (which doesn't need to be nested) to differing coordinates depending on how many of that block there already is.

I am having doubts to whether this would even be possible but I thought I would ask.
Seeing as nested blocks can be counted through Lisp, I figured it might be possible.

I've began to explore the world of Lisp and am using a few different routines currently.
They work great but I am nowhere near at a stage where I can write a detailed Lisp routine myself.

[Using AutoCAD 2017 full version]

Thanks guys,

Kyle

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Do you mean nested block in MS that are visible through the viewports in a layout?
« Last Edit: January 10, 2017, 11:33:51 AM by roy_043 »

Kylaughlan

  • Guest
I've just had a rethink, the block to be counted will no longer be nested.  :idiot2: So, the block will simply need to be counted.
Then, a block with the same name would then be inserted into paper space at coordinates relative to the block count found.

For example:

Block count = 1, insert block at 0,0,0
Block count = 2, insert block at 0,50,0
Block count = 3, insert block at 0,100,0
...and so on.

Thanks

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Do you mean blocks in MS that are visible through the viewport(s) in a layout? Or every block in MS?

Kylaughlan

  • Guest
Sorry, I mean only the block type in paper space. The specific block would only ever be inserted into paper space and never model space.

Thanks

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
The confusing portion of your original post is 'count ... within a single layout'.

What do you mean by this:
Do you want to count blocks with a certain name in MS that are visible through the viewport(s) in a layout?
Or do you want to count every block with a certain name in MS?
Or do you want to count blocks with a certain name is the PS of a layout?
« Last Edit: January 10, 2017, 10:09:48 PM by roy_043 »

Kylaughlan

  • Guest
I want to count blocks with a certain name is the PS of a layout.

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
Several approaches are possible for this task. You can use command calls, use entmake or work with Visual Lisp functions in your code. Since you are a novice I have used the first and simplest approach. To help you make sense of it I have added comments. You will have to change the name of the block.
Code - Auto/Visual Lisp: [Select]
  1. (defun c:CountMyBlock ( / blk dist pt ss)
  2.   (setq blk "MyBlock")                ; Set the block name.
  3.   (setq dist 50.0)                    ; Set the X distance for the new inserts.
  4.   (setvar 'cmdecho 0)                 ; Temporarily switch off the CMDECHO.
  5.   (command "_.undo" "_end")           ; End open undo group (there is no problem if there is no open undo group).
  6.   (command "_.undo" "_group")         ; Start new undo group.
  7.   (if
  8.     (and
  9.       (= 1 (getvar 'cvport))          ; Check if PS is active.
  10.       (setq ss                        ; Create a selection set.
  11.         (ssget
  12.           "_X"                        ; Select everything in the drawing...
  13.           (list                       ; ... But filter for:
  14.             '(0 . "INSERT")           ; Only inserts.
  15.             (cons 410 (getvar 'ctab)) ; AND Only on the current tab.
  16.             (cons 2 blk)              ; AND With the correct block name.
  17.           )
  18.         )
  19.       )
  20.     )
  21.     (progn                            ; This will only execute if PS is active and there is a selection set.
  22.       (setq pt '(0.0 0.0 0.0))        ; Initialize the insertion point.
  23.       (repeat (sslength ss)           ; Sslength returns the number of entities in the selection set (= block count).
  24.         (command                      ; Use the Insert command.
  25.           "_.insert"
  26.           blk
  27.           "_non"                      ; _Non is used to override running OSMODE settings.
  28.           pt
  29.           1.0
  30.           1.0
  31.           0.0
  32.         )
  33.         (setq pt (cons (+ dist (car pt)) (cdr pt))) ; Update the insertion point.
  34.       )
  35.     )
  36.   )
  37.   (command "_.undo" "_end")           ; End open undo group.
  38.   (setvar 'cmdecho 1)                 ; Switch CMDECHO back on.
  39.   (princ)
  40. )

Kylaughlan

  • Guest
Thank you so much!! This is great!

It is very close to what I want it to do but just not quite. After using the command, I see it inserts double the amount of blocks that are in the drawing. I only need it to insert one additional block every time I use the command, at an offset distance.
So effectively add one block to the end of the row each time I use the lisp command.

Thank you for making the code so easy to read!
I will try and update it myself to see if I can get it to do what I need it to do but if not I will get back to you if that's alright.

Thanks a bunch!
« Last Edit: January 12, 2017, 02:55:14 AM by Kylaughlan »

Kylaughlan

  • Guest
Hi Roy,

I've managed to crack it!
Without your help and a little help elsewhere, this wouldn't have been possible so thank you.

Here is the code I am using, for reference:

Code - Auto/Visual Lisp: [Select]
  1. (defun c:CMB ( / blk Ydist pt ss)
  2.   (setq blk "blockname")   ; Set the block name.
  3.   (setvar 'cmdecho 0)                        ; Temporarily switch off the CMDECHO.
  4.   (command "_.undo" "_end")                  ; End open undo group (there is no problem if there is no open undo group).
  5.   (command "_.undo" "_group")                ; Start new undo group.
  6.   (if
  7.     (and
  8.       (= 1 (getvar 'cvport))                 ; Check if PS is active.
  9.       (setq ss                               ; Create a selection set.
  10.         (sslength                            ; Get count of selected blocks.
  11.           (ssget
  12.             "X"                              ; Select everything in the drawing...
  13.             (list                            ; ... But filter for:
  14.               '(0 . "INSERT")                ; Only inserts.
  15.               (cons 410 (getvar 'ctab))      ; AND Only on the current tab.
  16.               (cons 2 blk)                   ; AND With the correct block name.
  17.             )
  18.           )
  19.         )
  20.       )
  21.     )
  22.     (progn                                   ; This will only execute if PS is active and there is a selection set.
  23.       (setq Ydist 50)                        ; Set the Y distance.
  24.         (command                             ; Use the Insert command.
  25.           "_.insert"
  26.           blk
  27.           "_non"                             ; _Non is used to override running OSMODE settings.
  28.           (list 0 (* ss Ydist) 0) "" "" ""
  29.         )
  30.     )
  31.   )
  32.   (command "_.undo" "_end")                  ; End open undo group.
  33.   (setvar 'cmdecho 1)                        ; Switch CMDECHO back on.
  34.   (princ)
  35. )

Thank you so much again for your help, it's been really useful.

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
If you test your code in a layout without any "blockname" inserts it will fail. Ssget returns nil then and the sslength function requires a valid selection set as input. Putting the call to sslength inside the progn will fix this.

Kylaughlan

  • Guest
Roy,

Thank you for the tip, and I've actually just realised this myself.
I kind of understand where you're coming from but I am unsure just how I put the call to sslength inside the progn?

roy_043

  • Water Moccasin
  • Posts: 1895
  • BricsCAD 18
This is what I mean:
Code - Auto/Visual Lisp: [Select]
  1. (defun c:CMB ( / blk Ydist pt ss)
  2.   (setq blk "blockname")              ; Set the block name.
  3.   (setvar 'cmdecho 0)                 ; Temporarily switch off the CMDECHO.
  4.   (command "_.undo" "_end")           ; End open undo group (there is no problem if there is no open undo group).
  5.   (command "_.undo" "_group")         ; Start new undo group.
  6.   (if
  7.     (and
  8.       (= 1 (getvar 'cvport))          ; Check if PS is active.
  9.       (setq ss                        ; Create a selection set.
  10.         (ssget
  11.           "X"                         ; Select everything in the drawing...
  12.           (list                       ; ... But filter for:
  13.             '(0 . "INSERT")           ; Only inserts.
  14.             (cons 410 (getvar 'ctab)) ; AND Only on the current tab.
  15.             (cons 2 blk)              ; AND With the correct block name.
  16.           )
  17.         )
  18.       )
  19.     )
  20.     (progn                            ; This will only execute if PS is active and there is a selection set.
  21.       (setq Ydist 50)                 ; Set the Y distance.
  22.       (command                        ; Use the Insert command.
  23.         "_.insert"
  24.         blk
  25.         "_non"                        ; _Non is used to override running OSMODE settings.
  26.         (list 0 (* (sslength ss) Ydist) 0) "" "" ""
  27.       )
  28.     )
  29.   )
  30.   (command "_.undo" "_end")           ; End open undo group.
  31.   (setvar 'cmdecho 1)                 ; Switch CMDECHO back on.
  32.   (princ)
  33. )

Kylaughlan

  • Guest
Ah I see what you mean now! Thank you for clearing that up!
Its working great now, no errors.

I've also added an else to the if statement and now it will place a block at 0,0,0 if it doesn't find the block in the drawing.

Code - Auto/Visual Lisp: [Select]
  1. (defun c:CMB ( / blk Ydist pt ss)
  2.   (setq blk "blockname")              ; Set the block name.
  3.   (setq blkpath "blockpath")              ; Set the block path.
  4.   (setvar 'cmdecho 0)                 ; Temporarily switch off the CMDECHO.
  5.   (command "_.undo" "_end")           ; End open undo group (there is no problem if there is no open undo group).
  6.   (command "_.undo" "_group")         ; Start new undo group.
  7.   (if
  8.     (and
  9.       (= 1 (getvar 'cvport))          ; Check if PS is active.
  10.       (setq ss                        ; Create a selection set.
  11.         (ssget
  12.           "X"                         ; Select everything in the drawing...
  13.           (list                       ; ... But filter for:
  14.             '(0 . "INSERT")           ; Only inserts.
  15.             (cons 410 (getvar 'ctab)) ; AND Only on the current tab.
  16.             (cons 2 blk)              ; AND With the correct block name.
  17.           )
  18.         )
  19.       )
  20.     )
  21.     (progn                            ; This will only execute if PS is active and there is a selection set.
  22.       (setq Ydist 50)                 ; Set the Y distance.
  23.       (command                        ; Use the Insert command.
  24.         "_.insert"
  25.         blk
  26.         "_non"                        ; _Non is used to override running OSMODE settings.
  27.         (list 0 (* (sslength ss) Ydist) 0) "" "" ""
  28.       )
  29.     )
  30.     (progn                            ; This will only execute if PS is active and there is no selection set.
  31.       (setq Ydist 50)                 ; Set the Y distance.
  32.       (command                        ; Use the Insert command.
  33.         "_.insert"
  34.         blkpath
  35.         "_non"                        ; _Non is used to override running OSMODE settings.
  36.         (list 0 0 0) "" "" ""
  37.       )
  38.     )
  39.   )
  40.   (command "_.undo" "_end")           ; End open undo group.
  41.   (setvar 'cmdecho 1)                 ; Switch CMDECHO back on.
  42.   (princ)
  43. )


Thank you so so much for this! It's going to make things run much more smoothly.