Doc批量离线转PDF

11 11月
作者:cinjep|分类:代码开源

虽然WPS和Office都自带转Pdf功能,但是批量转对于普通用户来说有一定难度,所以写此小应用(文末有下载)

软件运行需要调用 wps文字 或 word 组件,优先调用wps文字

支持文件拖拽放入,最大测试量500个 doc或docx 。

转换后pdf文件与源文件对比无任何格式失真。 

图片.png

图片.png

widget.cpp

#include "widget.h"
#include "ui_widget.h"

#include <QAxObject>
#include <QDebug>
#include <QMessageBox>

#include <QTextCodec>

#include <QFileDialog>
#include <QDir>
#include <QMenu>
#include <QPoint>
#include <QMimeData>
#include <QDropEvent>
#include <QProgressBar>
#include "about.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->initUI();

    ui->listWidget->setDragDropMode(QAbstractItemView::InternalMove);
    ui->listWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
    this->setAcceptDrops(true);
    ui->topWidget->installEventFilter(this);

    ui->listWidget->setContextMenuPolicy(Qt::CustomContextMenu);
    ui->lineEdit->setPlaceholderText("选择文件保存路径");

    connect(ui->setPathBtn,&QPushButton::clicked,this,&Widget::setPdfPath);
    connect(ui->listWidget,SIGNAL(customContextMenuRequested(const QPoint &)),this,SLOT(onCustomContextMenuRequested(const QPoint &)));
    connect(ui->lineEdit,&QLineEdit::textChanged,this,&Widget::isReady);
    connect(ui->coverBtn,&QPushButton::clicked,this,&Widget::coverToPdf);
    connect(ui->closeBtn,&QPushButton::clicked,this,&Widget::close);
    connect(ui->helpBtn,&QPushButton::clicked,this,&Widget::openAbout);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::initUI(){
    this->setWindowFlags(Qt::FramelessWindowHint);
    this->setMaximumHeight(591);
    this->setMinimumHeight(591);
    this->setMaximumWidth(511);
    this->setMinimumWidth(511);
    ui->lineEdit->setFocusPolicy(Qt::NoFocus);
    ui->coverBtn->setEnabled(false);
    ui->progressBar->setOrientation(Qt::Horizontal);  // 水平方向
    ui->progressBar->setMinimum(0);
    ui->progressBar->setMaximum(100);
    ui->progressBar->setMaximumHeight(22);
    ui->progressBar->setMaximumWidth(401);
    QPixmap pixmap(":/res/bg.png"); //通过构造函数载入图片方式
    pixmap.scaled(ui->bgLabel->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
    ui->bgLabel->setScaledContents(true);
    ui->bgLabel->setPixmap(pixmap);
    QFile file(":/res/style.qss");
    file.open(QFile::ReadOnly);
    QString styleSheet = QLatin1String(file.readAll());
    this->setStyleSheet(styleSheet);
    file.close();
    ui->coverLabel->setAlignment(Qt::AlignLeft);
}

void Widget::setPdfPath(){

    QString defaultPath = QDir::currentPath();
    QString dirPath = QFileDialog::getExistingDirectory(this,tr("浏览选择文件夹"),defaultPath);

    QTextCodec *code = QTextCodec::codecForName("UTF-8");
    QString filename = QString::fromStdString(code->fromUnicode(dirPath).data());
    dirPath = QDir::toNativeSeparators(dirPath);

    if(dirPath.isEmpty())
    {
        return;
    }
    else
    {
        ui->lineEdit->setText(dirPath);
    }
}

void Widget::convertWpsToPdf(const QString &docFilePath, const QString &pdfFilePath) {
    QAxObject wpsApp("KWPS.Application");
    wpsApp.dynamicCall("SetVisible(bool)", false);
    QAxObject* docs = wpsApp.querySubObject("Documents");
    QAxObject* doc = docs->querySubObject("Open(const QString&)", docFilePath);
    if (doc) {
        doc->dynamicCall("ExportAsFixedFormat(const QString&, WdExportFormat)", pdfFilePath, 17); 
        doc->dynamicCall("Close()");
    }
    wpsApp.dynamicCall("Quit()");
}

void Widget::convertDocToPdf(const QString &docFilePath, const QString &pdfFilePath) {
    QAxObject wordApp("Word.Application");
    wordApp.dynamicCall("SetVisible(bool)", false); // 隐藏Word界面
    QAxObject* docs = wordApp.querySubObject("Documents");
    QAxObject* doc = docs->querySubObject("Open(const QString&)", docFilePath);
    if (doc) {
        doc->dynamicCall("ExportAsFixedFormat(const QString&, WdExportFormat)", pdfFilePath, 17); 
        doc->dynamicCall("Close()");
    }
    wordApp.dynamicCall("Quit()");
}

//右键删除
void Widget::onCustomContextMenuRequested(const QPoint &pos)
{
    QListWidgetItem* curItem = ui->listWidget->itemAt(pos);
    if( curItem == NULL )
        return;

    QIcon icon3 = QIcon(":/res/del.png");
    QMenu *popMenu = new QMenu(ui->listWidget);
    QAction *Menu3 = new QAction(icon3,"删除");
    popMenu->addAction(Menu3);
    connect(Menu3, SIGNAL(triggered(bool)), this, SLOT(onDelItem()));
    popMenu->exec(QCursor::pos());
}

//删除选中
void Widget::onDelItem()
{
    QList<QListWidgetItem*> list = ui->listWidget->selectedItems();
    if(list.size() == 0)
        return;
    for(int i=0;i<list.count();i++){
        QListWidgetItem *sel = list[i];
        if(sel){
            ui->listWidget->removeItemWidget(sel);
            delete sel;

            this->listWidgetChanged();
            this->isReady();
        }
    }
}

void Widget::dragEnterEvent(QDragEnterEvent *event)
{
    if(event->mimeData()->hasUrls())
    {
        event->acceptProposedAction(); //事件数据中存在路径,方向事件
    }
    else
    {
        event->ignore();
    }
}

//拖动文件到窗口释放文件,触发
void Widget::dropEvent(QDropEvent *event)
{
    const QMimeData *mimeData = event->mimeData();
    if(mimeData->hasUrls())
    {
        QList<QUrl> urls = mimeData->urls();
        for(int i=0;i<urls.count();i++)
        {
            QListWidgetItem *item = new QListWidgetItem;
            item->setSizeHint(QSize(0,24));
            QString fileName = urls.at(i).toLocalFile();
            QFileInfo fileinfo = QFileInfo(fileName);
            item->setText(fileinfo.fileName());
            QString suf = fileinfo.suffix();
            if(suf == "doc" || suf == "docx" || suf == "DOC" || suf == "DOCX")
            {
                ui->listWidget->addItem(item);
                item->setData(Qt::UserRole,fileName);
                this->listWidgetChanged();
                this->isReady();
            }
        }
    }
}

void Widget::listWidgetChanged(){
    int itemCount = ui->listWidget->count();
    if(itemCount==0){
        ui->statusLabel->setVisible(false);
        ui->coverLabel->setVisible(false);
        ui->progressBar->setValue(0);
    }
    else{
        ui->statusLabel->setAlignment(Qt::AlignLeft);
        QString countInfo = QString("文件数:%1").arg(itemCount);
        ui->statusLabel->setVisible(true);
        ui->statusLabel->setText(countInfo);
        ui->coverLabel->setVisible(true);
    }
}

void Widget::isReady(){
    if(ui->lineEdit->text().isEmpty() || ui->listWidget->count()==0){
        ui->coverBtn->setEnabled(false);
    }
    else{
        ui->coverBtn->setEnabled(true);
    }
}

void Widget::coverToPdf(){
    if(!(ui->lineEdit->text().isEmpty() || ui->listWidget->count()==0)){
        ui->coverLabel->setVisible(true);
        ui->coverLabel->setText("准备转换 ......");
        QAxObject wpsApp("KWPS.Application");
        QAxObject wordApp("Word.Application");
        ui->progressBar->setValue(0);
        int docCount = ui->listWidget->count();
        int coverCount = 0;
        QString currentInfo;
        int currentPro = 0;
        int appFlag = 0;
        for(int i = 0; i< docCount; i++){
            QString docFullName = ui->listWidget->item(i)->data(Qt::UserRole).toString();
            QFileInfo docInfo(docFullName);
            QString pdfPath = ui->lineEdit->text();
            QString pdfFullName = pdfPath +"\\"+ docInfo.baseName()+".pdf";

            QTextCodec *code = QTextCodec::codecForName("UTF-8");
            docFullName = QString::fromStdString(code->fromUnicode(docFullName).data());
            docFullName = QDir::toNativeSeparators(docFullName); 

            pdfPath = QString::fromStdString(code->fromUnicode(pdfPath).data()); 
            pdfPath = QDir::toNativeSeparators(pdfPath); 

            ui->listWidget->setCurrentRow(i);
            if(!wpsApp.isNull()){
               convertWpsToPdf(docFullName, pdfFullName);
               coverCount = coverCount + 1;
               appFlag = 1;
            }
            else if(!wordApp.isNull()){
               convertDocToPdf(docFullName, pdfFullName);
               coverCount = coverCount + 1;
               appFlag = 2;
            }
            else{
               QMessageBox msgbox;
               msgbox.setWindowTitle("出错提示");
               msgbox.setInformativeText("无法进行格式转换,程序将正常退出!");
               msgbox.setStandardButtons(QMessageBox::Ok);
               msgbox.setButtonText(QMessageBox::Ok, QStringLiteral("确定"));
               int reply = msgbox.exec();
               if(reply == QMessageBox::Ok)
               {
                   break;
                   this->close();
               }
            }
            currentInfo = QString("完成数:%1").arg(coverCount);
            ui->coverLabel->setText(currentInfo);
            currentPro = int((i+1)*100/docCount);
            ui->progressBar->setValue(currentPro);
        }


        if(appFlag>0){
            if(appFlag == 1){
                wpsApp.clear();
                //wpsApp.dynamicCall("Quit()");
            }
            else{
                wordApp.clear();
                //wordApp.dynamicCall("Quit()");
            }
        }
    }
}

void Widget::closeEvent(QCloseEvent *event)
{
        event->accept();
        Widget::deleteLater();
}

void Widget::openAbout()
{
    about *a = new about(this);
    a->setModal(false);
    a->show();
}

void Widget::mouseMoveEvent(QMouseEvent *event)
{
    if(m_leftButtonPressed && !this->window()->isMaximized())
    {
        this->window()->move(this->window()->geometry().topLeft()+event->globalPos()-m_start);
        m_start = event->globalPos();
    }
}

void Widget::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button()==Qt::LeftButton){
        m_leftButtonPressed = false;
    }
}

bool Widget::eventFilter(QObject *watched, QEvent * event)
{
    if(event->type()==QEvent::MouseButtonDblClick)
    {
        QMouseEvent * e = static_cast<QMouseEvent *>(event);
        if(e->button() == Qt::LeftButton)
        {
            if(watched==ui->topWidget)
                //ui->restoreBtn->click();
            return true;
        }
    }
    return QWidget::eventFilter(watched, event);
}
void Widget::mousePressEvent(QMouseEvent *event)
{
    if(event->button()==Qt::LeftButton)
    {
        m_leftButtonPressed = true;
        m_start = event->globalPos();
    }
}

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QAxWidget>


QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    void dragEnterEvent(QDragEnterEvent *event);
    void dropEvent(QDropEvent *event);

    void mousePressEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);
    bool eventFilter(QObject *watched, QEvent *event);

private slots:
    void convertWpsToPdf(const QString &docFilePath, const QString &pdfFilePath);
    void convertDocToPdf(const QString &docFilePath, const QString &pdfFilePath);
    void setPdfPath();
    void onDelItem();
    void onCustomContextMenuRequested(const QPoint &pos);
    void listWidgetChanged();
    void isReady();
    void coverToPdf();
    void closeEvent(QCloseEvent *event);
    void openAbout();

private:
    Ui::Widget *ui;

    void initUI();
    QPoint m_start;  //起始点
    QPoint m_end;    //结束点
    bool m_leftButtonPressed;   //鼠标左键按下标记




};
#endif // WIDGET_H

widget.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Widget</class>
 <widget class="QWidget" name="Widget">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>511</width>
    <height>591</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Doc批量转Pdf</string>
  </property>
  <widget class="QLabel" name="label">
   <property name="geometry">
    <rect>
     <x>20</x>
     <y>502</y>
     <width>51</width>
     <height>16</height>
    </rect>
   </property>
   <property name="text">
    <string>保存位置</string>
   </property>
  </widget>
  <widget class="QLineEdit" name="lineEdit">
   <property name="geometry">
    <rect>
     <x>80</x>
     <y>500</y>
     <width>331</width>
     <height>23</height>
    </rect>
   </property>
  </widget>
  <widget class="QPushButton" name="setPathBtn">
   <property name="geometry">
    <rect>
     <x>420</x>
     <y>500</y>
     <width>71</width>
     <height>23</height>
    </rect>
   </property>
   <property name="text">
    <string>选择</string>
   </property>
  </widget>
  <widget class="QProgressBar" name="progressBar">
   <property name="geometry">
    <rect>
     <x>20</x>
     <y>530</y>
     <width>391</width>
     <height>23</height>
    </rect>
   </property>
   <property name="value">
    <number>0</number>
   </property>
   <property name="alignment">
    <set>Qt::AlignCenter</set>
   </property>
   <property name="textVisible">
    <bool>true</bool>
   </property>
   <property name="orientation">
    <enum>Qt::Horizontal</enum>
   </property>
   <property name="textDirection">
    <enum>QProgressBar::TopToBottom</enum>
   </property>
  </widget>
  <widget class="QPushButton" name="coverBtn">
   <property name="geometry">
    <rect>
     <x>420</x>
     <y>530</y>
     <width>71</width>
     <height>23</height>
    </rect>
   </property>
   <property name="text">
    <string>开始</string>
   </property>
  </widget>
  <widget class="QLabel" name="statusLabel">
   <property name="geometry">
    <rect>
     <x>10</x>
     <y>572</y>
     <width>91</width>
     <height>16</height>
    </rect>
   </property>
   <property name="text">
    <string/>
   </property>
   <property name="alignment">
    <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
   </property>
  </widget>
  <widget class="QListWidget" name="listWidget">
   <property name="geometry">
    <rect>
     <x>20</x>
     <y>50</y>
     <width>471</width>
     <height>441</height>
    </rect>
   </property>
  </widget>
  <widget class="QLabel" name="coverLabel">
   <property name="geometry">
    <rect>
     <x>110</x>
     <y>572</y>
     <width>391</width>
     <height>16</height>
    </rect>
   </property>
   <property name="text">
    <string/>
   </property>
   <property name="alignment">
    <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
   </property>
  </widget>
  <widget class="QLabel" name="bgLabel">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>511</width>
     <height>591</height>
    </rect>
   </property>
   <property name="text">
    <string/>
   </property>
  </widget>
  <widget class="QPushButton" name="closeBtn">
   <property name="geometry">
    <rect>
     <x>480</x>
     <y>7</y>
     <width>22</width>
     <height>22</height>
    </rect>
   </property>
   <property name="text">
    <string/>
   </property>
  </widget>
  <widget class="QPushButton" name="helpBtn">
   <property name="geometry">
    <rect>
     <x>450</x>
     <y>7</y>
     <width>22</width>
     <height>22</height>
    </rect>
   </property>
   <property name="text">
    <string/>
   </property>
  </widget>
  <widget class="QWidget" name="topWidget" native="true">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>511</width>
     <height>33</height>
    </rect>
   </property>
  </widget>
  <zorder>topWidget</zorder>
  <zorder>bgLabel</zorder>
  <zorder>label</zorder>
  <zorder>lineEdit</zorder>
  <zorder>setPathBtn</zorder>
  <zorder>progressBar</zorder>
  <zorder>coverBtn</zorder>
  <zorder>statusLabel</zorder>
  <zorder>listWidget</zorder>
  <zorder>coverLabel</zorder>
  <zorder>closeBtn</zorder>
  <zorder>helpBtn</zorder>
 </widget>
 <resources/>
 <connections/>
</ui>

下载: Doc批量离线转Pdf

浏览121
返回
目录
返回
首页
LNMP环境搭建 单摆实验模拟 探索简谐运动与物理原理