Eks6666 发表于 2024-4-8 02:13

(超级干货)python打印cad图纸

本帖最后由 Eks6666 于 2024-4-8 02:15 编辑

有了python打印cad,从此告别插件!!哈哈哈

from pyautocad import Autocadimport win32com.client
import win32print
import pythoncom

#acad = Autocad(create_if_not_exists = True)
acad = win32com.client.Dispatch("AutoCAD.Application.23")   # AutoCAD.Application.23为 ProgID

acaddoc = acad.ActiveDocument
acadmod = acaddoc.ModelSpace
layout = acaddoc.layouts.item('Model')
plot = acaddoc.Plot



_PRINTER = win32print.GetDefaultPrinter()
_HPRINTER = win32print.OpenPrinter(_PRINTER)
#_PrinterStatus = 'Warning'




def PrinterStyleSetting():   
    acaddoc.SetVariable('BACKGROUNDPLOT', 0) # 前台打印
    layout.ConfigName = 'RICOH MP C2011' # 选择打印机
    layout.StyleSheet = 'monochrome.ctb' # 选择打印样式
    layout.PlotWithLineweights = False # 不打印线宽
    layout.CanonicalMediaName = 'A3' # 图纸大小这里选择A3
    layout.PlotRotation = 1 # 横向打印
    layout.CenterPlot = True # 居中打印
    layout.PlotWithPlotStyles = True # 依照样式打印
    layout.PlotHidden = False # 隐藏图纸空间对象
    print(layout.GetPlotStyleTableNames()[-1])
    layout.PlotType = 4
'''
    PlotType (enum类型):
    acDisplay: 按显示的内容打印.
    acExtents: 按当前选定空间范围内的所有内容打印.
    acLimits: 打印当前空间范围内的所有内容.
    acView: 打印由 ViewToPlot 属性命名的视图.
    acWindow: 打印由 SetWindowToPlot 方法指定的窗口中的所有内容.******
    acLayout: 打印位于指定纸张尺寸边缘的所有内容,原点从 0,0 坐标计算。
'''   
   
   


DEFAULT_START_POSITION =(3,3)

DRAWING_SIZE = (598,422)
DRAWING_INTEND = 700



class BackPrint(object):

    _instance = None
    def __new__(cls, *args, **kw):
      if cls._instance is None:
            cls._instance = super(BackPrint, cls).__new__(cls)
      return cls._instance
    def __init__(self,PositionX,PositionY):
      self.x = PositionX
      self.y = PositionY
    @staticmethod
    def APoint(x,y):
      """坐标点转化为浮点数"""
      # 需要两个点的坐标
      return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, (x,y))
    def run(self,Scale = 1.0):
      #self.PrinterStyleSetting()
      po1 = self.APoint(self.x * Scale - 1, self.y * Scale)
      po2 = self.APoint(self.x * Scale - 1 + DRAWING_SIZE, self.y * Scale + DRAWING_SIZE) # 左下点和右上点
      layout.SetWindowToPlot(po1, po2)
      PrinterStyleSetting()
      plot.PlotToDevice()      



class PrintTask:
    def __init__(self,maxPrintPositionArray,startPosition=(DEFAULT_START_POSITION,DEFAULT_START_POSITION)):
   
      self._PrinterStatus = 'Waiting'
      self.maxPrintPositionArray = maxPrintPositionArray # 此处要进行数据验证
      self.printBasePointArray = []
      self.taskPoint = startPosition
      self.PrintingTaskNumber = 0
      
      
      
    def runtask(self,):
      if not self.printBasePointArray:
            self.printBasePointArray = self.generalPrintBasePointArray(self.maxPrintPositionArray)
      
      for position in self.printBasePointArray:
            #printBasePointArray形式 : [(,),(,),]
            self.taskPoint = position
            current_task = BackPrint(*position)
            current_task.run()
            
            self.PrintingTaskNumber = len(win32print.EnumJobs(_HPRINTER,0,-1,1))
            #print('ing-> ',self.PrintingTaskNumber,'position',position)

            while self.PrintingTaskNumber >= 5:               
                time.sleep(1)
                self.PrintingTaskNumber = len(win32print.EnumJobs(_HPRINTER,0,-1,1))
            time.sleep(1)
            

    def ResumeTask(self,):
      pass
    def generalPrintBasePointArray(self,maxPrintPositionArray):
      printBasePointArray = []
      next_drawing_xORy_intend = DRAWING_INTEND
      
      current_x = int((self.taskPoint - 4)/ DRAWING_INTEND)*DRAWING_INTEND + DEFAULT_START_POSITION
      current_y = int((self.taskPoint - 4)/DRAWING_INTEND)*DRAWING_INTEND + DEFAULT_START_POSITION
      
      
      #print(current_x,current_y)
      
      for position in maxPrintPositionArray:
            while current_x <= position + DEFAULT_START_POSITION:
                printBasePointArray.append((current_x,current_y))
                current_x += next_drawing_xORy_intend
            current_x = DEFAULT_START_POSITION
            current_y += next_drawing_xORy_intend         
      return printBasePointArray #printBasePointArray形式 : [(,),(,),]
   
    def getTaskNumber(self,):
      TaskNumber = self.PrintingTaskNumber
      try:
            TaskNumber = len(win32print.EnumJobs(_HPRINTER,0,-1,1))
            return TaskNumber
      except Exception as e:
            return TaskNumber


if __name__ == '__main__':
    task = PrintTask(,(6194,4))
    task.runtask()

q28066 发表于 2024-4-8 09:20

import win32com.client
import win32print
import pythoncom

class AutoCADPrint:
    def __init__(self):
      self.acad = None
      self.acaddoc = None
      self.layout = None
      self.plot = None
      self.hprinter = None

    def connect_autocad(self):
      """连接到 AutoCAD 应用程序并获取相关对象"""
      try:
            self.acad = win32com.client.Dispatch("AutoCAD.Application.23")
            self.acaddoc = self.acad.ActiveDocument
            self.layout = self.acaddoc.layouts.item('Model')
            self.plot = self.acaddoc.Plot
      except Exception as e:
            print(f"Error connecting to AutoCAD: {e}")

    def connect_printer(self):
      """连接默认打印机"""
      try:
            self.hprinter = win32print.OpenPrinter(win32print.GetDefaultPrinter())
      except Exception as e:
            print(f"Error connecting to printer: {e}")

    def set_printer_style(self):
      """设置打印机的打印样式等参数"""
      try:
            self.layout.ConfigName = 'RICOH MP C2011'
            self.layout.StyleSheet = 'monochrome.ctb'
            self.layout.CanonicalMediaName = 'A3'
            self.layout.PlotRotation = 1
            self.layout.CenterPlot = True
            self.layout.PlotWithPlotStyles = True
            self.layout.PlotHidden = False
            self.layout.PlotType = 4
      except Exception as e:
            print(f"Error setting printer style: {e}")

    def plot_to_device(self, x, y, scale=1.0):
      """将指定区域的图形打印到设备上"""
      try:
            po1 = self.acaddoc.Utility.Point(x * scale - 1, y * scale)
            po2 = self.acaddoc.Utility.Point(x * scale - 1 + 598, y * scale + 422)# Assuming DRAWING_SIZE is (598, 422)
            self.layout.SetWindowToPlot(po1, po2)
            self.plot.PlotToDevice()
      except Exception as e:
            print(f"Error plotting: {e}")

    def close_connections(self):
      """关闭连接,释放资源"""
      if self.hprinter:
            win32print.ClosePrinter(self.hprinter)
      if self.acad:
            self.acad.Quit()

def run_print_tasks(tasks):
    """执行打印任务"""
    autocad_printer = AutoCADPrint()
    autocad_printer.connect_autocad()
    autocad_printer.connect_printer()
    autocad_printer.set_printer_style()

    for task in tasks:
      autocad_printer.plot_to_device(*task)

    autocad_printer.close_connections()

if __name__ == '__main__':
    # 示例打印任务列表,格式为 (x坐标, y坐标)
    tasks = [(6194, 4), (6194, 100), (10000, 10000)]
    run_print_tasks(tasks)

wjbg2022 发表于 2024-4-8 08:07

楼主厉害,但是插件会更加方便些,有的插件可以识别图块为打印框,有的可以判断最大的矩形为打印框,有的可以自动判断纸张大小,楼主请继续加油!

ytdzjun 发表于 2024-4-8 06:00

666666牛叉~沙发占定~

xiaosha521 发表于 2024-4-8 07:17

先抢占一个沙发,楼主的技术{:1_921:}

龍謹 发表于 2024-4-8 08:04

可实现多图打印到文件吗?

Corgibro 发表于 2024-4-8 08:10

厉害,这下打印图纸又方便快速了一些

1e3e 发表于 2024-4-8 08:14

晕,这就厉害了哈

shishiaiyin 发表于 2024-4-8 08:25


厉害厉害,能人辈出

tnancy2kk 发表于 2024-4-8 08:29

厉害呀,学习一下代码

lzspain 发表于 2024-4-8 08:50

看了一下打印设置部分,我还是选择用插件
页: [1] 2 3 4
查看完整版本: (超级干货)python打印cad图纸