当前位置:首页>python>《彻底告别逐张打印!用Python打造AutoCAD批量打印工具,效率无敌猛!》

《彻底告别逐张打印!用Python打造AutoCAD批量打印工具,效率无敌猛!》

  • 2026-10-11 06:14:09
《彻底告别逐张打印!用Python打造AutoCAD批量打印工具,效率无敌猛!》

“带你横跨办公自动化的数据江海”

@摸鱼

前言

关于摸鱼

(

ABOUT MOYU

)

闻道有先后,术业有专攻。

各位大佬朋友们好!

~我依旧是你们的老朋友摸鱼~

在职场摸爬滚打的这十多年里,我用Python悄悄干了不少“正事”——不知不觉攒下了一整套办公自动化的实用项目技巧。去年10月初创立了公众号 「码海听潮」 ,初衷很简单:把重复的劳动交给代码,把摸鱼的时间留给生活。

目前已经吭哧吭哧更新了140多篇原创文章,每一篇都是实操干货,不讲虚的,只聊怎么用代码真正解放双手,帮大家早点下班、准点摸鱼

好了,多了不说,少了不唠,今天给大佬们分享一款本人原创的【AutoCAD批量打印工具 - BatchPlot】。这款工具相比手动逐张框选打印,效率提升数十倍,这是一个非常实用的CAD自动化工具,特别适合需要批量出图、多图框打印的场景。支持图块、理正图框、图层三种图框识别模式,批量打印、生成布局、打印预览三种输出方式一键切换,差异内容自动红字黄底标注,一目了然!图框自动排序、自动旋转、自动适配比例,真正做到解放双手,让批量打印变得如此简单!

《该办公工具成品展示:》

《该办公工具核心功能亮点:》

01

 亮点1:智能化图框识别⭐

        • 三种识别模式:支持图块识别、理正图框识别、图层识别,适配不同图纸标准

        • 一键搜索:点击"选择图框"自动扫描当前图纸中的所有图框

        • 高亮显示:选中图框可在AutoCAD中高亮标记,直观确认选择范围

        02

         亮点2:灵活的打印设置🎨

            • 多种输出方式:支持直接打印到设备、打印到PLT文件、预览三种模式

            • 智能比例适配:自动计算最佳打印比例,支持"适合纸张"、"自动"、"自定义"多种比例选项

            • 自动旋转与排序:图框自动旋转适配纸张方向,支持从左到右/从上到下排序,可反向输出

            • 批量打印份数:支持设置打印份数,一次性完成多份输出

            03

            亮点3:布局批量生成⚙️

            • 一键生成布局:将多个图框自动转换为独立的布局选项卡

            • 自定义布局前缀:支持设置布局名称前缀,便于管理

            • 自动清理:可自动删除已有同前缀布局,避免重复

            《该办公工具代码展示:》

            下面,我就用python代码让各位大佬见识一下,什么叫"传统文化"遇上"赛博效率"

            """BatchPlot - AutoCAD批量打印工具 """import sysfrom typing import List, Optionalfrom dataclasses import dataclass, fieldfrom PyQt6.QtWidgets import (    QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,    QGroupBox, QLabel, QPushButton, QComboBox, QSpinBox, QCheckBox,    QRadioButton, QButtonGroup, QTextEdit, QFileDialog,    QMessageBox, QLineEdit, QListWidget, QListWidgetItem,    QSplitter, QGridLayout, QProgressBar, QScrollArea, QFrame)from PyQt6.QtCore import Qtfrom PyQt6.QtGui import QFont, QTextCursor@dataclassclass PlotSettings:    """打印设置"""    frame_mode: str = "BlockRadio"    block_name: str = ""    layer_name: str = ""    output_mode: str = "PlotRadio"    plot_scale: str = "Auto"    copies: int = 1    auto_rotate: bool = True    upside_down: bool = False    layout_prefix: str = "BP_"    plot_file_prefix: str = "PLOT_"    plot_file_folder: str = ""    delete_plot_file: bool = False    delete_layout: bool = False    ms_line_scale: bool = True    reverse_order: bool = False    selected_frames: List = field(default_factory=list)class MainWindow(QMainWindow):    """主窗口 - 纯界面设计"""    def __init__(self):        super().__init__()        self.settings = PlotSettings()        self.frames = []        self.init_ui()        self.setup_connections()    def init_ui(self):        """初始化UI"""        self.setWindowTitle("BatchPlot - AutoCAD批量打印工具")        self.setMinimumSize(900, 650)        font = QFont("Microsoft YaHei", 9)        self.setFont(font)        self.setStyleSheet("""            QMainWindow { background-color: #f0f2f5; }            QGroupBox {                font-weight: bold;                border: 1px solid #d0d7de;                border-radius: 6px;                margin-top: 8px;                padding-top: 8px;                background-color: white;                font-size: 11px;            }            QGroupBox::title {                subcontrol-origin: margin;                left: 10px;                padding: 0 6px;                color: #24292f;            }            QPushButton {                background-color: #2d8cf0;                color: white;                border: none;                border-radius: 4px;                padding: 5px 12px;                font-weight: bold;                font-size: 11px;            }            QPushButton:hover { background-color: #1a7ad4; }            QPushButton:pressed { background-color: #1664b8; }            QPushButton:disabled {                background-color: #b0b8c4;                color: #8a94a0;            }            QPushButton#dangerButton { background-color: #ed4014; }            QPushButton#dangerButton:hover { background-color: #d4390f; }            QPushButton#successButton { background-color: #19be6b; }            QPushButton#successButton:hover { background-color: #16a85a; }            QPushButton#warningButton { background-color: #f7a11a; }            QPushButton#warningButton:hover { background-color: #e0910e; }            QPushButton#connectButton { background-color: #8b5cf6; }            QPushButton#connectButton:hover { background-color: #7c3aed; }            QLineEdit, QComboBox, QSpinBox {                border: 1px solid #d0d7de;                border-radius: 4px;                padding: 4px 8px;                background-color: white;                font-size: 11px;            }            QLineEdit:focus, QComboBox:focus, QSpinBox:focus {                border-color: #2d8cf0;                outline: none;            }            QTextEdit {                border: 1px solid #d0d7de;                border-radius: 4px;                background-color: #1a1a2e;                color: #e0e0e0;                font-family: Consolas, "Courier New", monospace;                font-size: 10px;            }            QListWidget {                border: 1px solid #d0d7de;                border-radius: 4px;                background-color: white;                font-size: 10px;            }            QListWidget::item:selected {                background-color: #2d8cf0;                color: white;            }            QListWidget::item:hover { background-color: #e8ecf1; }            QCheckBox { spacing: 6px; font-size: 11px; }            QRadioButton { spacing: 6px; font-size: 11px; }            QProgressBar {                border: 1px solid #d0d7de;                border-radius: 3px;                text-align: center;                height: 18px;                background-color: white;                font-weight: bold;                font-size: 10px;            }            QProgressBar::chunk {                background: qlineargradient(x1:0, y1:0, x2:1, y2:0,                    stop:0 #19be6b, stop:1 #2d8cf0);                border-radius: 3px;            }            QStatusBar {                background-color: #24292f;                color: #e8ecf1;                font-size: 11px;            }            QLabel { font-size: 11px; }            QScrollArea {                border: none;                background-color: transparent;            }            QScrollBar:vertical {                border: none;                background: #f0f2f5;                width: 10px;                border-radius: 5px;            }            QScrollBar::handle:vertical {                background: #c1c7cd;                border-radius: 5px;                min-height: 20px;            }            QScrollBar::handle:vertical:hover { background: #a0a8b0; }            QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {                border: none;                background: none;            }        """)        central_widget = QWidget()        self.setCentralWidget(central_widget)        main_layout = QVBoxLayout(central_widget)        main_layout.setSpacing(6)        main_layout.setContentsMargins(8, 8, 8, 8)        splitter = QSplitter(Qt.Orientation.Horizontal)        main_layout.addWidget(splitter, 1)        left_panel = self.create_left_panel()        splitter.addWidget(left_panel)        right_panel = self.create_right_panel()        splitter.addWidget(right_panel)        splitter.setSizes([450, 450])        # 状态栏        self.status_bar = self.statusBar()        self.status_label = QLabel("就绪")        self.status_bar.addWidget(self.status_label)        self.progress_bar = QProgressBar()        self.progress_bar.setMaximumWidth(160)        self.progress_bar.setVisible(False)        self.status_bar.addPermanentWidget(self.progress_bar)        self.connection_indicator = QLabel("● 未连接")        self.connection_indicator.setStyleSheet("color: #ed4014; font-weight: bold; font-size: 10px;")        self.status_bar.addPermanentWidget(self.connection_indicator)    def create_left_panel(self) -> QWidget:        """创建左侧设置面板"""        panel = QWidget()        layout = QVBoxLayout(panel)        layout.setSpacing(0)        layout.setContentsMargins(0, 0, 0, 0)        scroll_area = QScrollArea()        scroll_area.setWidgetResizable(True)        scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)        scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)        content_widget = QWidget()        content_layout = QVBoxLayout(content_widget)        content_layout.setSpacing(5)        content_layout.setContentsMargins(0, 0, 8, 0)        # ===== 图框选择 =====        frame_group = QGroupBox("📋 图框选择")        frame_layout = QVBoxLayout(frame_group)        frame_layout.setSpacing(5)        # 连接按钮        connect_layout = QHBoxLayout()        self.btn_connect = QPushButton("🔗 连接 AutoCAD")        self.btn_connect.setObjectName("connectButton")        self.btn_connect.setMinimumHeight(30)        connect_layout.addWidget(self.btn_connect)        self.lbl_connect_status = QLabel("⚪ 未连接")        self.lbl_connect_status.setStyleSheet("color: #ed4014; font-weight: bold; font-size: 11px;")        connect_layout.addWidget(self.lbl_connect_status)        connect_layout.addStretch()        frame_layout.addLayout(connect_layout)        # 分隔线        line = QFrame()        line.setFrameShape(QFrame.Shape.HLine)        line.setFrameShadow(QFrame.Shadow.Sunken)        line.setStyleSheet("background-color: #d0d7de; max-height: 1px;")        frame_layout.addWidget(line)        # 模式选择        mode_layout = QHBoxLayout()        self.frame_mode_group = QButtonGroup()        self.radio_block = QRadioButton("图块")        self.radio_lz = QRadioButton("理正图框")        self.radio_layer = QRadioButton("图层")        self.radio_block.setChecked(True)        self.frame_mode_group.addButton(self.radio_block, 0)        self.frame_mode_group.addButton(self.radio_lz, 1)        self.frame_mode_group.addButton(self.radio_layer, 2)        mode_layout.addWidget(self.radio_block)        mode_layout.addWidget(self.radio_lz)        mode_layout.addWidget(self.radio_layer)        mode_layout.addStretch()        frame_layout.addLayout(mode_layout)        # 图块名称        block_layout = QHBoxLayout()        block_layout.addWidget(QLabel("图块名称:"))        self.cmb_block = QComboBox()        self.cmb_block.setEditable(True)        block_layout.addWidget(self.cmb_block, 1)        frame_layout.addLayout(block_layout)        # 图层名称        layer_layout = QHBoxLayout()        layer_layout.addWidget(QLabel("图层名称:"))        self.cmb_layer = QComboBox()        self.cmb_layer.setEditable(True)        self.cmb_layer.setEnabled(False)        layer_layout.addWidget(self.cmb_layer, 1)        frame_layout.addLayout(layer_layout)        # 操作按钮        select_layout = QHBoxLayout()        self.btn_select = QPushButton("🔍 选择图框")        self.btn_select.setObjectName("successButton")        select_layout.addWidget(self.btn_select)        self.btn_highlight = QPushButton("✨ 高亮显示")        select_layout.addWidget(self.btn_highlight)        select_layout.addStretch()        frame_layout.addLayout(select_layout)        # 图框数量        info_layout = QHBoxLayout()        info_layout.addWidget(QLabel("已选图框:"))        self.lbl_frame_count = QLabel("0 个")        self.lbl_frame_count.setStyleSheet("font-weight: bold; color: #2d8cf0; font-size: 12px;")        info_layout.addWidget(self.lbl_frame_count)        info_layout.addStretch()        frame_layout.addLayout(info_layout)        content_layout.addWidget(frame_group)        # ===== 打印设置 =====        plot_group = QGroupBox("🖨️ 打印设置")        plot_layout = QVBoxLayout(plot_group)        plot_layout.setSpacing(5)        # 输出方式        output_layout = QHBoxLayout()        output_layout.addWidget(QLabel("输出方式:"))        self.cmb_output = QComboBox()        self.cmb_output.addItems(["打印到设备", "打印到文件 (PLT)", "预览"])        output_layout.addWidget(self.cmb_output, 1)        plot_layout.addLayout(output_layout)        # 打印比例        scale_layout = QHBoxLayout()        scale_layout.addWidget(QLabel("打印比例:"))        self.cmb_scale = QComboBox()        self.cmb_scale.addItems(["自动", "适合纸张", "1:50", "1:75", "1:100", "1:150", "1:200", "自定义"])        scale_layout.addWidget(self.cmb_scale, 1)        plot_layout.addLayout(scale_layout)        # 自定义比例        custom_layout = QHBoxLayout()        custom_layout.addWidget(QLabel("自定义 (1:"))        self.spin_scale = QSpinBox()        self.spin_scale.setRange(1, 10000)        self.spin_scale.setValue(100)        self.spin_scale.setEnabled(False)        custom_layout.addWidget(self.spin_scale)        custom_layout.addWidget(QLabel(")"))        custom_layout.addStretch()        plot_layout.addLayout(custom_layout)        # 打印份数        copies_layout = QHBoxLayout()        copies_layout.addWidget(QLabel("打印份数:"))        self.spin_copies = QSpinBox()        self.spin_copies.setRange(1, 999)        self.spin_copies.setValue(1)        copies_layout.addWidget(self.spin_copies)        copies_layout.addStretch()        plot_layout.addLayout(copies_layout)        # 选项        options_layout = QGridLayout()        options_layout.setSpacing(6)        self.chk_auto_rotate = QCheckBox("自动旋转")        self.chk_auto_rotate.setChecked(True)        options_layout.addWidget(self.chk_auto_rotate, 0, 0)        self.chk_upside_down = QCheckBox("上下颠倒")        options_layout.addWidget(self.chk_upside_down, 0, 1)        self.chk_reverse = QCheckBox("反向顺序")        options_layout.addWidget(self.chk_reverse, 1, 0)        self.chk_center = QCheckBox("居中打印")        self.chk_center.setChecked(True)        options_layout.addWidget(self.chk_center, 1, 1)        plot_layout.addLayout(options_layout)        content_layout.addWidget(plot_group)        # ===== 文件设置 =====        file_group = QGroupBox("📁 文件设置")        file_layout = QVBoxLayout(file_group)        file_layout.setSpacing(5)        # 文件名前缀        file_prefix_layout = QHBoxLayout()        file_prefix_layout.addWidget(QLabel("文件名前缀:"))        self.edit_prefix = QLineEdit("PLOT_")        file_prefix_layout.addWidget(self.edit_prefix, 1)        file_layout.addLayout(file_prefix_layout)        # 保存路径        file_folder_layout = QHBoxLayout()        file_folder_layout.addWidget(QLabel("保存路径:"))        self.edit_folder = QLineEdit()        self.edit_folder.setReadOnly(True)        file_folder_layout.addWidget(self.edit_folder, 1)        self.btn_folder = QPushButton("📁")        self.btn_folder.setFixedWidth(28)        self.btn_folder.setStyleSheet("background-color: #e8ecf1; color: #24292f; padding: 2px;")        file_folder_layout.addWidget(self.btn_folder)        file_layout.addLayout(file_folder_layout)        self.chk_delete_plot = QCheckBox("删除已有打印文件")        file_layout.addWidget(self.chk_delete_plot)        content_layout.addWidget(file_group)        # ===== 布局设置 =====        layout_group = QGroupBox("📐 布局设置")        layout_layout = QVBoxLayout(layout_group)        layout_layout.setSpacing(5)        layout_prefix_layout = QHBoxLayout()        layout_prefix_layout.addWidget(QLabel("布局前缀:"))        self.edit_layout_prefix = QLineEdit("BP_")        layout_prefix_layout.addWidget(self.edit_layout_prefix, 1)        layout_layout.addLayout(layout_prefix_layout)        self.chk_delete_layout = QCheckBox("删除已有同前缀布局")        layout_layout.addWidget(self.chk_delete_layout)        self.chk_ms_line_scale = QCheckBox("模型空间线型比例")        self.chk_ms_line_scale.setChecked(True)        layout_layout.addWidget(self.chk_ms_line_scale)        content_layout.addWidget(layout_group)        # ===== 操作按钮 =====        action_group = QGroupBox("🚀 操作")        action_layout = QGridLayout(action_group)        action_layout.setSpacing(6)        self.btn_plot = QPushButton("🖨️ 批量打印")        self.btn_plot.setObjectName("successButton")        self.btn_plot.setMinimumHeight(36)        action_layout.addWidget(self.btn_plot, 0, 0)        self.btn_layout = QPushButton("📐 生成布局")        self.btn_layout.setObjectName("warningButton")        self.btn_layout.setMinimumHeight(36)        action_layout.addWidget(self.btn_layout, 0, 1)        self.btn_preview = QPushButton("👁️ 预览")        self.btn_preview.setMinimumHeight(32)        action_layout.addWidget(self.btn_preview, 1, 0)        self.btn_cancel = QPushButton("⏹ 取消")        self.btn_cancel.setObjectName("dangerButton")        self.btn_cancel.setMinimumHeight(32)        self.btn_cancel.setEnabled(False)        action_layout.addWidget(self.btn_cancel, 1, 1)        content_layout.addWidget(action_group)        content_layout.addStretch()        scroll_area.setWidget(content_widget)        layout.addWidget(scroll_area)        return panel    def create_right_panel(self) -> QWidget:        """创建右侧面板"""        panel = QWidget()        layout = QVBoxLayout(panel)        layout.setSpacing(5)        layout.setContentsMargins(0, 0, 0, 0)        # 图框列表        list_group = QGroupBox("📋 图框列表")        list_layout = QVBoxLayout(list_group)        list_layout.setSpacing(4)        self.frame_list = QListWidget()        list_layout.addWidget(self.frame_list)        layout.addWidget(list_group, 1)        # 日志        log_group = QGroupBox("📝 日志")        log_layout = QVBoxLayout(log_group)        log_layout.setSpacing(4)        self.log_text = QTextEdit()        self.log_text.setReadOnly(True)        log_layout.addWidget(self.log_text)        log_control = QHBoxLayout()        log_control.setSpacing(6)        self.btn_clear_log = QPushButton("清空日志")        self.btn_clear_log.setStyleSheet("background-color: #e8ecf1; color: #24292f; padding: 3px 10px; font-size: 10px;")        log_control.addWidget(self.btn_clear_log)        log_control.addStretch()        self.chk_auto_scroll = QCheckBox("自动滚动")        self.chk_auto_scroll.setChecked(True)        self.chk_auto_scroll.setStyleSheet("font-size: 10px;")        log_control.addWidget(self.chk_auto_scroll)        log_layout.addLayout(log_control)        layout.addWidget(log_group, 1)        return panel    def setup_connections(self):        """设置信号连接"""        self.frame_mode_group.buttonClicked.connect(self.on_frame_mode_changed)        self.btn_connect.clicked.connect(self.on_connect_clicked)        self.btn_select.clicked.connect(self.on_select_clicked)        self.btn_highlight.clicked.connect(self.on_highlight_clicked)        self.btn_plot.clicked.connect(self.on_plot_clicked)        self.btn_layout.clicked.connect(self.on_layout_clicked)        self.btn_preview.clicked.connect(self.on_preview_clicked)        self.btn_cancel.clicked.connect(self.on_cancel_clicked)        self.btn_folder.clicked.connect(self.on_folder_clicked)        self.btn_clear_log.clicked.connect(self.on_clear_log_clicked)        self.cmb_scale.currentIndexChanged.connect(self.on_scale_changed)        self.cmb_output.currentIndexChanged.connect(self.on_output_changed)    # ===== 界面事件处理方法 =====    def on_frame_mode_changed(self, button):        """图框模式切换"""        if button == self.radio_block:            self.settings.frame_mode = "BlockRadio"            self.cmb_block.setEnabled(True)            self.cmb_layer.setEnabled(False)        elif button == self.radio_lz:            self.settings.frame_mode = "LzFrameRadio"            self.cmb_block.setEnabled(False)            self.cmb_layer.setEnabled(False)        elif button == self.radio_layer:            self.settings.frame_mode = "LayerRadio"            self.cmb_block.setEnabled(False)            self.cmb_layer.setEnabled(True)    def on_scale_changed(self, index):        """比例选择变化"""        text = self.cmb_scale.currentText()        self.spin_scale.setEnabled(text == "自定义")        if text == "自动":            self.settings.plot_scale = "Auto"        elif text == "适合纸张":            self.settings.plot_scale = "ScaleToFit"        elif text == "自定义":            self.settings.plot_scale = str(self.spin_scale.value())        else:            try:                scale_text = text.replace("1:", "")                self.settings.plot_scale = scale_text            except:                self.settings.plot_scale = "Auto"    def on_output_changed(self, index):        """输出方式变化"""        mode = self.cmb_output.currentText()        if mode == "打印到设备":            self.settings.output_mode = "PlotRadio"            self.spin_copies.setEnabled(True)        elif mode == "打印到文件 (PLT)":            self.settings.output_mode = "PlotFileRadio"            self.spin_copies.setEnabled(False)        elif mode == "预览":            self.settings.output_mode = "PreviewRadio"            self.spin_copies.setEnabled(False)    def on_connect_clicked(self):        """连接按钮点击"""        self.log("🔄 正在尝试连接 AutoCAD...")        self.btn_connect.setEnabled(False)        self.btn_connect.setText("⏳ 连接中...")        # 模拟连接成功        from PyQt6.QtCore import QTimer        QTimer.singleShot(1000, self._simulate_connect_success)    def _simulate_connect_success(self):        """模拟连接成功"""        self.lbl_connect_status.setText("🟢 已连接")        self.lbl_connect_status.setStyleSheet("color: #19be6b; font-weight: bold; font-size: 11px;")        self.connection_indicator.setText("● 已连接")        self.connection_indicator.setStyleSheet("color: #19be6b; font-weight: bold; font-size: 10px;")        self.btn_connect.setText("🔗 已连接")        self.btn_connect.setStyleSheet("""            QPushButton#connectButton {                background-color: #19be6b;            }            QPushButton#connectButton:hover {                background-color: #16a85a;            }        """)        self.btn_connect.setEnabled(True)        self.log("✅ 成功连接到 AutoCAD")        # 模拟加载图块和图层        self.cmb_block.addItems(["图框A1", "图框A2", "图框A3", "标准图框"])        self.cmb_layer.addItems(["图层1", "图层2", "图层3"])    def on_select_clicked(self):        """选择图框点击"""        self.log("🔍 正在搜索图框...")        self.update_settings()        # 模拟找到图框        self.frames = [            {"ll": (0, 0), "ur": (100, 70), "landscape": True},            {"ll": (120, 0), "ur": (220, 70), "landscape": True},            {"ll": (240, 0), "ur": (340, 70), "landscape": True},        ]        self.frame_list.clear()        for i, bbox in enumerate(self.frames, 1):            orientation = "横向" if bbox["landscape"] else "纵向"            item = QListWidgetItem(                f"{i:3d}.  ({bbox['ll'][0]:.1f}, {bbox['ll'][1]:.1f}) → "                f"({bbox['ur'][0]:.1f}, {bbox['ur'][1]:.1f})  [{orientation}]"            )            self.frame_list.addItem(item)        self.lbl_frame_count.setText(f"{len(self.frames)} 个")        self.log(f"✅ 找到 {len(self.frames)} 个图框")    def on_highlight_clicked(self):        """高亮显示点击"""        if not self.frames:            QMessageBox.information(self, "提示", "请先选择图框")            return        self.log("✨ 高亮显示图框...")        self.log("✅ 高亮显示完成")    def on_plot_clicked(self):        """批量打印点击"""        if not self.frames:            QMessageBox.information(self, "提示", "请先选择图框")            return        self.update_settings()        self.log("🖨️ 开始批量打印...")        self._simulate_progress("打印")    def on_layout_clicked(self):        """生成布局点击"""        if not self.frames:            QMessageBox.information(self, "提示", "请先选择图框")            return        self.update_settings()        self.log("📐 开始生成布局...")        self._simulate_progress("布局")    def on_preview_clicked(self):        """预览点击"""        if not self.frames:            QMessageBox.information(self, "提示", "请先选择图框")            return        self.update_settings()        self.log("👁️ 开始预览...")        self.log("✅ 预览完成")        QMessageBox.information(self, "预览", "预览功能已触发")    def on_cancel_clicked(self):        """取消点击"""        self.log("⏹ 正在取消操作...")        self.btn_cancel.setEnabled(False)        self.set_buttons_enabled(True)        self.progress_bar.setVisible(False)    def on_folder_clicked(self):        """选择文件夹点击"""        folder = QFileDialog.getExistingDirectory(            self, "选择保存路径", self.edit_folder.text() or ""        )        if folder:            self.edit_folder.setText(folder)            self.settings.plot_file_folder = folder            self.log(f"📁 选择保存路径: {folder}")    def on_clear_log_clicked(self):        """清空日志"""        self.log_text.clear()    def _simulate_progress(self, action: str):        """模拟进度"""        self.set_buttons_enabled(False)        self.progress_bar.setVisible(True)        self.progress_bar.setValue(0)        from PyQt6.QtCore import QTimer        self._progress_value = 0        def update_progress():            self._progress_value += 10            self.progress_bar.setValue(self._progress_value)            self.status_label.setText(f"{action}中... {self._progress_value}%")            self.log(f"{action}中... {self._progress_value}%")            if self._progress_value >= 100:                self.progress_bar.setVisible(False)                self.set_buttons_enabled(True)                self.status_label.setText(f"✅ {action}完成")                self.log(f"✅ {action}完成")                QMessageBox.information(self, "完成", f"{action}操作完成")            else:                QTimer.singleShot(300, update_progress)        QTimer.singleShot(300, update_progress)    def update_settings(self):        """更新设置"""        if self.radio_block.isChecked():            self.settings.frame_mode = "BlockRadio"            self.settings.block_name = self.cmb_block.currentText()        elif self.radio_lz.isChecked():            self.settings.frame_mode = "LzFrameRadio"        elif self.radio_layer.isChecked():            self.settings.frame_mode = "LayerRadio"            self.settings.layer_name = self.cmb_layer.currentText()        output_text = self.cmb_output.currentText()        if output_text == "打印到设备":            self.settings.output_mode = "PlotRadio"        elif output_text == "打印到文件 (PLT)":            self.settings.output_mode = "PlotFileRadio"        elif output_text == "预览":            self.settings.output_mode = "PreviewRadio"        scale_text = self.cmb_scale.currentText()        if scale_text == "自动":            self.settings.plot_scale = "Auto"        elif scale_text == "适合纸张":            self.settings.plot_scale = "ScaleToFit"        elif scale_text == "自定义":            self.settings.plot_scale = str(self.spin_scale.value())        else:            try:                scale_text = scale_text.replace("1:", "")                self.settings.plot_scale = scale_text            except:                self.settings.plot_scale = "Auto"        self.settings.copies = self.spin_copies.value()        self.settings.auto_rotate = self.chk_auto_rotate.isChecked()        self.settings.upside_down = self.chk_upside_down.isChecked()        self.settings.reverse_order = self.chk_reverse.isChecked()        self.settings.ms_line_scale = self.chk_ms_line_scale.isChecked()        self.settings.layout_prefix = self.edit_layout_prefix.text()        self.settings.plot_file_prefix = self.edit_prefix.text()        self.settings.plot_file_folder = self.edit_folder.text()        self.settings.delete_plot_file = self.chk_delete_plot.isChecked()        self.settings.delete_layout = self.chk_delete_layout.isChecked()    def set_buttons_enabled(self, enabled: bool):        """设置按钮启用状态"""        self.btn_connect.setEnabled(enabled)        self.btn_select.setEnabled(enabled)        self.btn_highlight.setEnabled(enabled)        self.btn_plot.setEnabled(enabled)        self.btn_layout.setEnabled(enabled)        self.btn_preview.setEnabled(enabled)        self.btn_cancel.setEnabled(not enabled)    def log(self, message: str):        """添加日志"""        self.log_text.append(message)        if self.chk_auto_scroll.isChecked():            cursor = self.log_text.textCursor()            cursor.movePosition(QTextCursor.MoveOperation.End)            self.log_text.setTextCursor(cursor)def main():    app = QApplication(sys.argv)    app.setApplicationName("BatchPlot")    window = MainWindow()    window.show()    sys.exit(app.exec())if __name__ == "__main__":    main()

            这款AutoCAD批量打印工具,可自动完成原需手动逐张框选、反复调整设置、一张张打印一整天的图纸输出工作。从最初打开图纸来回缩放查找图框、肉眼逐张框选打印区域、手动调整打印比例、反复设置输出路径的繁琐与崩溃,到用自动化工具实现一键搜索图框、批量自动打印、布局智能生成、比例自动适配的畅快,工作效率获得指数级提升,终于解放了双手和时间!

            大佬们也可以举一反三,参照上面的代码思路根据自己工作中的实际情况来具体问题具体分析,实现自己定制化的需求。

            《该办公工具的应用场景:》

              人群
              使用场景

              建筑设计师

              施工图批量打印、布局生成

              结构工程师

              结构图纸批量输

              给排水/暖通/电气设计师

              专业图纸批量打印

              项目负责人

              全套图纸集中打印、分发

              档案管理员

              图纸数字化归档整理

              施工技术人员

              现场施工图批量打印

              结语

              当Python遇见办公,牛马打工人终于笑出了猪叫声

              【职场人必看】每天早上一睁眼,想到又要面对:

              1.📊 堆积如山的Excel表格

              2.📑 机械重复的复制粘贴

              3.✍️ 永远改不完的各类文档

              4.诸如此类的更多........

              是不是连Ctrl+Alt+Delete的心都有了?

              别慌!别急,摸鱼这位“职场外挂”已经带着Python代码来拯救你了!

              另外本篇文章的代码和exe已经上传到nas私有云盘,需要的大佬私信进进群获取下载链接~

              感谢各位大佬观看,还望各位大佬抬抬贵手一键三连,多多关注点赞转发评论,大佬们的支持才是摸鱼孜孜不倦更新原创干货的动力!

              最新文章

              随机文章