Search code examples
autocadautolisp

Counting blocks in a specific location (autolisp)


So I'm making a simple function in autolisp to count the number of a specific block in a drawing, and it looks like this:

(defun c:contarblocos()
    (setq ss (ssget "x" ' ((0. "INSERT") (2. "Nome do bloco"))))
    (setq count (sslength ss))
    (alert(strcat "Total de blocos no desenho: " (itoa count)))
)

Now, what I really want is to count the number of blocks in a specific area, defined by the user. In other words, the user will call the function, and then the function will ask for a specific area, where it will look for the specific block and count them, not counting any blocks from outside the selected area.


Solution

  • Rather than using the x mode string of the ssget function (which searches the entire drawing database for all entities which fulfil the criteria of the filter list argument), simply omit this argument to permit the user to make a selection using any valid selection method, e.g.:

    (defun c:contarblocos ( / sel )
        (if (setq sel (ssget '((0 . "INSERT") (2 . "Nome do bloco"))))
            (alert (strcat "Total de blocos no desenho: " (itoa (sslength sel))))
        )
        (princ)
    )
    

    There are a few other issues with your current code:

    • Always declare the variables whose scope is local to your function: in my above example, you will note that the sel symbol is declared in the variable list within the defun expression. For more information on why this is important, you may wish to refer to my tutorial here.

    • You should test whether ssget returns a valid selection set before calling the sslength function to obtain the number of items in the set, since (sslength nil) will error. You will see that I use an if statement in my code to accomplish this.

    • The ssget filter list argument should be an association list of dotted pairs, and as such, there should be a space between the key and the value in each list item, hence this:

      (0. "INSERT")
      

      Should become:

      (0 . "INSERT")
      
    • You should include a final (princ) or (prin1) expression within the defun expression so that the function returns a null symbol to the command line, rather than returning the value returned by the last evaluated expression (i.e. the alert expression, which will return nil). Including a (princ) expression per my example will ensure that the function exits 'cleanly'.