Visual Lisp and Attributes
You can find the VBA equivalent to this application here.
And the AutoLisp version here.
When you want to edit attributes in AutoCAD most of
us use the "Attedit" command. Firstly, we must select the
attribute we would like to edit. Then the "Edit Attribute"
dialogue box appears which allows us to add or change the values of our
attribute. Personally, I think this dialogue leaves a lot to be desired.
You cannot customise it in any way, and it displays all attributes whether
you want them or not. As well, if you have a lot of attributes you need to
page your way through numerous dialogues before reaching the attribute you
want to edit.
In this tutorial we are going to have a look at
extracting attribute data from a block, displaying the data in a custom
dialogue box, and then updating the attribute data on exit.
Right, what do we need to do?
1. Find the block containing the
attribute data. (Why select it when we can get AutoCAD to find it for us.)
2. Extract the attribute data and
display it in a dialogue box.
3. Allow the user to change the
data if he so wishes.
4. Update the attribute data with
the new information entered into the dialogue box.
O.K. fire up AutoCAD and open the drawing
Attab-vl.dwg.
Alright, I admit that it's not much of
a title block, but it's enough to give you the general idea.
Now, at the command prompt type (load
"Addat-vl") and then enter.
Now, type "Addat-vl" and press enter again.
This dialogue should appear :
Change some of the data and then press
the "OK" button.
The title block data should be updated. Clever hey?
You can expand on this routine as much
as you like using the following coding as a template.
Hint : You don't have to display all the attribute data stored in a block.
Only display what you want the user to modify. As well, you can split your
data over multiple dialogue boxes. eg. One for title block, one for
revisions, one for reference drawings, etc. All the data though is
contained in one attribute.
Here's the coding, DCL code first :
attabvl : dialog {
label = "Drawing Title Block";
: edit_box {
label = "&Drawing Number";
key = "eb1";
edit_width = 30;
}
: edit_box {
label = "&Revision";
key = "eb2";
edit_width = 30;
}
: edit_box {
label = "Drawn &By";
key = "eb3";
edit_width = 30;
}
: edit_box {
label = "D&ate";
key = "eb4";
edit_width = 30;
}
: edit_box {
label = "&Title";
key = "eb5";
edit_width = 30;
}
ok_cancel ;
:text_part {
label = "AfraLisp - http://www.afralisp.com";
}
}
And now the Visual Lisp coding with
plenty of in-line comments to assist you:
;CODING STARTS HERE
;
;All Tutorials and Code are provided "as-is" for purposes of
instruction and
;utility and may be used by anyone for any purpose entirely at their own
risk.
;Please respect the intellectual rights of others.
;All material provided here is unsupported and without warranty of any
kind.
;No responsibility will be taken for any direct or indirect consequences
;resulting from or associated with the use of these Tutorials or Code.
;*******************************************************************************
; AfraLisp
; http://www.afralisp.com
; afralisp@afralisp.com
; afralisp@mweb.com.na
;*******************************************************************************
;This application will extract attributes from a block and display them in
a
;dialog box. The attributes will then be updated.
;
;Dependencies : Attab-vl.dcl and Attab-vl.dwg are
;required and must be within the AutoCAD search path.
;
;Usage : Open Attab-vl.dwg then load and run Attab-vl.lsp.
;*******************************************************************************
(prompt "\nATTAB-VL Loaded....Type ATTAB-VL to run.....")
(defun c:attab-vl (/)
;load visual lisp extensions
(vl-load-com)
;retrieve reference to the active document
(setq acadDocument (vla-get-activedocument (vlax-get-acad-object)))
;retrieve reference to the selection set collection
(setq ssets (vla-get-selectionsets acadDocument))
;check if the selection set exists - $Set
(if (vl-catch-all-error-p (vl-catch-all-apply 'vla-item (list ssets
"$Set")))
;if it doesn't create a new one
(setq newsset (vla-add ssets "$Set"))
;if it does exist
(progn
;delete it
(vla-delete (vla-item ssets "$Set"))
;then create a new one
(setq newsset (vla-add ssets "$Set"))
);progn
);if
;create a single element array - integer
(setq filter_code (vlax-make-safearray vlax-vbinteger '(0 . 0)))
;create a single element array - variant
(setq filter_value (vlax-make-safearray vlax-vbvariant '(0 . 0)))
;filter for name - code 2
(vlax-safearray-fill filter_code '(2))
;filter for block name - attab-info
(vlax-safearray-fill filter_value '("attab-info"))
;filter the drawing for the block
(vla-select newsset acSelectionSetAll nil nil filter_code filter_value)
;if the block is found
(if (>= (vla-get-count newsset) 1)
;display the dialog
(ddisplay)
;if the block is not found
(alert
"\nIncorrect Drawing Sheet
\n Use Manual Edit"
)
);if
;finish clean
(princ)
);defun
;;;**********************************************************
(defun ddisplay (/)
;load the dialog
(setq dcl_id (load_dialog "attab-vl.dcl"))
;check it exists
(if (not (new_dialog "attabvl" dcl_id))
(exit)
);if
;retrieve the block reference
(setq item (vla-item newsset 0))
;retrieve the attributes
(setq theatts (vla-getattributes item))
;convert to a list
(setq attlist (vlax-safearray->list (variant-value theatts)))
;extract the attributes
(mapcar 'set '(theattribute1 theattribute2 theattribute3 theattribute4
theattribute5) attlist)
;extract the text strings from the attributes
(setq eb1 (vla-get-textstring theattribute1)
eb2 (vla-get-textstring
theattribute2)
eb3 (vla-get-textstring
theattribute3)
eb4 (vla-get-textstring
theattribute4)
eb5 (vla-get-textstring
theattribute5)
);setq
;put the info into the dialog
(set_tile "eb1" eb1)
(set_tile "eb2" eb2)
(set_tile "eb3" eb3)
(set_tile "eb4" eb4)
(set_tile "eb5" eb5)
;set the focus to the drawing number
(mode_tile "eb1" 2)
;if cancel selected exit
(action_tile
"cancel"
"(done_dialog) (setq userclick nil)"
)
;if OK selected, retrieve the tile values
(action_tile
"accept"
(strcat
"(progn (setq eb1a (get_tile
\"eb1\"))"
"(setq eb2a (get_tile
\"eb2\"))"
"(setq eb3a (get_tile
\"eb3\"))"
"(setq eb4a (get_tile
\"eb4\"))"
"(setq eb5a (get_tile
\"eb5\"))"
" (done_dialog)(setq userclick T))"
)
)
;start the dialog
(start_dialog)
;unload the dialog
(unload_dialog dcl_id)
;if OK was selected
(if userclick
;do the following
(progn
;update the attribute textstrings
(vla-put-textstring theattribute1 eb1a)
(vla-put-textstring theattribute2 eb2a)
(vla-put-textstring theattribute3 eb3a)
(vla-put-textstring theattribute4 eb4a)
(vla-put-textstring theattribute5 eb5a)
;update the block
(vla-update newsset)
;regen the drawing
(command "REGEN")
);progn
);if
);defun
;;;***********************************************************
;load clean
(princ)
;;;**********************************************************
;
;CODING ENDS HERE
Please note that there is no error checking in this
routine and I have left all variables as global to assist you in checking
their values whilst you are analyzing the code.
If you are too lazy to type, and don't know how to
copy and paste, you can download the coding and sample drawing by very
gently placing your cursor here and
clicking once. "Hey, not so hard!!!!" |