dber Posted 22 hours ago Posted 22 hours ago I was wondering if it was possible to turn a multiline-text list of construction notes into a standard way we label construction notes using this hexagon and numbering them. I included a CAD file with sample text (paperspace) and the final product of hexagon placement (0.25" from text, centered with text for 1-line, centered between top 2 lines for multi-line text). NotesLispTest.dwg Quote
BIGAL Posted 20 hours ago Posted 20 hours ago Yep an easy solution, if you make a block with an attribute of mtext, so can be one or more lines. You insert the block, add attribute value. You can adjust the insertion point of the mtext attribute, via lisp (vlax-put attobj 'insertionpoint (list 10 5)). You can control the text pt to be say even with top, mid aligned, bottom aligned and so on even to left or right. In image I just made a simple block with a single attribute. If you dont know how to write a lisp for the task just ask. You may need to use "Bounding box" on the attribute to work out its corners or mid points and so on. Can use my Multi radio buttons.lsp to select alignment . The Multi radio buttons 2 col.lsp may be useful for a advanced version of moving attribute. Quote
Romero Posted 12 hours ago Posted 12 hours ago hello @dber I get what you're after — numbered construction notes with a hexagon bubble, text wrapping at a fixed column width. I can put a LISP together for you. Just answer these and I'll build it — letters are fine: 1. Where does the text come from? a) I type it in as I go b) it's already scattered in the drawing c) I paste it from Word or Excel 2. If it's already in the drawing, what is it? a) TEXT b) MTEXT c) not sure / it's mixed 3. How are the notes split up? a) one text object per note b) all in one MTEXT, one paragraph per note c) not sure 4. Is the number already written into the text? a) yes, like "1. Pour slab..." b) no, it needs to be added c) some yes, some no 5. Does the hexagon already exist? a) yes b) no, it needs to be created 6. If it exists, what is it? a) a block with an attribute for the number b) a block with no attribute (number sits separately) c) loose geometry, just lines d) not sure 7. Column width? a) I'll pick it in the drawing b) I'll give you a number 8. Does the text have hard line breaks already in it? a) yes, keep them b) yes, strip them and let it wrap on its own c) no 9. Where do the notes go? a) model space b) layout / paper space Answer those and I'll know exactly what to write. Quote
dber Posted 4 hours ago Author Posted 4 hours ago 15 hours ago, BIGAL said: Yep an easy solution, if you make a block with an attribute of mtext, so can be one or more lines. You insert the block, add attribute value. You can adjust the insertion point of the mtext attribute, via lisp (vlax-put attobj 'insertionpoint (list 10 5)). You can control the text pt to be say even with top, mid aligned, bottom aligned and so on even to left or right. In image I just made a simple block with a single attribute. OnlineImage Galleries If you dont know how to write a lisp for the task just ask. You may need to use "Bounding box" on the attribute to work out its corners or mid points and so on. Can use my Multi radio buttons.lsp to select alignment . The Multi radio buttons 2 col.lsp may be useful for a advanced version of moving attribute. Sadly I don't know how to write this code, i'm pretty new to LISP and have only used some made by others. The sample DWG has the hexagon as a block that we use with a floating # on top. If a LISP code can just take the MText notes and convert it using the ConstructionNote block (with text or attribute on top, doesn't matter) and automatically number them in order, that would be nice. Quote
Romero Posted 51 minutes ago Posted 51 minutes ago (edited) 3 hours ago, dber said: Sadly I don't know how to write this code, i'm pretty new to LISP and have only used some made by others. The sample DWG has the hexagon as a block that we use with a floating # on top. If a LISP code can just take the MText notes and convert it using the ConstructionNote block (with text or attribute on top, doesn't matter) and automatically number them in order, that would be nice. @dber From your post, I understood that you want to number construction detail notes from an existing MTEXT object. I put together two versions so you can try both and choose whichever suits your workflow: - Loose geometry: separate hexagon outlines, solid fills and text numbers. - Block with attribute: each marker is a block with an editable number attribute. Both versions read manual paragraph breaks in the MTEXT. Wrapped lines remain part of the same numbered paragraph, and empty paragraphs are skipped. Each hexagon is sized proportionally to the text and centered vertically beside its paragraph. Commands: - HENL / HENB: add markers beside the existing MTEXT without moving or splitting it. - HENLC / HENBC: create separate numbered paragraphs at a location you pick, with the option to keep or delete the original. You can load both files together—their commands are different. These versions are intended for single-column, non-annotative MTEXT without fields. Give them a try and let me know how they work for your example. Code below. ;;; HEXENUM 1.2 - Loose geometry | AutoCAD Windows / Visual LISP ;;; HENL / HEXENUML: number the existing MTEXT in place. ;;; HENLC / HEXENUMLC: create separate paragraphs at a picked location. ;;; Hexagon side = 1.8 x nominal text height; SOLID fill = ACI 255. ;;; Both editions can be loaded together; command and helper names are isolated. (vl-load-com) (defun R0:HENL-Fail (msg) (setq henl-msg msg) (exit)) (defun R0:HENL-Prefix (frames / result frame) (setq result "") (foreach frame (reverse frames) (setq result (strcat result "{" frame))) result) (defun R0:HENL-Close (frames / result) (setq result "") (repeat (length frames) (setq result (strcat result "}"))) result) (defun R0:HENL-Records (s / i n ch next token frames part visible result j brk start) (setq i 1 n (strlen s) frames (list "") part "{" visible nil) (while (<= i n) (setq start i ch (substr s i 1) next (substr s (1+ i) 1) brk nil) (cond ((or (= ch (chr 10)) (= ch (chr 13))) (setq brk T) (if (and (= ch (chr 13)) (= next (chr 10))) (setq i (1+ i))) (setq i (1+ i))) ((= ch "\\") (cond ((= next "P") (setq brk T i (+ i 2))) ((= next "N") (R0:HENL-Fail "Column breaks found. Set the MTEXT to a single column.")) ((member next '("\\" "{" "}" "~")) (setq part (strcat part (substr s i 2)) i (+ i 2)) (if (/= next "~") (setq visible T))) ((member next '("A" "C" "c" "F" "f" "H" "Q" "T" "W" "p" "S")) (setq j (+ i 2)) (while (and (<= j n) (/= (substr s j 1) ";")) (setq j (1+ j))) (if (> j n) (R0:HENL-Fail "Incomplete MTEXT formatting code.")) (setq token (substr s i (1+ (- j i))) part (strcat part token) i (1+ j)) (if (= next "S") (setq visible T) (setq frames (cons (strcat (car frames) token) (cdr frames))))) ((member next '("L" "l" "O" "o" "K" "k")) (setq token (substr s i 2) part (strcat part token) i (+ i 2) frames (cons (strcat (car frames) token) (cdr frames)))) ((and (= next "U") (= (substr s (+ i 2) 1) "+")) (setq part (strcat part (substr s i 7)) i (+ i 7) visible T)) (T (setq part (strcat part ch) i (1+ i) visible T)))) ((= ch "{") (setq frames (cons "" frames) part (strcat part ch) i (1+ i))) ((= ch "}") (if (null (cdr frames)) (R0:HENL-Fail "Unbalanced formatting braces.")) (setq frames (cdr frames) part (strcat part ch) i (1+ i))) (T (setq part (strcat part ch) i (1+ i)) (if (not (member ch (list " " (chr 9)))) (setq visible T)))) (if brk (progn (if visible (setq result (cons (list (strcat part (R0:HENL-Close frames)) (1- start) (R0:HENL-Close frames)) result))) (setq part (R0:HENL-Prefix frames) visible nil)))) (if (/= (length frames) 1) (R0:HENL-Fail "Unbalanced formatting braces.")) (if visible (setq result (cons (list (strcat part (R0:HENL-Close frames)) n (R0:HENL-Close frames)) result))) (reverse result)) (defun R0:HENL-Split (s) (mapcar 'car (R0:HENL-Records s))) (defun R0:HENL-Normalize (s) (while (vl-string-search (strcat (chr 13) (chr 10)) s) (setq s (vl-string-subst "\\P" (strcat (chr 13) (chr 10)) s))) (while (vl-string-search (chr 13) s) (setq s (vl-string-subst "\\P" (chr 13) s))) (while (vl-string-search (chr 10) s) (setq s (vl-string-subst "\\P" (chr 10) s))) s) (defun R0:HENL-Register (obj) (setq henl-created (cons obj henl-created)) obj) (defun R0:HENL-Box (obj / lo hi) (vla-Update obj) (vla-GetBoundingBox obj 'lo 'hi) (list (vlax-safearray->list lo) (vlax-safearray->list hi))) (defun R0:HENL-Props (obj src) (vla-put-Layer obj (vla-get-Layer src)) (vla-put-TrueColor obj (vla-get-TrueColor src)) obj) (defun R0:HENL-Text (space src content width h at attach / obj) (setq obj (R0:HENL-Register (vla-AddMText space (vlax-3d-point at) width content))) (R0:HENL-Props obj src) (vla-put-StyleName obj (vla-get-StyleName src)) (vla-put-Height obj h) (vla-put-Rotation obj 0.0) (vla-put-AttachmentPoint obj attach) (vla-put-InsertionPoint obj (vlax-3d-point at)) (vla-put-LineSpacingStyle obj (vla-get-LineSpacingStyle src)) (vla-put-LineSpacingFactor obj (vla-get-LineSpacingFactor src)) obj) (defun R0:HENL-Hex (space src center side / coords k a arr obj) (setq k 5) (repeat 6 (setq a (* pi (/ k 3.0)) coords (cons (+ (car center) (* side (cos a))) (cons (+ (cadr center) (* side (sin a))) coords)) k (1- k))) (setq arr (vlax-make-safearray vlax-vbDouble '(0 . 11))) (vlax-safearray-fill arr coords) (setq obj (R0:HENL-Register (vla-AddLightWeightPolyline space arr))) (R0:HENL-Props obj src) (vla-put-Elevation obj (caddr center)) (vla-put-Closed obj :vlax-true) (vla-put-ConstantWidth obj 0.0) (vla-put-Lineweight obj 0) obj) (defun R0:HENL-Number (space src number center h side / obj box w ht factor p q) (setq obj (R0:HENL-Text space src (itoa number) 0.0 h center 5) box (R0:HENL-Box obj) p (car box) q (cadr box) w (- (car q) (car p)) ht (- (cadr q) (cadr p)) factor (min 1.0 (/ (* side 1.45) (max w 1e-12)) (/ (* side 1.2) (max ht 1e-12)))) (if (< factor 1.0) (vla-put-Height obj (* h factor))) (setq box (R0:HENL-Box obj) p (car box) q (cadr box)) (vla-Move obj (vlax-3d-point (mapcar '(lambda (a b) (/ (+ a b) 2.0)) p q)) (vlax-3d-point center)) obj) (defun R0:HENL-Fill (space src boundary / arr obj) (setq arr (vlax-make-safearray vlax-vbObject '(0 . 0))) (vlax-safearray-put-element arr 0 boundary) (setq obj (R0:HENL-Register (vla-AddHatch space 0 "SOLID" :vlax-false 0))) (vla-AppendOuterLoop obj arr) (vla-put-Elevation obj (vla-get-Elevation boundary)) (vla-put-Layer obj (vla-get-Layer src)) (vla-put-Color obj 255) (vla-put-EntityTransparency obj "0") (vla-Evaluate obj) (setq henl-fills (cons obj henl-fills)) obj) (defun R0:HENL-FillsBack (space / dict table arr) (if henl-fills (progn (setq dict (vla-GetExtensionDictionary space) table (vl-catch-all-apply 'vla-GetObject (list dict "ACAD_SORTENTS"))) (if (vl-catch-all-error-p table) (setq table (vla-AddObject dict "ACAD_SORTENTS" "AcDbSortentsTable"))) (setq arr (vlax-make-safearray vlax-vbObject (cons 0 (1- (length henl-fills))))) (vlax-safearray-fill arr henl-fills) (vla-MoveToBottom table arr)))) (defun R0:HENL-CenterY (obj box cy / mid) (setq mid (/ (+ (cadar box) (cadadr box)) 2.0)) (vla-Move obj (vlax-3d-point '(0.0 0.0 0.0)) (vlax-3d-point (list 0.0 (- cy mid) 0.0))) obj) (defun R0:HENL-Discard (obj) (vla-Delete obj) (setq henl-created (vl-remove obj henl-created))) (defun R0:HENL-InPlace (space src content records height width point initial / probe single box top left side rec prefix total partheight cy center boundary number previous overlaps) (setq probe (R0:HENL-Text space src content width height point (vla-get-AttachmentPoint src))) (vla-put-Visible probe :vlax-false) (setq box (R0:HENL-Box probe) top (cadadr box) left (caar box) side (* 1.8 height) number initial overlaps 0) (vla-put-AttachmentPoint probe 1) (vla-put-InsertionPoint probe (vlax-3d-point point)) (setq single (R0:HENL-Text space src "M" width height point 1)) (vla-put-Visible single :vlax-false) (foreach rec records (setq prefix (strcat "{" (substr content 1 (cadr rec)) (caddr rec))) (vla-put-TextString probe prefix) (setq box (R0:HENL-Box probe) total (- (cadadr box) (cadar box))) (vla-put-TextString single (car rec)) (setq box (R0:HENL-Box single) partheight (- (cadadr box) (cadar box)) cy (+ (- top total) (/ partheight 2.0)) center (list (- left side (* 0.7 height)) cy (caddr point))) (if (and previous (< (abs (- previous cy)) (* (sqrt 3.0) side))) (setq overlaps (1+ overlaps))) (setq boundary (R0:HENL-Hex space src center side)) (R0:HENL-Fill space src boundary) (R0:HENL-Number space src number center height side) (setq previous cy number (1+ number))) (R0:HENL-Discard single) (R0:HENL-Discard probe) (if (> overlaps 0) (princ (strcat "\n[!] " (itoa overlaps) " pairs of hexagons may overlap: insufficient paragraph spacing."))) number) (defun R0:HENL-Initial (/ s n valid) (while (not valid) (setq s (getstring "\nStarting NUMBER <1>: ")) (if (= s "") (setq s "1")) (if (and (<= (strlen s) 9) (vl-every '(lambda (c) (and (>= c 48) (<= c 57))) (vl-string->list s))) (setq n (atoi s) valid T) (princ "\nEnter an integer from 0 to 999999999."))) n) (defun R0:HENL-Annotative (ename / data) (setq data (assoc -3 (entget ename '("AcadAnnotative")))) (and data (member '(1070 . 1) (cdr (cadr data))))) (defun R0:HENL-Select (/ pick en data layer done) (while (not done) (setq pick (entsel "\nHENL | Select the MTEXT to number <Exit>: ")) (cond ((null pick) (setq done T en nil)) (T (setq en (car pick) data (entget en) layer (tblsearch "LAYER" (cdr (assoc 8 data)))) (cond ((/= (cdr (assoc 0 data)) "MTEXT") (princ "\nSelect an MTEXT object, not single-line text or a block.")) ((/= 0 (logand 5 (cdr (assoc 70 layer)))) (princ "\nThe layer is locked or frozen.")) ((minusp (cdr (assoc 62 layer))) (princ "\nThe layer is turned off.")) (T (setq done T)))))) en) (defun R0:HENL-Cleanup (rollback / obj result) (if (and rollback henl-retiring henl-source (null (entget henl-source))) (if (not (entdel henl-source)) (princ "\n[!] Check whether the original MTEXT was restored."))) (if rollback (foreach obj henl-created (setq result (vl-catch-all-apply 'vla-Delete (list obj))) (if (vl-catch-all-error-p result) (princ "\n[!] Could not remove an output object; check the drawing.")))) (if henl-highlight (vl-catch-all-apply 'redraw (list henl-source 4))) (if henl-undo (vl-catch-all-apply 'vla-EndUndoMark (list henl-doc))) (foreach obj henl-vars (vl-catch-all-apply 'setvar (list (car obj) (cdr obj)))) (princ)) (defun R0:HENL-Run (relocate / *error* henl-msg henl-created henl-source henl-highlight henl-doc henl-undo henl-vars henl-retiring henl-fills src data content parts height width angle normal space initial option point side cy center para textobj box realheight obj number style rowheight bottom boundary records) (defun *error* (msg) (R0:HENL-Cleanup T) (cond (henl-msg (princ (strcat "\n[!] HENL: " henl-msg))) ((and msg (not (wcmatch (strcase msg) "*CANCEL*,*QUIT*,*BREAK*,*EXIT*"))) (princ (strcat "\n[!] HENL: " msg))) (T (princ "\nHENL canceled. Original preserved."))) (princ)) (setq henl-doc (vla-get-ActiveDocument (vlax-get-acad-object)) henl-vars (list (cons "DYNMODE" (getvar "DYNMODE")) (cons "DYNPROMPT" (getvar "DYNPROMPT")))) (setvar "DYNMODE" 3) (setvar "DYNPROMPT" 1) (if (setq henl-source (R0:HENL-Select)) (progn (setq src (vlax-ename->vla-object henl-source) data (entget henl-source) content (R0:HENL-Normalize (vla-get-TextString src)) height (vla-get-Height src) width (vla-get-Width src) angle (vla-get-Rotation src) normal (cdr (assoc 210 data)) style (tblobjname "STYLE" (vla-get-StyleName src))) (if (and normal (not (equal normal '(0.0 0.0 1.0) 1e-8))) (R0:HENL-Fail "This version requires text on a plane parallel to WCS XY.")) (if (vl-string-search "%<" content) (R0:HENL-Fail "MTEXT fields are not supported; the original has been preserved.")) (if (and (assoc 75 data) (/= 0 (cdr (assoc 75 data)))) (R0:HENL-Fail "Disable MTEXT columns before numbering.")) (if (or (= (cdr (assoc 72 data)) 3) (/= 0 (logand 4 (cdr (assoc 70 (tblsearch "STYLE" (vla-get-StyleName src))))))) (R0:HENL-Fail "Vertical text is not supported in this version.")) (if (or (R0:HENL-Annotative henl-source) (and style (R0:HENL-Annotative style))) (R0:HENL-Fail "Use non-annotative MTEXT and a non-annotative text style.")) (if (<= height 0.0) (R0:HENL-Fail "Invalid text height.")) (setq records (R0:HENL-Records content) parts (mapcar 'car records)) (if (null parts) (R0:HENL-Fail "No non-empty paragraphs found.")) (if (> (length parts) 10000) (R0:HENL-Fail "The limit is 10000 paragraphs per run.")) (redraw henl-source 3) (setq henl-highlight T) (princ (strcat "\n" (itoa (length parts)) " paragraphs | Hexagon side length: " (rtos (* 1.8 height) 2 4))) (setq initial (R0:HENL-Initial)) (if relocate (progn (initget "Keep Delete") (setq option (getkword "\nORIGINAL [Keep/Delete] <Keep>: ")) (initget 1) (setq point (trans (getpoint (strcat "\nCenter of the FIRST hexagon (" (itoa initial) "): ")) 1 0))) (setq option "Keep" point (vlax-safearray->list (vlax-variant-value (vla-get-InsertionPoint src))))) (setq space (vlax-ename->vla-object (cdr (assoc 330 (reverse data))))) (if (and (= 1 (logand 1 (getvar "UNDOCTL"))) (= 0 (logand 8 (getvar "UNDOCTL")))) (progn (vla-StartUndoMark henl-doc) (setq henl-undo T))) (setq side (* 1.8 height) cy (cadr point) number initial) (if relocate (progn (foreach para parts (setq textobj (R0:HENL-Text space src para width height (list (+ (car point) side (* 0.7 height)) cy (caddr point)) 1) box (R0:HENL-Box textobj) realheight (- (cadadr box) (cadar box)) rowheight (max realheight (* (sqrt 3.0) side))) (if bottom (setq cy (- bottom (* 0.8 height) (/ rowheight 2.0)))) (R0:HENL-CenterY textobj box cy) (setq center (list (car point) cy (caddr point)) boundary (R0:HENL-Hex space src center side)) (R0:HENL-Fill space src boundary) (R0:HENL-Number space src number center height side) (setq bottom (- cy (/ rowheight 2.0)) number (1+ number)))) (setq number (R0:HENL-InPlace space src content records height width point initial))) (foreach obj henl-created (if (not (equal angle 0.0 1e-12)) (vla-Rotate obj (vlax-3d-point point) angle)) (vla-Update obj) (if (not (entget (vlax-vla-object->ename obj))) (R0:HENL-Fail "Could not verify the output."))) (if (/= (length henl-created) (* (if relocate 4 3) (length parts))) (R0:HENL-Fail "The output is incomplete.")) (R0:HENL-FillsBack space) (vla-Regen henl-doc 0) (redraw henl-source 4) (setq henl-highlight nil) (if (= option "Delete") (progn (setq henl-retiring T) (if (not (entdel henl-source)) (R0:HENL-Fail "Could not delete the original.")))) (setq henl-created nil henl-retiring nil) (R0:HENL-Cleanup nil) (princ (strcat "\n[OK] " (itoa (length parts)) " paragraphs | Numbers " (itoa initial) " to " (itoa (1- number)) " | " (if relocate (strcat "Original " (if (= option "Delete") "deleted." "preserved.")) "Original MTEXT unchanged.")))) (R0:HENL-Cleanup nil)) (princ)) (defun c:HEXENUML () (R0:HENL-Run nil)) (defun c:HENL () (R0:HENL-Run nil)) (defun c:HEXENUMLC () (R0:HENL-Run T)) (defun c:HENLC () (R0:HENL-Run T)) (princ "\nHEXENUM 1.2 (loose geometry) | HENL: number in place | HENLC: create at another point.") (princ) ;;; HEXENUM 1.3 - Block with NUM attribute | AutoCAD Windows / Visual LISP ;;; HENB / HEXENUMB: number the existing MTEXT in place. ;;; HENBC / HEXENUMBC: create separate paragraphs at a picked location. ;;; Hexagon side = 1.8 x nominal text height; SOLID fill = ACI 255. ;;; Both editions can be loaded together; command and helper names are isolated. (vl-load-com) (defun R0:HENB-Fail (msg) (setq henb-msg msg) (exit)) (defun R0:HENB-Prefix (frames / result frame) (setq result "") (foreach frame (reverse frames) (setq result (strcat result "{" frame))) result) (defun R0:HENB-Close (frames / result) (setq result "") (repeat (length frames) (setq result (strcat result "}"))) result) (defun R0:HENB-Records (s / i n ch next token frames part visible result j brk start) (setq i 1 n (strlen s) frames (list "") part "{" visible nil) (while (<= i n) (setq start i ch (substr s i 1) next (substr s (1+ i) 1) brk nil) (cond ((or (= ch (chr 10)) (= ch (chr 13))) (setq brk T) (if (and (= ch (chr 13)) (= next (chr 10))) (setq i (1+ i))) (setq i (1+ i))) ((= ch "\\") (cond ((= next "P") (setq brk T i (+ i 2))) ((= next "N") (R0:HENB-Fail "Column breaks found. Set the MTEXT to a single column.")) ((member next '("\\" "{" "}" "~")) (setq part (strcat part (substr s i 2)) i (+ i 2)) (if (/= next "~") (setq visible T))) ((member next '("A" "C" "c" "F" "f" "H" "Q" "T" "W" "p" "S")) (setq j (+ i 2)) (while (and (<= j n) (/= (substr s j 1) ";")) (setq j (1+ j))) (if (> j n) (R0:HENB-Fail "Incomplete MTEXT formatting code.")) (setq token (substr s i (1+ (- j i))) part (strcat part token) i (1+ j)) (if (= next "S") (setq visible T) (setq frames (cons (strcat (car frames) token) (cdr frames))))) ((member next '("L" "l" "O" "o" "K" "k")) (setq token (substr s i 2) part (strcat part token) i (+ i 2) frames (cons (strcat (car frames) token) (cdr frames)))) ((and (= next "U") (= (substr s (+ i 2) 1) "+")) (setq part (strcat part (substr s i 7)) i (+ i 7) visible T)) (T (setq part (strcat part ch) i (1+ i) visible T)))) ((= ch "{") (setq frames (cons "" frames) part (strcat part ch) i (1+ i))) ((= ch "}") (if (null (cdr frames)) (R0:HENB-Fail "Unbalanced formatting braces.")) (setq frames (cdr frames) part (strcat part ch) i (1+ i))) (T (setq part (strcat part ch) i (1+ i)) (if (not (member ch (list " " (chr 9)))) (setq visible T)))) (if brk (progn (if visible (setq result (cons (list (strcat part (R0:HENB-Close frames)) (1- start) (R0:HENB-Close frames)) result))) (setq part (R0:HENB-Prefix frames) visible nil)))) (if (/= (length frames) 1) (R0:HENB-Fail "Unbalanced formatting braces.")) (if visible (setq result (cons (list (strcat part (R0:HENB-Close frames)) n (R0:HENB-Close frames)) result))) (reverse result)) (defun R0:HENB-Split (s) (mapcar 'car (R0:HENB-Records s))) (defun R0:HENB-Normalize (s) (while (vl-string-search (strcat (chr 13) (chr 10)) s) (setq s (vl-string-subst "\\P" (strcat (chr 13) (chr 10)) s))) (while (vl-string-search (chr 13) s) (setq s (vl-string-subst "\\P" (chr 13) s))) (while (vl-string-search (chr 10) s) (setq s (vl-string-subst "\\P" (chr 10) s))) s) (defun R0:HENB-Register (obj) (setq henb-created (cons obj henb-created)) obj) (defun R0:HENB-Box (obj / lo hi) (vla-Update obj) (vla-GetBoundingBox obj 'lo 'hi) (list (vlax-safearray->list lo) (vlax-safearray->list hi))) (defun R0:HENB-Props (obj src) (vla-put-Layer obj (vla-get-Layer src)) (vla-put-TrueColor obj (vla-get-TrueColor src)) obj) (defun R0:HENB-Text (space src content width h at attach / obj) (setq obj (R0:HENB-Register (vla-AddMText space (vlax-3d-point at) width content))) (R0:HENB-Props obj src) (vla-put-StyleName obj (vla-get-StyleName src)) (vla-put-Height obj h) (vla-put-Rotation obj 0.0) (vla-put-AttachmentPoint obj attach) (vla-put-InsertionPoint obj (vlax-3d-point at)) (vla-put-LineSpacingStyle obj (vla-get-LineSpacingStyle src)) (vla-put-LineSpacingFactor obj (vla-get-LineSpacingFactor src)) obj) (defun R0:HENB-BlockDef (doc nom / blks blk coords k a arr pl hat lazo att) (if (not (vl-catch-all-error-p (vl-catch-all-apply 'vla-Item (list (vla-get-Blocks doc) nom)))) T (progn (setq blks (vla-get-Blocks doc) blk (vla-Add blks (vlax-3d-point '(0.0 0.0 0.0)) nom) k 5 coords nil) (repeat 6 (setq a (* pi (/ k 3.0)) coords (cons (cos a) (cons (sin a) coords)) k (1- k))) (setq arr (vlax-make-safearray vlax-vbDouble '(0 . 11))) (vlax-safearray-fill arr coords) (setq pl (vla-AddLightWeightPolyline blk arr)) (vla-put-Closed pl :vlax-true) (setq hat (vla-AddHatch blk 0 "SOLID" :vlax-false 0) lazo (vlax-make-safearray vlax-vbObject '(0 . 0))) (vlax-safearray-put-element lazo 0 pl) (vla-AppendOuterLoop hat lazo) (vla-put-Layer hat "0") (vla-put-Color hat 255) (vla-Evaluate hat) (vla-Delete pl) (setq pl (vla-AddLightWeightPolyline blk arr)) (vla-put-Closed pl :vlax-true) (vla-put-Layer pl "0") (vla-put-ConstantWidth pl 0.0) (setq att (vla-AddAttribute blk (/ 1.0 1.8) 0 "Number" (vlax-3d-point '(0.0 0.0 0.0)) "NUM" "1")) (vla-put-Layer att "0") (vla-put-Alignment att 10) (vla-put-TextAlignmentPoint att (vlax-3d-point '(0.0 0.0 0.0))) (not (vl-catch-all-error-p (vl-catch-all-apply 'vla-Item (list blks nom))))))) (defun R0:HENB-Marker (space src center side number / obj atts a box p q w ht factor) (setq obj (R0:HENB-Register (vla-InsertBlock space (vlax-3d-point center) "IR_HEX" side side side 0.0))) (vla-put-Layer obj (vla-get-Layer src)) (vla-put-TrueColor obj (vla-get-TrueColor src)) (setq atts (vl-catch-all-apply 'vla-GetAttributes (list obj))) (if (vl-catch-all-error-p atts) (R0:HENB-Fail "Could not read the marker attributes.") (foreach a (vlax-safearray->list (vlax-variant-value atts)) (vla-put-TextString a (itoa number)) (setq box (R0:HENB-Box a) p (car box) q (cadr box) w (- (car q) (car p)) ht (- (cadr q) (cadr p)) factor (min 1.0 (/ (* side 1.45) (max w 1e-12)) (/ (* side 1.2) (max ht 1e-12)))) (if (< factor 1.0) (vla-put-Height a (* (vla-get-Height a) factor))) (if (/= (itoa number) (vla-get-TextString a)) (R0:HENB-Fail (strcat "Marker " (itoa number) " has no number."))))) obj) (defun R0:HENB-CenterY (obj box cy / mid) (setq mid (/ (+ (cadar box) (cadadr box)) 2.0)) (vla-Move obj (vlax-3d-point '(0.0 0.0 0.0)) (vlax-3d-point (list 0.0 (- cy mid) 0.0))) obj) (defun R0:HENB-Discard (obj) (vla-Delete obj) (setq henb-created (vl-remove obj henb-created))) (defun R0:HENB-InPlace (space src content records height width point initial / probe single box top left side rec prefix total partheight cy center number previous overlaps) (setq probe (R0:HENB-Text space src content width height point (vla-get-AttachmentPoint src))) (vla-put-Visible probe :vlax-false) (setq box (R0:HENB-Box probe) top (cadadr box) left (caar box) side (* 1.8 height) number initial overlaps 0) (vla-put-AttachmentPoint probe 1) (vla-put-InsertionPoint probe (vlax-3d-point point)) (setq single (R0:HENB-Text space src "M" width height point 1)) (vla-put-Visible single :vlax-false) (foreach rec records (setq prefix (strcat "{" (substr content 1 (cadr rec)) (caddr rec))) (vla-put-TextString probe prefix) (setq box (R0:HENB-Box probe) total (- (cadadr box) (cadar box))) (vla-put-TextString single (car rec)) (setq box (R0:HENB-Box single) partheight (- (cadadr box) (cadar box)) cy (+ (- top total) (/ partheight 2.0)) center (list (- left side (* 0.7 height)) cy (caddr point))) (if (and previous (< (abs (- previous cy)) (* (sqrt 3.0) side))) (setq overlaps (1+ overlaps))) (R0:HENB-Marker space src center side number) (setq previous cy number (1+ number))) (R0:HENB-Discard single) (R0:HENB-Discard probe) (if (> overlaps 0) (princ (strcat "\n[!] " (itoa overlaps) " pairs of hexagons may overlap: insufficient paragraph spacing."))) number) (defun R0:HENB-Initial (/ s n valid) (while (not valid) (setq s (getstring "\nStarting NUMBER <1>: ")) (if (= s "") (setq s "1")) (if (and (<= (strlen s) 9) (vl-every '(lambda (c) (and (>= c 48) (<= c 57))) (vl-string->list s))) (setq n (atoi s) valid T) (princ "\nEnter an integer from 0 to 999999999."))) n) (defun R0:HENB-Annotative (ename / data) (setq data (assoc -3 (entget ename '("AcadAnnotative")))) (and data (member '(1070 . 1) (cdr (cadr data))))) (defun R0:HENB-Select (/ pick en data layer done) (while (not done) (setq pick (entsel "\nHENB | Select the MTEXT to number <Exit>: ")) (cond ((null pick) (setq done T en nil)) (T (setq en (car pick) data (entget en) layer (tblsearch "LAYER" (cdr (assoc 8 data)))) (cond ((/= (cdr (assoc 0 data)) "MTEXT") (princ "\nSelect an MTEXT object, not single-line text or a block.")) ((/= 0 (logand 5 (cdr (assoc 70 layer)))) (princ "\nThe layer is locked or frozen.")) ((minusp (cdr (assoc 62 layer))) (princ "\nThe layer is turned off.")) (T (setq done T)))))) en) (defun R0:HENB-Cleanup (rollback / obj result) (if (and rollback henb-retiring henb-source (null (entget henb-source))) (if (not (entdel henb-source)) (princ "\n[!] Check whether the original MTEXT was restored."))) (if rollback (foreach obj henb-created (setq result (vl-catch-all-apply 'vla-Delete (list obj))) (if (vl-catch-all-error-p result) (princ "\n[!] Could not remove an output object; check the drawing.")))) (if henb-highlight (vl-catch-all-apply 'redraw (list henb-source 4))) (if henb-undo (vl-catch-all-apply 'vla-EndUndoMark (list henb-doc))) (foreach obj henb-vars (vl-catch-all-apply 'setvar (list (car obj) (cdr obj)))) (princ)) (defun R0:HENB-Run (relocate / *error* henb-msg henb-created henb-source henb-highlight henb-doc henb-undo henb-vars henb-retiring src data content parts height width angRot normal space initial option point side cy center para textobj box realheight obj number style rowheight bottom records) (defun *error* (msg) (R0:HENB-Cleanup T) (cond (henb-msg (princ (strcat "\n[!] HENB: " henb-msg))) ((and msg (not (wcmatch (strcase msg) "*CANCEL*,*QUIT*,*BREAK*,*EXIT*"))) (princ (strcat "\n[!] HENB: " msg))) (T (princ "\nHENB canceled. Original preserved."))) (princ)) (setq henb-doc (vla-get-ActiveDocument (vlax-get-acad-object)) henb-vars (list (cons "DYNMODE" (getvar "DYNMODE")) (cons "DYNPROMPT" (getvar "DYNPROMPT")))) (setvar "DYNMODE" 3) (setvar "DYNPROMPT" 1) (if (setq henb-source (R0:HENB-Select)) (progn (setq src (vlax-ename->vla-object henb-source) data (entget henb-source) content (R0:HENB-Normalize (vla-get-TextString src)) height (vla-get-Height src) width (vla-get-Width src) angRot (vla-get-Rotation src) normal (cdr (assoc 210 data)) style (tblobjname "STYLE" (vla-get-StyleName src))) (if (and normal (not (equal normal '(0.0 0.0 1.0) 1e-8))) (R0:HENB-Fail "This version requires text on a plane parallel to WCS XY.")) (if (vl-string-search "%<" content) (R0:HENB-Fail "MTEXT fields are not supported; the original has been preserved.")) (if (and (assoc 75 data) (/= 0 (cdr (assoc 75 data)))) (R0:HENB-Fail "Disable MTEXT columns before numbering.")) (if (or (= (cdr (assoc 72 data)) 3) (/= 0 (logand 4 (cdr (assoc 70 (tblsearch "STYLE" (vla-get-StyleName src))))))) (R0:HENB-Fail "Vertical text is not supported in this version.")) (if (or (R0:HENB-Annotative henb-source) (and style (R0:HENB-Annotative style))) (R0:HENB-Fail "Use non-annotative MTEXT and a non-annotative text style.")) (if (<= height 0.0) (R0:HENB-Fail "Invalid text height.")) (setq records (R0:HENB-Records content) parts (mapcar 'car records)) (if (null parts) (R0:HENB-Fail "No non-empty paragraphs found.")) (if (> (length parts) 10000) (R0:HENB-Fail "The limit is 10000 paragraphs per run.")) (redraw henb-source 3) (setq henb-highlight T) (princ (strcat "\n" (itoa (length parts)) " paragraphs | Hexagon side length: " (rtos (* 1.8 height) 2 4))) (setq initial (R0:HENB-Initial)) (if relocate (progn (initget "Keep Delete") (setq option (getkword "\nORIGINAL [Keep/Delete] <Keep>: ")) (initget 1) (setq point (trans (getpoint (strcat "\nCenter of the FIRST hexagon (" (itoa initial) "): ")) 1 0))) (setq option "Keep" point (vlax-safearray->list (vlax-variant-value (vla-get-InsertionPoint src))))) (setq space (vlax-ename->vla-object (cdr (assoc 330 (reverse data))))) (if (and (= 1 (logand 1 (getvar "UNDOCTL"))) (= 0 (logand 8 (getvar "UNDOCTL")))) (progn (vla-StartUndoMark henb-doc) (setq henb-undo T))) (if (not (R0:HENB-BlockDef henb-doc "IR_HEX")) (R0:HENB-Fail "Could not create the IR_HEX block.")) (setq side (* 1.8 height) cy (cadr point) number initial) (if relocate (progn (foreach para parts (setq textobj (R0:HENB-Text space src para width height (list (+ (car point) side (* 0.7 height)) cy (caddr point)) 1) box (R0:HENB-Box textobj) realheight (- (cadadr box) (cadar box)) rowheight (max realheight (* (sqrt 3.0) side))) (if bottom (setq cy (- bottom (* 0.8 height) (/ rowheight 2.0)))) (R0:HENB-CenterY textobj box cy) (setq center (list (car point) cy (caddr point))) (R0:HENB-Marker space src center side number) (setq bottom (- cy (/ rowheight 2.0)) number (1+ number)))) (setq number (R0:HENB-InPlace space src content records height width point initial))) (foreach obj henb-created (if (not (equal angRot 0.0 1e-12)) (vla-Rotate obj (vlax-3d-point point) angRot)) (vla-Update obj) (if (not (entget (vlax-vla-object->ename obj))) (R0:HENB-Fail "Could not verify the output."))) (if (/= (length henb-created) (* (if relocate 2 1) (length parts))) (R0:HENB-Fail "The output is incomplete.")) (vla-Regen henb-doc 0) (redraw henb-source 4) (setq henb-highlight nil) (if (= option "Delete") (progn (setq henb-retiring T) (if (not (entdel henb-source)) (R0:HENB-Fail "Could not delete the original.")))) (setq henb-created nil henb-retiring nil) (R0:HENB-Cleanup nil) (princ (strcat "\n[OK] " (itoa (length parts)) " paragraphs | Numbers " (itoa initial) " to " (itoa (1- number)) " | " (if relocate (strcat "Original " (if (= option "Delete") "deleted." "preserved.")) "Original MTEXT unchanged.")))) (R0:HENB-Cleanup nil)) (princ)) (defun c:HEXENUMB () (R0:HENB-Run nil)) (defun c:HENB () (R0:HENB-Run nil)) (defun c:HEXENUMBC () (R0:HENB-Run T)) (defun c:HENBC () (R0:HENB-Run T)) (princ "\nHEXENUM 1.3 (block + attribute) | HENB: number in place | HENBC: create at another point.") (princ) Edited 47 minutes ago by Romero Quote
Steven P Posted 39 minutes ago Posted 39 minutes ago So the blocks are easy to make with an attribute for the number. Have the attribute with a default value such as '.' If you have one block entered with the attribute competed, this should allow you to increment the others - you need to select the first block attribute to get the value needed and then hit each other attribute in turn to add the next number. Try this LISP for incremental numbering - a part of something much larger so perhaps it isn't as nice as it could be but it works. This should also work for lettering (A -> B, and 1A ->1B, A1 ->A2) Then just have to split the mtext into parts I think - Lee Macs string to list can do part of this - just making a note in case I get time tomorrow to do that for you. Suspect you will need 2 LISPS, the one below to number the block attributes and one to split the text. (defun c:ctx+ ( / increment sel ) ;;Sub Functions (defun LM:roundm ( n m ) ;;http://www.lee-mac.com/round.html (* m (atoi (rtos (/ n (float m)) 2 0))) ) (defun uprev (base sel increments / ent entlst currentrevision revlength revisionprefix anumber ones leadingzero revcode revletter revnumber leadingzeros RL) ;;Sub routines (defun itsnotadate ( increments revlength entlst currentrevision base revisionprefix anumber / currentrevision revlength revisionprefix anumber ones leadingzero revcode revletter) (if (or (= (rtos (atof currentrevision)) currentrevision) (= (type currentrevision) 'INT) ) ; endor (progn (if (= (type currentrevision) 'STR) (setq revletter (+ (atof currentrevision) increments )) (setq revletter (+ currentrevision increments)) ) ; end if (setq revletter (rtos revletter)) ) ; end progn numbers only (progn (setq increments (LM:roundm increments 1 )) ;; set increments to integer, nearest nth (if (< 0 revlength) (progn (setq ones (substr currentrevision revlength)) (if (numberp (read ones))(setq anumber 1)) ) ) ;end if end progn (setq RL 0) ; length or numerical part (while (< RL revlength) (if (and (= RL anumber) (numberp (read (substr (substr currentrevision (- revlength RL) RL ) 1 1)))) (setq anumber (+ RL 1))) (setq RL (+ RL 1)) ) ; end while ;;work out numerical revision. (if (> anumber 0) (progn (setq revnumber (substr currentrevision (- revlength (- anumber 1)) anumber)) (setq revnumber (itoa (+ increments (read revnumber)))) ;;increase rev number by 1 (if (and (> revlength anumber)(/= revlength anumber)) (setq revisionprefix (substr currentrevision 1 (- revlength anumber))) ;;first characters of revision ) ; end if ;;fix leading zeros (setq leadingzeros (- anumber (strlen revnumber))) (setq leadingzero "") (repeat leadingzeros (setq leadingzero (strcat leadingzero "0")) ) ; end repeat (setq revletter (strcat revisionprefix leadingzero revnumber)) ) ; end progn ) ; end if anumber > 0 ;;Work out letters revisions (if (= anumber 0) (progn (setq revcode (+ increments (ascii ones))) ;;increase rev letter by 1 ;;set exceptions here ; (if (= 73 revcode)(setq revcode 74)) ;;I ;; if Rev Box, skip I ; (if (= 79 revcode)(setq revcode 80)) ;;O ;; If Rev Box, skip O ; (if (= 105 revcode)(setq revcode 106)) ;;i ; (if (= 111 revcode)(setq revcode 112)) ;;o.. its of to work we go. (if (= 91 revcode)(setq revcode 65)) ;;Z -> A. Won't increment 'tens' value (if (= 123 revcode)(setq revcode 97)) ;;z -> a Won't increment 'tens' value (setq revisionprefix (substr currentrevision 1 (- revlength 1))) ;;first characters of revision (setq revletter (strcat revisionprefix (chr revcode))) ) ; end progn ) ; end if ) ; end progn alpha-numeric ) ; end if number processing revletter ) ; end defun not date ;;;;;;;;;;;;;; (if (= (type sel) 'LIST) ; if selection is (<entname> (0 1 2)) or just <entname> (setq ent (car sel)) (setq ent sel) ) (setq entlst (entget ent)) ;;entity definiton (setq currentrevision base) ;;text string passed to function (setq revlength (strlen currentrevision)) ;;length of selected revision (setq revisionprefix "") ;;set prefix to blank (setq anumber 0) ;;a counter (setq revletter (itsnotadate increments revlength entlst currentrevision base revisionprefix anumber) ) (setq entlst (subst (cons 1 revletter) (assoc 1 entlst) entlst)) (entmod entlst) (entupd ent) revletter ) (if (= increments nil)(setq increments 1) ) ;; Checks if increments is a value (if (= (type increments) 'STR) (if (= nil (distof increments)) (setq increments 1) (setq increments (distof increments)) ) ) (setq increments (atoi (rtos increments))) (setq endloop "No") ; a marker (setq sel "1") ; Increment amount (while (= endloop "No") ; Select a text of enter a value loop (initget "4 3 2 1 0 -1 -2 -3 -4 Exit") ; increment amount accepted. Increase list if needed (setq sel (nentsel (strcat "\nSelect Text or Enter Text Increment (" (itoa increments) ") [3/2/1/0/-1/-2/-3/Exit]: ") ) ) (cond ( (null sel)(setq endloop "Yes") ) ( (= "Exit" sel)(princ)(exit) ) ((member sel '("-4" "-3" "-2" "-1" "0" "1" "2" "3" "4")) (setq increments (atoi sel)) ) ( (if (and (cdr (assoc 1 (entget (car sel))))(wcmatch (cdr (assoc 0 (entget (car sel)))) "TEXT,MTEXT,ATTRIB,*LEADER") ) (setq endloop "Yes")) ) ( (if (not (wcmatch (cdr (assoc 0 (entget (car sel)))) "TEXT,MTEXT,ATTRIB,*LEADER") ) (princ "\nThats not text...\n")) ) ) ) ;;end while (setq endloop "No") (setq ent (car sel)) (setq entlst (entget ent)) (setq base (cdr (assoc 1 entlst))) (setq base (vl-string-right-trim " " base)) ;; remove trailing spaces (princ ": ")(princ base) (if (= increment nil) (setq increment increments)) (while (while (= endloop "No") (setq sel (nentsel "\nSelect Text to Replace and Increment: ") ) (cond ( (null sel)(setq endloop "Yes") ) ( (= "Exit" sel)(princ)(exit) ) ( (if (and (cdr (assoc 1 (entget (car sel))))(wcmatch (cdr (assoc 0 (entget (car sel)))) "TEXT,MTEXT,ATTRIB,*LEADER") ) (setq endloop "Yes")) ) ( (if (not (wcmatch (cdr (assoc 0 (entget (car sel)))) "TEXT,MTEXT,ATTRIB,*LEADER") ) (princ "\nThats not text...\n")) ) ) ) ;;end while (princ (uprev base sel increment)) (setq endloop "No") (setq increment (+ increment increments)) );;end while (setvar "CMDECHO" 0) (command "regen") ;;in case of nested blocks (setvar "CMDECHO" 1) (princ) ) Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.