pefi Posted Wednesday at 08:29 AM Posted Wednesday at 08:29 AM I need to modify a few block definitions per drawing by adding 2 new attributes. Fixed location, they wont be visible, so I do not care if they are overlapping with other content or not. I use them as a "meta data" storage. Now, what's the best way to do it? I'm considering reinserting the block (prepared separately, with required modifications) or editing the block definition in place. The number of drawings and blocks is too large for manual modifications. I'm OK with LISP as well, but I will be populating the data from excel, so VBA seems to be the natural choice. Any advice if there is abetter way of doing it? Any opinions, comments, are more than welcome. I'm at the "brain storm" stage P.S. I currently open the block editor, paste the 2 attributes, close block editor, attsync, done. Maybe recreating that process in a scripted way with LISP would be easier? Quote
SLW210 Posted Wednesday at 10:38 AM Posted Wednesday at 10:38 AM Probably the same either way. LISP/Script would be quite capable, lot's of code around for adding attributes, pretty sure Lee Mac has something. VBA, IMO, might have a slight advantage running on multiple drawings. .NET or Python an option? 1 Quote
pefi Posted Wednesday at 11:52 AM Author Posted Wednesday at 11:52 AM (edited) Thanks! I'm OK to do it drawing by drawing. I can script handling the batch. I think in python , so definitely yes. .NET - never used it. I just found out the expresstools command blockreplace, but I'm struggling to convince it to use external file as the new block. I might dig into Lee Mac library... I prepared the new block as external file, but I'm not asked to redefine the block even when inserting with full file path. Possibly some system variable controls that (*). Edit: * https://help.autodesk.com/view/ACD/2022/ENU/?guid=GUID-15A13868-7582-4CCD-A8FC-9AF2D05E689C BLOCKREDEFINEMODE Edited Wednesday at 11:54 AM by pefi add link Quote
pefi Posted Wednesday at 12:09 PM Author Posted Wednesday at 12:09 PM (edited) Looks like a lot can be done with -bedit, -insert, -bsave, -bclose, attsync . I just need to put it together, bur I think I have a solution. 1. Prepare external drawing with attributes for adding 2. Open the drawing that needs to be modified (easily scripted for batch work) Script: (defun c:add_to_block_from_file ( / ) ;Add attribues or anything else from external file to a block definition (setq block_name "BLOCK_NAME") (setq att_file_path "C:\\PATH_TO_THE_FILE_FOR_ADDING.dwg") ;Use \\ in the path! (command "-bedit" block_name) (command "insert" att_file_path "E" "Y" "0,0" "1" "1" "0") (command "bsave") (command "bclose" "") (command "attsync" "Name" block_name) ) at this moment the blocks contain the new attributes so the drawing can be modified or saved. Edited Wednesday at 12:59 PM by pefi Quote
BIGAL Posted yesterday at 12:33 AM Posted yesterday at 12:33 AM You mention reading from Excel, its not a problem you can read cells from CAD, so if you have multiple blocks can be done. It would be simple to add to your defun say two columns in Excel Blocknames & dwgname with path. Need a sample Excel. 1 Quote
pefi Posted yesterday at 08:48 AM Author Posted yesterday at 08:48 AM Thank you very much! I'm not sure if I understand you, you mean reading excel directly using AutoLISP? I never tried to do anything with excel and LISP together. When I have data in excel I use VBA and calling LISP scripts from VBA. The sample data set attached - there are 4 columns, file, bhd_ins - block handle that needs to get the "data injection", bhd_type and bhd_line - are the names of attributes in that block. The block handles in the sample set correspond to the real handles on the sample drawing. The content of bhd_type and bhd_line is made up, but that won't make a difference. sample_drawing.dwg handle_table.xlsx Quote
BIGAL Posted 19 hours ago Posted 19 hours ago (edited) This is read an Excel example it just reads an open spreadsheet, and shows the result of a read cells. You could make a list of the cells. For your task you will probably need to use OBDX as you may have different dwg names, OBDX will allow you to change multiple dwgs. ; https://www.cadtutor.net/forum/topic/98627-block-definition-modification-adding-2-attributes/ ; Excel link by AlanH Aug 2025 (defun wow ( / myxl) ; thanks to Lee-mac for this defun ; 58 is Colon ; thanks to Lee-mac for this defun ; www.lee-mac.com ; 44 is comma 9 is tab 34 is space 58 is colon (defun csv->lst58 ( str / pos ) (if (setq pos (vl-string-position 58 str)) (cons (substr str 1 pos) (csv->lst58 (substr str (+ pos 2)))) (list str) ) ) ; get range (defun AH:getrangexl ( / lst1 myrange lst1) (setq lst1 '()) (setq myrange (vlax-get-property (vlax-get-property (vlax-get-property myxl "ActiveSheet") 'UsedRange) 'address)) (setq lst1 (csv->lst58 myrange)) (setq st (vl-string-subst "" "$" (vl-string-subst "" "$" (nth 0 lst1) ))) (setq end (vl-string-subst "" "$" (vl-string-subst "" "$" (nth 1 lst1) ))) (setq row1 (cadr (columnrow st))) (setq endrow (cadr (columnrow end))) (setq endcol (car (columnrow end))) ) ; Alpha2Number - Converts Alpha string into Number ; Function By: Gilles Chanteau from Marseille, France ; Arguments: 1 ; Str$ = String to convert ; Syntax example: (Alpha2Number "ABC") = 731 ;------------------------------------------------------------------------------- (defun Alpha2Number (Str$ / Num#) (if (= 0 (setq Num# (strlen Str$))) 0 (+ (* (- (ascii (strcase (substr Str$ 1 1))) 64) (expt 26 (1- Num#))) (Alpha2Number (substr Str$ 2)) ) ) ) ; ColumnRow - Returns a list of the Column and Row number ; Function By: Gilles Chanteau from Marseille, France ; Arguments: 1 ; Cell$ = Cell ID ; Syntax example: (ColumnRow "ABC987") = '(731 987) ;default to "A1" if there's a problem ;------------------------------------------------------------------------------- (defun ColumnRow (Cell$ / Column$ Char$ Row#) (setq Column$ "") (while (< 64 (ascii (setq Char$ (strcase (substr Cell$ 1 1)))) 91) (setq Column$ (strcat Column$ Char$) Cell$ (substr Cell$ 2) ) ) (if (and (/= Column$ "") (numberp (setq Row# (read Cell$)))) (list (Alpha2Number Column$) Row#) '(1 1) ) ) ;; Thanks to fixo (defun getcell2 (row column / ) (setq cells (vlax-get-property (vlax-get-property myxl "ActiveSheet") "Cells")) (setq cell (vlax-get (vlax-variant-value (vlax-get-property cells "Item" row column)) 'value)) ) (defun openxl ( / ) (setq myxl (vl-catch-all-apply 'vlax-get-or-create-object '("Excel.Application"))) (if (vl-catch-all-error-p myxl) (progn (prompt "\nError: Could not start Excel.") (exit) ) ) (if (= (vlax-get-property (vlax-get-property myXL 'WorkBooks) 'count) 0) (vlax-invoke-method (vlax-get-property myXL 'WorkBooks) 'Add) ) (vla-put-visible myXL :vlax-true) (vlax-put-property myxl 'ScreenUpdating :vlax-true) (vlax-put-property myXL 'DisplayAlerts :vlax-true) (princ) ) ; starts here (openxl) (AH:getrangexl) ; ignore 1st line (setq row (+ row1 1)) (repeat (- endrow 1) (setq dwgname (getcell2 row 1)) (setq bhd_inst (getcell2 row 2)) (setq bhd_line (getcell2 row 3)) (setq bhd_type (getcell2 row 4)) (princ (strcat"\n" dwgname " " bhd_inst " " bhd_line " " bhd_type)) (setq row (1+ row)) ;*********************************** ; do your thing here ;*********************************** ) (if (not (vlax-object-released-p myXL))(progn(vlax-release-object myXL)(setq myXL nil))) (princ) ) (wow) Edited 19 hours ago by BIGAL 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.