Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt Общие вопросы _ Cells в QT при работе с MS Office

Автор: abra 24.3.2009, 19:27

Привет.
Здесь столкнулся с такой заботой.
QAxObject *range = StatSheet->querySubObject( "Range(const QVariant&)",QVariant(QString("A1:B6"))); (выделяем диапозон для работы)
QAxObject *range = StatSheet->querySubObject( "Range(const QVariant&)",QVariant(QString("A1"))) (выделяем 1 ячейку)
QAxObject *range = StatSheet->querySubObject( "Cells(const QVariant&)",QVariant(QString("1"))) ( выделяем 1 ячейку(аналог Cells(1,1))
QAxObject *range = StatSheet->querySubObject( "Cells(const QVariant&)",QVariant(QString("2"))) (выделяем вторую ячейку (аналог Cells(1,2))

Но у меня есть таблица БД.В ней поля.СЛедовательно,должна соблюдаться структура при выводе данных в Эксель

1 поле 2 поле 3 поле 4 поле 5 поле

Но!Как мне обратиться скажем к Cells(2,2)...или Cells(3,4)...Причем это обязательно нужно сделать через цифры (Cells(X,Y) (X,Y- целочисленные указатели на ячейки))
Потому что через A1 нельзя вызывать(в таком случае будет слишком мудрено вызываться ячейка B1)


________________________________________________________________________________
____________________________________________

Хм...Ребят,подождите...Сейчас одна идейка возникла...Может написать

QAxObject *range = StatSheet->querySubObject( "Cells(const QVariant&,const QVariant&)",QVariant(QString("2")),QVariant(QString("1")))

попробовать.........

________________________________________________________________________________
______________________________________________
Не помогло........

QAxObject *range = StatSheet->querySubObject( "Cells(const QVariant&;const QVariant&)",QVariant(QString("4")),QVariant(QString("8")));

Пишет значение в ячейку D1(принял первый параметр равный 4) :((((
Он почему то принимает только первый параметр,и всё.........

Какие будут предложения?

Автор: abra 24.3.2009, 21:34

Проблема решена)))

Может кому понадобится

QAxObject *range = StatSheet->querySubObject( "Cells(const QVariant&,const QVariant&)",QVariant(4),QVariant(8 ));

Вместо 4 и 8 можно использовать например i и j ,как входные параметры.

Автор: Rocky 25.3.2009, 20:21

abra, а можно вопросик? А как вообще начинать работу с офисом? Не подскажешь, может ссылки какие-нить, можно на английском. Сейчас сам вплотную подошел к этому: надо выгружать данные в Excel или word (не особо важно вочто). А чистый COM не хочется использовать....

Автор: ViGOur 25.3.2009, 20:54

abra, если не лень, то может и правда опишешь?
А то эта тема очень плохо освещена. :(

Заодно и в вику выложим, как и что там.

Автор: abra 1.4.2009, 0:17

Оу.Извините))))
Чот как то решил для себя проблему,описал вам её,так и не заходил больше.
Я вот сейчас вплотную занимаюсь работой с MS Office под QT на высоком уровне.Вот сейчас сам ищу статьи,но в инете их нет,поэтому писать самому приходится.

Для начала советую почитать вам вот это

http://hardclub.donntu.edu.ua/projects/qt/articles/qt-excel.html

Чтобы подключить библиотеку,вам необходимо в .pro файле (в каталоге с вашим проектом),дописать LIBS += -lqaxcontainer
Ну теперь собственно приступаем к кодингу.

#include <ActiveQt/qaxobject.h>
#include <ActiveQt/qaxbase.h>

    QAxObject *mExcel = new QAxObject( "Excel.Application",this);  //Это мы получаем указатель на Excel
    QAxObject *workbooks = mExcel->querySubObject( "Workbooks" ); //это на книги
    QAxObject *workbook = workbooks->querySubObject( "Open(const QString&)", "C:\\q\\1\\otchet.xls" ); //это на директорию,откуда грузить книгу
    QAxObject *mSheets = workbook->querySubObject( "Sheets" ); //это на листы(снизу вкладки)
    QAxObject *StatSheet = mSheets->querySubObject( "Item(const QVariant&)", QVariant("topic") ); //Это мы указываем,какой лист выбрать.У меня он называется topic.


Здесь идёт работа с макросами MS Office.

Скопировать данные из 1 ячейки в другую:

QAxObject *rangec = StatSheet->querySubObject( "Cells(const QVariant&,const QVariant&)",QVariant(2),QVariant(1)); /получаем указатель на ячейку,откуда будем копировать.
QAxObject *rangep = StatSheet->querySubObject( "Cells(const QVariant&,const QVariant&)",QVariant(3),QVariant(1)); / получаем указатель на ячейку,куда будем копировать.
rangec->dynamicCall("Copy()"); /осуществляем запрос на копирование.
rangep->dynamicCall("Select()"); ///выбираем ячейку,в которую будем вставлять данные
StatSheet->dynamicCall("Paste()");  ///вставляем.



Работа со шрифтами.Дополнение:

QAxObject *rangec = StatSheet->querySubObject( "Range(const QVariant&)",QVariant("D2")); //Получаю указатель на D2
QAxObject *rangep = StatSheet->querySubObject("Cells(const QVariant&,const QVariant&)",QVariant(2),QVariant(2)); //получаю указатель на 2;2
(ну тут и Range можно,просто разные ячейки.В одной у меня текст забит,и я хочу получить,каким шрифтом он напечатан)
QAxObject *shrift = rangep->querySubObject("Font"); //ввожу новую переменную,обращаюсь к параметру Font(шрифт) в данной чейке(где у меня текст уже вбит(хотя можно и без текста))
QString lol = shrift->property("Name").toString(); // Возвращаю имя шрифта.
rangec->dynamicCall("setValue(const QVariant&)",QVariant(lol));// отображаю в D2 имя шрифта,который установлен в 2;2



Редактирование высоты,ширины строк или столбцов(вместо Rows указываем Columns,вместо RowHeight указываем ColumnWidth )

QAxObject *rangec = StatSheet->querySubObject( "Range(const QVariant&)",QVariant("D2"));//опять же,указатель на D2
QAxObject *razmer = rangec->querySubObject("Rows"); //получаю указатель на строку
razmer->setProperty("RowHeight",34);// устанавливаю её размер.


Объединение ячеек:

QAxObject *rangec = StatSheet->querySubObject( "Range(const QVariant&)",QVariant(QString("D2:D5")));//получаю указатель
rangec->dynamicCall("Select()");//выбираю их
rangec->dynamicCall("MergeCells",TRUE);//устанавливаю свойство объединения.


Вот еще сейчас покодил.Разрешает перенос:

QAxObject *rangep = StatSheet->querySubObject( "Range(const QVariant&)",QVariant(QString("A5"))); //указатель на А5
rangep->dynamicCall("Select()"); //выбираю её
rangep->dynamicCall("WrapText",TRUE);//устанавливаю свойство разрешения переноса
rangep->dynamicCall("setValue(const QVariant&)",QVariant("This text is so long:)))WordWrap is working"));//Всё пашет :))))Сорри за мой английский)))


Вот еще накодил)))) Устанавливает положение текста.

QAxObject *rangep = StatSheet->querySubObject( "Range(const QVariant&)",QVariant(QString("A5")));//указатель,как обычно)))
rangep->dynamicCall("Select()");//выбираю
rangep->dynamicCall("HorizontalAlignment",-4108);//по горизонтальной оси \\устанавливаю по центру.(Excel интерпретирует числовые значения положений в свои строковые.например xlCenter.)

Я здесь напишу основные.
Выравнивание по левому краю: -4131
Выравнивание по центру: -4108
Выравнивание по правому краю: -4152

Это для вертикального выравнивания:
QAxObject *rangep = StatSheet->querySubObject( "Range(const QVariant&)",QVariant(QString("A5")));//указатель,как обычно)))
rangep->dynamicCall("Select()");//выбираю
rangep->dynamicCall("VerticalAlignment",-4160) //по вертикальной оси


Выравнивание по верхнему краю: -4160
Выравнивание по центру: -4108
Выравнивание по нижнему краю: -4107

Вот еще написал=)))

Удаление\добавление строк
QAxObject *rangec = StatSheet->querySubObject( "Range(const QVariant&)",QVariant(QString("4:4")));
    rangec->dynamicCall("Select()");
    rangec->dynamicCall("Delete");

QAxObject *rangec1 = StatSheet->querySubObject( "Range(const QVariant&)",QVariant(QString("2:2")));
    rangec1->dynamicCall("Select()");
    rangec1->dynamicCall("Insert");


Удаление\добавление столбцов
QAxObject *rangec = StatSheet->querySubObject( "Range(const QVariant&)",QVariant(QString("E:E")));
    rangec->dynamicCall("Select()");
    rangec->dynamicCall("Delete");

QAxObject *rangec1 = StatSheet->querySubObject( "Range(const QVariant&)",QVariant(QString("B:B")));
    rangec1->dynamicCall("Select()");
    rangec1->dynamicCall("Insert");


Обещаная работа с границами ячеек =)))
 QAxObject *rangec = StatSheet->querySubObject( "Range(const QVariant&)",QVariant(QString("A4")));//указатель на ячейку
    QAxObject *border = rangec->querySubObject("Borders(xlEdgeTop)"); //  xlEdgeTop(верхняя граница) (xlEdgeLeft) левая, (xlEdgeRight) правая,(xlEdgeBottom) нижняя и 2 диагонали (xlDiagonalDown) (xlDiagonalUp)
    border->setProperty("LineStyle",1); //тип линии (там пунктиры,сплошная и так далее)
    border->setProperty("Weight",2);  //толщина



Ну вот собственно на этом я наверно и завершу написание статьи по работе библиотеки QT c MS Office Excel. Далее задавайте вопросы,будем уже на конкретных примерах разбираться.
:)))

Автор: abra 1.4.2009, 18:42

Статью я постоянно редактирую(дополняю),по мере того,как кодю=)))

P.S Сейчас рассмотрю вопрос с границами ячеек,и на этом наверно закончу.Далее задавайте конкретные вопросы.Статью, я могу отредактировать,и можно на Вику выложить.

Автор: Litkevich Yuriy 1.4.2009, 18:54

супер!

Автор: abra 1.4.2009, 19:37

:) Спасибо.

Автор: ViGOur 1.4.2009, 20:11

abra, бросил твою статью в Faq нашей вики: http://wiki.crossplatform.ru/index.php/%D0%A0%D0%B0%D0%B1%D0%BE%D1%82%D0%B5_%D1%81_MS_Office_%D1%81_%D0%BF%D0%BE%D0%BC%D0%BE%D1%89%D1%8C%D1%8E_ActiveQt

Если что, то можешь зайти в нее сам и поправить - добавить.
Имя пользователя и пароль в вики тот же, что ты входишь в форум.

Автор: abra 1.4.2009, 21:27

Хорошо.Только у меня просьба.Подправь пожалуйста заголовок.
А то там написано - РаботЕ,вместо РаботА
:)

Автор: Litkevich Yuriy 2.4.2009, 7:31

abra, ты можешь сделать это сам.
В верху страницы есть вкладки, щёлкни "Переименовать" и введи новое имя статьи.

только желателно залогинится в вики

Автор: ViGOur 2.4.2009, 8:11

Поправил...

Автор: abra 2.4.2009, 8:46

Цитата(Litkevich Yuriy @ 2.4.2009, 7:31) *
abra, ты можешь сделать это сам.
В верху страницы есть вкладки, щёлкни "Переименовать" и введи новое имя статьи.

только желателно залогинится в вики

Оке=)Буду знать.
Кстати,а вот там каждый человек может статью править.А акт вандализма никто не совершит?

Автор: Litkevich Yuriy 2.4.2009, 8:49

Цитата(abra @ 2.4.2009, 12:46) *
Кстати,а вот там каждый человек может статью править.А акт вандализма никто не совершит?
Да каждый. Вслучае вандализма всегда можно откатиться, вики - версионированная система, все правки сохраняются.

Автор: abra 2.4.2009, 20:48

Дополнение к статье:
Значения

Выравнивание по верхнему краю: -4160
Выравнивание по центру: -4108 (xlCenter)
Выравнивание по нижнему краю: -4107

и для остальных,которые содержат xl(указатель на Excel приложение), Вы можете взять из help`a в MS Office Excel

Автор: Наставник 3.5.2009, 19:53

Цитата(ViGOur @ 25.3.2009, 20:54) *
abra, если не лень, то может и правда опишешь?
А то эта тема очень плохо освещена. :(

Заодно и в вику выложим, как и что там.


Это все хорошо, но только надо заметить, что все это будет работать только в коммерческой версии QT.

Автор: igor_bogomolov 3.5.2009, 20:21

Цитата(Гость_Наставник_* @ 3.5.2009, 20:53) *
Это все хорошо, но только надо заметить, что все это будет работать только в коммерческой версии QT
Эт почему? Исходники activeqt входят в opensource версию, начиная с 4.5.0
Вот здесь (http://www.prog.org.ru/topic_9013_0.html) ребята писали как этот модуль собрать.

Автор: Гость_abra 4.5.2009, 13:26

Вот и ответ получен=))))

Автор: Tonal 5.5.2009, 7:20

Включение исходников ещё не значит что они халявные:

Цитата
The ActiveQt modules are part of the Qt Full Framework Edition. They are not part of the Open Source Versions of Qt.

http://doc.trolltech.com/4.5/activeqt.html

Автор: Rocky 29.5.2009, 20:07

Всем привет!
Начал потихоньку разбираться с activeqt...
Хочу чутка дополнить пример со шрифтами:

Цитата
QAxObject *pFont = pCell->querySubObject("Font"); //получаем шрифт в выбранной ячейке
pFont->setProperty("Size", 15); //задаем размер шрифта
pFont->setProperty("Bold", bBold); //делаем его полужирным ...
pFont->setProperty("Italic", bItalic);
//... и курсивным

Цитата(abra @ 1.4.2009, 19:42) *
...Далее задавайте конкретные вопросы...

Возникла пара вопросов:
1. Как вставить картинку в ячейку?
2. Как создать новый workbook и в нем sheet с заданным именем?
3. Как изменить формат представления данных в ячейке? (например, я ввожу число "5.2" - а отображается "5 февраля")
4. Как изменить параметры страницы? (например, сделать лист альбомной ориентации, чтобы после вывода данных в excel пользователю в случае печати не нужно было ничего настраивать).

Если кто что знает, отпишитесь плиз )) Спасибо!

Автор: ViGOur 29.5.2009, 21:12

Цитата(Rocky @ 29.5.2009, 21:07) *
4. Как изменить параметры страницы? (например, сделать лист альбомной ориентации, чтобы после вывода данных в excel пользователю в случае печати не нужно было ничего настраивать).
На VBA это будет так:
   ' альбомная ориентация 
   ActiveSheet.PageSetup.Orientation = xlLandscape
   ' книжная ориентация
   ActiveSheet.PageSetup.Orientation = xlPortrait
следовательно, делаем примерно так:
QAxObject *mExcel = new QAxObject( "Excel.Application",this); 
QAxObject *workbooks = mExcel->querySubObject( "Workbooks" );
QAxObject *workbook = workbooks->querySubObject( "Open(const QString&)", "C:\\q\\1\\otchet.xls" );
QAxObject *mSheets = workbook->querySubObject( "Sheets" );
QAxObject *StatSheet = mSheets->querySubObject( "Item(const QVariant&)", QVariant("topic") );

QAxObject *pageSetup  = StatSheet ->querySubObject( "PageSetup");
// устанавливаем альбомную ориентацию
pageSetup->setProperty( "Orientation ", "xlLandscape");
код не проверял, но думаю должен работать. :)

Если работает, то можно будет данный код добавить в вики, как и твой.

p.s. будет время приведу пример, как сделать остальные пункты. :)

Автор: Rocky 29.5.2009, 21:54

Хе-хе )) работает ))

Автор: Rocky 2.6.2009, 21:59

Вспомнил что когда-то давно что-то писал на VBA. Вобщем, общая идея работы с ActiveQT - эта библиотека позволяет работать с любыми библиотеками/приложениями, поддерживающими COM. Список методов и свойств объектов можно посмотреть в tlb-хе соответствующего приложения (например, через OLEView). Если етсь *.tlh или idl-ник - можно и там напрямую через текстовые редакторы. В случае с Excel идеально помогает VBA. Запускаем Excel, жмем Alt+F11, пишем процедуру открытия книги например и там эксперементируем. По "F2" можно посмотреть список классов их методов и свойств. Выбираем метод - давим "F1", читаем как им пользоваться. Далее читаем документацию по функциям ActiveQt - querySubObject/dynamicCall/setProperty/property.

1. Как вставить картинку в ячейку?
На VBA будет так:

Worksheets(1).Shapes.AddPicture "filename.bmp", True, True, 100, 100, 70, 70

Пробовал переписать так:
QAxObject *pShape = pNewSheet->querySubObject("Shapes");
if (pShape)
{
           QAxObject *pShape2 = pShape->querySubObject("AddPicture(const QString&, bool, bool, int, int, int, int)", "filename.bmp", true, true, 100, 100, 70, 70);
           int z = 0;
}

не фурычит. pShape2 == NULL и картинка не грузица. В querySubObject если нужно вызывать функцию, нужно описать сигнатуру этой функции.. А сигнатура такая:
Function AddPicture(Filename As String, LinkToFile As MsoTriState, SaveWithDocument As MsoTriState, Left As Single, Top As Single, Width As Single, Height As Single) As Shape

Я много как пробовал: не хотит пока. Че писать пока не понял (особенно насчет MsoTriState)....

2. Как создать новый workbook и в нем sheet с заданным именем?

Создаем новую книгу (при этом совершенно необязательно что-то там открывать с диска)
QAxObject *pWorkbooks = m_pExcel->querySubObject("Workbooks");
if (!pWorkbooks)
{
         return NULL;
}

QAxObject *pWorkbook = pWorkbooks->querySubObject("Add");
if (!pWorkbook)
{
         return NULL;
}

QAxObject *pSheets = pWorkbook->querySubObject("Sheets");
if (!pSheets)
{
         return NULL;
}


Удалить листы можно так:
QAxObject *pSheet1 = pSheets->querySubObject("Item(const QString&)", qApp->tr("Лист1")); 
if (pSheet1) pSheet1->querySubObject("Delete");
QAxObject *pSheet2 = pSheets->querySubObject("Item(const QString&)", qApp->tr("Лист2"));
if (pSheet2) pSheet2->querySubObject("Delete");
QAxObject *pSheet3 = pSheets->querySubObject("Item(const QString&)", qApp->tr("Лист3"));
if (pSheet3) pSheet3->querySubObject("Delete");

Новый лист создать можно так:
//добавляем новый лист и обзываем его sSheetName
QAxObject *pNewSheet = pSheets->querySubObject("Add");
if (!pNewSheet)
{
          return NULL;
}
pNewSheet->setProperty("Name", sSheetName);



3. Как изменить формат представления данных в ячейке? (например, я ввожу число "5.2" - а отображается "5 февраля")
На VBA так:
Worksheets("Лист1").Range("A1").NumberFormat = "General"


На ActiveQT чет не особо работает. Поэтому решил проблему так:
//проверяем цифра ли sText или текст (чтобы заменить "." на ",")
bool bOK;
sText.toDouble(&bOK);

QString sText2 = sText;
if (bOK) sText2 = sText2.replace('.', ",");

//выводим в ячейку текст
pRange->dynamicCall("setValue(const QVariant&)", sText2);

//вот так пробовал, но формат особо не меняется
//pRange->setProperty("NumberFormat", "General");


4. Как изменить параметры страницы? (например, сделать лист альбомной ориентации, чтобы после вывода данных в excel пользователю в случае печати не нужно было ничего настраивать).

Вот так можно задать границы области печати (и задать ориентацию (собсно ка ViGOur писал выше)):
QAxObject *pPageSetup = pNewSheet->querySubObject("PageSetup");
if (pPageSetup)
{
          pPageSetup->setProperty("LeftMargin", 5);
          pPageSetup->setProperty("RightMargin", 5);
          pPageSetup->setProperty("TopMargin", 5);
          pPageSetup->setProperty("BottomMargin", 5);
          pPageSetup->setProperty("HeaderMargin", 5);
          pPageSetup->setProperty("FooterMargin", 5);
          pPageSetup->setProperty("Orientation", "xlLandscape");
}

Автор: Litkevich Yuriy 2.6.2009, 22:21

Цитата(Rocky @ 3.6.2009, 1:59) *
"I:\1\2\4.bmp"
заэкранируй слэши.

Автор: croc 10.9.2009, 9:22

А как получать массив значений определенного range?

Иногда ячейке назначено свойство контроля вводимых значений, иногда бывает полезно получить список допустимых значений, искомый обьект называется Validation и является членом класса Range, обратиться к нему можно так:

QAxObject *or = range->querySubObject("Validation"); 
//ссылка на обьект реализующий контроль вводимых значений

QString s = or->dynamicCall("formula1").toString();
//в формула этого обьекта и содержит знание о том какие значения в ячейке будут являться допустимыми, там правда еще formula2 есть, но она в моем случае была пуста.


Не удивительно что там окажется ссылка именнованного массива "Name" (=имя_именнованного_массива) член класса WorkBook или WorkSheet, по этому вот пример обращния к нему:

name = workbook->querySubObject("Names(const QVariant&)", QVariant(s));
//получаем ссылку на именованный массив

s = name->dynamicCall("RefersTo").toString();
//получаем ссылку на искомый массив

Автор: ViGOur 10.9.2009, 14:23

Добавил в вики.
croc, в случае чего, каждый участник форума может залогинится в вики, под тем же именем пользователя и паролем, что и на форуме.

Автор: admsasha 5.10.2009, 6:07

А как в открытом документе сделать "поиск и замена"

открыл, например test.doc, а дальше ?

    QAxObject word("Word.Application");
    word.setProperty("Visible", true);
    word.dynamicCall("Activate()");
    word.querySubObject("Documents")->querySubObject("Open(QVariant)", "c:\\test.doc");

Автор: arial 16.10.2009, 7:46

Цитата(abra @ 1.4.2009, 0:17) *
Вот еще накодил)))) Устанавливает положение текста.
...
Я здесь напишу основные.
Выравнивание по левому краю: -4131
Выравнивание по центру: -4108
Выравнивание по правому краю: -4152

Это для вертикального выравнивания:
...
Выравнивание по верхнему краю: -4160
Выравнивание по центру: -4108
Выравнивание по нижнему краю: -4107

Полный список констант можно найти http://msdn.microsoft.com/en-us/library/aa221100%28office.11%29.aspx.
Конкретно по выравниванию:
Цитата
xlHAlignCenter -4108
xlHAlignCenterAcrossSelection 7
xlHAlignDistributed -4117
xlHAlignFill 5
xlHAlignGeneral 1
xlHAlignJustify -4130
xlHAlignLeft -4131
xlHAlignRight -4152
xlVAlignBottom -4107
xlVAlignCenter -4108
xlVAlignDistributed -4117
xlVAlignJustify -4130
xlVAlignTop -4160


Автор: admsasha 24.10.2009, 16:35

Открытие и печать документа

    QAxObject * word = new QAxObject("Word.Application");
    word->setProperty("DisplayAlerts", "0");
    word->querySubObject("Documents")->querySubObject("Open(QVariant)", "c:\\test.xml");
    word->querySubObject("ActiveDocument")->dynamicCall("PrintOut()");
    word->querySubObject("ActiveDocument")->dynamicCall("Close()");
    word->dynamicCall("Quit()");


Автор: ViGOur 24.10.2009, 18:23

Добавил в вики

Автор: Professor 28.10.2009, 13:35

Получение количества таблиц(sheet):

int sheet_count = [b]sheets_ascii[/b]->property("Count").toInt();


Получение количества использованных строк/столбцов:
QAxObject *usedRange = [b]sheet_ascii[/b]->querySubObject("UsedRange");
QAxObject *usedRows = usedRange->querySubObject("Rows");
QAxObject *usedCols = usedRange->querySubObject("Columns");


int rows = usedRows->property("Count").toInt();
int cols = usedCols->property("Count").toInt();

Автор: Chesterfilda 29.10.2009, 10:36

Доброго время суток!!!Очень полезная тема...
А не подскажете,как вот такой код на VBA:

Selection.QueryTable.Refresh BackgroundQuery:=False

можно переписать на Qt


Автор: Professor 29.10.2009, 13:46

Chesterfilda попробуйте добраться до объекта QueryTable и выполнить generateDocumantation().

Новые находки - доступ к символам внутри ячейки:

cell_ascii = sheet_ascii->querySubObject("cells(int,int)",i,j);
cell_ascii->dynamicCall("Select()");
char_ascii = cell_ascii->querySubObject("Characters(int,int)",s,l);
QChar char = char_ascii->property("Text").toString().at(0);

Автор: Chesterfilda 30.10.2009, 15:36

Чуть-чуть разобралась...
Только вот небольшая проблемка...
Есть такая функция:

IDispatch* Add (QVariant Connection, IDispatch* Destination, QVariant Sql)

,которая как раз-таки и создает QueryTable...
только не получается задать второй параметр этой функции,который указывает ячейку с которой начинается вставка данных.
В этом случае должна помочь
IDispatch* Range (QVariant Cell1, QVariant Cell2),но как-то не получается с помощью нее определить ячейку

Точнее никак не получается написть это на QT

    QAxObject *excel = new QAxObject( "Excel.Application",this); //получаем указатьтель на excel
    excel->dynamicCall( "SetVisible(bool)", TRUE ); //делаем его видимым
    QAxObject *workbooks = excel->querySubObject("Workbooks");
    QAxObject *workbook = workbooks->querySubObject("Open(const QString&)", "E:\\workspace\\test\\debug\\Отчет.xls");
    QAxObject *sheets=workbook->querySubObject("Sheets");
    QAxObject *statSheet=sheets->querySubObject("Item(const QVariant&)",QVariant("Лист1"));
    QAxObject *range=statSheet->querySubObject("Range(QVariant &)",QVariant(QString("A4")));
    //range->dynamicCall("Select()");
    QAxObject *table=statSheet->querySubObject("QueryTables");
    QAxObject *result=table->querySubObject("Add(QVariant &,IDispatch *,QVariant &)",QVariant(QString("DRIVER={Microsoft Access Driver (*.mdb)};FIL={MS Access};DBQ=E:\workspace\LS\release\data\oms_LS.mdb")),range,"select * from [result]"); //только сдесь не range нужно указать,а вот как обратится к ячейке в таком случае??


Автор: Chesterfilda 3.11.2009, 10:02

Нашла где-то на сайте:

Цитата
Если методу нужно передать аргумент типа IDispatch * или IUnknown *, то можно сначала инкапсулировать его в объект QAxObject, а затем вызвать метод asVariant(), чтобы преобразовать его в тип QVariant

Но это не помогает :-(...Если пишу:
QAxObject *result=table->querySubObject("Add(QVariant &,IDispatch *,QVariant &)",QVariant(QString("DRIVER={Microsoft Access Driver (*.mdb)};FIL={MS Access};DBQ=E:\workspace\LS\release\data\oms_LS.mdb")),range->asVariant(),QVariant(QString("SELECT * FROM [result]")));

то выдает след ошибку:
QAxBase: Error calling IDispatch member Add: Exception thrown by server
Как же обратится к этой ячейке??

Автор: Professor 4.11.2009, 19:45

Chesterfilda а может вместо:
QAxObject *range=statSheet->querySubObject("Range(QVariant &)",QVariant(QString("A4")));
попробовать:
QAxObject *range=statSheet->querySubObject("Range(QVariant &)",QVariant(QString("A4:C8")));
Я не проверят но может сработает.

Автор: dim_san 13.11.2009, 14:09

Создаю документ ворда таким образом:

QAxWidget *activeX = new QAxWidget( );
activeX->setControl( "Word.Document" );
ui->verticalLayout->insertWidget(0, activeX );

при этом размещаю его в лайауте. Показывается документ как и надо (встроенный в мой виджет).
Можно ли каким-то образом достать вордовский тулбар и разместить его куда надо мне, например на основной тулбар моего приложения?
Или придется делать собственный?

Автор: arial 20.11.2009, 9:27

Цитата(dim_san @ 13.11.2009, 14:09) *
Можно ли каким-то образом достать вордовский тулбар и разместить его куда надо мне, например на основной тулбар моего приложения?
Или придется делать собственный?

Разобрался с этим вопросом?

Автор: dim_san 23.11.2009, 15:27

arial, неа.
Такое впечатление, что он пытается сам появиться, панелька пустая появляется и тут же исчезает.
Но теоретически это должно быть можно сделать, т.к. видел работающий пример на mfc вроде...

Кстати, меню вордовское формируется прямо в главном qt-шном окне, но оно не действует...

Автор: Rosster 23.11.2009, 20:51

Всем привет. А откуда вы берете все эти команды?
Open(const QString&)
Item(const QVariant&)
QAxObject *rangep = StatSheet->querySubObject( "Cells(const QVariant&,const QVariant&)",QVariant(3),QVariant(1));
rangec->dynamicCall("Copy()");
и так далее?
и еще:
получаем указатель на листы:
QAxObject *mSheets = workbook->querySubObject( "Sheets" );
а как узнать какие листы вообще в документе есть? Ибо возможности узнать название листа и вписать в прогу нету возможности (много разных документов имеются)
Спасибо

Автор: ViGOur 23.11.2009, 21:02

В microsoft Excel и Word есть замечательная вешь как макросы, с помощью них и можно это все делать.
А ActiveQt дает механизм работы с ними, а следовательно и манипулирования данными документами.

Смотришь как работает макрос, ставишь запись макроса и делаешь руками необходимые тебе действия, смотришь, что там записалось и затем переводишь в Qt. В принципе ничего сложно нет, если разобраться как работаю макросы. :)

Автор: Rosster 24.11.2009, 21:57

Цитата(ViGOur @ 23.11.2009, 21:02) *
В microsoft Excel и Word есть замечательная вешь как макросы, с помощью них и можно это все делать.
А ActiveQt дает механизм работы с ними, а следовательно и манипулирования данными документами.

Смотришь как работает макрос, ставишь запись макроса и делаешь руками необходимые тебе действия, смотришь, что там записалось и затем переводишь в Qt. В принципе ничего сложно нет, если разобраться как работаю макросы.

ну вот я и не понял как получить список листов, уже все перепробовал с этими макросами, все время пишется типа "Лист 1", "Лист 2", но сами названия то я не могу знать,мне как-то названия и надо получить в QT :)

Автор: ViGOur 24.11.2009, 23:19

Цитата
Узнать количество листов в книге можно в цикле по коллекции Workbook.Sheets.
Количество листов — свойство Sheets.Count.
Имя листа — свойство Worksheet.Name.


Попробуй руководствуясь данной цитатой набросать макрос в Excel, а потом перевести в Qt.
Была бы у меня винда сам набросал бы, но чего нет того нет. :)

Автор: Гость_dim_san_* 26.11.2009, 13:17

Цитата(Rosster @ 23.11.2009, 20:51) *
Всем привет. А откуда вы берете все эти команды?


по командам можно документацию сгенерировать:
http://www.doc.crossplatform.ru/qt/4.3.2/qaxbase.html#generateDocumentation

Автор: MJIbIu 4.10.2010, 13:08

   
    QString fileName = QFileDialog::getOpenFileName(this, "Open");

    QAxObject *mExcel = new QAxObject( "Excel.Application",this);

    QAxObject *workbooks = mExcel->querySubObject( "Workbooks" );

    QAxObject *workbook = workbooks->querySubObject( "Open(const QString&)", fileName );

    QAxObject *mSheets = workbook->querySubObject( "Sheets" );

    QAxObject *StatSheet = mSheets->querySubObject( "Item(const QVariant&)", QVariant("1") );

    QAxObject* cell = StatSheet->querySubObject("Cells(QVariant,QVariant)", 1, 1);

    QVariant result = cell->property("Value");
    if (result.toString() != NULL)
        qDebug() << result.toString();
  
    delete cell;
    delete StatSheet;
    delete mSheets;
    delete workbook;
    delete workbooks;
    delete mExcel;

все бы ок тока вот у меня в системе висит процесс Excel.ехе и файл который я прочел пишет доступен тока для чтения и так с любой копией моего файла

Автор: MJIbIu 5.10.2010, 8:59

Цитата(MJIbIu @ 4.10.2010, 14:08) *
все бы ок тока вот у меня в системе висит процесс Excel.ехе и файл который я прочел пишет доступен тока для чтения и так с любой копией моего файла

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

Автор: breeve 16.2.2011, 20:04

Может кто подсказать, а если у меня в документе Word есть таблица(правда там есть еще пару строк текста до и после нее), тока как с ней работать. Мне бы, хотя бы узнать как получить данные из 1-ой ячейки этой таблицы.

Автор: breeve 20.2.2011, 13:13

Разобрался как доставать текст из таблицы. Но только из 1 элемента, пытаюсь вытащить из всей таблицы. У меня в таблице 3 колонки первые две он считывает должным образом. А вот переходя к 3-ей, он сразу же выдает ошибку.

code1
    mWord = new QAxObject(/*"Word.Application", this*/);
    mWord->setControl("Word.Application");
    mDocs = mWord->querySubObject( "Documents");
    mMyDoc = mDocs->querySubObject("Open(const QString&)", "C:\\timeTable.doc");

    mTimeTable = mMyDoc->querySubObject("Tables(1)");
    int rows = mTimeTable->querySubObject("Rows")->property("Count").toInt();
    int cols = mTimeTable->querySubObject("Columns")->property("Count").toInt();
    qDebug() << rows << cols;
    QStringList list[cols];
    const int b = 1;

    for(int j = 1; j < cols+1; j++)
    {
        for(int i = 1; i < rows+1; i++)
        {
           qDebug() << "i: " << i << "j: " << j;

           QAxObject *cell = mTimeTable->querySubObject("Cell(int, int)", i, j);
           qDebug() << 1;
           if(!cell)
           {
               if(i == rows || j == cols)
               {
                   qDebug() << "break";
                   break;
               }
               else
               {
                   qDebug() << "Continue";
                   continue;
               }
           }
           qDebug() << 2;
           QString str = cell->querySubObject("Range")->property("Text").toString();
           qDebug() << 3;
           if(str.isEmpty())
               list[j].append("Empty");
           else
               list[j].append(str);
           qDebug() <<3<<str;
           delete cell;
        }
    }

Вот вывод:
25 3
i: 1 j: 3
1
2
3
Invalid parameter passed to C runtime function.
Invalid parameter passed to C runtime function.
.. завершился с кодом 3

Еще появляеться MsgBox следующего содержания:
Microsoft Visual C++ Runtime Library
This application has requested th Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

У меня в таблице 3 колонки первые две он считывает должным образом. А вот переходя к 3-ей, он сразу же выдает ошибку.
Суть даже в том что если я делаю не в цикле а просто вытаскиваю определенный элемент из 3-го столбца то все в порядке.
code2
/    QAxObject *cell = mTimeTable->querySubObject("Cell(int, int)", QVariant(1), QVariant(3));
    qDebug() << cell->querySubObject("Range")->property("Text").toString();




Не могу понять в чем ошибка. И какой такой параметр передается в функцию не правильно.

Автор: Rocky 20.2.2011, 14:57

    for(int j = 1; j < cols+1; j++)
    {
        for(int i = 1; i < rows+1; i++)
        {


А если попробовать так:
    for(int j = 0; j < cols; j++)
    {
        for(int i = 0; i < rows; i++)
        {

?

Автор: breeve 20.2.2011, 19:21

Цитата(Rocky @ 20.2.2011, 14:57) *
А если попробовать так?

То в функции QAxObject *cell = mTimeTable->querySubObject("Cell(int, int)", i, j);
придется прибавлять единицу, поскольку отсчет элементов идет с единицы.

Автор: Rocky 20.2.2011, 20:46

Ясно.

Цитата(breeve @ 20.2.2011, 13:13) *
QStringList list[cols];
.........
for(int j = 1; j < cols+1; j++) {
.........
if(str.isEmpty()) list[j].append("Empty");
else list[j].append(str);

Имхо криминал тут. Понятно почему? (нужно быть внимательнее с индексами)

Автор: AlexeyDonald 22.2.2011, 1:56

Народ подскажите, цель поменять имя листа в документе, не пойму в чем ошибка. Вот проблема, я экспортирую дату в excel, открываю документ, все нормально работает до определенного момента, код ниже:

    QAxObject* excel = new QAxObject( "Excel.Application" );
    excel->dynamicCall( "SetVisible(bool)", TRUE );
    QAxObject *workbooks = excel->querySubObject( "Workbooks()" );

    QAxObject* workbook = workbooks->querySubObject( "Add()" );
    QAxObject* Sheets = workbook->querySubObject( "Sheets" );
    QAxObject* Sheet;
    Sheets->querySubObject("Add");
    Sheets->querySubObject("Add");
    Sheets->querySubObject("Add");

    Sheet =Sheets->querySubObject( "Item(int)" ,1);
    Sheet->dynamicCall( "Select()" );
    Sheet->setProperty("Name","name1");
    ExportToPage1(Sheet,model_1);

После этого названия листа меняется нормально.
Но дальше отказывается менять имя листа.
    Sheet =Sheets->querySubObject( "Item(int)" ,2); 
    Sheet->dynamicCall( "Select()" );
    Sheet->dynamicCall("Name","name2");
    ExportToPage2(Sheet,model_2);

    Sheet =Sheets->querySubObject( "Item(int)" ,3);
    Sheet->dynamicCall( "Select()" );
    Sheet->setProperty("Name(QString)","name3");
    ExportToPage2(Sheet,model_3);

    Sheet = Sheets->querySubObject( "Item(int)" ,4);
    Sheet->dynamicCall( "Select()" );
    Sheet->setProperty("SetName(QString)","name4");
    ExportToPage2(Sheet,model_4);

пишет:

QAxBase: Error calling IDispatch member Name: Exception thrown by server
Code : 1004
Source : Microsoft Excel
Description: ??????? ???????????? ??? ??? ????? ??? ?????????. ?????????, ???:

? ????? ?????????? ????? ?? ????????? 31 ?????;
? ??? ?? ???????? ?? ?????? ?? ????????? ??????: : \ / ? * [ ??? ];
? ??? ?? ????????? ??????.
Help : xlmain11.chm
Connect to the exception(int,QString,QString,QString) signal to catch this exception

Кто нибудь знает в чем дело? Спасибо!!!

Автор: pavelqt 7.9.2011, 8:33

Уже который день мучаюсь, не получается, подскажите пожалуйста, где не прав?
Qt + MS Outlook -> заводим новый контакт
QAxObject *contactItems = myFolder->querySubObject( "Items" );

// удалять контакты без проблем!
// contactItems->dynamicCall("remove(int )", 1 );

//А вот добавить не хочет никак :(
// contactItems->querySubObject( "CreateItem(olContactItem)", "olContactItem" );

// QAxObject *item = contactItems->querySubObject( "Add(const QVariant&)", QVariant("0099881") );

И второе, как ловить и читать данные исключения?

QAxBase: Error calling IDispatch member Add: Exception thrown by server
Code : 4096
Source : Microsoft Office Outlook
Description: ?????? ?? ??????.
Help :
Connect to the exception(int,QString,QString,QString) signal to catch this exception

Автор: Litkevich Yuriy 9.9.2011, 16:25

Цитата(pavelqt @ 7.9.2011, 11:33) *
И второе, как ловить и читать данные исключения?
Цитата(pavelqt @ 7.9.2011, 11:33) *
Connect to the exception(int,QString,QString,QString) signal to catch this exception

Автор: Alisher 22.9.2011, 11:29

Подскажите пожалуйста, как в цикле вывести все значения ячеек дипазона
QAxObject* range = StatSheet->querySubObject("Range(const QVariant&)",QVariant(QString("B9:B29")) );
такого например.
Можно это сделать без использования контейнеров?

Автор: Данил 20.12.2011, 13:45

Мне кажется, что тему нужно назвать работа с Excel, а не работа с MS Office. Там, кроме Excel ничего не затронуто.

Автор: Maclaren 21.4.2012, 1:44

Цитата(Данил @ 20.12.2011, 13:45) *
Мне кажется, что тему нужно назвать работа с Excel, а не работа с MS Office. Там, кроме Excel ничего не затронуто.

Подскажите как добавить строку в таблицу в word ??

Автор: romeodka 9.8.2012, 8:34

Я открыл документ word, изменил нужные мне данные. как теперь сохранить его в другой файл?

doc->querySubObject("SaveAs (const QString&)", initialName+"/pko1.docx");
и
doc->dynamicCall("SaveAs (const QString&)", initialName+"/pko1.docx");
не работает

Автор: gp 9.11.2013, 14:23

Что-то никак не могу извлечь значение ячейки... Выводит пустую строку, вместо необходимой информации. Уж умаялся искать, где загвоздка. Подскажите, пожалуйста.

Вот мой исходный код:

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <ActiveQt/qaxobject.h>
#include <ActiveQt/qaxbase.h>

#include <QMessageBox>
#include <QDebug>


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

    // получаем указатель на Excel
    mExcel = new QAxObject( "Excel.Application",this);
    mExcel->dynamicCall( "SetVisible(bool)", TRUE );
    // на книги
    workbooks = mExcel->querySubObject( "Workbooks" );
    // на директорию, откуда грузить книгу
    workbook = workbooks->querySubObject(
                "Open(const QString&)", "D:\\Guest\\collection.xls" );
    // на листы (снизу вкладки)
    mSheets = workbook->querySubObject( "Sheets" );
    // указываем, какой лист выбрать.
    sheet = mSheets->querySubObject( "Item(int)" ,2); //( "Item(const QVariant&)", QVariant("Common") );
    //gp
    sheet->dynamicCall( "Select" );

    qDebug()<<sheet->property("Name").toString();
}

MainWindow::~MainWindow()
{
    delete ui;

    delete sheet;
    delete mSheets;
    workbook->dynamicCall("Close()");
    delete workbook;
    delete workbooks;
    mExcel->dynamicCall("Quit()");
    delete mExcel;
}


QString MainWindow::getCellValue(int row, int col)
{
    // получение указателя на ячейку [row][col] ((!)нумерация с единицы)
    QAxObject* cell = sheet->querySubObject("Cells(const QVariant&,const QVariant&)",
                                            QVariant(row), QVariant(col));
    // получение содержимого
    QVariant result = cell->property("Value()");
    qDebug()<<"row=="<<row<<" col=="<<col<<" result=="<<result.toString();
    // освобождение памяти
    delete cell;

    return result.toString();
}

void MainWindow::on_pushButton_clicked()
{
    QMessageBox::information(this,"Считанное значение",
                             getCellValue(ui->spinBoxRow->value(), ui->spinBoxCol->value()));
}

Автор: avanGARd 9.11.2013, 18:03

Цитата(gp @ 9.11.2013, 15:23) *
Что-то никак не могу извлечь значение ячейки... Выводит пустую строку, вместо необходимой информации. Уж умаялся искать, где загвоздка. Подскажите, пожалуйста.


Это я под гостём писал. Выяснил случайно, что дело было в версии Qt. Собирал поначалу под 4.7.1, а вот http://www.prog.org.ru/topic_19719_0.html написано, что и под 4.7.0 при попытке считать или записать значения в ячейку таблицы Excel ничего не получается.
Я сразу же попробовал собрать под Qt 4.7.4, как было рекомендовано на том форуме. И всё сразу же заработало. Так вот ведь, в чём загвоздка была!!! Почти пол-дня потратил на выяснение причины, наткнулся на решение чисто случайно :)

Автор: avanGARd 10.11.2013, 8:12

Кто шарит в теме. Есть вопросик. Как осуществить средствами ActiveQt поиск в заданном столбце таблицы Excel ячейки с требуемым текстом?
Я имею в виду нахождение адреса ячейки с требуемым текстом.

Автор: Olga 5.2.2014, 15:11

Добрый день!
Подскажите пожалуйста в чём может быть проблема:

QAxObject* excel = new QAxObject( "Excel.Application", this );
excel->dynamicCall( "SetVisible(bool)", TRUE );
QAxObject *workbooks = excel->querySubObject( "Workbooks" );
QAxObject *workbook = workbooks->querySubObject( "Open(const QString&)", "E:\\OLGA\\table.xls");
QAxObject *sheets = workbook->querySubObject( "Sheets" );
QAxObject *statsheet=sheets->querySubObject("Item (const QVariant&)",QVariant("Лист1"));
statsheet->dynamicCall("Select");
QAxObject *range=statsheet->querySubObject("Range(const QVariant&)",QVariant(QString("A4:A4")));
range->dynamicCall("Clear");
range->dynamicCall("SetValue(const QVariant&)",QVariant("6"));


до строки statsheet->dynamicCall("Select") все работает нормально, а потом Excel выдает ошибку стандартную ошибку работы Office Microsoft

и в Qt в консоли приложения выводится ошибка E:\OLGA\Jobs\spr_windows\qw-build-desktop\debug\qw.exe завершился с кодом -1073741819

Автор: Litkevich Yuriy 5.2.2014, 16:35

ну для начала проверь этот указатель на нуль, может querySubObject() не удалось получить объект, который ты запрашиваешь и он вернул нулевой указатель.

Автор: Olga 5.2.2014, 20:29

QAxObject *statsheet=sheets->querySubObject("Item (const QVariant&)",QVariant("Лист1"));
Вот тут он почему-то не выбирает нужный лист(((, а почему не знаю

Автор: Olga 6.2.2014, 10:29

Разобралась, всё подключается и работает. Но теперь вопрос, почему если прописывать полный путь к экселевскому файлу, то он нормально запускается.
А если добавить его в файл ресурсов, то он не открывается?

Автор: Litkevich Yuriy 7.2.2014, 0:50

Цитата(Olga @ 6.2.2014, 12:29) *
А если добавить его в файл ресурсов, то он не открывается?
а как ты себе представляешь открытие экселем файла, который находится в коде программы?

Автор: Гость 13.8.2014, 9:56

Добрый день.

У меня Excel закрывается вместе с программой. Как сделать, чтобы при закрытии программы Excel оставался открытым?

Автор: JohnCS 13.8.2014, 10:14

Цитата(Гость @ 13.8.2014, 9:56) *
Добрый день.

У меня Excel закрывается вместе с программой. Как сделать, чтобы при закрытии программы Excel оставался открытым?


Разобрался.
Такое происходит только если открыть пустой Excel (без книг), при добавлении книги Excel остается открытым.

Автор: Vincent_vega 8.10.2014, 11:06

Друзья, подскажите пожалуйста
возникает ошибка
servertcp.obj:-1: ошибка: LNK2019: unresolved external symbol "public: __thiscall QAxObject::QAxObject(class QString const &,class QObject *)" (??0QAxObject@@QAE@ABVQString@@PAVQObject@@@Z) referenced in function "private: void __thiscall ServerTCP::on_pushButton_XLSX_clicked(void)" (?on_pushButton_XLSX_clicked@ServerTCP@@AAEXXZ)

в .pro прописал
QT += axcontainer
LIBS += -lqaxcontainer

код
#include <ActiveQt/qaxobject.h>
#include <ActiveQt/qaxbase.h>

void ServerTCP::on_pushButton_XLSX_clicked()
{

// получаем указатель на Excel
QAxObject *mExcel = new QAxObject( "Excel.Application",this);
}

Автор: Гость 10.6.2015, 16:25

с помощью active qt работаю с excel.
имеется массив вида
int mas[5]
строю в excel график, есть указатель
series на seriescollection(ну,как обычно)
теперь надо вызвать values и передать
массив,чтоб он появился на графике.
пожалуйста выручите!
получилось только передать одно
значение
series->setproperty("values",42)

Автор: lanz 10.6.2015, 21:02

Передавайте QVariantList со всеми нужными числами.

Автор: ViGOur 25.12.2015, 13:50

Разделил тему, сообщения перенес в новою тему: http://www.forum.crossplatform.ru/index.php?showtopic=10672

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)