【DBF格式转换器.exe】

一、概要

       DBF文件是一种数据库文件格式,通常用于存储表格数据。这种文件格式曾经被广泛使用,尤其是在一些较旧的数据库系统中。然而,随着时间的推移,其他更现代的文件格式,如XLS(Excel)、CSV、DOCX(Word文档)和TXT(文本文件)变得越来越流行。转换成这些现代文件格式的主要优势包括:

       1、兼容性:这些格式被更广泛的软件支持,包括Microsoft Office套件和其他许多现代的数据分析工具;(主要是用DBF的软件需要付费阅读)

       2、可读性:这些格式更容易被人类读取和理解。例如,CSV和TXT文件是纯文本文件,可以用任何文本编辑器打开。而XLS和DOCX文件则可以用Microsoft Office或类似的软件打开,这些软件提供了丰富的用户界面和数据分析工具;

       3、数据处理:转换成CSV或XLS格式可以使数据更容易被导入到数据分析工具或电子表格软件中,从而进行更高级的数据处理和分析;

       4、共享和发布:这些现代文件格式更适合于共享和发布数据。例如,如果你有一个数据集并希望其他人能够查看或分析,将其转换为CSV或XLS格式可能会更加方便。

       因此,将DBF文件转换为这些现代文件格式可以提高数据的可用性、可读性和可处理性。

二、使用说明

       1、在“DBF文件路径“中输入DBF文件路径;

       2、在“存储路径”中输入要存储的路径;

       3、选择要生成的文件格式,默认“EXCEL”;

       4、点击“运行”即可生成。

在这里插入图片描述

图1   软件操作界面

三、完整代码

       代码的整体架构比较清晰,阅读以下代码中的注释即理解。
源文件下载请点击这里【DBF格式转换器.zip

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2023-08-27 14:11
# @Author : Leuanghing Chen
# @Blog : https://blog.csdn.net/weixin_46153372?spm=1010.2135.3001.5421
# @File : DBF格式转换器.py
# @Software : PyCharm
# pyinstaller --exclude-module EXCLUDES --onefile -F -w --icon F:\python_demo\1、pyqt5_projects\25_读取dbf文件\format_conversion.ico F:\python_demo\1、pyqt5_projects\25_读取dbf文件\DBF格式转换器.py

import sys
import dbfread
import pandas as pd
from openpyxl import Workbook
from docx import Document                   # 导入docx包
from docx.shared import Pt, RGBColor, Cm    # 设置字体大小、颜色、页面边距
from docx.oxml.ns import qn                 # 中文字体
from docx.enum.table import WD_CELL_VERTICAL_ALIGNMENT      # 导入单元格垂直对齐
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT           # 导入段落对齐
from PyQt5.QtCore import QSize, QTimer
from PyQt5.QtGui import QIcon, QPixmap, QFont
from PyQt5.QtWidgets import QFileDialog, QMainWindow, QDialog, QSizePolicy, QGridLayout, QTextEdit, QWidget, QLineEdit, QLabel, QToolButton
from PyQt5 import QtCore, QtGui, QtWidgets


# 使用说明对话框
class Instructions_Dialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.setWindowTitle("使用说明")
        self.resize(420, 270)
        sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth())
        self.setSizePolicy(sizePolicy)
        self.setMinimumSize(QSize(420, 270))
        self.setMaximumSize(QSize(420, 270))

        self.icon = QIcon()
        self.icon.addPixmap(QPixmap(r"F:\python_demo\1、pyqt5_projects\25_读取dbf文件\illustrate.ico"), QIcon.Normal, QIcon.Off)
        self.setWindowIcon(self.icon)

        self.gridLayout = QGridLayout(self)
        self.textEdit = QTextEdit(self)
        sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.textEdit.sizePolicy().hasHeightForWidth())
        self.textEdit.setSizePolicy(sizePolicy)
        self.textEdit.setMinimumSize(QSize(400, 250))
        self.textEdit.setMaximumSize(QSize(400, 250))
        self.textEdit.setFont(QFont("Times New Roman", 12))
        self.textEdit.setStyleSheet("font: 12pt \"Times New Roman\";")
        self.textEdit.insertHtml(
            "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
            "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
            "p, li { white-space: pre-wrap; }\n"
            "</style></head><body style=\" font-family:\'Times New Roman\'; font-size:12pt; font-weight:400; font-style:normal;\">\n"
            "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'SimSun\';\">1</span><span style=\" font-family:\'宋体\';\">、在“新</span><span style=\" font-family:\'SimSun\';\">BOM</span><span style=\" font-family:\'宋体\';\">路径“中输入新</span><span style=\" font-family:\'SimSun\';\">BOM</span><span style=\" font-family:\'宋体\';\">表所在的文件夹路径;</span><span style=\" font-family:\'SimSun\';\"> </span></p>\n"
            "<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'SimSun\';\">2</span><span style=\" font-family:\'宋体\';\">、在“存储路径”中输入公司统一整理的</span><span style=\" font-family:\'SimSun\';\">BOM</span><span style=\" font-family:\'宋体\';\">文件夹,其中记录了新旧</span><span style=\" font-family:\'SimSun\';\">BOM</span><span style=\" font-family:\'宋体\';\">表;</span><span style=\" font-family:\'SimSun\';\"> </span></p>\n"
            "<p style=\" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'SimSun\';\">3</span><span style=\" font-family:\'宋体\';\">、点击“</span><span style=\" font-family:\'SimSun\';\">create</span><span style=\" font-family:\'宋体\';\">”即可将新</span><span style=\" font-family:\'SimSun\';\">BOM</span><span style=\" font-family:\'宋体\';\">表放入指定的文件夹:新</span><span style=\" font-family:\'SimSun\';\">BOM</span><span style=\" font-family:\'宋体\';\">表会移至“可编辑</span><span style=\" font-family:\'SimSun\';\">EXCEL</span><span style=\" font-family:\'宋体\';\">版本”和“最新版本”两个文件夹中,原在这两个文件夹的文件会移至“旧版本”文件夹,用于留档记录。</span><span style=\" font-family:\'SimSun\';\"> </span></p></body></html>")
        self.gridLayout.addWidget(self.textEdit, 0, 0, 1, 1)


# 版本对话框
class version_Dialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.setObjectName("Dialog")

        self.icon = QtGui.QIcon()
        self.icon.addPixmap(
            QtGui.QPixmap(r"F:\python_demo\1、pyqt5_projects\25_读取dbf文件\version.ico"),
            QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.setWindowIcon(self.icon)

        self.resize(420, 270)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth())
        self.setSizePolicy(sizePolicy)
        self.setMinimumSize(QtCore.QSize(420, 270))
        self.setMaximumSize(QtCore.QSize(420, 270))
        self.gridLayout = QtWidgets.QGridLayout(self)
        self.gridLayout.setObjectName("gridLayout")
        self.version_textEdit = QtWidgets.QTextEdit(self)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.version_textEdit.sizePolicy().hasHeightForWidth())
        self.version_textEdit.setSizePolicy(sizePolicy)
        self.version_textEdit.setMinimumSize(QtCore.QSize(400, 250))
        self.version_textEdit.setMaximumSize(QtCore.QSize(400, 250))
        font = QtGui.QFont()
        font.setFamily("Times New Roman")
        font.setPointSize(12)
        self.version_textEdit.setFont(font)
        self.version_textEdit.setStyleSheet("font: 12pt \"Times New Roman\";")
        self.version_textEdit.setObjectName("version_textEdit")
        self.version_textEdit.setReadOnly(True)         # 禁止编辑version_textEdit
        self.gridLayout.addWidget(self.version_textEdit)

        _translate = QtCore.QCoreApplication.translate
        self.setWindowTitle(_translate("Dialog", "版本"))
        self.version_textEdit.setHtml(_translate("Dialog",
                                                 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
                                                 "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
                                                 "p, li { white-space: pre-wrap; }\n"
                                                 "</style></head><body style=\" font-family:\'Times New Roman\'; font-size:12pt; font-weight:400; font-style:normal;\">\n"
                                                 "<p align=\"justify\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'SimSun\';\">Version:V1.0.20230902</span></p>\n"
                                                 "<p align=\"justify\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'SimSun\';\">Author:Leuanghing Chen</span></p>\n"
                                                 "<p align=\"justify\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-family:\'SimSun\';\">Blog:https://blog.csdn.net/weixin_46153372?spm=1010.2135.3001.5421</span></p></body></html>"))


# 主界面
class Ui_MainWindow(object):
    savepath_lineEdit: QLineEdit
    dbfpath_toolButton: QToolButton
    savepath_label: QLabel
    dbfpath_label: QLabel
    dbfpath_lineEdit: QLineEdit
    gridLayout: QGridLayout
    gridLayout_2: QGridLayout
    centralwidget: QWidget

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(750, 405)
        font = QtGui.QFont()
        font.setFamily("楷体")
        font.setPointSize(14)
        MainWindow.setFont(font)
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap("format_conversion.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        MainWindow.setWindowIcon(icon)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout_2 = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.gridLayout = QtWidgets.QGridLayout()
        self.gridLayout.setObjectName("gridLayout")
        self.dbfpath_label = QtWidgets.QLabel(self.centralwidget)
        self.dbfpath_label.setMinimumSize(QtCore.QSize(150, 30))
        self.dbfpath_label.setMaximumSize(QtCore.QSize(150, 30))
        font = QtGui.QFont()
        font.setFamily("楷体")
        font.setPointSize(14)
        font.setBold(True)
        font.setWeight(75)
        self.dbfpath_label.setFont(font)
        self.dbfpath_label.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter)
        self.dbfpath_label.setObjectName("dbfpath_label")
        self.gridLayout.addWidget(self.dbfpath_label, 0, 0, 1, 1)
        self.dbfpath_lineEdit = QtWidgets.QLineEdit(self.centralwidget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.dbfpath_lineEdit.sizePolicy().hasHeightForWidth())
        self.dbfpath_lineEdit.setSizePolicy(sizePolicy)
        self.dbfpath_lineEdit.setMinimumSize(QtCore.QSize(450, 30))
        self.dbfpath_lineEdit.setMaximumSize(QtCore.QSize(16777215, 30))
        font = QtGui.QFont()
        font.setFamily("楷体")
        font.setPointSize(12)
        self.dbfpath_lineEdit.setFont(font)
        self.dbfpath_lineEdit.setObjectName("dbfpath_lineEdit")
        self.gridLayout.addWidget(self.dbfpath_lineEdit, 0, 1, 1, 6)
        self.dbfpath_toolButton = QtWidgets.QToolButton(self.centralwidget)
        self.dbfpath_toolButton.setMinimumSize(QtCore.QSize(60, 30))
        self.dbfpath_toolButton.setMaximumSize(QtCore.QSize(60, 30))
        font = QtGui.QFont()
        font.setFamily("楷体")
        font.setPointSize(14)
        font.setBold(True)
        font.setWeight(75)
        self.dbfpath_toolButton.setFont(font)
        self.dbfpath_toolButton.setObjectName("dbfpath_toolButton")
        self.gridLayout.addWidget(self.dbfpath_toolButton, 0, 7, 1, 1)
        self.savepath_label = QtWidgets.QLabel(self.centralwidget)
        self.savepath_label.setMinimumSize(QtCore.QSize(150, 30))
        self.savepath_label.setMaximumSize(QtCore.QSize(150, 30))
        font = QtGui.QFont()
        font.setFamily("楷体")
        font.setPointSize(14)
        font.setBold(True)
        font.setWeight(75)
        self.savepath_label.setFont(font)
        self.savepath_label.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter)
        self.savepath_label.setObjectName("savepath_label")
        self.gridLayout.addWidget(self.savepath_label, 1, 0, 1, 1)
        self.savepath_lineEdit = QtWidgets.QLineEdit(self.centralwidget)
        self.savepath_lineEdit.setMinimumSize(QtCore.QSize(450, 30))
        self.savepath_lineEdit.setMaximumSize(QtCore.QSize(16777215, 30))
        font = QtGui.QFont()
        font.setFamily("楷体")
        font.setPointSize(12)
        self.savepath_lineEdit.setFont(font)
        self.savepath_lineEdit.setObjectName("savepath_lineEdit")
        self.gridLayout.addWidget(self.savepath_lineEdit, 1, 1, 1, 6)
        self.savepath_toolButton = QtWidgets.QToolButton(self.centralwidget)
        self.savepath_toolButton.setMinimumSize(QtCore.QSize(60, 30))
        self.savepath_toolButton.setMaximumSize(QtCore.QSize(60, 30))
        font = QtGui.QFont()
        font.setFamily("楷体")
        font.setPointSize(14)
        font.setBold(True)
        font.setWeight(75)
        self.savepath_toolButton.setFont(font)
        self.savepath_toolButton.setObjectName("savepath_toolButton")
        self.gridLayout.addWidget(self.savepath_toolButton, 1, 7, 1, 1)
        self.savepath_type_label = QtWidgets.QLabel(self.centralwidget)
        self.savepath_type_label.setMinimumSize(QtCore.QSize(150, 60))
        self.savepath_type_label.setMaximumSize(QtCore.QSize(150, 60))
        font = QtGui.QFont()
        font.setFamily("楷体")
        font.setPointSize(14)
        font.setBold(True)
        font.setWeight(75)
        self.savepath_type_label.setFont(font)
        self.savepath_type_label.setAlignment(QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter)
        self.savepath_type_label.setObjectName("savepath_type_label")
        self.gridLayout.addWidget(self.savepath_type_label, 2, 0, 1, 1)
        self.excel_radioButton = QtWidgets.QRadioButton(self.centralwidget)
        self.excel_radioButton.setEnabled(True)
        font = QtGui.QFont()
        font.setFamily("楷体")
        font.setPointSize(14)
        font.setBold(True)
        font.setWeight(75)
        font.setKerning(True)
        self.excel_radioButton.setFont(font)
        self.excel_radioButton.setMouseTracking(True)
        self.excel_radioButton.setTabletTracking(False)
        self.excel_radioButton.setChecked(True)
        self.excel_radioButton.setObjectName("excel_radioButton")
        self.gridLayout.addWidget(self.excel_radioButton, 2, 1, 1, 1)
        self.csv_radioButton = QtWidgets.QRadioButton(self.centralwidget)
        font = QtGui.QFont()
        font.setFamily("楷体")
        font.setPointSize(14)
        font.setBold(True)
        font.setWeight(75)
        self.csv_radioButton.setFont(font)
        self.csv_radioButton.setObjectName("csv_radioButton")
        self.gridLayout.addWidget(self.csv_radioButton, 2, 2, 1, 1)
        self.word_radioButton = QtWidgets.QRadioButton(self.centralwidget)
        font = QtGui.QFont()
        font.setFamily("楷体")
        font.setPointSize(14)
        font.setBold(True)
        font.setWeight(75)
        self.word_radioButton.setFont(font)
        self.word_radioButton.setObjectName("word_radioButton")
        self.gridLayout.addWidget(self.word_radioButton, 2, 3, 1, 1)
        self.txt_radioButton = QtWidgets.QRadioButton(self.centralwidget)
        font = QtGui.QFont()
        font.setFamily("楷体")
        font.setPointSize(14)
        font.setBold(True)
        font.setWeight(75)
        self.txt_radioButton.setFont(font)
        self.txt_radioButton.setObjectName("txt_radioButton")
        self.gridLayout.addWidget(self.txt_radioButton, 2, 4, 1, 1)
        spacerItem = QtWidgets.QSpacerItem(78, 57, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.gridLayout.addItem(spacerItem, 2, 5, 1, 1)
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(120)
        sizePolicy.setVerticalStretch(60)
        sizePolicy.setHeightForWidth(self.pushButton.sizePolicy().hasHeightForWidth())
        self.pushButton.setSizePolicy(sizePolicy)
        self.pushButton.setMinimumSize(QtCore.QSize(120, 60))
        self.pushButton.setMaximumSize(QtCore.QSize(120, 60))
        palette = QtGui.QPalette()
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.WindowText, brush)
        brush = QtGui.QBrush(QtGui.QColor(85, 170, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Button, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.ButtonText, brush)
        brush = QtGui.QBrush(QtGui.QColor(85, 170, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(85, 170, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Window, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.WindowText, brush)
        brush = QtGui.QBrush(QtGui.QColor(85, 170, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Button, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.ButtonText, brush)
        brush = QtGui.QBrush(QtGui.QColor(85, 170, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(85, 170, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Window, brush)
        brush = QtGui.QBrush(QtGui.QColor(120, 120, 120))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.WindowText, brush)
        brush = QtGui.QBrush(QtGui.QColor(85, 170, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Button, brush)
        brush = QtGui.QBrush(QtGui.QColor(120, 120, 120))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.ButtonText, brush)
        brush = QtGui.QBrush(QtGui.QColor(85, 170, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(85, 170, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Window, brush)
        self.pushButton.setPalette(palette)
        font = QtGui.QFont()
        font.setFamily("楷体")
        font.setPointSize(20)
        self.pushButton.setFont(font)
        self.pushButton.setStyleSheet("background-color: rgb(85, 170, 255);\n"
                                      "")
        self.pushButton.setObjectName("pushButton")
        self.gridLayout.addWidget(self.pushButton, 2, 6, 1, 2)
        self.textEdit = QtWidgets.QTextEdit(self.centralwidget)
        self.textEdit.setEnabled(False)
        self.textEdit.setMinimumSize(QtCore.QSize(680, 200))
        self.textEdit.setStyleSheet("QTextEdit {  \n"
                                    "    background-color: rgb(199, 237, 204);   \n"
                                    "    selection-color: rgb(85, 255, 255);\n"
                                    "    font-family: \"楷体\";  \n"
                                    "    font-size: 14px; \n"
                                    "    }  \n"
                                    "QTextEdit::cursor {  \n"
                                    "    background-color: transparent;  \n"
                                    "    }  ")
        self.textEdit.setObjectName("textEdit")
        self.gridLayout.addWidget(self.textEdit, 3, 0, 1, 8)
        self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 750, 23))
        self.menubar.setObjectName("menubar")
        self.menu = QtWidgets.QMenu(self.menubar)
        self.menu.setObjectName("menu")
        MainWindow.setMenuBar(self.menubar)
        self.illustration_action = QtWidgets.QAction(MainWindow)
        font = QtGui.QFont()
        font.setFamily("楷体")
        font.setPointSize(12)
        self.illustration_action.setFont(font)
        self.illustration_action.setObjectName("illustration_action")
        self.version_action = QtWidgets.QAction(MainWindow)
        font = QtGui.QFont()
        font.setFamily("楷体")
        font.setPointSize(12)
        self.version_action.setFont(font)
        self.version_action.setObjectName("version_action")
        self.menu.addAction(self.illustration_action)
        self.menu.addAction(self.version_action)
        self.menubar.addAction(self.menu.menuAction())

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

        # 连接信号
        self.dbfpath_toolButton.clicked.connect(self.openFile)
        self.savepath_toolButton.clicked.connect(self.open_folder)
        self.pushButton.clicked.connect(self.format_conversion)

        # 连接对话框弹框
        self.illustration_action.triggered.connect(self.open_dialog)
        self.version_action.triggered.connect(self.open_version_dialog)

        self.textedit_initialization()

        # 创建一个定时器,每当文本改变时,都会在100毫秒后调用 self.scroll_to_bottom
        self.timer = QTimer()
        self.timer.timeout.connect(self.scroll_to_bottom)
        # 每当文本改变时,启动定时器
        self.textEdit.textChanged.connect(self.timer.start)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "DBF格式转换器"))
        self.dbfpath_label.setText(_translate("MainWindow", "DBF文件路径:"))
        self.dbfpath_toolButton.setText(_translate("MainWindow", "..."))
        self.savepath_label.setText(_translate("MainWindow", "保存路径:"))
        self.savepath_toolButton.setText(_translate("MainWindow", "..."))
        self.savepath_type_label.setText(_translate("MainWindow", "保存文件类型:"))
        self.excel_radioButton.setText(_translate("MainWindow", "EXCEL"))
        self.csv_radioButton.setText(_translate("MainWindow", "CSV"))
        self.word_radioButton.setText(_translate("MainWindow", "WORD"))
        self.txt_radioButton.setText(_translate("MainWindow", "TXT"))
        self.pushButton.setText(_translate("MainWindow", "运行"))
        self.menu.setTitle(_translate("MainWindow", "菜单"))
        self.illustration_action.setText(_translate("MainWindow", "说明"))
        self.version_action.setText(_translate("MainWindow", "版本"))

    # 确保光标在可见的范围内
    def scroll_to_bottom(self):
        self.textEdit.ensureCursorVisible()

    # 使用说明对话框
    def open_dialog(self):
        # 创建对话框实例
        dialog = Instructions_Dialog()
        # 显示对话框并等待用户响应
        dialog.exec_()

    # 版本对话框
    def open_version_dialog(self):
        # 创建对话框实例
        dialog = version_Dialog()
        # 显示对话框并等待用户响应
        dialog.exec_()

    # textEdit文本框信息初始化
    def textedit_initialization(self):
        self.textEdit.clear()
        self.textEdit.insertPlainText('Version:V1.0.20230826\n')
        self.textEdit.insertPlainText('Author:Leuanghing Chen\n')
        self.textEdit.insertPlainText('Blog:https://blog.csdn.net/weixin_46153372?spm=1010.2135.3001.5421\n')
        self.textEdit.insertPlainText('————————————————————————————————————————————————\n')
        self.textEdit.insertPlainText('The operation records are as follows:\n')

    # dbfpath_lineEdit打开文件
    def openFile(self):
        mainWindow = QMainWindow()
        file_path, _ = QFileDialog.getOpenFileName(mainWindow, 'Open file', './')
        if file_path:
            self.dbfpath_lineEdit.setText(file_path)
            self.textEdit.insertPlainText(self.dbfpath_label.text() + self.dbfpath_lineEdit.text() + "\n")

    # savepath_lineEdit打开文件夹
    def open_folder(self):
        file_dialog = QFileDialog()
        file_dialog.setFileMode(QFileDialog.Directory)
        if file_dialog.exec_() == QFileDialog.Accepted:
            directory = file_dialog.directory().absolutePath()
            self.savepath_lineEdit.setText(directory)
            self.textEdit.insertPlainText(self.savepath_label.text() + self.savepath_lineEdit.text() + "\n")

    # 转换格式
    def format_conversion(self):
        if len(self.dbfpath_lineEdit.text()) != 0 and len(self.savepath_lineEdit.text()) != 0:
            encodings = ['gbk', 'ascii', 'big5', 'big5hk', 'cp037', 'cp273', 'cp424', 'cp437', 'cp500', 'cp720', 'cp737',
                         'cp775', 'cp850', 'cp852', 'cp855', 'cp856', 'cp857', 'cp858', 'cp860', 'cp861', 'cp862', 'cp863',
                         'cp864', 'cp865', 'cp866', 'cp869', 'cp874', 'cp1006', 'cp1250', 'cp1251', 'cp1252', 'cp1253',
                         'cp1254', 'cp1255', 'cp1256', 'cp1257', 'cp1258', 'euc_cn', 'euc_jis_2004', 'euc_jisx0213',
                         'euc_jp', 'euc_kr', 'gb18030', 'gb2312', 'hz', 'iso2022_jp', 'iso2022_jp_1', 'iso2022_jp_2',
                         'iso2022_jp_2ext', 'iso2022_jp_3', 'iso2022_jp_ext', 'iso2022_kr', 'iso8859_10', 'iso8859_13',
                         'iso8859_14', 'iso8859_15', 'iso8859_16', 'iso8859_2', 'iso8859_3', 'iso8859_4', 'iso8859_5',
                         'iso8859_6', 'iso8859_7', 'iso8']

            # 尝试使用不同的编码方式读取文件
            for encoding in encodings:
                try:
                    # 读取DBF文件并转换为DataFrame
                    with dbfread.DBF(self.dbfpath_lineEdit.text(), encoding=encoding) as table:
                        records = [record for record in table]
                        df = pd.DataFrame(records)
                    self.textEdit.insertPlainText("Reading file in “{}” encoding format.\n".format(encoding))

                    # 1、文件保存为excel
                    if self.excel_radioButton.isChecked():
                        wb = Workbook()  # 创建一个新的工作簿
                        ws = wb.active  # 选择活动工作表

                        # 写入数据
                        self.textEdit.insertPlainText("Writing data......\n")
                        # 写入表头
                        for i in range(len(df.columns.tolist()) + 1):
                            if i == 0:
                                ws.cell(row=1, column=1, value="序号")
                            else:
                                ws.cell(row=1, column=i + 1, value=df.columns.tolist()[i - 1])

                        # 写入数据
                        for row in range(len(df)):
                            for col in range(len(df.columns) + 1):
                                if col == 0:
                                    ws.cell(row=row + 2, column=col + 1, value=str(df.index.tolist()[row] + 1))
                                else:
                                    ws.cell(row=row + 2, column=col + 1, value=df.iloc[row, col - 1])

                        # 保存为Excel文件
                        wb.save(self.savepath_lineEdit.text() + "/{}.xlsx".format(self.dbfpath_lineEdit.text().split(r'/')[-1].split('.')[0]))
                        self.textEdit.insertPlainText("Excel file saved.\n")
                        break

                    # 2、文件保存为csv
                    elif self.csv_radioButton.isChecked():
                        # 写入数据
                        self.textEdit.insertPlainText("Writing data......\n")

                        # 在第一列插入新的列'序号'
                        new_column = pd.Series(list(map(lambda x: x + 1, df.index.tolist())))  # df.index.tolist()元素自加1
                        df.insert(0, '序号', new_column)

                        df.to_csv(self.savepath_lineEdit.text() + "/{}.csv".format(self.dbfpath_lineEdit.text().split(r'/')[-1].split('.')[0]), index=False, encoding='gbk')
                        self.textEdit.insertPlainText("CSV file saved.\n")
                        break

                    # 3、文件保存为word
                    elif self.word_radioButton.isChecked():
                        # 写入数据
                        self.textEdit.insertPlainText("Writing data......\n")

                        # 生成word文档
                        Doc = Document()

                        # 设置页面边距
                        sec = Doc.sections[0]  # sections对应文档中的“节”
                        sec.left_margin = Cm(1.5)  # 以下依次设置左、右、上、下页面边距
                        sec.right_margin = Cm(1.5)
                        sec.top_margin = Cm(1.5)
                        sec.bottom_margin = Cm(1.5)

                        # 创建表格
                        tab = Doc.add_table(len(df) + 1, len(df.columns) + 1, style="Table Grid")

                        # 列宽
                        tab.cell(0, 0).width = Cm(1.01)
                        tab.cell(0, 1).width = Cm(3.34)
                        tab.cell(0, 2).width = Cm(3.43)
                        tab.cell(0, 3).width = Cm(5.76)
                        tab.cell(0, 4).width = Cm(3.00)
                        tab.cell(0, 5).width = Cm(2.45)

                        # 将文字写入表格
                        # 写入表头
                        for i in range(len(df.columns.tolist()) + 1):
                            if i == 0:
                                tab.cell(0, i).text = "序号"
                            else:
                                tab.cell(0, i).text = df.columns.tolist()[i - 1]

                        # 写入内容
                        for row in range(len(df)):
                            for column in range(len(df.columns) + 1):
                                try:
                                    if column == 0:
                                        tab.cell(row + 1, 0).text = str(df.index.tolist()[row] + 1)
                                    else:
                                        tab.cell(row + 1, column).text = str(df.iloc[row, column - 1])

                                except AttributeError:
                                    self.textEdit.insertPlainText("AttributeError occurred, please contact the designer!!!\n")

                        # 将表格中所有单元格修改字体
                        for col in tab.rows:
                            # 单元格
                            for cell in col.cells:
                                # 单元格对齐方式为:中部居中对齐
                                cell.vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER
                                cell.paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER

                                # 单元格的段落
                                for par in cell.paragraphs:
                                    # 设置行距
                                    par.paragraph_format.line_spacing = 1.0
                                    # 段前与段后间距
                                    par.paragraph_format.space_before = Pt(0)
                                    par.paragraph_format.space_after = Pt(0)

                                    for block in par.runs:
                                        # 字体样式操作:bold:加粗、italic:斜体、underline:带下划线、strike:删除线、double_strike:双删除线、shadow:阴影
                                        block.font.bold = False
                                        block.font.italic = False
                                        block.font.underline = False
                                        block.font.strike = False
                                        block.font.double_strike = False
                                        block.font.shadow = False
                                        # 初号=42磅 小初=36磅 一号=26磅 小一=24磅 二号=22磅 小二=18磅 三号=16磅 小三=15磅 四号=14磅
                                        # 小四=12磅 五号=10.5磅 小五=9磅 六号=7.5磅 小六=6.5磅 七号=5.5磅 八号=5磅
                                        block.font.size = Pt(12)
                                        block.font.color.rgb = RGBColor(0, 0, 0)  # rgb(0,0,0)为黑色
                                        block.font.name = '宋体'  # 英文字体设置
                                        block._element.rPr.rFonts.set(qn('w:eastAsia'), '宋体')  # 设置中文字体

                        # 第一行加粗
                        run = tab.cell(0, 0).paragraphs[0].runs[0]
                        run.font.bold = True  # 将文字块设置为粗体
                        run = tab.cell(0, 1).paragraphs[0].runs[0]
                        run.font.bold = True  # 将文字块设置为粗体
                        run = tab.cell(0, 2).paragraphs[0].runs[0]
                        run.font.bold = True  # 将文字块设置为粗体
                        run = tab.cell(0, 3).paragraphs[0].runs[0]
                        run.font.bold = True  # 将文字块设置为粗体
                        run = tab.cell(0, 4).paragraphs[0].runs[0]
                        run.font.bold = True  # 将文字块设置为粗体
                        run = tab.cell(0, 5).paragraphs[0].runs[0]
                        run.font.bold = True  # 将文字块设置为粗体

                        # 保存为Word文档
                        Doc.save(self.savepath_lineEdit.text() + "/{}.docx".format(self.dbfpath_lineEdit.text().split(r'/')[-1].split('.')[0]))
                        self.textEdit.insertPlainText("Word file saved.\n")
                        break

                    # 4、文件保存为txt
                    elif self.txt_radioButton.isChecked():
                        # 写入数据
                        self.textEdit.insertPlainText("Writing data......\n")

                        # 写入数据到txt文件
                        txt_filename = self.savepath_lineEdit.text() + "/{}.txt".format(self.dbfpath_lineEdit.text().split(r'/')[-1].split('.')[0])
                        with open(txt_filename, 'w') as file:
                            for row in range(len(df)):
                                if row == 0:
                                    for i in range(len(df.columns.tolist()) + 1):
                                        if i == 0:
                                            file.write(f"{'序号'}\t")  # 添加一个制表符
                                        else:
                                            file.write(f"{df.columns.tolist()[i - 1]}\t")  # 使用制表符(\t)分隔数据
                                    file.write("\n")  # 每行数据结束后添加换行符
                                else:
                                    file.write(f"{df.index.tolist()[row]}\t")
                                    for col in range(len(df.columns)):
                                        file.write(f"{df.iloc[row, col]}\t")  # 使用制表符(\t)分隔数据
                                    file.write("\n")  # 每行数据结束后添加换行符
                        self.textEdit.insertPlainText("TXT file saved.\n")
                        break

                    else:
                        self.textEdit.insertPlainText("Please select the file type to save.\n")

                except UnicodeDecodeError:
                    self.textEdit.insertPlainText("Failed to read file in “{}” encoding format.\n".format(encoding))

                except Exception as e:
                    # 处理未知错误
                    self.textEdit.insertPlainText("Error: {} occurred. Please contact the designer or try restarting the software!!!\n".format(str(e)))

        else:
            if len(self.dbfpath_lineEdit.text()) == 0:
                self.textEdit.insertPlainText(self.dbfpath_label.text().replace(":", "") + " is null.\n")

                if len(self.savepath_lineEdit.text()) == 0:
                    self.textEdit.insertPlainText(self.savepath_label.text().replace(":", "") + " is null.\n")


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)  # 创建一个QApplication对象
    MainWindow = QtWidgets.QMainWindow()  # 创建一个主窗口对象
    ui = Ui_MainWindow()  # 创建一个界面对象
    ui.setupUi(MainWindow)  # 设置主窗口的界面
    MainWindow.show()  # 显示主窗口
    sys.exit(app.exec_())  # 进入主事件循环,并监听窗口关闭事件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值