Chinaunix首页 | 论坛 | 博客
  • 博客访问: 414912
  • 博文数量: 168
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 0
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-09 13:46
文章分类

全部博文(168)

文章存档

2015年(51)

2014年(30)

2013年(87)

我的朋友

分类:

2015-04-09 14:42:12

原文地址:qt嵌入office 作者:landuochong

write to an excel file:





I need write data to Excel from my  Qt  application.
I do such way:

QAxObject* excel = new QAxObject( "Excel.Application", 0 );
excel->dynamicCall("SetVisible(bool)",true);
QAxObject *workbooks = excel->querySubObject( "Workbooks" );
QAxObject *workbook = workbooks->querySubObject( "Open(const
QString&)", "C:\\A.xls" );
QAxObject *sheets = workbook->querySubObject( "Sheets" );


QAxObject *StatSheet = sheets->querySubObject( "Item(const
QVariant&)", QVariant(QString::fromLocal8Bit("test")) );
StatSheet->dynamicCall( "Select()" );


excel->dynamicCall(" SetScreenUpdating(bool)",false);

//here I write data...It's not have a matter of principle...

excel->dynamicCall(" SetScreenUpdating(bool)",true);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
All work perfect but this must take place insensibly to user... How I
can do this?


Most office files are OLE compound files, so you should first use libole2 to 
access them (OLD compound files are like small filesystems, imagine a floppy
disk image or somesuch, although they use their own filesystem not compatible
with vfat). You'll see that .xls file (like .doc, .dbs, etc) contains a few
streams (stream = file in OLE compound file terminology), one per worksheet I
assume, plus some other gibberish.

Another issue is to filter data in those streams.

You can look into KOffice filters, GNumeric and OpenOffice. I think that
GNumeric filters are the best (simplicity of code vs. completeness).


Open Ms Word, Ms excel, ppt files in QT -Linux:

need to open Ms Word, excel, powerpoint files in a QT application. The files need to show in a widget. Is there a plugin available which can allow the files to be opened? On windows we can do it through ActiveX component but the application will be on Embedded linux. Even if there is a utility on x11(desktop), please do reply as it will be of great help. This can be customised for embedded environment.
OpenOffice and KOffice can open MS office documents (not absolutely sure about KOffice), so maybe you should get some info on how they do it.

Solution 1: Try to use the openoffice SDK to read and display MS office documents:


Solution 2: Koffice uses Qt and is open-source, so if you are also writing an open-source application, you might be able to reuse some of their code:


Solution 3: Understand the word/excel/powerpoint formats and create custom Qt widgets which can read them (the custom widget part is probably the easiest here)... 0.O
If you find a library to import MS office documents, it might not be to hard. Perhaps the openoffice code/SDK will help.
KOffice seems to have "import/export filters for many of the binary MS Office file formats -- .doc, .xls, .rtf.". ;)


Note: There's also which I just discovered now.


Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    Word::Application *app;
try {
app = new Word::Application;
} catch (...) {
Utils::error("Some exception raised");
return false;
}
Word::Document *doc = app->Documents()->Open(fileTemplate);
Word::Range *rng = doc->Range(0, 200); // (1)
...
Excel::Application *app;
try {
app = new Excel::Application;
} catch (...) {
Utils::error("Some exception raised");
return false;
}
app->SetDisplayAlerts(false);
Excel::Workbook *wb = app->Workbooks()->Open(fileTemplate);
// process each worksheet
for (int i = 1; i <= wb->Worksheets()->Count(); ++i) {
Excel::_Worksheet *ws = new Excel::_Worksheet(wb->Worksheets()->Item(i));
QList keys = substParams.keys();
for (QList::const_iterator key = keys.begin();
key != keys.end(); ++key)
ws->Cells()->Replace("%" + *key + "%", "bla-bla", Excel::xlPart); // (2)
delete ws;
}
Problem occurs when control flow reaches line (2) -- it gives assert "id < 0" in qaxbase.cpp:3610 (qt_metacall). I've investigated that problem occurs beginning with line (1), commenting it out (and all Word-code below) "solves" the problem. Could someone tell me, what's going on? It seems like some internal structures are altered or something. Thanks in advance.

Problem was solved by patching dumpcpp tool to decorate type names, interned into meta-object system, with namespace. Now it works just fine.

Kind of interest, does Trolltech accept patches for proprietary code?

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
	QAxObject* excel = new QAxObject( "Excel.Application", 0 );
QAxObject* workbooks = excel->querySubObject( "Workbooks" );
QAxObject* workbook = workbooks->querySubObject( "Open(const QString&)", exchange->getFilename() );
QAxObject* sheets = workbook->querySubObject( "Worksheets" );

QList data; //Data list from excel, each QVariantList is worksheet row

//worksheets count
int count = sheets->dynamicCall("Count()").toInt();

for (int i=1; i<=count; i++) //cycle through sheets
{
//sheet pointer
QAxObject* sheet = sheets->querySubObject( "Item( int )", i );

QAxObject* rows = sheet->querySubObject( "Rows" );
int rowCount = rows->dynamicCall( "Count()" ).toInt(); //unfortunately, always returns 255, so you have to check somehow validity of cell values
QAxObject* columns = sheet->querySubObject( "Columns" );
int columnCount = columns->dynamicCall( "Count()" ).toInt(); //similarly, always returns 65535

//One of possible ways to get column count
int currentColumnCount = 0;
for (int col=1; col {
QAxObject* cell = sheet->querySubObject( "Cells( int, int )", COLUMN_COUNT_ROW, col );
QVariant value = cell->dynamicCall( "Value()" );
if (value.toString().isEmpty())
break;
else
currentColumnCount = col;
}
columnCount = currentColumnCount;

//sheet->dynamicCall( "Calculate()" ); //maybe somewhen it's necessary, but i've found out that cell values are calculated without calling this function. maybe it must be called just to recalculate

for (int row=1; row <= rowCount; row++)
{
QVariantList dataRow;
bool isEmpty = true; //when all the cells of row are empty, it means that file is at end (of course, it maybe not right for different excel files. it's just criteria to calculate somehow row count for my file)
for (int column=1; column <= columnCount; column++)
{
QAxObject* cell = sheet->querySubObject( "Cells( int, int )", row, column );
QVariant value = cell->dynamicCall( "Value()" );
if (!value.toString().isEmpty() && isEmpty)
isEmpty = false;
dataRow.append(value);
}
if (isEmpty) //criteria to get out of cycle
break;
data->append(dataRow);
}
}

workbook->dynamicCall("Close()");
excel->dynamicCall("Quit()");

Source code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
bool cMSExcelAutomation::initializeExcel97(bool isVisible) 
{
QString msg;
try {
m_excel = new QAxObject(EXCEL97);
if ( !m_excel ) {
msg = QObject::tr("Ei saatu instantioitua Excel-oliota (%1)").arg(EXCEL97);
logWriter().logMsg("cMSExcelAutomation::initializeExcel97", msg);
return false;
}
m_excel->disableEventSink();
// Asetetaan näkyville
QVariant visible(isVisible);
m_excel->dynamicCall("SetVisible(bool)",visible);
msg = QObject::tr("Excel-olio (%1) luotu").arg(EXCEL97);
logWriter().logMsg("cMSExcelAutomation::initializeExcel97", msg);
return true;
}
catch (...) {
msg = QObject::tr("Poikkeus Excel-olion (%1) luomisen yhteydessä").arg(EXCEL97);
logWriter().logMsg("cMSExcelAutomation::initializeExcel97", msg);
return false;
}
return false;
}


阅读(3527) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~