Библиотека COM (OLE Automation). Часть 1 - ArraySort (String)
Запись от bedvit размещена 13.11.2018 в 21:46
Показов 6244
Комментарии 18
Теперь часть библиотеки BedvitCOM. См. Часть 2. Решил запустить пробный шар, и если будет время и интерес к данной тематике, возможно сделаю что-то годное в своих COM и XLL библиотеках. Цель - скорость и удобство работы, создание для скриптовых языков, языков с поддержкой COM - того, чего там нет или есть, но хочется лучше. В данном момент ориентир на VBA. Добавил новый класс - "VBA" к двум уже существующим (см. ссылку выше). Добавил новый метод - "ArraySortS" - сортировка данных (String) в одномерном/двухмерном массиве. С выводом индексов, сортировка возможна практически в любой размерности, если сортировать по первым двум измерениям) + удаление дубликатов. COM упакована в XLL (распаковывается и регистрируется автоматом). Открываем XLL, пишем код в VBA - пользуемся. 26/11/2018 - Обновления функционала: 1.Сортировка одномерных и двухмерных массивов 2.Удаление дубликатов в одномерных массивах 3.Вывод по одномерному и двухмерному массивам индексов по строкам или столбцам. 4.Сортировка по столбцам, строкам, целому массиву с выводом строки/столбцы, столбцы/строки. 5.Сортировка по 3 ключам (столбцам, строкам) 6.Размерность массива может быть любой, в т.ч. и с минусовых значений -5+0+5... и т.д. (вывод индексов в такой же размерности) 7.Обработка NULL - строк (перемещение на последние позиции) 8.Использованы параллельные алгоритмы сортировки. (библиотеки PPL, костыли не прикручивал) Интерфейс класса:
1.array_in_out - указатель на массив (ввод/вывод) 2.sort_order - порядок сортировки : 0-по возрастанию, 1-по убыванию 3.key_1 - ключи сортировки (порядковый номер столбца/строки, начиная с 1) по умолчанию - первый столбец/строка 4.key_2 5.key_3 6.sort_orientation - ориентация сортировки (0 - по строкам, 1 - по столбцам, 2- целый массив вывод строка-столбец, 3- целый массив вывод столбец-строка) 7.delete_duplicates - удаляем дубликаты (в одномерных массивах) 8.out_array_index - выводим индексы, "булево" 1/0 (тогда основной массив array_in_out - не меняется, выводятся данные в index_array_out ) 9.index_array_out - одномерный массив с индексами (с учетом всех ключей), если задан out_array_index=1 Все параметры метода, кроме входящего массива - опциональные (с значениями по умолчанию - 0 (ключи-1)) Метод "ArraySortS" работает через Variant, т.к. на некоторых скриптовых языках SAFEARRAY ходит через границы COM, только в обертке VARIANT (без изобретения костылей). Пример тестирования и использования в VBA (элементарно через CreateObject("BedvitCOM.VBA")): Кликните здесь для просмотра всего текста
Результаты на 2-х млн. строк и 4-м столбцам: Алгоритмы в VBA (быстрейшее решения, для сравнения): QuickSort на VBA (простая сортировка одномерного массива) -6.8 сек. Кликните здесь для просмотра всего текста
Метод ArraySortS из класса BedvitCOM.VBA (тестовый стенд: ЦП-QuadCore Intel Core i7-3770, ОЗУ-16ГБ (DDR3-1600 DDR3 SDRAM), WIN7x64, MS Office2016x64): Простая сорт. 1х массива, по возрастанию (по умолч.): 0,21875 сек. Простая сорт.по убыванию 1x массива с удалением-34,5385136537159%: 0,3515625 сек. Вывод индексов для 1х массива, сортировка по убыванию:0,2460938 сек. Сортировка всего 2х массива - вывод строка-столбец: 1,75 сек. Сортировка всего 2х массива - вывод столбец-строка 1,78125 сек. Простая сортировка 2х массива: 0,390625 сек. Вывод индексов для 2х массива, по указанному столбцу: 0,28125 сек. Сортировка 2х массива по 5му столбцу: 0,05078125 сек. Вывод индексов для 2х массива, по 8й строке: 0 сек. Сортировка 2х массива по 8й строке: 0,05078125 сек. Вывод индексов для 2х массива, по 1,2,3му столбцу: 1,484375 сек. Сортировка 2х массива по 1,2,3му столбцу: 1,519531 сек. Вывод индексов для 8,9,10й строке: 0 сек. Сортировка 2х массива по 8,9,10й строке: 0,05078125E сек. 18/02/2018 - добавил СОМ-библиотеки Для возможности использовать данную сортировку в СОМ-поддерживающих программах. Регистрация COM реализовано как под админом, так и под пользователем (актуально в офисной части клиентов) Регистрация стандартная: Админ: Regsvr32 "FullName.DLL" !ПОМНИМ! В Win10 регистрация под правами админа: "правая кнопка" - "Пуск" -"Командная строка (администратор)" Пользователь: Regsvr32 /i /n "FullName.DLL" Удалить из реестра: Regsvr32 /u "FullName.DLL" Последние версии библиотек. |
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 18
Комментарии
-
Запись от bedvit размещена 27.11.2018 в 09:08 -
подскажите, как сделать, чтобы в Ворде тоже работало? пока ошибку выдает на строке
спсVisual Basic 1
Set bVBA = CreateObject("BedvitCOM.VBA")
Запись от Ципихович Эндрю размещена 04.01.2019 в 09:50 -
Ципихович Эндрю, извините что с опозданием, дела не ждут, редко бываю. По вашему вопросу - для того, что бы использовать эту библиотеку в VBA (Word ), ее нужно зарегистрировать. И все заработает ) просто в Excel за вас это делает .xll Если тема ещё интересна, вышлю вам СОМ.DLL для использования в Word и любых других СОМ-поддерживающих программах.
Запись от bedvit размещена 16.02.2019 в 00:22 -
Если тема ещё интересна - ДА!
вышлю вам СОМ.DLL для использования в Word - спасибо, ждуЗапись от Ципихович Эндрю размещена 16.02.2019 в 11:47 -
Запись от bedvit размещена 17.02.2019 в 09:37 -
А у меня ваш код ошибку выдаёт "Invalid procedure call or argument"
Запись от FireHeadChaos размещена 26.10.2019 в 20:29 -
Запись от bedvit размещена 27.10.2019 в 12:53 -
вышлю вам СОМ.DLL для использования в Word
Выслал вам на указанную почту
решил вернуться к теме, приложите пжл здесь, спсЗапись от Ципихович Эндрю размещена 27.10.2019 в 13:08 -
Я пытаюсь использовать ваш тест: Пример тестирования и использования в VBA (элементарно через CreateObject("BedvitCOM.VBA")) . И что интересно объект создаётся. Открывал XLL
Запись от FireHeadChaos размещена 27.10.2019 в 13:09 -
Ципихович Эндрю, посмотрите по ссылке Последние версии библиотек. Там всегда самая последняя.
FireHeadChaos, можете показать код? Массив должен быть завернут в variant
Есть вариант сортировки любых данных (Variant), он более универсальный:Visual Basic 1
Dim Arr1: ReDim Arr1(-5 To testSize) As String
Библиотека COM (OLE Automation). Часть 2 - ArraySort (Variant)
FireHeadChaos, да есть такой момент, сейчас посмотрю.
Проблема решена. Залил новую версию.Запись от bedvit размещена 28.10.2019 в 00:03 -
Простая сорт. STRING 1х массива, по возрастанию (по умолч.): 0,9140625 сек.
Простая сорт. VARIANT 1х массива, по возрастанию (по умолч.): 1,132813 сек.
Простая сорт. VARIANT 2х массива, по возрастанию (по умолч.): 1,640625 сек.
Простая сорт. VARIANT 2х массива, по убыванию по первому ключу и по возрастанию по второму: 3,476563 сек.
Простая сорт. VARIANT 2х массива, по возрастанию по трём ключам: 4,257813 сек.
Простая сорт. VARIANT 2х массива, по убыванию, по первому столбцу и третьему: 0 сек.
Вот мой результат по сортировкам, заполнил предварительно колонки листа случайными значениями и ещё заметил нагрузку процессора на все 100Запись от FireHeadChaos размещена 28.10.2019 в 15:17 -
Спасибо за тест, у вас время больше, видимо машина слабее, чем тестовый стенд: ЦП-QuadCore Intel Core i7-3770, ОЗУ-16ГБ (DDR3-1600 DDR3 SDRAM), WIN7x64, MS Office2016x64Сообщение от FireHeadChaos
Нагрузка на ЦП 100% - потому как использованы параллельные алгоритмы сортировки (библиотеки PPL).
По выявленным ошибкам - прошу писать в блог или на почту.
В блог думаю лучше, будет информация для других пользователей.Запись от bedvit размещена 28.10.2019 в 16:46 -
bedvit, если будет время, посмотрите please мою неработающую попытку использовать BedvitCOM-сервер в с++-клиенте -- знаю, что писать клиента для COM на С/С++ не совсем то для чего делается COM, но для разработки обычно удобно заглянуть внутрь из C++, а не из excel... вобщем, что-то у меня не сортирует, может подскажете в чём проблема,
C++ 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
//mycom.h #ifndef _my__dynamiclinking2_mycom_h_ #define _my__dynamiclinking2_mycom_h_ #include <windowsx.h> #include <iostream> #include <initguid.h> /* in oleview.exe [ odl, uuid(8465DED5-1F50-4A34-B0BD-D4379FDDE618), dual, nonextensible, oleautomation ] interface IVBA : IDispatch { [id(0x00000001), helpstring("Array sort")] HRESULT ArraySort( [in, out] VARIANT* array_in_out, [in, optional, defaultvalue(0)] VARIANT_BOOL sort_order, [in, optional, defaultvalue(-1)] long key_1, [in, optional, defaultvalue(-1)] long key_2, [in, optional, defaultvalue(-1)] long key_3, [in, optional, defaultvalue(0)] long sort_orientation, [in, optional, defaultvalue(0)] VARIANT_BOOL delete_duplicates, [in, optional, defaultvalue(0)] VARIANT_BOOL out_array_index, [in, out, optional, defaultvalue(0)] VARIANT* index_array_out); }; */ DEFINE_GUID( IID_IVBA, 0x8465ded5,0x1f50,0x4a34,0xb0,0xbd,0xd4,0x37,0x9f,0xdd,0xe6,0x18); class IVBA : public IDispatch { public: IVBA(); virtual ~IVBA(); STDMETHOD(ArraySort) (VARIANT*) PURE; }; #endif
Запись от JeyCi размещена 01.05.2025 в 16:20 -
и коннектилась как по примеру с rsdn
может, свежим взглядом видно, почему из с++ не сортирует?C++ 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 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
#include <vector> #include <windows.h> #include <comdef.h> #include <stdio.h> #include <my__dynamiclinking2/mycom.h> // #import "C:\BedvitCOMx32.dll" - with TypeLib #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; void fillVariant(VARIANT& varIn, BSTR *srcArray, int srcArrayLen) { VARIANT *variantArray = &varIn; VariantInit(variantArray); SAFEARRAYBOUND aDim[1]; aDim[0].lLbound = 0; aDim[0].cElements = srcArrayLen; SAFEARRAY* sa = SafeArrayCreate(VT_BSTR, 1, aDim); if (sa) { BSTR* dwArray = NULL; SafeArrayAccessData(sa, (void**)&dwArray); for(int i = 0; i < srcArrayLen; i++) { // note: passing ownership, NOT making a copy dwArray[i] = srcArray[i]; std::wcout << dwArray[i] << endl; } SafeArrayUnaccessData(sa); variantArray->vt = VT_ARRAY|VT_BSTR; variantArray->parray = sa; } } BSTR foo(const char* s) { return _bstr_t(s).Detach(); } int main( int argc, char *argv[] ) { cout << "Initializing COM" << endl; if ( FAILED( CoInitialize( NULL ))) { cout << "Unable to initialize COM" << endl; return -1; } char* szProgID = "BedvitCOM.VBA"; WCHAR szWideProgID[128]; CLSID clsid; long lLen = MultiByteToWideChar( CP_ACP, 0, szProgID, strlen( szProgID ), szWideProgID, sizeof( szWideProgID ) ); szWideProgID[ lLen ] = '\0'; HRESULT hr = ::CLSIDFromProgID( szWideProgID, &clsid ); if ( FAILED( hr )) { cout.setf( ios::hex, ios::basefield ); cout << "Unable to get CLSID from ProgID. HR = " << hr << endl; return -1; } ////// // https://www.rsdn.org/article/com/introcom.xml IClassFactory* pCF; // Получить фабрику классов для класса Math hr = CoGetClassObject( clsid, CLSCTX_INPROC, NULL, IID_IClassFactory, (void**) &pCF ); if ( FAILED( hr )) { cout.setf( ios::hex, ios::basefield ); cout << "Failed to GetClassObject server instance. HR = " << hr << endl; return -1; } // с помощью фабрики классов создать экземпляр // компонента и получить интерфейс IUnknown. IUnknown* pUnk; hr = pCF->CreateInstance( NULL, IID_IUnknown, (void**) &pUnk ); // Release the class factory pCF->Release(); if ( FAILED( hr )) { cout.setf( ios::hex, ios::basefield ); cout << "Failed to create server instance. HR = " << hr << endl; return -1; } cout << "Instance created" << endl; /////// vector<char*> v; v={ "11", "1", "2", "8", "7" }; BSTR *theArray = new BSTR[5]; auto it { v.begin() }; // получаем итератор int i=0; //while(it!= v.end()) // пока не дойдем до конца for(auto it{begin(v)}; it != end(v); it++ ) { theArray[i] = foo(*it); //++iter; ++i; } VARIANT vArray; fillVariant(vArray, theArray, 5); //// IVBA* pVBA = NULL; hr = pUnk->QueryInterface( IID_IVBA, (LPVOID*)&pVBA ); pUnk->Release(); if ( FAILED( hr )) { cout << "QueryInterface() for IVBA failed" << endl; return -1; } ///// pVBA->ArraySort( &vArray ); // [in, out] ///// read vArray LPCWSTR pValsOut; hr = SafeArrayAccessData(vArray.parray, (void **)&pValsOut); // direct access to SA memory if (SUCCEEDED(hr)) { long lowerBound, upperBound; // get array bounds SafeArrayGetLBound(vArray.parray, 1 , &lowerBound); SafeArrayGetUBound(vArray.parray, 1, &upperBound); long cnt_elements = upperBound - lowerBound + 1; long ix=0; for (long i = 0; i < cnt_elements; ++i) // iterate through returned values { LPCWSTR lVar; hr= SafeArrayGetElement(vArray.parray, &ix, &lVar); wcout << lVar << endl; ix++; } //for(auto& it : Var.parray) cout << "el. " << pVals[i] << endl; SafeArrayUnaccessData(vArray.parray); } // don't forget to free memory when done! // note: the VARIANT owns the BSTRs, so DON'T free them! VariantClear(&vArray); delete[] theArray; ///// cout << "Releasing instance" << endl; pVBA->Release(); cout << "Shuting down COM" << endl; CoUninitialize(); return 0; }
возможно, использую более позднюю версию - ваша новая была здесь... а у меня на компе, вероятно, эта ArraySort без SЗапись от JeyCi размещена 01.05.2025 в 16:20 -
P.S. я не думаю, что надо усложнять передачей параметров через IDispatch, как здесь к Excel, или всё-таки придётся использовать DISPPARAMS?
Запись от JeyCi размещена 01.05.2025 в 16:44 -
JeyCi, приветствую. Разместите тему в профильном разделе по С++. Скиньте ссылку сюда. У меня не всегда есть время быстро ответить, а там возможно вам быстрее помогут. Если функция в других языках работает, то дело скорее всего в вашем коде на С++.
Интерфейс метода:
Но удобнее использовать другой метод/вариант сортировки любых данных (Variant), он более универсальный и его проще тестировать на С++, если использовать библиотеку ATL и ATL::CComVariant.C++ 1 2 3
interface IVBA : IDispatch { [id(1), helpstring("Array sort (String)")] HRESULT ArraySortS([in, out] VARIANT* array_in_out, [in,defaultvalue(0)] VARIANT_BOOL sort_order, [in, defaultvalue(0)] LONG key_1, [in, defaultvalue(0)] LONG key_2, [in, defaultvalue(0)] LONG key_3, [in, defaultvalue(0)] LONG sort_orientation, [in, defaultvalue(0)] VARIANT_BOOL delete_duplicates,[in, defaultvalue(0)] VARIANT_BOOL out_array_index, [in, out, defaultvalue(0)] VARIANT* index_array_out);
C++ 1
[id(7), helpstring("Array sort (Variant)")] HRESULT ArraySortV([in, out] VARIANT* array_in_out, [in, defaultvalue(1)] LONG key_1, [in, defaultvalue(0)] VARIANT_BOOL sort_order1, [in, defaultvalue(0)] LONG key_2, [in, defaultvalue(0)] VARIANT_BOOL sort_order2, [in, defaultvalue(0)] LONG key_3, [in, defaultvalue(0)] VARIANT_BOOL sort_order3, [in, defaultvalue(L"")] BSTR key_and_sort_order_next, [in, defaultvalue(0)] LONG optionCompare);
Запись от bedvit размещена 01.05.2025 в 18:33 -
bedvit, перенесла вопрос по подключению к с++-Клиенту сюда -- можете удалить мои посты, если модерируете блог, или мне удалить?
P.S. под рукой ATL нет,Запись от JeyCi размещена 01.05.2025 в 18:59 -
Запись от bedvit размещена 02.05.2025 в 17:23