Работа с 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. Далее задавайте вопросы,будем уже на конкретных примерах разбираться.