最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用Python設置Word文檔中表格的格式的方法

 更新時間:2025年12月01日 09:25:13   作者:溫輕舟  
本文介紹了使用PyQt5和python-docx庫開發(fā)的圖形化應用程序,用于對Word文檔中的表格進行格式化設置,該應用程序提供文件操作、基本格式設置、條件格式設置、邊框和背景設置等功能,支持跨平臺運行,并提供詳細的錯誤處理和用戶反饋,需要的朋友可以參考下

一:效果展示:

本項目是基于PyQt5python-docx庫開發(fā)的圖形化應用程序,用于對Word文檔中的表格進行格式化設置。用戶可以通過直觀的界面調(diào)整表格的各種格式屬性,包括基本格式、條件格式、邊框和背景等

二:功能描述:

1. 核心功能

(1)文件操作模塊

  • 打開文件:允許用戶選擇并加載.docx文件,自動檢測文件中的第一個表格
  • 保存文件:將修改后的文檔保存為新文件(在原文件名后添加"-整理"后綴)
  • 文件狀態(tài)顯示:在界面頂部顯示當前打開的文件名

(2)基本格式設置

  1. 行高設置:
  • 默認行高:設置表格數(shù)據(jù)行的默認高度(單位:磅)
  • 表頭行數(shù):指定表格中表頭的行數(shù)(表頭行高固定為1cm)
  1. 對齊方式:
  • 水平對齊:居中/左對齊/右對齊
  • 垂直對齊:居中/頂部/底部
  1. 字體設置:
  • 字體名稱:下拉選擇常見中英文字體(包括系統(tǒng)默認字體)
  • 字體大小:8-72磅可調(diào)
  • 字體樣式:加粗/斜體復選框
  • 字體顏色:通過顏色選擇器設置

(3)條件格式設置

  1. 條件1設置:
  • 應用列:指定要應用條件的列號
  • 操作符:>=, >, =, <=, <, <>
  • 比較值:數(shù)值比較
  • 背景色:滿足條件時單元格的背景顏色
  1. 條件2設置:
  • 應用列:指定要應用條件的列號
  • 操作符:>=, >, =, <=, <, <>
  • 比較值:支持數(shù)值和文本比較
  • 背景色:滿足條件時單元格的背景顏色

(4)邊框和背景設置

  1. 邊框設置:
  • 邊框樣式:單線/虛線/點線/雙線/無線條
  • 邊框?qū)挾龋?-24磅可調(diào)
  • 邊框顏色:通過顏色選擇器設置
  • 應用邊框:可單獨選擇應用左邊框、上邊框、右邊框或下邊框
  1. 背景設置:
  • 背景顏色:通過顏色選擇器設置
  • 應用范圍:所有單元格/表頭/數(shù)據(jù)行/特定列
  • 列選擇:當選擇 “特定列” 時指定列號

2. 功能實現(xiàn)細節(jié)

(1)表格格式化核心類 - DocxTableEditor

  • set_cell_border:使用python-docx的底層XML操作設置單元格邊框樣式
  • set_background_color:通過XML操作設置單元格背景顏色
  • set_cell_font:設置單元格內(nèi)文本的字體屬性(名稱、大小、加粗、斜體、顏色)

(2)條件格式實現(xiàn)

  • 支持數(shù)值比較(條件1)和文本比較(條件2)
  • 只有當用戶選擇了背景顏色時才應用條件格式
  • 自動跳過表頭行(根據(jù)表頭行數(shù)設置)

(3)用戶界面特性

  • 使用選項卡組織不同功能模塊
  • 顏色選擇后實時預覽(標簽顯示顏色并設置背景色)
  • 智能字體選擇(包含常見中英文字體并嘗試檢測系統(tǒng)默認字體)
  • 詳細的錯誤處理和用戶反饋(通過QMessageBox

3. 使用流程

(1)打開文檔:

點擊"打開文件"按鈕選擇包含表格的Word文檔

(2)設置格式

  • 在"基本格式"選項卡中設置表格的基礎樣式
  • 在"條件格式"選項卡中設置基于單元格值的條件格式
  • 在"邊框和背景"選項卡中設置邊框樣式和單元格背景

(3)保存文檔

點擊"保存文件"按鈕將修改保存為新文檔

4. 技術特點

  1. 跨平臺性:基于PyQt5開發(fā),可在WindowsmacOSLinux上運行
  2. 非破壞性編輯:保留原始文檔內(nèi)容,只修改指定格式屬性
  3. 直觀的用戶界面:通過圖形化控件簡化復雜的表格格式設置

5. 適用場景

  1. 批量處理報表文檔的格式
  2. 標準化不同來源的Word表格樣式
  3. 通過條件格式可突出顯示特定數(shù)據(jù)

三:完整代碼:

import sys
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
                             QLabel, QPushButton, QFileDialog, QGroupBox, QGridLayout,
                             QCheckBox, QComboBox, QLineEdit, QSpinBox, QColorDialog,
                             QMessageBox, QTabWidget, QFormLayout)
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QColor
from docx import Document
from docx.shared import Cm, Pt, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_ALIGN_VERTICAL
from docx.oxml import OxmlElement
from docx.oxml.ns import qn, nsdecls
from docx.oxml import parse_xml

class DocxTableEditor:
    @staticmethod
    def set_cell_border(cell, **kwargs):
        tc = cell._tc
        tcPr = tc.get_or_add_tcPr()

        tcBorders = tcPr.first_child_found_in("w:tcBorders")
        if tcBorders is None:
            tcBorders = OxmlElement('w:tcBorders')
            tcPr.append(tcBorders)

        for edge in ('start', 'top', 'end', 'bottom', 'insideH', 'insideV'):
            edge_data = kwargs.get(edge)
            if edge_data:
                tag = 'w:{}'.format(edge)

                element = tcBorders.find(qn(tag))
                if element is None:
                    element = OxmlElement(tag)
                    tcBorders.append(element)

                for key in ["sz", "val", "color", "space", "shadow"]:
                    if key in edge_data:
                        element.set(qn('w:{}'.format(key)), str(edge_data[key]))

    @staticmethod
    def set_background_color(cell, rgb_color):
        if isinstance(rgb_color, QColor):
            rgb_color = rgb_color.name()[1:]  
        elif isinstance(rgb_color, str) and rgb_color.startswith('#'):
            rgb_color = rgb_color[1:]
        rgb_color = f"{rgb_color:0>6}"

        shading_elm = parse_xml(r'<w:shd {} w:fill="{color_value}"/>'.format(nsdecls('w'), color_value=rgb_color))
        cell._tc.get_or_add_tcPr().append(shading_elm)

    @staticmethod
    def set_cell_font(cell, font_name=None, font_size=None, bold=None, italic=None, color=None):
        for paragraph in cell.paragraphs:
            for run in paragraph.runs:
                if font_name:
                    run.font.name = font_name
                if font_size:
                    run.font.size = Pt(font_size)
                if bold is not None:
                    run.font.bold = bold
                if italic is not None:
                    run.font.italic = italic
                if color:
                    if isinstance(color, QColor):
                        run.font.color.rgb = RGBColor(color.red(), color.green(), color.blue())
                    elif isinstance(color, str):
                        if color.startswith('#'):
                            color = color[1:]
                        try:
                            r = int(color[0:2], 16)
                            g = int(color[2:4], 16)
                            b = int(color[4:6], 16)
                            run.font.color.rgb = RGBColor(r, g, b)
                        except (ValueError, IndexError):
                            run.font.color.rgb = RGBColor(0, 0, 0)
                    else:
                        run.font.color.rgb = RGBColor(0, 0, 0)

class TableFormatterApp(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("設置Word文檔表格格式")
        self.setGeometry(100, 100, 800, 600)
        self.doc = None
        self.table = None
        self.file_path = ""
        self.font_color_label = QLabel("未選擇")
        self.cond1_color_label = QLabel("未選擇")
        self.cond2_color_label = QLabel("未選擇")
        self.border_color_label = QLabel("未選擇")
        self.bg_color_label = QLabel("未選擇")
        self.init_ui()

    def init_ui(self):
        main_widget = QWidget()
        main_layout = QVBoxLayout()
        file_group = QGroupBox("文件操作")
        file_layout = QHBoxLayout()
        self.file_label = QLabel("未選擇文件")
        self.file_label.setAlignment(Qt.AlignCenter)
        open_btn = QPushButton("打開文件")
        open_btn.clicked.connect(self.open_file)
        save_btn = QPushButton("保存文件")
        save_btn.clicked.connect(self.save_file)
        file_layout.addWidget(self.file_label)
        file_layout.addWidget(open_btn)
        file_layout.addWidget(save_btn)
        file_group.setLayout(file_layout)
        tab_widget = QTabWidget()
        basic_tab = QWidget()
        basic_layout = QVBoxLayout()
        row_group = QGroupBox("行高設置")
        row_form = QFormLayout()
        self.row_height_spin = QSpinBox()
        self.row_height_spin.setRange(10, 100)
        self.row_height_spin.setValue(30)
        self.row_height_spin.setSuffix(" 磅")
        self.header_row_spin = QSpinBox()
        self.header_row_spin.setRange(0, 10)
        self.header_row_spin.setValue(1)
        row_form.addRow("默認行高:", self.row_height_spin)
        row_form.addRow("表頭行數(shù):", self.header_row_spin)
        row_group.setLayout(row_form)
        align_group = QGroupBox("對齊方式")
        align_layout = QHBoxLayout()
        self.align_combo = QComboBox()
        self.align_combo.addItems(["居中", "左對齊", "右對齊"])
        self.valign_combo = QComboBox()
        self.valign_combo.addItems(["居中", "頂部", "底部"])
        align_layout.addWidget(QLabel("水平對齊:"))
        align_layout.addWidget(self.align_combo)
        align_layout.addWidget(QLabel("垂直對齊:"))
        align_layout.addWidget(self.valign_combo)
        align_group.setLayout(align_layout)
        font_group = QGroupBox("字體設置")
        font_layout = QFormLayout()
        self.font_name_combo = QComboBox()
        common_fonts = [
            "默認字體",  
            "宋體", "黑體", "楷體", "仿宋", "微軟雅黑", "Arial", "Times New Roman",
            "Calibri", "Courier New", "Verdana", "Tahoma", "Helvetica"
        ]
        self.font_name_combo.addItems(common_fonts)

        try:
            import matplotlib.font_manager as fm
            default_font = fm.FontProperties().get_name()
            if default_font not in common_fonts:
                self.font_name_combo.insertItem(1, default_font)
        except:
            pass

        self.font_size_spin = QSpinBox()
        self.font_size_spin.setRange(8, 72)
        self.font_size_spin.setValue(11)
        self.bold_check = QCheckBox("加粗")
        self.italic_check = QCheckBox("斜體")
        font_color_layout = QHBoxLayout()
        self.font_color_btn = QPushButton("字體顏色")
        self.font_color_btn.clicked.connect(self.choose_font_color)
        font_color_layout.addWidget(self.font_color_btn)
        font_color_layout.addWidget(self.font_color_label)
        font_layout.addRow("字體名稱:", self.font_name_combo)
        font_layout.addRow("字體大小:", self.font_size_spin)
        font_layout.addRow(self.bold_check)
        font_layout.addRow(self.italic_check)
        font_layout.addRow("字體顏色:", font_color_layout)
        font_group.setLayout(font_layout)
        apply_basic_btn = QPushButton("應用基本格式")
        apply_basic_btn.clicked.connect(self.apply_basic_formatting)
        basic_layout.addWidget(row_group)
        basic_layout.addWidget(align_group)
        basic_layout.addWidget(font_group)
        basic_layout.addWidget(apply_basic_btn)
        basic_tab.setLayout(basic_layout)
        cond_tab = QWidget()
        cond_layout = QVBoxLayout()
        cond_group = QGroupBox("條件格式設置")
        cond_grid = QGridLayout()
        cond_grid.addWidget(QLabel("條件1:"), 0, 0)
        self.cond1_col_spin = QSpinBox()
        self.cond1_col_spin.setRange(1, 20)
        self.cond1_col_spin.setValue(6)  # 默認第6列(數(shù)量列)
        cond_grid.addWidget(QLabel("列號:"), 0, 1)
        cond_grid.addWidget(self.cond1_col_spin, 0, 2)
        self.cond1_op_combo = QComboBox()
        self.cond1_op_combo.addItems([">=", ">", "=", "<=", "<", "<>"])
        cond_grid.addWidget(QLabel("操作符:"), 0, 3)
        cond_grid.addWidget(self.cond1_op_combo, 0, 4)
        self.cond1_value_spin = QSpinBox()
        self.cond1_value_spin.setRange(0, 10000)
        self.cond1_value_spin.setValue(85)
        cond_grid.addWidget(QLabel("值:"), 0, 5)
        cond_grid.addWidget(self.cond1_value_spin, 0, 6)
        cond1_color_layout = QHBoxLayout()
        self.cond1_color_btn = QPushButton("背景色")
        self.cond1_color_btn.clicked.connect(lambda: self.choose_condition_color(1))
        cond1_color_layout.addWidget(self.cond1_color_btn)
        cond1_color_layout.addWidget(self.cond1_color_label)
        cond_grid.addLayout(cond1_color_layout, 0, 7)
        cond_grid.addWidget(QLabel("條件2:"), 1, 0)
        self.cond2_col_spin = QSpinBox()
        self.cond2_col_spin.setRange(1, 20)
        cond_grid.addWidget(QLabel("列號:"), 1, 1)
        cond_grid.addWidget(self.cond2_col_spin, 1, 2)
        self.cond2_op_combo = QComboBox()
        self.cond2_op_combo.addItems([">=", ">", "=", "<=", "<", "<>"])
        cond_grid.addWidget(QLabel("操作符:"), 1, 3)
        cond_grid.addWidget(self.cond2_op_combo, 1, 4)
        self.cond2_value_edit = QLineEdit()
        self.cond2_value_edit.setPlaceholderText("數(shù)值或文本")
        cond_grid.addWidget(QLabel("值:"), 1, 5)
        cond_grid.addWidget(self.cond2_value_edit, 1, 6)
        cond2_color_layout = QHBoxLayout()
        self.cond2_color_btn = QPushButton("背景色")
        self.cond2_color_btn.clicked.connect(lambda: self.choose_condition_color(2))
        cond2_color_layout.addWidget(self.cond2_color_btn)
        cond2_color_layout.addWidget(self.cond2_color_label)
        cond_grid.addLayout(cond2_color_layout, 1, 7)
        cond_group.setLayout(cond_grid)
        apply_cond_btn = QPushButton("應用條件格式")
        apply_cond_btn.clicked.connect(self.apply_condition_formatting)
        cond_layout.addWidget(cond_group)
        cond_layout.addWidget(apply_cond_btn)
        cond_tab.setLayout(cond_layout)
        border_tab = QWidget()
        border_layout = QVBoxLayout()
        border_group = QGroupBox("邊框設置")
        border_form = QFormLayout()
        self.border_style_combo = QComboBox()
        self.border_style_combo.addItems(["single", "dashed", "dotted", "double", "none"])
        self.border_style_combo.setCurrentText("single")
        self.border_width_spin = QSpinBox()
        self.border_width_spin.setRange(1, 24)
        self.border_width_spin.setValue(4)
        self.border_width_spin.setSuffix(" 磅")
        border_color_layout = QHBoxLayout()
        self.border_color_btn = QPushButton("邊框顏色")
        self.border_color_btn.clicked.connect(self.choose_border_color)
        border_color_layout.addWidget(self.border_color_btn)
        border_color_layout.addWidget(self.border_color_label)
        self.border_sides_check = []
        side_layout = QHBoxLayout()
        sides = ["左邊框", "上邊框", "右邊框", "下邊框"]
        for side in sides:
            check = QCheckBox(side)
            check.setChecked(True)
            self.border_sides_check.append(check)
            side_layout.addWidget(check)

        border_form.addRow("邊框樣式:", self.border_style_combo)
        border_form.addRow("邊框?qū)挾?", self.border_width_spin)
        border_form.addRow("邊框顏色:", border_color_layout)
        border_form.addRow("應用邊框:", side_layout)
        border_group.setLayout(border_form)
        bg_group = QGroupBox("背景設置")
        bg_layout = QHBoxLayout()
        bg_color_layout = QHBoxLayout()
        self.bg_color_btn = QPushButton("選擇背景色")
        self.bg_color_btn.clicked.connect(self.choose_bg_color)
        bg_color_layout.addWidget(self.bg_color_btn)
        bg_color_layout.addWidget(self.bg_color_label)
        self.bg_range_combo = QComboBox()
        self.bg_range_combo.addItems(["所有單元格", "表頭", "數(shù)據(jù)行", "特定列"])
        self.bg_col_spin = QSpinBox()
        self.bg_col_spin.setRange(1, 20)
        self.bg_col_spin.setValue(1)
        bg_layout.addLayout(bg_color_layout)
        bg_layout.addWidget(QLabel("應用范圍:"))
        bg_layout.addWidget(self.bg_range_combo)
        bg_layout.addWidget(QLabel("列號:"))
        bg_layout.addWidget(self.bg_col_spin)
        bg_group.setLayout(bg_layout)
        apply_border_btn = QPushButton("應用邊框和背景")
        apply_border_btn.clicked.connect(self.apply_border_and_background)
        border_layout.addWidget(border_group)
        border_layout.addWidget(bg_group)
        border_layout.addWidget(apply_border_btn)
        border_tab.setLayout(border_layout)
        tab_widget.addTab(basic_tab, "基本格式")
        tab_widget.addTab(cond_tab, "條件格式")
        tab_widget.addTab(border_tab, "邊框和背景")
        main_layout.addWidget(file_group)
        main_layout.addWidget(tab_widget)
        main_widget.setLayout(main_layout)
        self.setCentralWidget(main_widget)

    def open_file(self):
        file_path, _ = QFileDialog.getOpenFileName(self, "打開Word文件", "", "Word文件 (*.docx)")
        if file_path:
            self.file_path = file_path
            self.file_label.setText(file_path.split("/")[-1])
            try:
                self.doc = Document(file_path)
                if len(self.doc.tables) > 0:
                    self.table = self.doc.tables[0]
                    QMessageBox.information(self, "成功", "文件加載成功!")
                else:
                    QMessageBox.warning(self, "警告", "文件中沒有表格!")
                    self.table = None
            except Exception as e:
                QMessageBox.critical(self, "錯誤", f"無法打開文件:\n{str(e)}")
                self.table = None

    def save_file(self):
        if not self.doc:
            QMessageBox.warning(self, "警告", "請先打開文件!")
            return

        if not self.file_path:
            save_path, _ = QFileDialog.getSaveFileName(self, "保存Word文件", "", "Word文件 (*.docx)")
            if not save_path:
                return
        else:
            save_path = self.file_path.replace(".docx", "-整理.docx")

        try:
            self.doc.save(save_path)
            QMessageBox.information(self, "成功", f"文件已保存到:\n{save_path}")
        except Exception as e:
            QMessageBox.critical(self, "錯誤", f"保存文件失敗:\n{str(e)}")

    def choose_font_color(self):
        color = QColorDialog.getColor()
        if color.isValid():
            self.font_color = color
            self.font_color_label.setText(color.name())
            self.font_color_label.setStyleSheet(f"background-color: {color.name()}; color: white;")

    def choose_condition_color(self, cond_num):
        color = QColorDialog.getColor()
        if color.isValid():
            if cond_num == 1:
                self.cond1_color = color.name()[1:]
                self.cond1_color_label.setText(color.name())
                self.cond1_color_label.setStyleSheet(f"background-color: {color.name()}; color: black;")
            else:
                self.cond2_color = color.name()[1:]
                self.cond2_color_label.setText(color.name())
                self.cond2_color_label.setStyleSheet(f"background-color: {color.name()}; color: black;")

    def choose_border_color(self):
        color = QColorDialog.getColor()
        if color.isValid():
            self.border_color = color.name()[1:]
            self.border_color_label.setText(color.name())
            self.border_color_label.setStyleSheet(f"background-color: {color.name()}; color: black;")

    def choose_bg_color(self):
        color = QColorDialog.getColor()
        if color.isValid():
            self.bg_color = color.name()[1:]
            self.bg_color_label.setText(color.name())
            self.bg_color_label.setStyleSheet(f"background-color: {color.name()}; color: black;")

    def apply_basic_formatting(self):
        if not self.table:
            QMessageBox.warning(self, "警告", "請先打開文件!")
            return

        try:
            align_map = {"居中": WD_ALIGN_PARAGRAPH.CENTER, "左對齊": WD_ALIGN_PARAGRAPH.LEFT,
                         "右對齊": WD_ALIGN_PARAGRAPH.RIGHT}
            valign_map = {"居中": WD_ALIGN_VERTICAL.CENTER, "頂部": WD_ALIGN_VERTICAL.TOP, "底部": WD_ALIGN_VERTICAL.BOTTOM}

            align = align_map[self.align_combo.currentText()]
            valign = valign_map[self.valign_combo.currentText()]
            font_name = self.font_name_combo.currentText() if self.font_name_combo.currentText() != "默認字體" else None
            font_size = self.font_size_spin.value() if self.font_size_spin.value() > 0 else None
            bold = self.bold_check.isChecked()
            italic = self.italic_check.isChecked()
            header_rows = self.header_row_spin.value()
            default_row_height = self.row_height_spin.value()

            for i, row in enumerate(self.table.rows):
                if i < header_rows:
                    row.height = Cm(1)  
                else:
                    row.height = Pt(default_row_height)

                for cell in row.cells:
                    for paragraph in cell.paragraphs:
                        paragraph.alignment = align
                    cell.vertical_alignment = valign
                    DocxTableEditor.set_cell_font(
                        cell,
                        font_name=font_name,
                        font_size=font_size,
                        bold=bold,
                        italic=italic,
                        color=self.font_color  
                    )

            QMessageBox.information(self, "成功", "基本格式應用成功!")
        except Exception as e:
            QMessageBox.critical(self, "錯誤", f"應用基本格式時出錯:\n{str(e)}")

    def apply_condition_formatting(self):
        if not self.table:
            QMessageBox.warning(self, "警告", "請先打開文件!")
            return

        try:
            cond1_col = self.cond1_col_spin.value() - 1
            cond1_op = self.cond1_op_combo.currentText()
            cond1_value = self.cond1_value_spin.value()
            cond1_color = self.cond1_color if hasattr(self, 'cond1_color') else None
            cond2_col = self.cond2_col_spin.value() - 1
            cond2_op = self.cond2_op_combo.currentText()
            cond2_value = self.cond2_value_edit.text()
            cond2_color = self.cond2_color if hasattr(self, 'cond2_color') else None

            for row in self.table.rows[self.header_row_spin.value():]:
                try:
                    cell_text = row.cells[cond1_col].text.strip()
                    if cell_text and cond1_color: 
                        try:
                            cell_value = float(cell_text)
                            condition_met = self.evaluate_condition(cell_value, cond1_op, cond1_value)

                            if condition_met:
                                DocxTableEditor.set_background_color(row.cells[cond1_col], cond1_color)
                        except ValueError:
                            pass

                    if cond2_value and cond2_color:  
                        cell_text = row.cells[cond2_col].text.strip()
                        try:
                            cell_value = float(cell_text)
                            cond2_value_float = float(cond2_value)
                            condition_met = self.evaluate_condition(cell_value, cond2_op, cond2_value_float)
                        except ValueError:
                            condition_met = self.evaluate_text_condition(cell_text, cond2_op, cond2_value)

                        if condition_met:
                            DocxTableEditor.set_background_color(row.cells[cond2_col], cond2_color)

                except (ValueError, IndexError):
                    continue

            QMessageBox.information(self, "成功", "條件格式應用成功!")
        except Exception as e:
            QMessageBox.critical(self, "錯誤", f"應用條件格式時出錯:\n{str(e)}")

    def evaluate_condition(self, value, op, compare_value):
        if op == ">=":
            return value >= compare_value
        elif op == ">":
            return value > compare_value
        elif op == "=":
            return value == compare_value
        elif op == "<=":
            return value <= compare_value
        elif op == "<":
            return value < compare_value
        elif op == "<>":
            return value != compare_value
        return False

    def evaluate_text_condition(self, text, op, compare_text):
        if op == "=":
            return text == compare_text
        elif op == "<>":
            return text != compare_text
        return False

    def apply_border_and_background(self):
        if not self.table:
            QMessageBox.warning(self, "警告", "請先打開文件!")
            return

        try:
            border_style = self.border_style_combo.currentText()
            border_width = self.border_width_spin.value()
            border_color = self.border_color

            sides = []
            if self.border_sides_check[0].isChecked(): sides.append('start')
            if self.border_sides_check[1].isChecked(): sides.append('top')
            if self.border_sides_check[2].isChecked(): sides.append('end')
            if self.border_sides_check[3].isChecked(): sides.append('bottom')

            bg_range = self.bg_range_combo.currentText()
            bg_col = self.bg_col_spin.value() - 1  
            header_rows = self.header_row_spin.value()

            for i, row in enumerate(self.table.rows):
                for j, cell in enumerate(row.cells):
                    if sides:
                        border_settings = {}
                        for side in sides:
                            border_settings[side] = {
                                "val": border_style,
                                "sz": border_width,
                                "color": border_color
                            }
                        DocxTableEditor.set_cell_border(cell, **border_settings)

                    if self.bg_color:
                        apply_bg = False

                        if bg_range == "所有單元格":
                            apply_bg = True
                        elif bg_range == "表頭" and i < header_rows:
                            apply_bg = True
                        elif bg_range == "數(shù)據(jù)行" and i >= header_rows:
                            apply_bg = True
                        elif bg_range == "特定列" and j == bg_col:
                            apply_bg = True

                        if apply_bg:
                            DocxTableEditor.set_background_color(cell, self.bg_color)

            QMessageBox.information(self, "成功", "邊框和背景應用成功!")
        except Exception as e:
            QMessageBox.critical(self, "錯誤", f"應用邊框和背景時出錯:\n{str(e)}")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = TableFormatterApp()
    window.show()
    sys.exit(app.exec_())

四:代碼分析:

1.DocxTableEditor工具類

class DocxTableEditor:
    """用于操作Word表格樣式的工具類"""
    
    @staticmethod
    def set_cell_border(cell, **kwargs):
        """設置單元格邊框樣式
        
        Args:
            cell: 表格單元格對象
            **kwargs: 邊框參數(shù),如 start/top/end/bottom/insideH/insideV 等邊的樣式
                     每邊參數(shù)格式: {'val': 'single', 'sz': 4, 'color': 'FF0000'}
        """
        tc = cell._tc
        tcPr = tc.get_or_add_tcPr()
        tcBorders = tcPr.first_child_found_in("w:tcBorders")
        
        # 如果不存在邊框定義則創(chuàng)建
        if tcBorders is None:
            tcBorders = OxmlElement('w:tcBorders')
            tcPr.append(tcBorders)

        # 遍歷所有指定的邊
        for edge in ('start', 'top', 'end', 'bottom', 'insideH', 'insideV'):
            edge_data = kwargs.get(edge)
            if edge_data:
                tag = 'w:{}'.format(edge)
                element = tcBorders.find(qn(tag))
                
                # 如果不存在該邊的定義則創(chuàng)建
                if element is None:
                    element = OxmlElement(tag)
                    tcBorders.append(element)

                # 設置邊框?qū)傩?
                for key in ["sz", "val", "color", "space", "shadow"]:
                    if key in edge_data:
                        element.set(qn('w:{}'.format(key)), str(edge_data[key]))

    @staticmethod
    def set_background_color(cell, rgb_color):
        """設置單元格背景色
        
        Args:
            cell: 表格單元格對象
            rgb_color: 顏色值,可以是QColor對象或十六進制字符串(帶#或不帶)
        """
        # 統(tǒng)一顏色格式為6位十六進制字符串
        if isinstance(rgb_color, QColor):
            rgb_color = rgb_color.name()[1:]  # 去掉QColor返回的#前綴
        elif isinstance(rgb_color, str) and rgb_color.startswith('#'):
            rgb_color = rgb_color[1:]
        rgb_color = f"{rgb_color:0>6}"  # 確保6位長度

        # 創(chuàng)建shading元素并設置填充色
        shading_elm = parse_xml(r'<w:shd {} w:fill="{color_value}"/>'.format(
            nsdecls('w'), color_value=rgb_color))
        cell._tc.get_or_add_tcPr().append(shading_elm)

    @staticmethod
    def set_cell_font(cell, font_name=None, font_size=None, bold=None, italic=None, color=None):
        """設置單元格內(nèi)文字樣式
        
        Args:
            cell: 表格單元格對象
            font_name: 字體名稱
            font_size: 字體大小(pt)
            bold: 是否加粗
            italic: 是否斜體
            color: 字體顏色(QColor/十六進制字符串)
        """
        for paragraph in cell.paragraphs:
            for run in paragraph.runs:
                if font_name:
                    run.font.name = font_name
                if font_size:
                    run.font.size = Pt(font_size)
                if bold is not None:
                    run.font.bold = bold
                if italic is not None:
                    run.font.italic = italic
                if color:
                    # 處理不同顏色輸入格式
                    if isinstance(color, QColor):
                        run.font.color.rgb = RGBColor(color.red(), color.green(), color.blue())
                    elif isinstance(color, str):
                        if color.startswith('#'):
                            color = color[1:]
                        try:
                            r = int(color[0:2], 16)
                            g = int(color[2:4], 16)
                            b = int(color[4:6], 16)
                            run.font.color.rgb = RGBColor(r, g, b)
                        except (ValueError, IndexError):
                            run.font.color.rgb = RGBColor(0, 0, 0)
                    else:
                        run.font.color.rgb = RGBColor(0, 0, 0)

2. 主窗口初始化 (TableFormatterApp類)

class TableFormatterApp(QMainWindow):
    """主應用程序窗口"""
    
    def __init__(self):
        super().__init__()
        self.setWindowTitle("設置Word文檔表格格式")
        self.setGeometry(100, 100, 800, 600)
        self.doc = None  # 當前打開的Document對象
        self.table = None  # 當前操作的表格對象
        self.file_path = ""  # 當前文件路徑
        
        # 初始化顏色標簽(用于顯示當前選擇的顏色)
        self.font_color_label = QLabel("未選擇")
        self.cond1_color_label = QLabel("未選擇")
        self.cond2_color_label = QLabel("未選擇")
        self.border_color_label = QLabel("未選擇")
        self.bg_color_label = QLabel("未選擇")
        
        self.init_ui()  # 初始化界面

    def init_ui(self):
        """初始化用戶界面"""
        main_widget = QWidget()
        main_layout = QVBoxLayout()

        # ========== 文件操作區(qū)域 ==========
        file_group = QGroupBox("文件操作")
        file_layout = QHBoxLayout()
        self.file_label = QLabel("未選擇文件")
        self.file_label.setAlignment(Qt.AlignCenter)
        
        open_btn = QPushButton("打開文件")
        open_btn.clicked.connect(self.open_file)
        
        save_btn = QPushButton("保存文件")
        save_btn.clicked.connect(self.save_file)
        
        file_layout.addWidget(self.file_label)
        file_layout.addWidget(open_btn)
        file_layout.addWidget(save_btn)
        file_group.setLayout(file_layout)

        # ========== 選項卡區(qū)域 ==========
        tab_widget = QTabWidget()
        
        # 基本格式選項卡
        basic_tab = self._create_basic_tab()
        # 條件格式選項卡
        cond_tab = self._create_cond_tab()
        # 邊框和背景選項卡
        border_tab = self._create_border_tab()
        
        tab_widget.addTab(basic_tab, "基本格式")
        tab_widget.addTab(cond_tab, "條件格式")
        tab_widget.addTab(border_tab, "邊框和背景")

        # ========== 主布局組裝 ==========
        main_layout.addWidget(file_group)
        main_layout.addWidget(tab_widget)
        main_widget.setLayout(main_layout)
        self.setCentralWidget(main_widget)

3. 核心功能方法

def open_file(self):
    """打開Word文件并加載第一個表格"""
    file_path, _ = QFileDialog.getOpenFileName(self, "打開Word文件", "", "Word文件 (*.docx)")
    if file_path:
        self.file_path = file_path
        self.file_label.setText(file_path.split("/")[-1])
        try:
            self.doc = Document(file_path)
            if len(self.doc.tables) > 0:
                self.table = self.doc.tables[0]
                QMessageBox.information(self, "成功", "文件加載成功!")
            else:
                QMessageBox.warning(self, "警告", "文件中沒有表格!")
                self.table = None
        except Exception as e:
            QMessageBox.critical(self, "錯誤", f"無法打開文件:\n{str(e)}")
            self.table = None

def save_file(self):
    """保存修改后的Word文件"""
    if not self.doc:
        QMessageBox.warning(self, "警告", "請先打開文件!")
        return

    if not self.file_path:
        save_path, _ = QFileDialog.getSaveFileName(self, "保存Word文件", "", "Word文件 (*.docx)")
        if not save_path:
            return
    else:
        save_path = self.file_path.replace(".docx", "-整理.docx")

    try:
        self.doc.save(save_path)
        QMessageBox.information(self, "成功", f"文件已保存到:\n{save_path}")
    except Exception as e:
        QMessageBox.critical(self, "錯誤", f"保存文件失敗:\n{str(e)}")

def apply_basic_formatting(self):
    """應用基本格式設置到表格"""
    if not self.table:
        QMessageBox.warning(self, "警告", "請先打開文件!")
        return

    try:
        # 獲取對齊方式設置
        align_map = {"居中": WD_ALIGN_PARAGRAPH.CENTER, 
                    "左對齊": WD_ALIGN_PARAGRAPH.LEFT,
                    "右對齊": WD_ALIGN_PARAGRAPH.RIGHT}
        valign_map = {"居中": WD_ALIGN_VERTICAL.CENTER, 
                     "頂部": WD_ALIGN_VERTICAL.TOP, 
                     "底部": WD_ALIGN_VERTICAL.BOTTOM}

        align = align_map[self.align_combo.currentText()]
        valign = valign_map[self.valign_combo.currentText()]
        
        # 獲取字體設置
        font_name = self.font_name_combo.currentText() if self.font_name_combo.currentText() != "默認字體" else None
        font_size = self.font_size_spin.value() if self.font_size_spin.value() > 0 else None
        bold = self.bold_check.isChecked()
        italic = self.italic_check.isChecked()
        header_rows = self.header_row_spin.value()
        default_row_height = self.row_height_spin.value()

        # 遍歷表格應用設置
        for i, row in enumerate(self.table.rows):
            # 設置行高(表頭行固定1cm,其他行使用指定磅值)
            if i < header_rows:
                row.height = Cm(1)
            else:
                row.height = Pt(default_row_height)

            # 設置單元格格式
            for cell in row.cells:
                # 設置段落對齊
                for paragraph in cell.paragraphs:
                    paragraph.alignment = align
                
                # 設置垂直對齊
                cell.vertical_alignment = valign
                
                # 設置字體
                DocxTableEditor.set_cell_font(
                    cell,
                    font_name=font_name,
                    font_size=font_size,
                    bold=bold,
                    italic=italic,
                    color=getattr(self, 'font_color', None)  # 使用getattr避免未定義屬性錯誤
                )

        QMessageBox.information(self, "成功", "基本格式應用成功!")
    except Exception as e:
        QMessageBox.critical(self, "錯誤", f"應用基本格式時出錯:\n{str(e)}")

def apply_condition_formatting(self):
    """應用條件格式到表格"""
    if not self.table:
        QMessageBox.warning(self, "警告", "請先打開文件!")
        return

    try:
        # 獲取條件1設置
        cond1_col = self.cond1_col_spin.value() - 1  # 轉換為0-based索引
        cond1_op = self.cond1_op_combo.currentText()
        cond1_value = self.cond1_value_spin.value()
        cond1_color = getattr(self, 'cond1_color', None)
        
        # 獲取條件2設置
        cond2_col = self.cond2_col_spin.value() - 1
        cond2_op = self.cond2_op_combo.currentText()
        cond2_value = self.cond2_value_edit.text()
        cond2_color = getattr(self, 'cond2_color', None)

        # 跳過表頭行
        for row in self.table.rows[self.header_row_spin.value():]:
            try:
                # 處理條件1(數(shù)值比較)
                cell_text = row.cells[cond1_col].text.strip()
                if cell_text and cond1_color:
                    try:
                        cell_value = float(cell_text)
                        if self.evaluate_condition(cell_value, cond1_op, cond1_value):
                            DocxTableEditor.set_background_color(row.cells[cond1_col], cond1_color)
                    except ValueError:
                        pass  # 非數(shù)值內(nèi)容跳過

                # 處理條件2(支持文本比較)
                if cond2_value and cond2_color:
                    cell_text = row.cells[cond2_col].text.strip()
                    try:
                        # 嘗試數(shù)值比較
                        cell_value = float(cell_text)
                        cond2_value_float = float(cond2_value)
                        condition_met = self.evaluate_condition(cell_value, cond2_op, cond2_value_float)
                    except ValueError:
                        # 回退到文本比較
                        condition_met = self.evaluate_text_condition(cell_text, cond2_op, cond2_value)

                    if condition_met:
                        DocxTableEditor.set_background_color(row.cells[cond2_col], cond2_color)

            except (ValueError, IndexError):
                continue  # 跳過格式錯誤的單元格

        QMessageBox.information(self, "成功", "條件格式應用成功!")
    except Exception as e:
        QMessageBox.critical(self, "錯誤", f"應用條件格式時出錯:\n{str(e)}")

def evaluate_condition(self, value, op, compare_value):
    """數(shù)值條件判斷"""
    if op == ">=":
        return value >= compare_value
    elif op == ">":
        return value > compare_value
    elif op == "=":
        return value == compare_value
    elif op == "<=":
        return value <= compare_value
    elif op == "<":
        return value < compare_value
    elif op == "<>":
        return value != compare_value
    return False

def evaluate_text_condition(self, text, op, compare_text):
    """文本條件判斷"""
    if op == "=":
        return text == compare_text
    elif op == "<>":
        return text != compare_text
    return False

def apply_border_and_background(self):
    """應用邊框和背景設置"""
    if not self.table:
        QMessageBox.warning(self, "警告", "請先打開文件!")
        return

    try:
        # 獲取邊框設置
        border_style = self.border_style_combo.currentText()
        border_width = self.border_width_spin.value()
        border_color = getattr(self, 'border_color', None)
        
        # 獲取要設置邊框的邊
        sides = []
        for idx, check in enumerate(self.border_sides_check):
            if check.isChecked():
                side_map = ['start', 'top', 'end', 'bottom']
                sides.append(side_map[idx])

        # 獲取背景設置
        bg_range = self.bg_range_combo.currentText()
        bg_col = self.bg_col_spin.value() - 1
        header_rows = self.header_row_spin.value()

        # 遍歷表格應用設置
        for i, row in enumerate(self.table.rows):
            for j, cell in enumerate(row.cells):
                # 應用邊框
                if sides and border_color:
                    border_settings = {}
                    for side in sides:
                        border_settings[side] = {
                            "val": border_style,
                            "sz": border_width,
                            "color": border_color
                        }
                    DocxTableEditor.set_cell_border(cell, **border_settings)

                # 應用背景色
                if hasattr(self, 'bg_color') and self.bg_color:
                    apply_bg = False
                    
                    # 判斷是否在指定范圍內(nèi)
                    if bg_range == "所有單元格":
                        apply_bg = True
                    elif bg_range == "表頭" and i < header_rows:
                        apply_bg = True
                    elif bg_range == "數(shù)據(jù)行" and i >= header_rows:
                        apply_bg = True
                    elif bg_range == "特定列" and j == bg_col:
                        apply_bg = True

                    if apply_bg:
                        DocxTableEditor.set_background_color(cell, self.bg_color)

        QMessageBox.information(self, "成功", "邊框和背景應用成功!")
    except Exception as e:
        QMessageBox.critical(self, "錯誤", f"應用邊框和背景時出錯:\n{str(e)}")

以上就是使用Python設置Word文檔中表格的格式的方法的詳細內(nèi)容,更多關于Python Word表格格式設置的資料請關注腳本之家其它相關文章!

相關文章

  • Python實現(xiàn)包含min函數(shù)的棧

    Python實現(xiàn)包含min函數(shù)的棧

    這篇文章主要介紹了Python實現(xiàn)包含min函數(shù)的棧,可實現(xiàn)棧中元素的計算及進棧出棧等操作,需要的朋友可以參考下
    2016-04-04
  • python中使用Celery容聯(lián)云異步發(fā)送驗證碼功能

    python中使用Celery容聯(lián)云異步發(fā)送驗證碼功能

    Celery 是一個 基于python開發(fā)的分布式異步消息任務隊列,通過它可以輕松的實現(xiàn)任務的異步處理,本文重點給大家介紹使用Celery容聯(lián)云異步發(fā)送驗證碼功能,感興趣的朋友一起看看吧
    2021-09-09
  • python中文分詞+詞頻統(tǒng)計的實現(xiàn)步驟

    python中文分詞+詞頻統(tǒng)計的實現(xiàn)步驟

    詞頻統(tǒng)計就是輸入一段句子或者一篇文章,然后統(tǒng)計句子中每個單詞出現(xiàn)的次數(shù),下面這篇文章主要給大家介紹了關于python中文分詞+詞頻統(tǒng)計的相關資料,需要的朋友可以參考下
    2022-06-06
  • Python利用PyQt5制作一個獲取網(wǎng)絡實時NBA數(shù)據(jù)并播報的GUI程序

    Python利用PyQt5制作一個獲取網(wǎng)絡實時NBA數(shù)據(jù)并播報的GUI程序

    現(xiàn)在NBA聯(lián)賽也進行到半決賽了,我們怎么樣才能以更快的方法獲取NBA的數(shù)據(jù)呢?這里我們就自己來做一個數(shù)據(jù)播報的程序,需要的朋友可以參考下
    2021-06-06
  • 解決TensorFlow訓練模型及保存數(shù)量限制的問題

    解決TensorFlow訓練模型及保存數(shù)量限制的問題

    這篇文章主要介紹了解決TensorFlow訓練模型及保存數(shù)量限制的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • 基于TensorBoard中graph模塊圖結構分析

    基于TensorBoard中graph模塊圖結構分析

    今天小編就為大家分享一篇基于TensorBoard中graph模塊圖結構分析,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-02-02
  • 你應該知道的python列表去重方法

    你應該知道的python列表去重方法

    初學者經(jīng)常會遇到如何移除list中重復元素的問題。 這個問題在其他語言中可能需要for循環(huán)什么的,而在python中不用這樣,非常簡單,下面來通過這篇文章主要介紹了關于python列表去重方法以及拓展,需要的朋友可以參考借鑒,一起來看看吧。
    2017-01-01
  • python生成器的使用方法

    python生成器的使用方法

    這篇文章主要介紹了什么是生成器,生成器如何使用,下文用例子說明了怎么使用生成器
    2013-11-11
  • 基于python log取對數(shù)詳解

    基于python log取對數(shù)詳解

    今天小編就為大家分享一篇基于python log取對數(shù)詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-06-06
  • python怎樣更加簡潔的解決小明種蘋果

    python怎樣更加簡潔的解決小明種蘋果

    這篇文章主要介紹了python怎樣更加簡潔的解決小明種蘋果。想了解數(shù)據(jù)結構和算法的同學,可以參考下
    2021-04-04

最新評論

青铜峡市| 塔城市| 涟源市| 石楼县| 双桥区| 双桥区| 天峨县| 丁青县| 达日县| 漯河市| 洛南县| 安阳市| 璧山县| 新巴尔虎右旗| 土默特左旗| 沁水县| 南澳县| 高阳县| 黄冈市| 治多县| 定边县| 来宾市| 西安市| 西宁市| 垣曲县| 罗城| 九台市| 同江市| 姜堰市| 福州市| 阿拉善右旗| 恩平市| 涞源县| 平舆县| 长汀县| 多伦县| 三穗县| 长岛县| 广灵县| 普宁市| 长治县|