Библиотека «Comtools»
Библиотека предназначеная для облегчения работы с технологией Automation, без использования директивы
#import.
Automation организует доступ к свойствам и вызов методов некоторого COM-объекта, посредством механизма IDispatch. Библиотека разрабатывалась с использованием компилятора mingw 3.4.5, на других компиляторах тестирование не проводилось. Архив с исходниками лежит
здесь
Описание
class Variant: public VARIANT {
public:
//Конструкторы и операторы '='
Variant();
Variant(const Variant& value) throw(HRESULT);
Variant& operator = (const Variant& other)throw(HRESULT);
template <typename T> Variant(const T& value)throw(HRESULT);
template <typename T> Variant& operator = (const T& value)throw(HRESULT)
template <VARTYPE vcode, typename T> Variant(const T& value)throw(HRESULT);
template <VARTYPE vcode, typename T> Variant& operator = (const T& value)throw(HRESULT);
// Предикаты
bool is_signed() const;
bool is_unsigned() const;
bool is_integral() const;
bool is_bstr() const;
bool is_floating() const;
bool is_pointer() const;
bool is_null() const;
bool empty() const;
bool operator < (const Variant& other);
bool operator == (const Variant& other);
template <typename T> bool operator < (const T& value);
template <typename T> bool operator == (const T& value);
//Арифметика
Variant& operator *= (const Variant& other) throw(HRESULT);
Variant& operator += (const Variant& other) throw(HRESULT);
Variant& operator -= (const Variant& other) throw(HRESULT);
Variant& operator /= (const Variant& other) throw(HRESULT);
template <typename T> Variant& operator *= (const T& value);
template <typename T> Variant& operator += (const T& value);
template <typename T> Variant& operator -= (const T& value);
template <typename T> Variant& operator /= (const T& value);
virtual ~Variant();
};
inline Variant operator * (const Variant& a, const Variant& b);
inline Variant operator + (const Variant& a, const Variant& b);
inline Variant operator - (const Variant& a, const Variant& b);
inline Variant operator / (const Variant& a, const Variant& b);
// Преобразует строку WideChar в строку MultiByte c указанием требуемой кодировки
// Параметр 'enc' одно из значений {CP_ACP,CP_OEMCP ,CP_UTF7, CP_UTF8}
std::string ConvertFromWideChar(const LPOLESTR str, int enc = CP_ACP);
inline std::string ConvertFromWideChar(const Variant& str, int enc = CP_ACP);
// Преобразует строку MultiByte в строку WideChar c указанием исходной кодировки
// Параметр 'enc' одно из значений {CP_ACP,CP_OEMCP ,CP_UTF7, CP_UTF8}
BSTR Convert2WideChar(const std::string& src, int enc = CP_ACP);
// Расшифровка кодов ошибок
std::string translateHRESULT(HRESULT hr);
// Запуск сервера автоматизации, параметр ctx должен соответствовать спецификации
// CoCreateInstance
Variant startApp(LPCOLESTR app_name, CLSCTX ctx = CLSCTX_LOCAL_SERVER) throw (HRESULT);
//Установить значение свойства mname у объекта disp значением value.
template <typename T>
inline void invokeSetProperty(const VARIANT& disp, LPOLESTR mname, const T& value);
//Вызвать метод mname у объекта disp. Также возможно указание до
//10 параметров произвольного типа a1—a10
inline Variant invokeMethod(const VARIANT& disp, LPOLESTR mname);
template <typename T1, typename T2,...,typename T10>
inline Variant invokeMethod(const VARIANT& disp, LPOLESTR mname, const T1& a1, const T2& a2,...,const T10& a10);
//Получить значение свойства с именем mname у объекта disp. Также возможно
//указание до 10 параметров произвольного типа a1 — a10
inline Variant invokeGetProperty(const Variant& disp, LPOLESTR mname);
template <typename T1, typename T2,...,typename T10>
inline Variant invokeGetProperty(const VARIANT& disp, LPOLESTR mname, const T1& a1, const T2& a2,...,const T10& a10);
Пример использования
В качестве примера я взял вот этот код и переписал его с использованием Comtools,сохранив функциональность.
#include <iostream>
#include "comtools.hpp"
using namespace std;
int main(){
try{
CoInitialize(static_cast<LPVOID>(0));
//Запускаем Excel
Variant xlApp = startApp(OLESTR("Excel.Application"));
//Делаем Excel видимым
invokeSetProperty(xlApp,OLESTR("Visible"), true);
//Получаем свойство 'Application.Workbooks'
Variant Wkbooks = invokeGetProperty(xlApp, OLESTR("Workbooks"));
//Вызываем метод 'Workbooks.Add' - создание новой книги
Variant Wkbook = invokeMethod(Wkbooks,OLESTR("Add"));
//Получаем свойство 'Workbook.ActiveSheet' - Активный лист
Variant ActSht = invokeGetProperty(Wkbook,OLESTR("ActiveSheet"));
//Получаем свойство 'Range("A1:O15")' активного листа
Variant Range = invokeGetProperty(ActSht,OLESTR("Range"), Convert2WideChar ( ("A1:O15")));
// Create a 15x15 safearray
SAFEARRAYBOUND sab[2];
sab[0].lLbound = 1; sab[0].cElements = 15;
sab[1].lLbound = 1; sab[1].cElements = 15;
SAFEARRAY* sarray = SafeArrayCreate (VT_VARIANT, 2, sab);
// Fill safearray with some values...
for(int i=1; i<=15; i++) {
for(int j=1; j<=15; j++) {
// Create entry value for (i,j)
Variant tmp = i*j;
// Add to safearray...
long indices[] = {i,j};
HRESULT hr = SafeArrayPutElement(sarray, indices, static_cast<void*>(dynamic_cast<VARIANT*>(&tmp)));
if (FAILED(hr))
throw hr;
}
}
//Для автоматической очистки созданного массива
Variant array = sarray;
//'Range.Value' заполняем значениями из массива
invokeSetProperty(Range,OLESTR("Value"),array);
::MessageBox(NULL, "All done.", "Notice", 0x10000);
//Типа, книгу мы уже сохранили
invokeSetProperty(Wkbook, OLESTR("Saved"), true);
//Выход
invokeMethod(xlApp,OLESTR("Quit"));
CoUninitialize();
}
catch(HRESULT hr){
cerr << hex << hr << "-" << translateHRESULT(hr)<< endl;
}
return 0;
}
Халин Андрей Борисович