欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python結(jié)合PyQt5實(shí)現(xiàn)MD(Markdown)轉(zhuǎn)DOCX工具

 更新時(shí)間:2025年07月23日 08:26:40   作者:老胖閑聊  
這篇文章主要為大家詳細(xì)介紹了Python如何結(jié)合PyQt5實(shí)現(xiàn)一個(gè)MD(Markdown)轉(zhuǎn)DOCX工具,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下

下面是一個(gè)使用 Python 和 PyQt5 實(shí)現(xiàn)的 Markdown 轉(zhuǎn) DOCX 工具,具有美觀的圖形界面,支持表格和代碼塊轉(zhuǎn)換,并提供轉(zhuǎn)換預(yù)覽功能。

效果圖

功能特點(diǎn)

一比一復(fù)刻 Markdown 格式到 DOCX

支持表格、代碼塊等復(fù)雜元素轉(zhuǎn)換

美觀的圖形界面

轉(zhuǎn)換過程實(shí)時(shí)預(yù)覽

文件選擇對話框

代碼實(shí)現(xiàn)

import sys
import os
from markdown import markdown
from docx import Document
from docx.shared import Pt, RGBColor, Inches
from docx.oxml.ns import qn
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from PyQt5.QtWidgets import (QApplication, QMainWindow, QVBoxLayout, QHBoxLayout, 
                            QPushButton, QFileDialog, QTextEdit, QLabel, 
                            QWidget, QMessageBox, QProgressBar)
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QFont, QIcon


class MarkdownToDocxConverter(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()
        self.setWindowIcon(QIcon('icon.png'))  # 請準(zhǔn)備一個(gè)圖標(biāo)文件或刪除這行
        
    def initUI(self):
        self.setWindowTitle('Markdown 轉(zhuǎn) DOCX 工具')
        self.setGeometry(300, 300, 800, 600)
        
        # 主窗口部件
        main_widget = QWidget()
        self.setCentralWidget(main_widget)
        
        # 主布局
        main_layout = QVBoxLayout()
        main_widget.setLayout(main_layout)
        
        # 標(biāo)題
        title_label = QLabel('Markdown 轉(zhuǎn) DOCX 轉(zhuǎn)換器')
        title_label.setFont(QFont('Microsoft YaHei', 16, QFont.Bold))
        title_label.setAlignment(Qt.AlignCenter)
        title_label.setStyleSheet('color: #2c3e50; margin-bottom: 20px;')
        main_layout.addWidget(title_label)
        
        # 文件選擇區(qū)域
        file_layout = QHBoxLayout()
        
        self.md_file_label = QLabel('未選擇文件')
        self.md_file_label.setFont(QFont('Microsoft YaHei', 10))
        self.md_file_label.setStyleSheet('border: 1px solid #ddd; padding: 5px;')
        self.md_file_label.setFixedHeight(30)
        
        select_btn = QPushButton('選擇 Markdown 文件')
        select_btn.setFont(QFont('Microsoft YaHei', 10))
        select_btn.setStyleSheet('''
            QPushButton {
                background-color: #3498db;
                color: white;
                border: none;
                padding: 8px 15px;
                border-radius: 4px;
            }
            QPushButton:hover {
                background-color: #2980b9;
            }
        ''')
        select_btn.clicked.connect(self.select_md_file)
        
        file_layout.addWidget(self.md_file_label, stretch=4)
        file_layout.addWidget(select_btn, stretch=1)
        main_layout.addLayout(file_layout)
        
        # 預(yù)覽區(qū)域
        preview_label = QLabel('預(yù)覽內(nèi)容:')
        preview_label.setFont(QFont('Microsoft YaHei', 10, QFont.Bold))
        main_layout.addWidget(preview_label)
        
        self.preview_text = QTextEdit()
        self.preview_text.setFont(QFont('Consolas', 10))
        self.preview_text.setReadOnly(True)
        self.preview_text.setStyleSheet('''
            QTextEdit {
                border: 1px solid #ddd;
                padding: 10px;
                background-color: #f9f9f9;
            }
        ''')
        main_layout.addWidget(self.preview_text, stretch=3)
        
        # 進(jìn)度條
        self.progress_bar = QProgressBar()
        self.progress_bar.setRange(0, 100)
        self.progress_bar.setValue(0)
        self.progress_bar.setTextVisible(True)
        self.progress_bar.setStyleSheet('''
            QProgressBar {
                border: 1px solid #ddd;
                border-radius: 3px;
                text-align: center;
                height: 20px;
            }
            QProgressBar::chunk {
                background-color: #2ecc71;
                width: 10px;
            }
        ''')
        main_layout.addWidget(self.progress_bar)
        
        # 轉(zhuǎn)換按鈕
        convert_btn = QPushButton('轉(zhuǎn)換為 DOCX')
        convert_btn.setFont(QFont('Microsoft YaHei', 12, QFont.Bold))
        convert_btn.setStyleSheet('''
            QPushButton {
                background-color: #2ecc71;
                color: white;
                border: none;
                padding: 10px 20px;
                border-radius: 4px;
                margin-top: 15px;
            }
            QPushButton:hover {
                background-color: #27ae60;
            }
            QPushButton:disabled {
                background-color: #95a5a6;
            }
        ''')
        convert_btn.clicked.connect(self.convert_to_docx)
        convert_btn.setEnabled(False)
        self.convert_btn = convert_btn
        main_layout.addWidget(convert_btn, alignment=Qt.AlignCenter)
        
        # 狀態(tài)欄
        self.statusBar().showMessage('準(zhǔn)備就緒')
        
        # 成員變量
        self.md_file_path = ''
        
    def select_md_file(self):
        options = QFileDialog.Options()
        file_path, _ = QFileDialog.getOpenFileName(
            self, "選擇 Markdown 文件", "", 
            "Markdown Files (*.md *.markdown);;All Files (*)", 
            options=options
        )
        
        if file_path:
            self.md_file_path = file_path
            self.md_file_label.setText(file_path)
            self.convert_btn.setEnabled(True)
            
            # 預(yù)覽文件內(nèi)容
            try:
                with open(file_path, 'r', encoding='utf-8') as f:
                    content = f.read()
                    self.preview_text.setPlainText(content)
                    self.statusBar().showMessage('文件加載成功')
            except Exception as e:
                QMessageBox.warning(self, '錯(cuò)誤', f'無法讀取文件: {str(e)}')
                self.statusBar().showMessage('文件讀取失敗')
    
    def convert_to_docx(self):
        if not self.md_file_path:
            QMessageBox.warning(self, '警告', '請先選擇 Markdown 文件')
            return
            
        # 設(shè)置保存路徑
        options = QFileDialog.Options()
        save_path, _ = QFileDialog.getSaveFileName(
            self, "保存 DOCX 文件", 
            os.path.splitext(self.md_file_path)[0] + '.docx', 
            "Word Documents (*.docx);;All Files (*)", 
            options=options
        )
        
        if not save_path:
            return
            
        self.progress_bar.setValue(10)
        self.statusBar().showMessage('正在轉(zhuǎn)換...')
        QApplication.processEvents()  # 更新UI
        
        try:
            # 讀取Markdown內(nèi)容
            with open(self.md_file_path, 'r', encoding='utf-8') as f:
                md_content = f.read()
            
            self.progress_bar.setValue(30)
            
            # 創(chuàng)建Word文檔
            doc = Document()
            
            # 設(shè)置默認(rèn)字體
            doc.styles['Normal'].font.name = '微軟雅黑'
            doc.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), '微軟雅黑')
            doc.styles['Normal'].font.size = Pt(10.5)
            
            # 轉(zhuǎn)換Markdown為HTML
            html_content = markdown(md_content, extensions=[
                'extra',  # 支持表格、代碼塊等
                'codehilite',  # 代碼高亮
                'tables',  # 表格支持
                'fenced_code'  # 圍欄代碼塊
            ])
            
            self.progress_bar.setValue(50)
            
            # 將HTML內(nèi)容添加到Word文檔
            self.add_html_to_doc(html_content, doc)
            
            self.progress_bar.setValue(80)
            
            # 保存文檔
            doc.save(save_path)
            
            self.progress_bar.setValue(100)
            self.statusBar().showMessage('轉(zhuǎn)換完成!')
            QMessageBox.information(self, '成功', '文件轉(zhuǎn)換完成!')
            
        except Exception as e:
            QMessageBox.critical(self, '錯(cuò)誤', f'轉(zhuǎn)換過程中出錯(cuò): {str(e)}')
            self.statusBar().showMessage('轉(zhuǎn)換失敗')
        finally:
            self.progress_bar.setValue(0)
    
    def add_html_to_doc(self, html, doc):
        from bs4 import BeautifulSoup
        
        soup = BeautifulSoup(html, 'html.parser')
        
        for element in soup.children:
            if element.name == 'h1':
                self.add_heading(doc, element.text, 0)
            elif element.name == 'h2':
                self.add_heading(doc, element.text, 1)
            elif element.name == 'h3':
                self.add_heading(doc, element.text, 2)
            elif element.name == 'h4':
                self.add_heading(doc, element.text, 3)
            elif element.name == 'h5':
                self.add_heading(doc, element.text, 4)
            elif element.name == 'h6':
                self.add_heading(doc, element.text, 5)
            elif element.name == 'p':
                self.add_paragraph(doc, element.text)
            elif element.name == 'ul':
                self.add_list(doc, element, False)
            elif element.name == 'ol':
                self.add_list(doc, element, True)
            elif element.name == 'table':
                self.add_table(doc, element)
            elif element.name == 'pre':
                self.add_code_block(doc, element)
            elif element.name == 'blockquote':
                self.add_quote(doc, element)
            elif element.name == 'hr':
                self.add_horizontal_rule(doc)
    
    def add_heading(self, doc, text, level):
        heading = doc.add_heading(text, level)
        # 設(shè)置中文字體
        for run in heading.runs:
            run.font.name = '微軟雅黑'
            run._element.rPr.rFonts.set(qn('w:eastAsia'), '微軟雅黑')
    
    def add_paragraph(self, doc, text):
        p = doc.add_paragraph(text)
        # 設(shè)置中文字體
        for run in p.runs:
            run.font.name = '微軟雅黑'
            run._element.rPr.rFonts.set(qn('w:eastAsia'), '微軟雅黑')
    
    def add_list(self, doc, element, ordered):
        for li in element.find_all('li', recursive=False):
            if ordered:
                doc.add_paragraph(li.text, style='List Number')
            else:
                doc.add_paragraph(li.text, style='List Bullet')
            # 遞歸處理子列表
            for child in li.children:
                if child.name in ['ul', 'ol']:
                    self.add_list(doc, child, child.name == 'ol')
    
    def add_table(self, doc, element):
        rows = element.find_all('tr')
        if not rows:
            return
            
        # 創(chuàng)建表格
        table = doc.add_table(rows=len(rows), cols=len(rows[0].find_all(['th', 'td'])))
        table.style = 'Table Grid'  # 添加邊框
        
        for i, row in enumerate(rows):
            cells = row.find_all(['th', 'td'])
            for j, cell in enumerate(cells):
                table.cell(i, j).text = cell.get_text()
                # 設(shè)置中文字體
                for paragraph in table.cell(i, j).paragraphs:
                    for run in paragraph.runs:
                        run.font.name = '微軟雅黑'
                        run._element.rPr.rFonts.set(qn('w:eastAsia'), '微軟雅黑')
                
                # 表頭加粗
                if cell.name == 'th':
                    for paragraph in table.cell(i, j).paragraphs:
                        for run in paragraph.runs:
                            run.font.bold = True
    
    def add_code_block(self, doc, element):
        code = element.find('code')
        if not code:
            return
            
        code_text = code.get_text()
        
        # 添加代碼段落
        p = doc.add_paragraph()
        p.paragraph_format.left_indent = Inches(0.5)
        p.paragraph_format.space_before = Pt(6)
        p.paragraph_format.space_after = Pt(6)
        
        run = p.add_run(code_text)
        run.font.name = 'Consolas'
        run.font.size = Pt(10)
        run.font.color.rgb = RGBColor(0x36, 0x36, 0x36)
        
        # 添加灰色背景
        shading_elm = p._element.get_or_add_pPr().get_or_add_shd()
        shading_elm.set(qn('w:fill'), 'F0F0F0')
    
    def add_quote(self, doc, element):
        p = doc.add_paragraph()
        p.paragraph_format.left_indent = Inches(0.5)
        p.paragraph_format.first_line_indent = Inches(-0.25)
        p.paragraph_format.space_before = Pt(6)
        p.paragraph_format.space_after = Pt(6)
        
        run = p.add_run(element.get_text())
        run.font.name = '微軟雅黑'
        run._element.rPr.rFonts.set(qn('w:eastAsia'), '微軟雅黑')
        run.font.italic = True
        run.font.color.rgb = RGBColor(0x66, 0x66, 0x66)
        
        # 添加左邊框
        p._element.get_or_add_pPr().get_or_add_pBdr().left.val = 'single'
        p._element.get_or_add_pPr().get_or_add_pBdr().left.sz = 4
        p._element.get_or_add_pPr().get_or_add_pBdr().left.color = 'auto'
    
    def add_horizontal_rule(self, doc):
        p = doc.add_paragraph()
        p.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
        run = p.add_run('―' * 30)  # 使用長破折號(hào)作為分隔線
        run.font.color.rgb = RGBColor(0xCC, 0xCC, 0xCC)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    
    # 設(shè)置應(yīng)用程序字體
    font = QFont('Microsoft YaHei', 10)
    app.setFont(font)
    
    # 設(shè)置樣式表
    app.setStyleSheet('''
        QMainWindow {
            background-color: #f5f7fa;
        }
        QLabel {
            color: #34495e;
        }
    ''')
    
    converter = MarkdownToDocxConverter()
    converter.show()
    sys.exit(app.exec_())

使用說明

運(yùn)行程序后,點(diǎn)擊"選擇 Markdown 文件"按鈕選擇要轉(zhuǎn)換的.md文件

文件內(nèi)容將顯示在預(yù)覽框中

點(diǎn)擊"轉(zhuǎn)換為 DOCX"按鈕選擇保存位置并開始轉(zhuǎn)換

轉(zhuǎn)換過程中會(huì)顯示進(jìn)度條和狀態(tài)信息

轉(zhuǎn)換完成后會(huì)彈出提示框

依賴安裝

在運(yùn)行此程序前,需要安裝以下依賴:

pip install PyQt5 markdown python-docx beautifulsoup4

功能擴(kuò)展建議

  • 可以添加批量轉(zhuǎn)換功能
  • 可以增加對更多Markdown擴(kuò)展語法的支持
  • 可以添加主題切換功能
  • 可以增加轉(zhuǎn)換歷史記錄功能

這個(gè)工具提供了美觀的界面和完整的Markdown到DOCX轉(zhuǎn)換功能,支持表格、代碼塊等復(fù)雜元素的轉(zhuǎn)換,并提供了實(shí)時(shí)預(yù)覽和進(jìn)度顯示。

到此這篇關(guān)于Python結(jié)合PyQt5實(shí)現(xiàn)MD(Markdown)轉(zhuǎn)DOCX工具的文章就介紹到這了,更多相關(guān)Python Markdown轉(zhuǎn)DOCX內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • python庫fire使用教程

    python庫fire使用教程

    本文主要介紹了python庫fire使用教程,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-01-01
  • Python OpenCV圖像復(fù)原的實(shí)現(xiàn)步驟

    Python OpenCV圖像復(fù)原的實(shí)現(xiàn)步驟

    Python OpenCV圖像復(fù)原是一個(gè)涉及去除噪聲、模糊等失真的過程,旨在恢復(fù)圖像的原始質(zhì)量,以下是一個(gè)詳細(xì)的案例教程,包括理論背景和具體實(shí)現(xiàn)步驟,需要的朋友可以參考下
    2024-12-12
  • python列表的逆序遍歷實(shí)現(xiàn)

    python列表的逆序遍歷實(shí)現(xiàn)

    這篇文章主要介紹了python列表的逆序遍歷實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04
  • python3對拉勾數(shù)據(jù)進(jìn)行可視化分析的方法詳解

    python3對拉勾數(shù)據(jù)進(jìn)行可視化分析的方法詳解

    這篇文章主要給大家介紹了關(guān)于python3對拉勾數(shù)據(jù)進(jìn)行可視化分析的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Python3具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • Python學(xué)習(xí)筆記之列表推導(dǎo)式實(shí)例分析

    Python學(xué)習(xí)筆記之列表推導(dǎo)式實(shí)例分析

    這篇文章主要介紹了Python學(xué)習(xí)筆記之列表推導(dǎo)式,結(jié)合實(shí)例形式分析Python列表推導(dǎo)式的原理、寫法與相關(guān)使用技巧,需要的朋友可以參考下
    2019-08-08
  • Python?socket如何解析HTTP請求內(nèi)容

    Python?socket如何解析HTTP請求內(nèi)容

    這篇文章主要介紹了Python?socket如何解析HTTP請求內(nèi)容,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • Python使用BeautifulSoup解析并獲取圖片的實(shí)戰(zhàn)分享

    Python使用BeautifulSoup解析并獲取圖片的實(shí)戰(zhàn)分享

    這篇文章主要介紹了Python使用BeautifulSoup解析并獲取圖片的實(shí)戰(zhàn)分享,文中通過代碼和圖文結(jié)合的方式給大家講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-06-06
  • Tensorflow加載Vgg預(yù)訓(xùn)練模型操作

    Tensorflow加載Vgg預(yù)訓(xùn)練模型操作

    這篇文章主要介紹了Tensorflow加載Vgg預(yù)訓(xùn)練模型操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-05-05
  • Python lambda表達(dá)式原理及用法解析

    Python lambda表達(dá)式原理及用法解析

    這篇文章主要介紹了Python lambda表達(dá)式原理及用法解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08
  • pytorch 如何查看數(shù)據(jù)類型和大小

    pytorch 如何查看數(shù)據(jù)類型和大小

    這篇文章主要介紹了pytorch 實(shí)現(xiàn)查看數(shù)據(jù)類型和大小的操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-05-05

最新評論