aridzv Posted April 16 Posted April 16 @Danielm103 and one last question: how do I set the save path to the drawing folder automatically? like using the "DWGPREFIX" in lisp? Quote
Danielm103 Posted April 16 Author Posted April 16 I was only centering the image, this version does all the modified cells You can use AcDbDatabase.getFilename to get the path, then use python’s pathlib (built in) to play with paths from pyrx import Rx, Ge, Gi, Gs, Db, Ap, Ed, Ax import traceback from openpyxl.drawing.image import Image as xlImage from openpyxl.utils.cell import get_column_letter from openpyxl.styles import Alignment import openpyxl as xl import pathlib import wx @Ap.Command() def doit(): try: db = Db.curDb() ps, id, _ = Ed.Editor.entSel("\nSelect a table: ", Db.Table.desc()) if ps != Ed.PromptStatus.eOk: raise RuntimeError("Selection Error! {}: ".format(ps)) #paths xlpath = pathlib.Path(db.getFilename()).parent xlname = pathlib.Path(db.getFilename()).stem wb = xl.Workbook() ws = wb.active table = Db.Table(id) opts = Db.TableIteratorOption.kTableIteratorSkipMerged for cell in table.cells(opts): # format all cells currentCell = ws.cell(cell.row + 1, cell.column + 1) currentCell.alignment = Alignment(horizontal="center", vertical="center") if table.cellType(cell.row, cell.column) == Db.CellType.kBlockCell: blk = table.blockTableRecordId(cell.row, cell.column) img: wx.Image = Gs.Core.getBlockImage(blk, 64, 64, 1.0, [0, 0, 0]) img.SetMaskColour(0, 0, 0) img.SetMask(True) imgpath = "{}/{}.png".format(xlpath, blk.handle()) img.SaveFile(imgpath, wx.BITMAP_TYPE_PNG) xlimg = xlImage(imgpath) xlimg.width = 64 xlimg.height = 64 cellref = "{}{}".format(get_column_letter(cell.column + 1), cell.row + 1) ws.add_image(xlimg, cellref) ws.row_dimensions[cell.row + 1].height = 64 else: ws.cell( row=cell.row + 1, column=cell.column + 1, value=table.textString(cell.row, cell.column), ) wb.save("{}/{}.xlsx".format(xlpath, xlname)) except Exception as err: traceback.print_exception(err) apparently xl has weirdness when it comes to images and alignment with regards to aspect ratio. 1 Quote
aridzv Posted April 16 Posted April 16 @Danielm103 thanks... I got as far as load "pathlib" and tried to work with it before you post your comment... see the (poor..) attemptes I did: from pyrx import Rx, Ge, Gi, Gs, Db, Ap, Ed, Ax import traceback import wx # wxPython import openpyxl as xl import pyautocad from pathlib import Path from openpyxl.drawing.image import Image as xlImage from openpyxl.utils.cell import get_column_letter from openpyxl.styles import Alignment #--------------------- @Ap.Command() def doit2(): try: a="this is best" b="no" c=a+b print(c) axApp = Ap.Application.acadApplication() axDoc = axApp.activeDocument() #acad = pyautocad.Autocad() print(axDoc.name) #print(acad.doc.Name) #p = Path(__file__).resolve() #p = Path(axDoc).resolve() #print(p) is there a way to set the column width like you set the row height: ws.row_dimensions[cell.row + 1].height = 64 thanks, aridzv Quote
aridzv Posted April 16 Posted April 16 44 minutes ago, Danielm103 said: apparently xl has weirdness when it comes to images and alignment with regards to aspect ratio. Yes... Align the image within the cell.. It's strange that there is no way to determine the position of the image relative to the cell. But in any case this is a great program, many Thanks!!! aridzv. Quote
aridzv Posted April 16 Posted April 16 @Danielm103 By the way, your code does work with "Modeling" visual style Quote
Danielm103 Posted April 17 Author Posted April 17 (edited) I found this https://stackoverflow.com/questions/13197574/openpyxl-adjust-column-width-size new code from pyrx import Rx, Ge, Gi, Gs, Db, Ap, Ed, Ax import traceback from openpyxl.drawing.image import Image as xlImage from openpyxl.utils.cell import get_column_letter from openpyxl.styles import Alignment import openpyxl as xl import pathlib import wx @Ap.Command() def doit(): try: db = Db.curDb() ps, id, _ = Ed.Editor.entSel("\nSelect a table: ", Db.Table.desc()) if ps != Ed.PromptStatus.eOk: raise RuntimeError("Selection Error! {}: ".format(ps)) # paths xlpath = pathlib.Path(db.getFilename()).parent xlname = pathlib.Path(db.getFilename()).stem wb = xl.Workbook() ws = wb.active table = Db.Table(id) opts = Db.TableIteratorOption.kTableIteratorSkipMerged for cell in table.cells(opts): # format all cells currentCell = ws.cell(cell.row + 1, cell.column + 1) currentCell.alignment = Alignment(horizontal="center", vertical="center") if table.cellType(cell.row, cell.column) == Db.CellType.kBlockCell: blk = table.blockTableRecordId(cell.row, cell.column) img: wx.Image = Gs.Core.getBlockImage(blk, 64, 64, 1.0, [0, 0, 0]) img.SetMaskColour(0, 0, 0) img.SetMask(True) imgpath = "{}/{}.png".format(xlpath, blk.handle()) img.SaveFile(imgpath, wx.BITMAP_TYPE_PNG) xlimg = xlImage(imgpath) xlimg.width = 64 xlimg.height = 64 cellref = "{}{}".format(get_column_letter(cell.column + 1), cell.row + 1) ws.add_image(xlimg, cellref) ws.row_dimensions[cell.row + 1].height = 64 else: ws.cell( row=cell.row + 1, column=cell.column + 1, value=table.textString(cell.row, cell.column), ) #nested function def as_text(value): if value is None: return "" return str(value) # make another pass to set the widths + a little extra for column_cells in ws.columns: length = max(len(as_text(cell.value)) for cell in column_cells) ws.column_dimensions[column_cells[0].column_letter].width = length * 1.25 wb.save("{}/{}.xlsx".format(xlpath, xlname)) except Exception as err: traceback.print_exception(err) Edited April 17 by Danielm103 Quote
BIGAL Posted April 17 Posted April 17 (edited) Thanks @Danielm103 for the instructions about running python in Bricscad. may give it a try. What is corrrect syntax for python, did see open BricsCAD, type in “pyload”, load your module, run your new command (defun C:dtop () (vl-vbaload "P:/AutoDESK/VBA/xxx filecopy.dvb") (vl-vbarun "xxxfilecopy") ) Edited April 17 by BIGAL Quote
Danielm103 Posted April 17 Author Posted April 17 2 hours ago, BIGAL said: Thanks @Danielm103 for the instructions about running python in Bricscad. may give it a try. What is corrrect syntax for python, did see open BricsCAD, type in “pyload”, load your module, run your new command (defun C:dtop () (vl-vbaload "P:/AutoDESK/VBA/xxx filecopy.dvb") (vl-vbarun "xxxfilecopy") ) Was this a question for me? the code translation would be https://help.autodesk.com/view/OARX/2025/ENU/?guid=GUID-4F19B20D-BF8C-4505-A13A-4B6102778E24 import traceback from pyrx import Rx, Ge, Gi, Gs, Db, Ap, Ed, Ax @Ap.Command() def dtop(): try: axApp = Ap.Application.acadApplication() axApp.loadDVB("c:/drawline.dvb") axApp.runMacro("Module1.Drawline") except Exception as err: traceback.print_exception(err) Quote may give it a try. That would be great, you know since its open source, I (we) could always use input from a master Quote
Danielm103 Posted April 17 Author Posted April 17 (edited) Something I noticed, one of your objects is black, so you might want to set the bk color and mask to the color of BricsCAD’s background color so it’s not xor'ed out... it seems okay though img: wx.Image = Gs.Core.getBlockImage(id, 256, 256, 1.0, [33, 40, 48]) img.SetMaskColour(33, 40, 48) Edited April 17 by Danielm103 1 Quote
aridzv Posted April 17 Posted April 17 (edited) @Danielm103 Hi. I have a question: How do I get the block name and use it for the image name instand of the block handle? I tried to do it but hit a wall. after the code get this object: blk = table.blockTableRecordId(cell.row, cell.column) I tried to use those tow line and both failed: 1. blkname = blk.EffectiveName 2. blkname = blk.Name when I try to print the "blk.ObjectName" I get an error in the command line this way: print (blk.ObjectName) ^^^^^^^^^^^^^^ AttributeError: 'ObjectId' object has no attribute 'ObjectName' when I print blk I get a referance this way: print (blk) . . 12d94b2e0 I also search for "Python ObjectId to ObjectName" but found nothing... I found this article but it didn't help me... how can I get the block "EffectiveName" property or atleast the block "Name" property? thanks, aridzv. Edited April 17 by aridzv Quote
Danielm103 Posted April 17 Author Posted April 17 (edited) EffectiveName is a property of Block references, the table is giving you the block record id a bit ugly as BricsCAD is missing dynamic block APIs so we will use this https://adndevblog.typepad.com/autocad/2025/02/how-to-get-dynamic-block-from-anonymous-block.html def getEffectiveNameFromBtrId(btrid: Db.ObjectId): rec = Db.BlockTableRecord(btrid) if rec.isAnonymous() and rec.hasXData("AcDbBlockRepBTag"): for dfx, val in rec.xData("AcDbBlockRepBTag"): if dfx == 1005: hnd = Db.Handle(val) dynid = rec.database().tryGetObjectId(False, hnd) dynrec = Db.BlockTableRecord(dynid) return dynrec.getName() return rec.getName() Edited April 17 by Danielm103 Quote
Danielm103 Posted April 17 Author Posted April 17 I’m going to add this to the API https://github.com/CEXT-Dan/PyRx/issues/278 1 Quote
aridzv Posted April 17 Posted April 17 (edited) 15 minutes ago, Danielm103 said: I’m going to add this to the API https://github.com/CEXT-Dan/PyRx/issues/278 @Danielm103 Thanks!! what about the block name (not the effective - I'm aware from lisp about its problems)... aridzv. Edited April 17 by aridzv Quote
aridzv Posted April 17 Posted April 17 23 minutes ago, Danielm103 said: EffectiveName is a property of Block references, the table is giving you the block record id a bit ugly as BricsCAD is missing dynamic block APIs so we will use this https://adndevblog.typepad.com/autocad/2025/02/how-to-get-dynamic-block-from-anonymous-block.html def getEffectiveNameFromBtrId(btrid: Db.ObjectId): rec = Db.BlockTableRecord(btrid) if not rec.isAnonymous(): return rec.getName() for dfx, val in rec.xData("AcDbBlockRepBTag"): if dfx == 1005: hnd = Db.Handle(val) dynid = rec.database().tryGetObjectId(False, hnd) dynrec = Db.BlockTableRecord(dynid) return dynrec.getName() @Danielm103 how do I use it in the code? Quote
Danielm103 Posted April 17 Author Posted April 17 new code that add the name, wait for the next release of you need effectiveName from pyrx import Rx, Ge, Gi, Gs, Db, Ap, Ed, Ax import traceback from openpyxl.drawing.image import Image as xlImage from openpyxl.utils.cell import get_column_letter from openpyxl.styles import Alignment import openpyxl as xl import pathlib import wx @Ap.Command() def doit(): try: db = Db.curDb() ps, id, _ = Ed.Editor.entSel("\nSelect a table: ", Db.Table.desc()) if ps != Ed.PromptStatus.eOk: raise RuntimeError("Selection Error! {}: ".format(ps)) # paths xlpath = pathlib.Path(db.getFilename()).parent xlname = pathlib.Path(db.getFilename()).stem wb = xl.Workbook() ws = wb.active table = Db.Table(id) opts = Db.TableIteratorOption.kTableIteratorSkipMerged for cell in table.cells(opts): # format all cells currentCell = ws.cell(cell.row + 1, cell.column + 1) currentCell.alignment = Alignment(horizontal="center", vertical="center") if table.cellType(cell.row, cell.column) == Db.CellType.kBlockCell: blkid = table.blockTableRecordId(cell.row, cell.column) blkrec = Db.BlockTableRecord(blkid) #open the block img: wx.Image = Gs.Core.getBlockImage(blkid, 64, 64, 1.0, [0, 0, 0]) img.SetMaskColour(0, 0, 0) img.SetMask(True) #change to effectiveName next release imgpath = "{}/{}.png".format(xlpath, blkrec.name()) img.SaveFile(imgpath, wx.BITMAP_TYPE_PNG) xlimg = xlImage(imgpath) xlimg.width = 64 xlimg.height = 64 cellref = "{}{}".format(get_column_letter(cell.column + 1), cell.row + 1) ws.add_image(xlimg, cellref) ws.row_dimensions[cell.row + 1].height = 64 else: ws.cell( row=cell.row + 1, column=cell.column + 1, value=table.textString(cell.row, cell.column), ) #nested function def as_text(value): if value is None: return "" return str(value) # make another pass to set the widths + a little extra for column_cells in ws.columns: length = max(len(as_text(cell.value)) for cell in column_cells) ws.column_dimensions[column_cells[0].column_letter].width = length * 1.25 wb.save("{}/{}.xlsx".format(xlpath, xlname)) except Exception as err: traceback.print_exception(err) 1 Quote
aridzv Posted April 17 Posted April 17 O.K., Got it.... here is the final code with the "getEffectiveNameFromBtrId" function. @Danielm103 -MANY MANY THANKS FOR YOUR HELP. #https://www.cadtutor.net/forum/topic/97450-export-table-with-blocks-to-excel-with-python/ from pyrx import Rx, Ge, Gi, Gs, Db, Ap, Ed, Ax import traceback from openpyxl.drawing.image import Image as xlImage from openpyxl.utils.cell import get_column_letter from openpyxl.styles import Alignment import openpyxl as xl import pathlib import ctypes import wx @Ap.Command() def Py_tablewithimagetoexcel(): try: db = Db.curDb() ps, id, _ = Ed.Editor.entSel("\nSelect a table: ", Db.Table.desc()) if ps != Ed.PromptStatus.eOk: raise RuntimeError("Selection Error! {}: ".format(ps)) # paths xlpath = pathlib.Path(db.getFilename()).parent xlname = pathlib.Path(db.getFilename()).stem #fpt = "{}/{}.png".format(xlpath, xlname) fpt = "{}\{}.xlsx".format(xlpath, xlname) wb = xl.Workbook() ws = wb.active table = Db.Table(id) opts = Db.TableIteratorOption.kTableIteratorSkipMerged for cell in table.cells(opts): # format all cells currentCell = ws.cell(cell.row + 1, cell.column + 1) currentCell.alignment = Alignment(horizontal="center", vertical="center") if table.cellType(cell.row, cell.column) == Db.CellType.kBlockCell: blk = table.blockTableRecordId(cell.row, cell.column) bname = getEffectiveNameFromBtrId(blk) print (bname) print (blk) img: wx.Image = Gs.Core.getBlockImage(blk, 64, 64, 1.0, [0, 0, 0]) img.SetMaskColour(0, 0, 0) img.SetMask(True) imgpath = "{}/{}.png".format(xlpath, bname)#blk.handle() img.SaveFile(imgpath, wx.BITMAP_TYPE_PNG) xlimg = xlImage(imgpath) xlimg.width = 64 xlimg.height = 64 cellref = "{}{}".format(get_column_letter(cell.column + 1), cell.row + 1) ws.add_image(xlimg, cellref) ws.row_dimensions[cell.row + 1].height = 64 else: ws.cell( row=cell.row + 1, column=cell.column + 1, value=table.textString(cell.row, cell.column), ) #nested function def as_text(value): if value is None: return "" return str(value) # make another pass to set the widths + a little extra for column_cells in ws.columns: length = max(len(as_text(cell.value)) for cell in column_cells) ws.column_dimensions[column_cells[0].column_letter].width = length * 1.25 wb.save("{}/{}.xlsx".format(xlpath, xlname)) ctypes.windll.user32.MessageBoxW(0, fpt , "Files Saved", 1) except Exception as err: traceback.print_exception(err) def getEffectiveNameFromBtrId(btrid: Db.ObjectId): rec = Db.BlockTableRecord(btrid) if rec.isAnonymous() and rec.hasXData("AcDbBlockRepBTag"): for dfx, val in rec.xData("AcDbBlockRepBTag"): if dfx == 1005: hnd = Db.Handle(val) dynid = rec.database().tryGetObjectId(False, hnd) dynrec = Db.BlockTableRecord(dynid) return dynrec.getName() return rec.getName() aridzv. 1 Quote
aridzv Posted April 17 Posted April 17 got ahead of me in few seconds.... thank!! 1 minute ago, aridzv said: O.K., Got it.... here is the final code with the "getEffectiveNameFromBtrId" function. @Danielm103 -MANY MANY THANKS FOR YOUR HELP. #https://www.cadtutor.net/forum/topic/97450-export-table-with-blocks-to-excel-with-python/ from pyrx import Rx, Ge, Gi, Gs, Db, Ap, Ed, Ax import traceback from openpyxl.drawing.image import Image as xlImage from openpyxl.utils.cell import get_column_letter from openpyxl.styles import Alignment import openpyxl as xl import pathlib import ctypes import wx @Ap.Command() def Py_tablewithimagetoexcel(): try: db = Db.curDb() ps, id, _ = Ed.Editor.entSel("\nSelect a table: ", Db.Table.desc()) if ps != Ed.PromptStatus.eOk: raise RuntimeError("Selection Error! {}: ".format(ps)) # paths xlpath = pathlib.Path(db.getFilename()).parent xlname = pathlib.Path(db.getFilename()).stem #fpt = "{}/{}.png".format(xlpath, xlname) fpt = "{}\{}.xlsx".format(xlpath, xlname) wb = xl.Workbook() ws = wb.active table = Db.Table(id) opts = Db.TableIteratorOption.kTableIteratorSkipMerged for cell in table.cells(opts): # format all cells currentCell = ws.cell(cell.row + 1, cell.column + 1) currentCell.alignment = Alignment(horizontal="center", vertical="center") if table.cellType(cell.row, cell.column) == Db.CellType.kBlockCell: blk = table.blockTableRecordId(cell.row, cell.column) bname = getEffectiveNameFromBtrId(blk) print (bname) print (blk) img: wx.Image = Gs.Core.getBlockImage(blk, 64, 64, 1.0, [0, 0, 0]) img.SetMaskColour(0, 0, 0) img.SetMask(True) imgpath = "{}/{}.png".format(xlpath, bname)#blk.handle() img.SaveFile(imgpath, wx.BITMAP_TYPE_PNG) xlimg = xlImage(imgpath) xlimg.width = 64 xlimg.height = 64 cellref = "{}{}".format(get_column_letter(cell.column + 1), cell.row + 1) ws.add_image(xlimg, cellref) ws.row_dimensions[cell.row + 1].height = 64 else: ws.cell( row=cell.row + 1, column=cell.column + 1, value=table.textString(cell.row, cell.column), ) #nested function def as_text(value): if value is None: return "" return str(value) # make another pass to set the widths + a little extra for column_cells in ws.columns: length = max(len(as_text(cell.value)) for cell in column_cells) ws.column_dimensions[column_cells[0].column_letter].width = length * 1.25 wb.save("{}/{}.xlsx".format(xlpath, xlname)) ctypes.windll.user32.MessageBoxW(0, fpt , "Files Saved", 1) except Exception as err: traceback.print_exception(err) def getEffectiveNameFromBtrId(btrid: Db.ObjectId): rec = Db.BlockTableRecord(btrid) if rec.isAnonymous() and rec.hasXData("AcDbBlockRepBTag"): for dfx, val in rec.xData("AcDbBlockRepBTag"): if dfx == 1005: hnd = Db.Handle(val) dynid = rec.database().tryGetObjectId(False, hnd) dynrec = Db.BlockTableRecord(dynid) return dynrec.getName() return rec.getName() aridzv. Quote
Danielm103 Posted April 17 Author Posted April 17 2 minutes ago, aridzv said: O.K., Got it.... here is the final code with the "getEffectiveNameFromBtrId" function. @Danielm103 -MANY MANY THANKS FOR YOUR HELP. #https://www.cadtutor.net/forum/topic/97450-export-table-with-blocks-to-excel-with-python/ from pyrx import Rx, Ge, Gi, Gs, Db, Ap, Ed, Ax import traceback from openpyxl.drawing.image import Image as xlImage from openpyxl.utils.cell import get_column_letter from openpyxl.styles import Alignment import openpyxl as xl import pathlib import ctypes import wx @Ap.Command() def Py_tablewithimagetoexcel(): try: db = Db.curDb() ps, id, _ = Ed.Editor.entSel("\nSelect a table: ", Db.Table.desc()) if ps != Ed.PromptStatus.eOk: raise RuntimeError("Selection Error! {}: ".format(ps)) # paths xlpath = pathlib.Path(db.getFilename()).parent xlname = pathlib.Path(db.getFilename()).stem #fpt = "{}/{}.png".format(xlpath, xlname) fpt = "{}\{}.xlsx".format(xlpath, xlname) wb = xl.Workbook() ws = wb.active table = Db.Table(id) opts = Db.TableIteratorOption.kTableIteratorSkipMerged for cell in table.cells(opts): # format all cells currentCell = ws.cell(cell.row + 1, cell.column + 1) currentCell.alignment = Alignment(horizontal="center", vertical="center") if table.cellType(cell.row, cell.column) == Db.CellType.kBlockCell: blk = table.blockTableRecordId(cell.row, cell.column) bname = getEffectiveNameFromBtrId(blk) print (bname) print (blk) img: wx.Image = Gs.Core.getBlockImage(blk, 64, 64, 1.0, [0, 0, 0]) img.SetMaskColour(0, 0, 0) img.SetMask(True) imgpath = "{}/{}.png".format(xlpath, bname)#blk.handle() img.SaveFile(imgpath, wx.BITMAP_TYPE_PNG) xlimg = xlImage(imgpath) xlimg.width = 64 xlimg.height = 64 cellref = "{}{}".format(get_column_letter(cell.column + 1), cell.row + 1) ws.add_image(xlimg, cellref) ws.row_dimensions[cell.row + 1].height = 64 else: ws.cell( row=cell.row + 1, column=cell.column + 1, value=table.textString(cell.row, cell.column), ) #nested function def as_text(value): if value is None: return "" return str(value) # make another pass to set the widths + a little extra for column_cells in ws.columns: length = max(len(as_text(cell.value)) for cell in column_cells) ws.column_dimensions[column_cells[0].column_letter].width = length * 1.25 wb.save("{}/{}.xlsx".format(xlpath, xlname)) ctypes.windll.user32.MessageBoxW(0, fpt , "Files Saved", 1) except Exception as err: traceback.print_exception(err) def getEffectiveNameFromBtrId(btrid: Db.ObjectId): rec = Db.BlockTableRecord(btrid) if rec.isAnonymous() and rec.hasXData("AcDbBlockRepBTag"): for dfx, val in rec.xData("AcDbBlockRepBTag"): if dfx == 1005: hnd = Db.Handle(val) dynid = rec.database().tryGetObjectId(False, hnd) dynrec = Db.BlockTableRecord(dynid) return dynrec.getName() return rec.getName() aridzv. perfect! 1 Quote
aridzv Posted April 17 Posted April 17 (edited) @Danielm103 Which one do you think is better/cleaner? the shorten one without the fuction (the last one you posted) or the long one with the "getEffectiveNameFromBtrId" function? Edited April 17 by aridzv Quote
aridzv Posted April 17 Posted April 17 26 minutes ago, Danielm103 said: new code that add the name, wait for the next release of you need effectiveName how do I know about updates/new releases? 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.