Multiple job

Mikael63
edited June 25 in LISP

Got a lot of DWG from eplan.
I have some script (scr) and some LISP for doing what I want but I'm stuck with LeeMac's Attcol and it's dialogue.

Here is what I want:

Create a new Layer, let say layer 800
Move all items to layer 800
Delete all layers except layer 0 and layer 800 and move remaining blocks to layer 800. (Like Change when doing it by Drawing Explorer - Layers)
Change ALL object, including nested block, as well as all attributes to colour ByLayer or (color 7)

Comments

  • Python is a cool option for stuff like this, a one-off script with the power of BRX without having to compile

    If you’re running V24-v25 check out pyrx

    import traceback
    import wx
    import os, pathlib
    from pyrx import Db, Ap
    
    
    def addLayer(sidedb: Db.Database, name: str):
        lt = Db.LayerTable(sidedb.layerTableId())
        if lt.has(name):
            return lt.getAt(name)
        clr = Db.Color()
        clr.setColorIndex(3)
        layer = Db.LayerTableRecord()
        layer.setName(name)
        layer.setColor(clr)
        lt.upgradeOpen()
        return lt.add(layer)
    
    
    def moveModelSpaceEntsToLayer(sidedb: Db.Database, lid: Db.ObjectId):
        model = Db.BlockTableRecord(sidedb.modelSpaceId())
        for id in model.objectIds():
            ent = Db.Entity(id, Db.OpenMode.kForWrite)
            ent.setLayer(lid)
    
    
    def moveBlockEntsToLayer(sidedb: Db.Database):
        bt = Db.BlockTable(sidedb.blockTableId())
        for _name, id in bt.toDict().items():
            block = Db.BlockTableRecord(id)
            # skip a name if you want
            if block.isLayout():
                continue
            if block.isFromExternalReference():
                continue
            for id in block.objectIds():
                ent = Db.Entity(id, Db.OpenMode.kForWrite)
                ent.setColorIndex(256)  # by layer
                ent.setLayer("0")
    
    
    def removeLayersExcept(sidedb: Db.Database, keep: list[str]):
        lt = Db.LayerTable(sidedb.layerTableId())
        for name, id in lt.asDict().items():
            if name in keep:
                continue
            layer = Db.LayerTableRecord(id, Db.OpenMode.kForWrite)
            try:
                layer.erase()
            except Exception as err:
                print("cannot delete {}".format(name))
    
    
    # do some stuff
    def worker(sidedb: Db.Database):
        lid = addLayer(sidedb, "800")
        moveModelSpaceEntsToLayer(sidedb, lid)
        moveBlockEntsToLayer(sidedb)
        removeLayersExcept(sidedb, ["0", "800"])
    
    
    # reads the .dwg can calls a worker function and provides a scope
    def openSideDatabase(path, worker):
        sideDb = Db.Database(False, True)  # no doc
        sideDb.readDwgFile(path)
        sideDb.closeInput(True)
        worker(sideDb)
        sideDb.saveAs(path)
    
    
    # get dwg paths from dir (top level only) using wxPython
    def getDwgFiles():
        paths = []
        dlg = wx.DirDialog(None, "Choose directory", "", wx.DD_DIR_MUST_EXIST)
    
        if dlg.ShowModal() != wx.ID_OK:
            print("You Cancelled The Dialog!")
            return
    
        fnames = next(os.walk(dlg.GetPath()), (None, None, []))[2]
        dwgex = ".dwg".casefold()
    
        for fname in fnames:
            ext = pathlib.Path(fname).suffix.casefold()
            if ext != dwgex:
                continue
            paths.append("{}\\{}".format(dlg.GetPath(), fname))
    
        return paths
    
    
    @Ap.Command()
    def doit() -> None:
        try:
            for _item in getDwgFiles():
                print("\nProccessing {}".format(_item))
                openSideDatabase(_item, worker)
    
            print("done")
        except Exception as err:
            traceback.print_exception(err)
    
    

  • ALANH
    edited June 26

    A couple of snippets of code.

    (command "-layer" "m" "800" "C" 7 "" "")

    (command "chprop" "all" "" "LA" "800" "Color" "Bylayer" "")

    (setq doc (vla-get-activedocument (vlax-get-acad-object))) ; open database

    (vlax-for block (vla-get-blocks doc)
    (if (not (wcmatch (strcase (vla-get-name block) t) "_space"))
    (vlax-for ent block
    (vla-put-layer ent "800")
    (vla-put-color ent "Bylayer")
    (vla-put-linetype ent "Bylayer")
    (vla-put-lineweight ent aclnwtbyblock)
    )
    )
    )

    I would do a purge for the layers only, may need to do twice.

  • Thanks!

    First I do a purge of all layers and all blocks.
    Then rename one (1) blockname to a "proper" blockname.
    Then I do a "changetag" by @Virgil

    Above is a absolute minimum for me to have any use of the dwgs.
    After that = as topic here.

    (command "-layer" "m" "800" "C" 7 "" "")
    
    (command "chprop" "all" "" "LA" "800" "Color" "Bylayer" "")
    

    Works nice. (kind of how I already do, but this is better)

    (vla-put-color ent "Bylayer")
    

    Does not work.
    ; error : Automation Error DISP_E_PARAMNOTOPTIONAL; [IAcadBlockReference] Required argument is not optional for [COLOR] property.

    But this works

    (vla-put-color ent 7)
    

    Still - all attributes is colored

    This works:

    But then I have to use that dialogue, for each file

  • If I use a script as scr (yes I assume also as a LISP?) I can use like

    Attedit
    Y
    *
    *
    *
    All

    C
    7
    N

    and so on for each attribute.

    How to write code so the C7N loops as long as there a next attribute to edit?

  • Found this

    https://www.cadtutor.net/forum/topic/23254-modify-lisp-for-changing-block-attributes/

    I then edit that as

    (defun c:ATR (/ com val)
    (initget 1 "Height Angle Style Layer Color")
    (setq com "Color")
    (setq val "7")
    (prompt "\nSelect Attributes by Crossing Window: ")
    (command ".attedit" "y" "" "" "*" "all" )
    (while (> (getvar "cmdactive") 0)
    (command com val "n")
    )
    (princ)
    )
    

    If I run ATR it does the job to change color for all attributes.

    If I call the atr.lsp from a scr-script - it never stops. How to prevent that?

    (I have a application where I can batch-select files and then run a scr for each file so my idea was to just call the lisp, as I do with "changetag")

  • @LeeMac posted a solution here:

    https://www.cadtutor.net/forum/topic/18816-pause-until-command-finishes/

    Another just for fun: 

     (while (= 1 (logand 1 (getvar 'CMDACTIVE)))

    [instead of (while (> (getvar "cmdactive") 0) above]