Doc批量离线转PDF
虽然WPS和Office都自带转Pdf功能,但是批量转对于普通用户来说有一定难度,所以写此小应用(文末有下载)
软件运行需要调用 wps文字 或 word 组件,优先调用wps文字
支持文件拖拽放入,最大测试量500个 doc或docx 。
转换后pdf文件与源文件对比无任何格式失真。


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_Hwidget.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
目录 返回
首页