Export / Import connector attributes

Export / Import connector attributes

steven.coxVCM6J
Advocate Advocate
1,105 Views
14 Replies
Message 1 of 15

Export / Import connector attributes

steven.coxVCM6J
Advocate
Advocate

Hi all,

 

Does anyone have a good way to export /  import connector attributes similar to how we can regular components?

 

I am working on a project that have a huge number of connectors and I would like to be able to make wholesale changes in Excel.

 

Thanks, Steven

 

0 Likes
1,106 Views
14 Replies
Replies (14)
Message 2 of 15

ec-cad
Collaborator
Collaborator

Could you attach a 'sample' drawing, with a few connectors - so we can see what the block names and

attribute tags are ? I'm sure it won't take a long time to get an answer. There's code here that can do

that job very nicely.

 

ECCAD

0 Likes
Message 3 of 15

steven.coxVCM6J
Advocate
Advocate

Thanks EC.

 

I have attached a sample.  I basically need the tag, location, installation, description, termXXp, and termdescXXp attributes but would prefer the ability to export/import all the attributes.

 

Thanks, Steven

0 Likes
Message 4 of 15

ec-cad
Collaborator
Collaborator

In your sample, there are (3) blocks that would be Connectors.

1) HCN1_11P,   2) HCN2_11P  3) (shown) HCN1_11P_3C0.

Since I'm sure that there may be 'more' Connectors, the approach I would take.

Make up a Excel file like:

Drawingname, Blockname, Handle (of the block), AttTagname, Value, AttTagname, Value, etc... to last Attribute.

It would be good to search for HCN* blocknames, if they are the same.

Would a .csv file be of any use to you. Later, it could be read-in, search for match 'drawingname', 'blockname' & Handle.

(You could supply a 'list' of the eplicit Tagnames to Export)

IF found, it could change the Values accordingly.

 

I have to run now, be back tomorrow.

 

ECCAD

0 Likes
Message 5 of 15

paullimapa
Mentor
Mentor

How’s about Attout and then Attin


Paul Li
IT Specialist
@The Office
Apps & Publications | Video Demos
0 Likes
Message 6 of 15

steven.coxVCM6J
Advocate
Advocate

ATTOUT  / ATTIN does what I need it to do.  I had actually forgotten about these useful commands until someone in the AutoCAD Electrical forum reminded me.

 

However, if I had a routine that would put it in a excel format like the export command does, that would make it much simpler.

 

I will likely have several hundred connectors across almost 100 drawings by the time I am finished.

 

Getting the entire project of connectors into excel will allow me to use that data as I prepare to link to Inventor later on.  Inevitably there will be changes that need to be made and I fully expect them to be significant (hope not, but...)

 

I figured someone has done this before and already had a routine to handle it.

 

Thanks, Steven

0 Likes
Message 7 of 15

ec-cad
Collaborator
Collaborator

I find the .txt file 'attout' outputs is not easy to modify.. try this Lisp and see if it is close to what you need

for the Export of those Connecters. You may want to change the 'outfile' path / name to suite.

The output format can be easily changed, along with a Header line if needbe.

I'm on vacation for a week, check back with you later.

 

 

ECCAD

 

;; Export_Connectors.lsp
;; Designed to be batched within a script.
;; Function: to find Connectors get the attribute Tags (attlist), and output
;;  the data to C:/data/Connectors.csv  file

 (defun C:GO (); called at end of program.
  (vl-load-com)
;;I basically need the tag, location, installation, description, termXXp, and termdescXXp attributes
  (setq attlist (list
      "LOC"
      "INST"
      "DESC1"
      "DESC2"
      "DESC3"
      "TERM01P"
      "TERM02P"
      "TERM03P"
      "TERMDESC01P"
      "TERMDESC02P"
      "TERMDESC03P"
   )); setq/list

;; Add your Blocknames here
  (setq blklist (list
    "HCN*"
  )); setq/list

;; Define your output list here
  (setq outfile "c:/data/connectors.csv")

 (defun report_str_csv ( str )
  (setq fil outfile)
  (setq ofil1 (open fil "a"))
  (write-line str ofil1)
  (close ofil1)
 ); function

;;
;; Get a selection set of each Block in blklist
;;
  (foreach bn blklist
  (setq ss nil)
  (setq ss (ssget "X" (list (cons 0 "INSERT")(cons 2 bn)(cons 66 1))))
  (if ss
   (progn
    (setq N 0 taglist (list) vallist (list) bnlist (list))
    (repeat (sslength ss)
     (setq bn (cdr (assoc 2 (entget (ssname ss N))))); grab the Block name
     (setq blk (vlax-ename->vla-object (ssname ss N))); make Object of Nth N ss
     (if (safearray-value (setq atts (vlax-variant-value (vla-getattributes blk))))
      (progn
       (setq atts (vlax-safearray->list (vlax-variant-value (vla-getattributes blk)))); list of attributes 
        (foreach att atts
         (setq Tag (strcase (vla-get-tagstring att))); Get the 'Tagname' of each Attribute
         (if (member Tag attlist); match to attlist
          (progn
           (setq val (vla-get-textstring att))
            (if val
             (progn
              (setq bnlist (cons bn bnlist)); add to Block name list
              (setq taglist (cons Tag taglist)); add to Tag name list
              (setq vallist (cons val vallist)); add to Value list
             ); progn
            ); if
           ); progn
          ); if
         ); foreach
        ); progn
       ); if
       (setq N (+ N 1))
      ); repeat
    ); progn
   ); if
  ); foreach
;;
;; Now, reverse the lists
  (if (> (length bnlist) 0)
   (progn
    (setq bnlist (reverse bnlist))
    (setq taglist (reverse taglist))
    (setq vallist (reverse vallist))
   ); progn
  ); if
;;
;; Report all

 (setq N 0)
 (repeat (length bnlist)
  (setq bn (nth N bnlist))
  (setq tag (nth N taglist))
  (setq val (nth N vallist))
  (setq O (strcat bn "," tag "," val ","))
  (report_str_csv O); and write it out
  (setq O "" val "" bn "" tag "")
  (setq N (+ N 1))
 ); repeat

); function C:GO
(princ)
(C:GO)

 

0 Likes
Message 8 of 15

Sea-Haven
Mentor
Mentor

You can write direct to a excel file doing the same as attout, you can then save and close the excel say as dwg name. @ec-cad has provided a lot of code already you would replace the write-line with a write cells, say adding a row when you look for a new block. 

 

Using a script would be the way to go to process a 100 dwg's. I don't know if Acoreconsole supports "get application" as its much faster for multiple dwg's.

 

Will try to find some time added to my to do list.

0 Likes
Message 9 of 15

Sea-Haven
Mentor
Mentor

Big thanks to @ec-cad ec-cad just changed the output to Excel instead of csv. Try it on a dwg. It would need a script open dwg then load the program, remove the alerts when happy. I am sure the Excel result can be improved.

 

 

; Code by ec-cad July 2024
;; Export_Connectors.lsp
;; Designed to be batched within a script.
;; Function: to find Connectors get the attribute Tags (attlist), and output
;;  the data to C:/data/Connectors.csv  file

;; Modified by AlanH to export direct to Excel.

(defun C:GO ( /  blklist attlist bnlist ss b n blk hand atts att tag val myxl row) ; called at end of program.
  (vl-load-com)
  
  ;;	Thanks to fixo			;;
;;   = Set Excel cell text =    ;;
;;				;;
(defun xlsetcelltext ( row column text)
(setq cells (vlax-get-property  (vlax-get-property myxl "ActiveSheet") "Cells"))
  (vl-catch-all-apply
    'vlax-put-property
    (list cells 'Item row column
	(vlax-make-variant (vl-princ-to-string text) vlax-vbstring)))
)
  
  (alert "Close and Exit any Excel you have open as it will be overwritten\n\nProgram will open a new Excel save it and close")
;;I basically need the tag, location, installation, description, termXXp, and termdescXXp attributes
  (setq attlist (list
      "LOC"
      "INST"
      "DESC1"
      "DESC2"
      "DESC3"
      "TERM01P"
      "TERM02P"
      "TERM03P"
      "TERMDESC01P"
      "TERMDESC02P"
      "TERMDESC03P"
   )); setq/list

;; Add your Blocknames here
  (setq blklist (list
    "HCN*"
  )); setq/list


;;
;; Get a selection set of each Block in blklist
;;
(setq bnlist '())
  (foreach bn blklist
  (setq ss nil)
  (setq ss (ssget "X" (list (cons 0 "INSERT")(cons 2 bn)(cons 66 1))))
  (if ss
   (progn
    (setq N 0 taglist (list) vallist (list) bnlist (list))
    (repeat (sslength ss)
     (setq bn (cdr (assoc 2 (entget (ssname ss N))))); grab the Block name
     (setq blk (vlax-ename->vla-object (ssname ss N))); make Object of Nth N ss
	 (setq hand (vlax-get blk 'handle))
     (if (safearray-value (setq atts (vlax-variant-value (vla-getattributes blk))))
      (progn
       (setq atts (vlax-safearray->list (vlax-variant-value (vla-getattributes blk)))); list of attributes 
        (foreach att atts
         (setq Tag (strcase (vla-get-tagstring att))); Get the 'Tagname' of each Attribute
         (if (member Tag attlist); match to attlist
          (progn
           (setq val (vla-get-textstring att))
            (if val
             (progn
              (setq bnlist (cons (list bn tag val hand) bnlist)); add to Block name list
             ; (setq taglist (cons Tag taglist)); add to Tag name list
             ; (setq vallist (cons val vallist)); add to Value list
             ); progn
            ); if
           ); progn
          ); if
         ); foreach
        ); progn
       ); if
       (setq N (+ N 1))
      ); repeat
    ); progn
   ); if
  ); foreach
;;

(setq bnlist (vl-sort bnlist
  '(lambda (a b)
   (cond
   ((< (car a) (car b)))
   ((= (car a) (car b)) (< (cadr a) (cadr b)))
   )
   )
  )
)

;; Now, reverse the list
    (setq bnlist (reverse bnlist))
;;
;; Report all

(or (setq myxl (vlax-get-object "Excel.Application"))
    (setq myxl (vlax-get-or-create-object "excel.Application"))
)
(vla-put-visible myXL :vlax-true)
(vlax-put-property myxl 'ScreenUpdating :vlax-true)
(vlax-put-property myXL 'DisplayAlerts :vlax-true)
(vlax-invoke (vlax-get myxl 'workbooks) 'Add)

(xlsetcelltext  1 1 "Bname")
(xlsetcelltext 1 2 "TAG")
(xlsetcelltext 1 3 "Att Val")
(xlsetcelltext 1 4 "Handle")
(setq row 2)
(foreach val bnlist
(xlsetcelltext row 1 (nth 0 val))
(xlsetcelltext row 2 (nth 1 val))
(xlsetcelltext row 3 (nth 2 val))
(xlsetcelltext row 4 (nth 3 val))
(setq Row (1+ row))
)

(setq pre (getvar 'dwgprefix))
(setq dwg (vl-filename-base (getvar "dwgname")))
(setq filename (strcat pre dwg))
(vlax-invoke-method (vlax-get-property myxl "ActiveWorkbook")  "SaveAs" filename -4143 "" "" :vlax-false :vlax-false nil )
(vlax-invoke-method (vlax-get-property myxl "ActiveWorkbook") 'Close :vlax-False)
(vlax-invoke-method myxl 'Quit)
(if (not (vlax-object-released-p myXL))(progn(vlax-release-object myXL)(setq myXL nil)))

(alert "Finished")
); function C:GO
(princ)
(C:GO)

 

 

 

0 Likes
Message 10 of 15

daniel_cadext
Advisor
Advisor

>100 drawings

 

Just a note, CSV is not very robust (think thousands separator), you would be better off actually writing to Excel as @Sea-Haven shows.

 

Handles are not guaranteed to be unique, in fact, they are almost certainly guaranteed to collide,  better to use path+handle or somehow store the path

 

Python for AutoCAD, Python wrappers for ARX https://github.com/CEXT-Dan/PyRx
0 Likes
Message 11 of 15

steven.coxVCM6J
Advocate
Advocate

@Sea-Haven/ all this works great.  However, I have questions and complications.

 

It tells me to close any excel I have open.  Does this mean of that file?

 

Can we make it ask me for a file name / location?  Not a huge deal, just thinking of the "next" project.

 

It does not pick up the TAG and I do not now what the Handle is.

 

It adds the data in rows.

BnameTAGAtt ValHandle
HCN1_11P_3C0DESC1SAMPLE PLUG3.00E+08
HCN1_11P_3C0DESC2 3.00E+08
HCN1_11P_3C0DESC3 3.00E+08
HCN1_11P_3C0INST 3.00E+08
HCN1_11P_3C0LOC 3.00E+08
HCN1_11P_3C0TERM01P13.00E+08
HCN1_11P_3C0TERM02P23.00E+08
HCN1_11P_3C0TERM03P33.00E+08
HCN1_11P_3C0TERMDESC01P+ test3.00E+08
HCN1_11P_3C0TERMDESC02Ptest3.00E+08
HCN1_11P_3C0TERMDESC03PSIGNAL test3.00E+08

 

This is what I would ideally like it to look like.  Note I removed the P/J suffix from the terms and termdesc as it will be either one.

TAG1TAG2DESC1DESC2DESC3INSTLOCTERM01TERMDESC01TERM02TERMDESC02TERM03TERMDESC03
P??1 SAMPLE PLUG    1+ test2test3SIGNAL test
P??3      1 2 3 

 

 

Can we pivot this so that there is a single row with the headers as TAG* (could be TAG1 (parent) or TAG2 (child), DESC1, DESC2, DESC3, INST, LOC, ...  this way, each connector takes a single row.  Don't really need the block name as the tag tells me what which one it is.  However, the block name tells it is a connection.  I change to this....

 

(setq blklist (list
"*CN*"
)); setq/list

 

to pick up verticals and horizontals and it worked fine.

 

Now the complication......

 

The TERMDESCXXP - P = PLUG.  it is a J for Jacks.  I tried adding a * in the list but that did not work.  This is also true for the TERMXXP.

 

 

The sample has 3 terms but this varies from 1 term to, so far, 81 terms but this could conceivably be hundreds I guess. 

 

I am trying to understand as much of this as I can.  I commented out this

;; Now, reverse the list
;; (setq bnlist (reverse bnlist))

because it reversed the order.  When the data goes left to right, it may be different.

 

Also, I have to "load" the app for it to run.  I only want it to run when I type in the command.  To do this do I add...

 

(defun C:exportcons (

rest of code here

)

?

 

Thanks so much for all y'alls help!!  I love this forum!

 

Steven

 

0 Likes
Message 12 of 15

daniel_cadext
Advisor
Advisor

IMHO, not sure it’s right for you, but with 100s of drawings, you might consider using more robust tooling

With something like pandas, which is designed for data analysis and manipulation, you may de able to do your ‘wholesale changes’ with automation.

 

Just throwing this out there as an idea

 

 

from pyrx_imp import Rx, Ge, Gi, Db, Ap, Ed
import traceback
import pandas as pd
import openpyxl  # for pandas

def processAttributes(path, db, blkname, data):
    bt = Db.BlockTable(db.blockTableId())
    if not bt.has(blkname):
        return
    btr = Db.BlockTableRecord(bt[blkname])
    refs = [Db.BlockReference(id) for id in btr.getBlockReferenceIds()]
    for ref in refs:
        data["DWG"].append(path)
        data["Handle"].append(ref.getHandle().toString())
        atts = [Db.AttributeReference(id) for id in ref.attributeIds()]
        for att in atts:
            tag = att.tag()
            if not tag in data:
                data[tag] = [att.textString()]
            else:
                data[tag].append(att.textString())

def processDb(path, blkname, data):
    sideDb = Db.Database(False, True)
    sideDb.readDwgFile(path)
    sideDb.closeInput(True)
    processAttributes(path, sideDb, blkname, data)

def PyRxCmd_doit():
    try:
        # setup data
        data = {"DWG": [], "Handle": []}

        # setup dwg
        blkName = "HCN1_11P_3C0"
        path = "E:\\Source.dwg"
        processDb(path, blkName, data)
        
        # pandas party
        df = pd.DataFrame(data)
        print("\nquery results = {}\n..\n".format(df.query('Handle == ["988"]')))
        print(df)
        # save to excel
        df.to_excel("e:\\output.xlsx")

    except Exception as err:
        traceback.print_exception(err)

 

 

pandas.png

 

excel.png

Python for AutoCAD, Python wrappers for ARX https://github.com/CEXT-Dan/PyRx
0 Likes
Message 13 of 15

steven.coxVCM6J
Advocate
Advocate

I am not opposed to this approach for sure.  I like learning, but not sure I would know where to begin.

 

When I type "Python" in my windows search bar, I get this in a cmd window.

 

Python 3.9.7 (tags/v3.9.7:1016ef3, Aug 30 2021, 20:19:38) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

 

When looking up Pandas, it says I need Anaconda. 

 

Suggestions?

 

Thanks, Steven

 

0 Likes
Message 14 of 15

steven.coxVCM6J
Advocate
Advocate

Couple of points here.

 

1) ATTOUT does what I need, but does not format correctly in Excel.  An example is "+ test" is converted to a formula even when I told it to format all as text.  ATTOUT also grabs EVERY attribute, which is not necessary and makes the spreadsheet very large.

 

2) The basic need it to be able to mass update every connector in a single drawing.  This is far better than what I have to do now.  If at some point we can make it cycle through drawings, that will be awesome, but a drawing at a time is cool for now.

 

3) I am very grateful for all the help and suggestions from everyone here.

 

Thanks so much!!

0 Likes
Message 15 of 15

steven.coxVCM6J
Advocate
Advocate

Correction, ATTOUT does format all properly when I set it properly!