Qt 生成 Word、PPT、PDF 文档

一、帮助手册

微软的官方文档链接 https://msdn.microsoft.com/zh-cn/vba/word-vba/articles/documents-open-method-word

// 代码打印官方帮助文档
// 包含头文件 #include 
// 包含lib Qt5AxContainerd.lib、Qt5AxServerd.lib、Qt5AxBased.lib

// 获取 Word 帮助文档;
QAxObject *pWordApplication = new QAxObject("Word.Application", 0);
QString docWord = pWordApplication->generateDocumentation();

QFile outFile("E:/wordLog.html");
outFile.open(QIODevice::WriteOnly | QIODevice::Append);
QTextStream ts(&outFile);
ts << docWord << endl;

// 获取 PPT 帮助文档;
QAxObject *pPPTApplication = new QAxObject("PowerPoint.Application", 0);
QString docPPT = pPPTApplication ->generateDocumentation();

QFile outFile("E:/wordLog.html");
outFile.open(QIODevice::WriteOnly | QIODevice::Append);
QTextStream ts(&outFile);
ts << docWord << endl;

二、生成 Word 文档

1. 使用 HTML 格式输出

    限制:不支持 .docx 格式的 Word 文档

void LHCCreateOfficeAPDF::UseHTMLToWord()
{
    QString docname = "E:/testhtmlword.doc";
    QString html = GetHtmlInfoToFile();
    QFile outFile(docname);
    outFile.open(QIODevice::WriteOnly | QIODevice::Append);
    QTextStream ts(&outFile);
    ts << html << endl;
}
QString LHCCreateOfficeAPDF::GetHtmlInfoToFile()
{
    QString imageData = "\"E:/1.png\"";

    QDateTime current_date_time = QDateTime::currentDateTime();
    QString current_date = current_date_time.toString("yyyy-MM-dd hh:mm:ss ddd");
    QString html = "";
    html += "";
    html += "";
    html += QStringLiteral("qt实现生成word文档");
    html += "";
    html += "";
    html += "

model

"; html += "

" + current_date + "


"; html += "

测试qt实现生成word文档

"; html += "
"; html += "

word插入图片\"picture\"

"; html += "
"; html += ""; html += ""; html += ""; html += ""; html += ""; html += ""; html += ""; html += "
编程语言统计
2017-01-18---2018-01-18
"; html += ""; html += ""; html += ""; html += ""; html += ""; html += ""; html += ""; html += ""; html += ""; html += ""; html += ""; html += ""; html += ""; html += ""; html += ""; html += "
C/C++pythonjavahtmlQt
上升上升下降下降上升
"; html += ""; html += ""; return html; }

2.   使用 QAxObject 插入图片

限制:速度较慢

void LHCCreateOfficeAPDF::UseQAxObjectToWord()
{
    QString filePN = QFileDialog::getSaveFileName(this, QStringLiteral("Save File"),
    QStringLiteral("./未命名"), tr("Word (*.docx *.doc)"));

    if (filePN.isEmpty()) return;

    // 初始化;
    HRESULT result = OleInitialize(0);
    if (result != S_OK && result != S_FALSE)
    {
        qDebug() << QString("Could not initialize OLE (error %x)").arg((unsigned int)result);
    }
    //新建一个word应用程序;
    QAxObject *m_pWord = new QAxObject();
    bool bFlag = m_pWord->setControl("word.Application");
    if (!bFlag) return;

    // 设置 Office 应用不可见;
    m_pWord->setProperty("Visible", false);

    // 获取所有的工作文档;
    QAxObject *m_pWorkDocuments = m_pWord->querySubObject("Documents");
    if (!m_pWorkDocuments) return;

    // 新建文档;
    m_pWorkDocuments->dynamicCall("Add(void)");
    // 以模板 sFile (.dot) 为基础创建文档, sFile为空 表示新建文档;
    // document->dynamicCall( "Add(QString)" , sFile);

    // 获取当前激活的文档;
    QAxObject *m_pWorkDocument = m_pWord->querySubObject("ActiveDocument");
    if (!m_pWorkDocument) return;
	
    for (int i = 0; i < 5; ++i)
    {
        QString picNamePath = "E:\1.png";
        QAxObject *  bookmark_pic = m_pWord->querySubObject("Selection");
        if (!bookmark_pic->isNull())
        {
            //光标跳到最后一行;
            bookmark_pic->dynamicCall("EndOf(QVariant&, QVariant&)", 6,0).toInt();
            // selection->dynamicCall("EndOf(void)").toInt();//使用"EndOf(void)"也可实现
            QAxObject* range = bookmark_pic->querySubObject("Range");
            //插入图片;
            range->querySubObject("InlineShapes")->dynamicCall("AddPicture(const    QString&)", picNamePath);
        }
    }

    // 保存 Word 文档;
    m_pWorkDocument->dynamicCall("SaveAs (const QString&)", filePN);

    // 删除 析构 操作;
    m_pWord->setProperty("DisplayAlerts", true);
    m_pWorkDocument->dynamicCall("Close(bool)", true);
    m_pWord->dynamicCall("Quit()");

    delete m_pWorkDocuments;
    delete m_pWord;

    OleUninitialize();
}

3.   Word 文档 转换为 PDF

void LHCCreateOfficeAPDF::on_pushB_WordToPDF_clicked()
{
    // 接口参照网址 https://docs.microsoft.com/zh-CN/office/vba/api/Word.Documents.Open;
    // 利用QAxObject实现word转pdf;
    QAxObject *pWordApplication = new QAxObject("Word.Application", 0); //获取Word.Application对象;
    QAxObject *pWordDocuments = pWordApplication->querySubObject("Documents"); //获取操作窗口对象;
    QString doc1 = pWordApplication->generateDocumentation();
    QFile outFile("E:/wordLog.html");
    outFile.open(QIODevice::WriteOnly | QIODevice::Append);
    QTextStream ts(&outFile);
    ts << doc1 << endl;
    QString fileName = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation) + "/11.docx";
    QString toFilePath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation) + "/11.pdf";

    QVariant filename(fileName);
    QVariant confirmconversions(false);
    QVariant readonly(true);
    QVariant addtorecentfiles(false);
    QVariant passworddocument("");
    QVariant passwordtemplate("");
    QVariant revert(false);
	
    // querySubObject 用法;
    // 参数传得少的时候可以用下面做法,如果多的话就用另外的重载版本,如下;
    // QAxObject* querySubObject(const char *name, QList &vars);
    // 参数装到一个list里,然后传参就行了

    // 打开;	
    QAxObject* doc = pWordDocuments->querySubObject("Open(const QVariant&, const QVariant&,const QVariant&, "
	"const QVariant&, const QVariant&, "
	"const QVariant&,const QVariant&)",
	filename,
	confirmconversions,
	readonly,
	addtorecentfiles,
	passworddocument,
	passwordtemplate,
	revert);

    if (doc)
    {
        QVariant OutputFileName(toFilePath);
        QVariant ExportFormat(17);      //17是pdf;
        QVariant OpenAfterExport(false); //保存后是否自动打开;
	
        //转成pdf;
        doc->querySubObject("ExportAsFixedFormat(const QVariant&,const QVariant&,const QVariant&)",
	OutputFileName,
	ExportFormat,
	OpenAfterExport);
        //关闭;
        doc->dynamicCall("Close(boolean)", false);
    }	
}

二、生成 PPT

   CoInitialize(NULL); // 创建com对象

   CoUninitialize(); // 析构com对象

1. 播放 PPT

PlayPPT("E:/embedded.pptx");
void LHCCreateOfficeAPDF::PlayPPT(const QString &pptFilePath)
{
    CoInitialize(NULL);

    QAxObject pp("PowerPoint.Application", nullptr);
    auto presentations = pp.querySubObject("Presentations");
    auto presentation = presentations->querySubObject("Open(QString)", pptFilePath);
    auto slides = presentation->querySubObject("Slides");

    auto sliseshowsettings = presentation->querySubObject("SlideShowSettings");
    sliseshowsettings->dynamicCall("Run()");
    auto slideshowwindow = presentation->querySubObject("SlideShowWindow");
    if (slideshowwindow)
    {
	auto slideshowview = slideshowwindow->querySubObject("View");
	int numSlides = slides->property("Count").toInt();
	for (int i = 1; i < numSlides; ++i) {
	    QThread::currentThread()->sleep(3);
	    slideshowview->dynamicCall("Next()");
	}
    }

    QThread::currentThread()->sleep(3);
    pp.dynamicCall("Quit()");
    
    CoUninitialize();
}

2.   使用 模板 向 PPT 中 插入图片

QAxObject *pptObject = new QAxObject("PowerPoint.Application", nullptr);
QAxObject *presentationsObj = pptObject->querySubObject("Presentations");
QAxObject *presentationObj = presentationsObj->querySubObject("Open(QString, Office::MsoTriState,\
	Office::MsoTriState, Office::MsoTriState)", "E:\\Self\\Model.potx", 0, 0, 0);

if (!presentationObj) return;

QVariantList params;
params.append(QVariant("E:\\11.png"));
params.append(-1);
params.append(-1);
params.append(100);
params.append(100);

if (QAxObject *slidesbj = presentationObj->querySubObject("Slides(1)"))
{
    if (QAxObject *shapesObj = slidesbj->querySubObject("Shapes"))
    {
	shapesObj->dynamicCall("AddPicture(QString, Office::MsoTriState, \
                    Office::MsoTriState,Office::Single, Office::Single)", params);
    }
}

presentationObj->dynamicCall("SaveAs (QString)", filePN.replace("/", "\\"));
		
pptObject->setProperty("DisplayAlerts", true);
pptObject->dynamicCall("Close(bool)", true);
pptObject->dynamicCall("Quit()");

delete presentationObj;
delete presentationsObj;
delete pptObject; 

3.   不使用 模板 向 PPT 中 插入图片

QString filePN = QFileDialog::getSaveFileName(this, QStringLiteral("Save File"),
	QStringLiteral(".\\default"), tr("PPT (*.pptx *.ppt)"));

if (filePN.isEmpty()) return;

QAxObject *pptObject = new QAxObject("PowerPoint.Application", nullptr);

//Create a presentation in this project
QAxObject *presentationsObj = pptObject->querySubObject("Presentations");
// 参数 Office::MsoTriState 是否在可视窗口中显示演示文稿; 0:不显示; 1:显示;
QAxObject *presentationObj = presentationsObj->querySubObject("Add(Office::MsoTriState)", 0);
		
if (!presentationObj)
{
	return;
}

QVariantList params;
params.append(QVariant("E:\\11.png"));
params.append(-1);
params.append(-1);
params.append(100);
params.append(100);

// Create new Slide
if (QAxObject *slidesbj = presentationObj->querySubObject("Slides"))
{
    int sCount = slidesbj->property("Count").toInt();
    if (QAxObject *slideMaster = presentationObj->querySubObject("SlideMaster"))
    {
        if (QAxObject *customLayouts = slideMaster->querySubObject("CustomLayouts"))
	{
	    if (QAxObject *customLayout = customLayouts->querySubObject("Item(QVariant)", QVariant(1)))
	    {
		QAxObject *addSlide = slidesbj->querySubObject("AddSlide(int,Office::CustomLayout)", \
                                                1, customLayout->asVariant());
		int sCount2 = slidesbj->property("Count").toInt();

		if (QAxObject *shapesObj = addSlide->querySubObject("Shapes"))
		{
		    // Add picture
		    shapesObj->querySubObject("AddPicture(QString, Office::MsoTriState, Office::MsoTriState, \
				Office::Single, Office::Single)", params);
		    shapesObj->querySubObject("AddPicture(QString, Office::MsoTriState, Office::MsoTriState, \
				Office::Single, Office::Single)", params);
		}
    	    }
	}
    }
}

presentationObj->querySubObject("SaveAs (QString)", filePN.replace("/", "\\"));

pptObject->setProperty("DisplayAlerts", true);
pptObject->dynamicCall("Close(bool)", true);
pptObject->dynamicCall("Quit()");

delete presentationObj;
delete presentationsObj;
delete pptObject;

4.   PPT 转换为 PDF

void MainWindow::openPPT()
{
    QFileDialog _dialog;
    _dialog.setFileMode(QFileDialog::ExistingFile);
    _dialog.setViewMode(QFileDialog::Detail);
    _dialog.setOption(QFileDialog::ReadOnly, true);
    _dialog.setDirectory(QString("./"));
    _dialog.setNameFilter(QString("ppt(*.pptx *.ppt)"));

     if (_dialog.exec())
    {
         QStringList files = _dialog.selectedFiles();
         for (auto fileName : files)
        {
             if (fileName.endsWith(".pptx")||fileName.endsWith(".ppt"))
             {
                 // Open parameter
                 QAxObject *_powerPointAxObj = new QAxObject("Powerpoint.Application", 0);
                 if (!_powerPointAxObj) continue;

                 _powerPointAxObj->dynamicCall("SetVisible(bool)", false);
                 QAxObject *presentations = _powerPointAxObj->querySubObject("Presentations");
                 QList paramList;
                 paramList.push_back(QVariant(fileName));
                 paramList.push_back(0);
                 paramList.push_back(0);
                 paramList.push_back(0);
                 //FileName   Required String. The name of the file to open
                 //ReadOnly   Optional Long. True to open the file with read-only status. If this argument is omitted, the file is opened with read/write status.
                 //Untitled   Optional Long. True to open the file without a title. This is equivalent to creating a copy of the file. If this argument isn't specified, the file name automatically becomes the title of the opened presentation.
                 //WithWindow Optional Long. True to open the file in a visible window. False to hide the opened presentation. The default value is True.
                 QAxObject *presentation = presentations->querySubObject("Open(const QString&,int,int,int)",paramList);
                 if (presentation != nullptr)
                {
                     paramList.clear();
                     QString application_path = QApplication::applicationDirPath();
                     application_path.replace("/", "\\");
                     application_path += "\\ShowFile.pdf";
                     paramList.push_back(application_path);
                     paramList.push_back(32);
                     paramList.push_back(0);
                     presentation->dynamicCall("SaveAs(const QString&,int,int)", paramList);
                     presentations->dynamicCall("Close()");  

                     delete presentations;
		    //this->OpenPdf(application_path);
             }
         }
     }
}

三、生成 PDF

1. 使用 HTML 格式输出;

void LHCCreateOfficeAPDF::UseHTMLToPdf()
{
    QPrinter printer_text;
    printer_text.setOutputFormat(QPrinter::PdfFormat);
    printer_text.setOutputFileName("E:/HTML.pdf");//pdfname为要保存的pdf文件名;

    QTextDocument text_document;
    QString html = GetHtmlInfoToFile();//自定义的函数,用来生成html代码;[见 生成Word部分]

    text_document.setHtml(html);
    text_document.print(&printer_text);
    QTextBlock it = text_document.end();
}

2. 使用 QPainter 输出;

限制:手动翻页

 参数说明:

QPrinter *m_printer(new QPrinter);

QPrinter *m_painter(new QPainter);

int m_Width = 0; // 插入图片的 width;

int m_Height = 0; // 插入图片的 height;

void LHCCreateOfficeAPDF::UseQPrinterToPdf()
{
    QString fileName = "E:/QPrinter.pdf";

    SetPdfName(fileName);
    WriteTextToPdf("ni hao wo shi 001 PDF TXT");
    InsertPictureToPdf("E:/1.png");
    CreateNewPage();
    WriteTextToPdf("ni hao wo shi 002 PDF TXT");
    InsertPictureToPdf("E:/1.png");
    EndPainterToPdf();
}
void LHCCreateOfficeAPDF::SetPdfName(const QString &fileName)
{
    // 重置绘制的位置;
    m_pStruct->m_Height = 0;

    m_pStruct->m_printer->setPageSize(QPrinter::A4);
    m_pStruct->m_printer->setOutputFormat(QPrinter::PdfFormat);
    m_pStruct->m_printer->setOutputFileName(fileName);
    m_pStruct->m_painter->begin(m_pStruct->m_printer);
}

void LHCCreateOfficeAPDF::WriteTextToPdf(const QString &text)
{
    if (m_pStruct->m_printer == NULL) return;
    int height = 10;
    int width = 300;
    m_pStruct->m_painter->drawText(m_pStruct->m_Width, m_pStruct->m_Height, width, height, 0, text);
    m_pStruct->m_Height += height + 10;
}

void LHCCreateOfficeAPDF::InsertPictureToPdf(const QString &picFile)
{
    if (m_pStruct->m_printer == NULL) return;
    QPixmap *pixmap = new QPixmap(picFile);
    int width = pixmap->width();
    int height = pixmap->height();
    m_pStruct->m_painter->drawPixmap(m_pStruct->m_Width, m_pStruct->m_Height, 300 * width / height, 300, *pixmap);
    m_pStruct->m_Height += height;
}

bool LHCCreateOfficeAPDF::CreateNewPage()
{
    bool isNew = m_pStruct->m_printer->newPage();
    // 重置绘制的位置;
    m_pStruct->m_Height = 0;
    return isNew;
}

void LHCCreateOfficeAPDF::InsertPictureToPdf(const QPixmap pixmap)
{
    if (m_pStruct->m_printer == NULL) return;
    int width = pixmap.width();
    int height = pixmap.height();
    m_pStruct->m_painter->drawPixmap(m_pStruct->m_Width, m_pStruct->m_Height, width, height, pixmap);
    m_pStruct->m_Height += height + 10;
}

void LHCCreateOfficeAPDF::EndPainterToPdf()
{
    m_pStruct->m_painter->end();
}

3. 使用 QPdfWriter 输出

限制:QT5 版本以上 、手动翻页

void LHCCreateOfficeAPDF::UseQPdfWriterToPdf()
{
    QString fileName = "E:/QPdfWriter.pdf";
    QFile pdfFile(fileName);
    pdfFile.open(QIODevice::WriteOnly);                 // 打开要写入的pdf文件
    QPdfWriter* pPdfWriter = new QPdfWriter(&pdfFile);  // 创建pdf写入器
    pPdfWriter->setPageSize(QPagedPaintDevice::A4);     // 设置纸张为A4
    pPdfWriter->setResolution(300);                     // 设置纸张的分辨率为300,因此其像素为3508X2479

    int iMargin = 60; // 页边距
    pPdfWriter->setPageMargins(QMarginsF(iMargin, iMargin, iMargin, iMargin));

    QPainter* pPdfPainter = new QPainter(pPdfWriter);   // qt绘制工具
    
    QTextOption option(Qt::AlignHCenter | Qt::AlignVCenter);  // 标题,居中
    option.setWrapMode(QTextOption::WordWrap);

    // 标题上边留白
    int iTop = 100;

    // 文本宽度2100
    int iContentWidth = 2100;

    // 标题,22号字
    QFont font;
    font.setFamily("simhei.ttf");
    int fontSize = 22;
    font.setPointSize(fontSize);
    pPdfPainter->setFont(font);  // 为绘制工具设置字体
    pPdfPainter->drawText(QRect(0, iTop, iContentWidth, 90), tr("我的标题我骄傲"), option);

    // 内容,16号字,左对齐
    fontSize = 16;
    font.setPointSize(fontSize);
    pPdfPainter->setFont(font);
    option.setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
    iTop += 60;
    pPdfPainter->drawText(QRect(0, iTop, iContentWidth, 60), tr("1、目录一"));
    iTop += 60;
    // 左侧缩进2字符
    int iLeft = 120;
    pPdfPainter->drawText(QRect(iLeft, iTop, iContentWidth - iLeft, 60), tr("我的目录一的内容。"), option);
    iTop += 60;
    pPdfPainter->drawText(QRect(0, iTop, iContentWidth, 60), tr("2、目录二"));
    iTop += 60;
    pPdfPainter->drawText(QRect(iLeft, iTop, iContentWidth - iLeft, 60), tr("我的目录一的内容"), option);

    delete pPdfPainter;
    delete pPdfWriter;
    pdfFile.close();
}

 

 

你可能感兴趣的:(Qt)