Работа с MS Office с помощью ActiveQt

Материал из Wiki.crossplatform.ru

Перейти к: навигация, поиск

Содержание


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

Совет: внимательно следите за создаваемыми объектами и указателями, возвращаемыми методом querySubObject(). Они не удаляются автоматически, нужно вызывать delete вручную. В противном случае будет эффективно расходоваться память, и после нескольких тысяч вызовов метода querySubObject() ваша программа и эксель в сумме займут всю память, но это полбеды - обращение к одной ячейке будет занимать секунду. Это всего лишь предостережение...

Ну теперь собственно приступаем к кодингу.

#include <ActiveQt/qaxobject.h>
#include <ActiveQt/qaxbase.h>
 
// получаем указатель на Excel
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" ); 
// указываем, какой лист выбрать. У меня он называется topic.
QAxObject *StatSheet = mSheets->querySubObject( "Item(const QVariant&)", QVariant("topic") );

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

[править] Операции с листами

// копирование листа "Старый лист" в "Новый лист"
// получение указателя
QAxObject* sheetToCopy = workbook->querySubObject("Worksheets(const QVariant&)", "Старый лист");
// создание копии листа в место перед копируемым (слева). имя по умолчанию - "Старый лист (2)"
sheetToCopy->dynamicCall("Copy(const QVariant&)", sheetToCopy->asVariant());
// очистка памяти
delete sheetToCopy;
// получение ссылки на новый лист
QAxObject* newSheet = workbook->querySubObject("Worksheets(const QVariant&)", "Старый лист (2)");
// переименование нового листа
newSheet->setProperty("Name", "Новый лист");
// очистка памяти
delete newSheet;

[править] Вставка значения в отдельную ячейку

// получение указателя на ячейку [row][col] ((!)нумерация с единицы)
QAxObject* cell = StatSheet->querySubObject("Cells(QVariant,QVariant)", row, col);
// вставка значения переменной data (любой тип, приводимый к QVariant) в полученную ячейку
cell->setProperty("Value", QVariant(data));
// освобождение памяти
delete cell;

[править] Извлечение значения из отдельной ячейки

// получение указателя на ячейку [row][col] ((!)нумерация с единицы)
QAxObject* cell = StatSheet->querySubObject("Cells(QVariant,QVariant)", row, col);
// получение содержимого
QVariant result = cell->property("Value");
// освобождение памяти
delete cell;

[править] Вставка данных в прямоугольную область

Значительно увеличивает скорость вывода в сравнении с поячеечным способом.

// получение указателя на левую верхнюю ячейку [row][col] ((!)нумерация с единицы)
QAxObject* Cell1 = StatSheet->querySubObject("Cells(QVariant&,QVariant&)", row, col);
// получение указателя на правую нижнюю ячейку [row + numRows - 1][col + numCols - 1] ((!) numRows>=1,numCols>=1)
QAxObject* Cell2 = StatSheet->querySubObject("Cells(QVariant&,QVariant&)", row + numRows - 1, col + numCols - 1);
// получение указателя на целевую область
QAxObject* range = StatSheet->querySubObject("Range(const QVariant&,const QVariant&)", Cell1->asVariant(), Cell2->asVariant() );
// список ячеек строки
QList<QVariant> cellsList;
// список строк
QList<QVariant> rowsList;
for (int i = 0; i < numRows; i++)
{
    cellsList.clear();
    for (int j = 0; j < numCols; j++)
        cellsList << i*j;
    // в список строк добавляется QVariant каждой строки
    rowsList << QVariant(cellsList);
}
// собственно вывод
range->setProperty("Value", QVariant(rowsList) );
// освобождение памяти
delete range;
delete Cell1;
delete Cell2;

[править] Изменение цвета фона и шрифта ячейки

[править] Цвет фона

// получаем указатель на ячейку [row][col] ((!)нумерация с единицы)
QAxObject* cell = StatSheet->querySubObject("Cells(QVariant,QVariant)", row, col);
// получаем указатель на её фон
QAxObject* interior=cell->querySubObject("Interior");
// устанавливаем цвет
interior->setProperty("Color",QColor("green"));
// освобождение памяти
delete interior;
delete cell;

[править] Цвет шрифта

// получаем указатель на ячейку [row][col] ((!)нумерация с единицы)
QAxObject* cell=sheet->querySubObject("Cells(QVariant,QVariant)", row, col);
// получаем указатель на её шрифт
QAxObject* font=cell->querySubObject("Font");
// устанавливаем цвет
font->setProperty("Color",QColor("blue"));
// освобождение памяти
delete font;
delete cell;

[править] Копирование данных из 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()");

[править] Работа со шрифтами

// Получаем указатель на D2
QAxObject *rangec = StatSheet->querySubObject( "Range(const QVariant&)",QVariant("D2")); 
// Получаем указатель на 2;2 
QAxObject *rangep = StatSheet->querySubObject("Cells(const QVariant&,const QVariant&)",QVariant(2),QVariant(2));

Тут и Range можно, просто разные ячейки.В одной у меня текст забит, и я хочу получить, каким шрифтом он напечатан

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

[править] Редактирование высоты, ширины строк или столбцов

В место Rows указываем Columns, в место RowHeight указываем ColumnWidth.

// опять же,указатель на D2
QAxObject *rangec = StatSheet->querySubObject( "Range(const QVariant&)",QVariant("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);

[править] Разрешает перенос

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

Я здесь напишу основные. Выравнивание по левому краю: -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")));
// xlEdgeTop(верхняя граница) (xlEdgeLeft) левая, 
// (xlEdgeRight) правая,(xlEdgeBottom) нижняя 
// и 2 диагонали (xlDiagonalDown) (xlDiagonalUp)
QAxObject *border = rangec->querySubObject("Borders(xlEdgeTop)");
// тип линии (там пунктиры,сплошная и так далее)
border->setProperty("LineStyle",1); 
// толщина
border->setProperty("Weight",2);

[править] Печать документа

    // Открываем документ
    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()");


[править] Как получить допустимые значения определенного range с контролируемым вводом

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

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

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

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

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


Обсудить на форуме...