使用Qt的AxContainer模块操作Office文档(二)

操作Word文档

取得Word内容

上面通过Range的Copy方法,把Word文档的内容,放入了剪贴板中。此时,可以在其它支持剪贴板的应用中粘贴,比如粘贴到PowerPoint或者画图程序中,还可以在我们的Qt程序中,获取这种内容。

方法是通过QClipboard

全局的QClipboard对象,可以通过QApplication来取得。

auto clipboard = QApplication::clipboard();

QClipboard类支持的主要只读方法有:

QImage 	image(QClipboard::Mode mode = Clipboard) const

QPixmap 	pixmap(QClipboard::Mode mode = Clipboard) const

QString 	text(QClipboard::Mode mode = Clipboard) const
QString 	text(QString &subtype, QClipboard::Mode mode = Clipboard) const

对于通过Range的Copy方法放入剪贴板的内容,通过text取出里面的文本,是最简单直观的方法。

另外,如果要保持Word文档的样式,还可以按照HTML格式取出,方法是使用QClipboard的mimeData()取得QMimeData(),之后调用QMimeData类的html方法。

如下代码,可以把Word文档指定页的内容,存成一个HTML文档。

bool
doc_to_html(QVarint doc, int pn, const QString &path)
{
  auto pageRange = doc->querySubObject (
      "GoTo(int, int, int, const QVariant&)", 1, 1, pn + 1);
  auto endRange = doc->querySubObject ("GoTo(int, int, int, const QVariant&)",
                                        1, 1, pn + 2);
  if (pageRange && endRange)
    {
      int endPosition;
      if (endRange->property ("Start").toInt () == 1)
        {
          auto content = doc->querySubObject ("Content");
          endPosition = content->property ("End").toInt ();
          delete content;
        }
      else
        {
          endPosition = endRange->property ("Start").toInt () - 1;
        }

      pageRange->setProperty ("End", endPosition);

      pageRange->dynamicCall ("Copy()");
    }
  else
    {
      qWarning ("Failed to get page range\n");
      return false;
    }

  auto clip = QApplication::clipboard ();
  auto mime = clip->mimeData ();
  auto qba = QByteArray::fromStdString (mime->html ().toStdString ());
  
  QFile qfile(path);
  qfile.open(QIODevice::WriteOnly);
  qfile.write(qba);
  qfile.close();
  return true;
}

取得Word页面大小

通过Document对象的ActiveWindow的ActivePane,取得Page对象,Page对象的属性有Width、Height。

如:

void
wordPageSize (QVarint doc, int pn, int *x, int *y)  
{  
      auto pnstr = QString ("Pages(%1)").arg (pn + 1);  
      auto win = doc->querySubObject ("ActiveWindow");  
      auto pane = win->querySubObject ("ActivePane");  
      auto page = pane->querySubObject (pnstr.toStdString ().c_str ());  
      auto width = page->property ("Width");  
      auto height = page->property ("Height");  
  if (x)  
    *x = width.toInt ();  
if (y)  
    *y = height.toInt ();
}

在Qt中内嵌Word

前面提到的使用Word.Application对象,会打开一个单独的Word程序,尽管可以设置为不可见(Visible=false),但是毕竟不是在Qt的组件之中显示与交互。

而使用QAxWidget,直接打开一个Word进程的ActiveX控件,显示在我们的Qt程序中。

只是这时候,我们不能再使用Word.Application对象,而是使用Word.Document对象。

同时,也不能再使用Application.Documents的Open对象打开文档,而是使用QAxWidget的基类QAxObjectInterface的setControl方法。

根据官方文档,QAxWidget的setControl方法的原型为:

bool QAxObjectInterface::setControl(const QString &c)

Returns whether setting the COM object succeeded.

Sets the name of the COM object wrapped by this QAxBase object to c.`

而setControl,可以有几个功能:

效率最高的是设置注册过的组件UUID。

如:

ctrl->setControl(“{8E27C92B-1264-101C-8A2F-040224009C02}”);

第二快的是设置组件名称。

如:

ctrl->setControl(“MSCal.Calendar”);

最慢,但是最容易使用的是设置程序的全名:

如:

ctrl->setControl(“Calendar Control 9.0”);

还可以通过文件名。

如:

ctrl->setControl(“c:/files/file.doc”);

所以,我们如果只是在Qt程序中,调用Word(或者Excel、PowerPoint,但是使用的参数不同),则可以很简单地使用QAxObjectInterface的setControl方法,设置文档名。

如:

#include <QtAxContainer>

int
main (int argc, char *argv[])
{
  QApplication app(argc, argv);
  QString path = QString::fromLocal8Bit (argv[1]);

  QAxWidget *doc_widget = new QAxWidget;
  doc_widget->setVisible (true);
  doc_widget->setControl (path);

  app.exec();
}

上面这样创建出来的QAxWidget,即doc_widget,就是一个继承自QWidget的组件,可以做为普通的QWidget使用。

如果只是显示或者操作Word等Office文档,使用上面这种内嵌QAxWidget,是最简单的方法。

操作PowerPoint

PowerPoint应用的对象名叫做PowerPoint.Application,这一点与Word一样。

但是,当使用这个对象打开本地文档的时候,就完全不一样了。Word叫做Documents与Document,而PowerPoint叫做Presentations与Presentation。

所以,打开PowerPoint本地文档的过程是先打开PowerPoint.Application,然后打开Presentations,然后打开Presentation。而且,如前所述,Presentations没有OpenNoRepairDialog函数,只有Open。

打开PowerPoint文档

// 为演示方便,下述代码没有进行错误处理以及资源清理
QVariant  
loadPPT (const QString &filename)  
{  
  auto application = new QAxObject ("PowerPoint.Applicatoin");  
  application->setProperty ("Visible", false);  
  auto documents = application->querySubObject ("Presentations");  
  auto doc = documents->querySubObject (  
      "Open(const QString&)", filename);  
  return doc;  
}

PowerPoint总页数

在PowerPoint中,页对应的对象叫Slide。

所以,取得一个PowerPoint文档的总页数,就是查询Presentation下面的Slides的长度。

如:

int  
pptSum (QVarint doc)  
{  
  auto slides = doc->querySubObject ("Slides");  
  auto count = slides->property ("Count");  
  return count.toInt ();  
}

PowerPoint的页面大小

可以通过Presentation的PageSetup对象,直接查询出来页面大小SlideWidth与SlideHeight。

如:

bool  
pptPageSize (QVarint doc, int *x, int *y)  
{  
  auto setup = mDoc->querySubObject ("PageSetup");  
  auto width = setup->property ("SlideWidth");  
  auto height = setup->property ("SlideHeight");  
  if (x)  
    *x = width.toInt ();  
  if (y)  
    *y = height.toInt ();  
  return true;  
}

导出PowerPoint成图片

PowerPoint有一点,与Word、Excel不一样,就是它可以把特定的页(即Slide),通过Slide的Export方法,导出成图片。

Slide的Export方法的原型为:

Syntax

expression.Export (FileName, FilterName, ScaleWidth, ScaleHeight)

expression A variable that represents a Slide object.

需要注意的是,FileName的路径分隔符必须是\,不能是/。

如下面的代码,把PowerPoint中特定的页数,导出到了临时文件,又加载到了QImage对象中:

bool
pptToImage (QVarint doc, int pn, QImage *pix)
{
  auto slides = doc->querySubObject ("Slides");
  auto slide = slides->querySubObject ("Item(int)", pn);
  auto temppath
      = QString ("%1/%2.png").arg (QDir::tempPath ()).arg (rand ());
  temppath.replace ("/", "\\");
  slide->dynamicCall ("Export(const QString &, const QString &)", temppath,
                      QString ("PNG"));

  if (QFile::exists (temppath) == false)
    {
      return false;
    }
  *pix = QImage (temppath);
  QFile::remove (temppath);
  return true;
}
  • 11
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值