Форум программистов, компьютерный форум, киберфорум
bedvit
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  

Библиотека COM (OLE Automation). Часть 1 - ArraySort (String)

Запись от bedvit размещена 13.11.2018 в 21:46
Показов 6244 Комментарии 18
Метки c++, vba, winapi

Теперь часть библиотеки BedvitCOM.
См. Часть 2.
Решил запустить пробный шар, и если будет время и интерес к данной тематике, возможно сделаю что-то годное в своих COM и XLL библиотеках.
Цель - скорость и удобство работы, создание для скриптовых языков, языков с поддержкой COM - того, чего там нет или есть, но хочется лучше.
В данном момент ориентир на VBA.
Добавил новый класс - "VBA" к двум уже существующим (см. ссылку выше).
Добавил новый метод - "ArraySortS" - сортировка данных (String) в одномерном/двухмерном массиве. С выводом индексов, сортировка возможна практически в любой размерности, если сортировать по первым двум измерениям) + удаление дубликатов.
На порядок быстрее QuickSort на массивах VBA. до 35 раз!
COM упакована в XLL (распаковывается и регистрируется автоматом).
Открываем XLL, пишем код в VBA - пользуемся.

26/11/2018 - Обновления функционала:
1.Сортировка одномерных и двухмерных массивов
2.Удаление дубликатов в одномерных массивах
3.Вывод по одномерному и двухмерному массивам индексов по строкам или столбцам.
4.Сортировка по столбцам, строкам, целому массиву с выводом строки/столбцы, столбцы/строки.
5.Сортировка по 3 ключам (столбцам, строкам)
6.Размерность массива может быть любой, в т.ч. и с минусовых значений -5+0+5... и т.д. (вывод индексов в такой же размерности)
7.Обработка NULL - строк (перемещение на последние позиции)
8.Использованы параллельные алгоритмы сортировки.
(библиотеки PPL, костыли не прикручивал)


Интерфейс класса:
C++
1
2
3
4
5
interface IVBA : IDispatch
{
    [id(1), helpstring("Array sort")] 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);
 
};
Параметры метода:
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")):
Кликните здесь для просмотра всего текста
Visual Basic
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
Sub Test_arr_sort()
'Dim bVBA As BedvitCOM.VBA: Set a = New BedvitCOM.VBA 'ранее связывание
Dim bVBA As Object: Set bVBA = CreateObject("BedvitCOM.VBA") 'позднее связывание
Dim testSize As Long: testSize = 2000000
Dim arr_index, arrTmp, i As Long, J As Long, t
 
''''''''''''1х массив'''''''''''''''''''''''
Dim Arr1: ReDim Arr1(-5 To testSize) As String
Dim Arr2: ReDim Arr2(-5 To testSize, -2 To 3) As String
 
'arr(5) - NULL - проверка для сортировки пустых
Arr1(6) = 0
Arr1(7) = "Test_arr_sort"
For i = 8 To testSize
  Arr1(i) = Format$(Int(Rnd * testSize), "0000000") '30% дубликатов
Next
 
arrTmp = Arr1 '!
t = Timer
bVBA.ArraySortS arrTmp
Debug.Print "Простая сорт. 1х массива, по возрастанию (по умолч.): " & Timer - t & " сек."
 
arrTmp = Arr1 '!!
t = Timer
bVBA.ArraySortS arrTmp, 1, , , , , 1, 0, 0
Debug.Print "Простая сорт.по убыванию 1x массива с удалением" & ((UBound(arrTmp) - LBound(arrTmp)) / (testSize - LBound(arrTmp)) - 1) * 100 & "%: " & Timer - t & " сек."
 
'arrTmp = arr - начальный массив не меняется, поэтому темповый - не нужен '!
t = Timer
bVBA.ArraySortS Arr1, 1, , , , , , 1, arr_index
Debug.Print "Вывод индексов для 1х массива, сортировка по убыванию:" & Timer - t & " сек."
 
''''''''''''2х массив'''''''''''''''''''''''
'arr(5) - NULL - проверка для сортировки пустых
Arr2(6, 2) = 0
Arr2(7, 2) = "Test_arr_sort"
For i = 8 To testSize
    For J = -2 To 3
        Arr2(i, J) = Format$(Int(Rnd * testSize), "0000000") '30% дубликатов
    Next
Next
 
arrTmp = Arr2 '!
t = Timer
bVBA.ArraySortS arrTmp, 0, , , , 2, 0, 0, 0
Debug.Print "Сортировка всего 2х массива - вывод строка-столбец: " & Timer - t & " сек."
 
arrTmp = Arr2 '!
t = Timer
bVBA.ArraySortS arrTmp, 0, 5, , , 3, 0, 0, 0
Debug.Print "Сортировка всего 2х массива - вывод столбец-строка " & Timer - t & " сек."
 
arrTmp = Arr2 '!
t = Timer
bVBA.ArraySortS arrTmp
Debug.Print "Простая сортировка 2х массива: " & Timer - t & " сек."
 
arrTmp = Arr2 '!
t = Timer '!
bVBA.ArraySortS arrTmp, 0, 3, , , , , 1, arr_index
Debug.Print "Вывод индексов для 2х массива, по указанному столбцу: " & Timer - t & " сек."
 
arrTmp = Arr2 '!
t = Timer
bVBA.ArraySortS arrTmp, 0, 5, , , 1, 0, 0, 0
Debug.Print "Сортировка 2х массива по 5му столбцу: " & Timer - t & " сек."
 
arrTmp = Arr2 '!
t = Timer '!
bVBA.ArraySortS arrTmp, 0, 8, , , 1, , 1, arr_index
Debug.Print "Вывод индексов для 2х массива, по 8й строке: " & Timer - t & " сек."
 
arrTmp = Arr2 '!
t = Timer
bVBA.ArraySortS arrTmp, 0, 8, , , 1, 0, 0, 0
Debug.Print "Сортировка 2х массива по 8й строке: " & Timer - t & " сек."
 
arrTmp = Arr2 '!
t = Timer
bVBA.ArraySortS arrTmp, 0, 1, 2, 3, 0, , 1, arr_index
Debug.Print "Вывод индексов для 2х массива, по 1,2,3му столбцу: " & Timer - t & " сек."
 
arrTmp = Arr2 '!
t = Timer
bVBA.ArraySortS arrTmp, 0, 1, 2, 3, 0, 0, 0, 0
Debug.Print "Сортировка 2х массива по 1,2,3му столбцу: " & Timer - t & " сек."
 
arrTmp = Arr2 '!
t = Timer
bVBA.ArraySortS arrTmp, 0, 8, 9, 10, 1, 0, 1, arr_index
Debug.Print "Вывод индексов для 8,9,10й строке: " & Timer - t & " сек."
 
arrTmp = Arr2 '!
t = Timer
bVBA.ArraySortS arrTmp, 0, 8, 9, 10, 1, 0, 0, 0
Debug.Print "Сортировка 2х массива по 8,9,10й строке: " & Timer - t & " сек."
 
Set bVBA = Nothing
End Sub


Результаты на 2-х млн. строк и 4-м столбцам:

Алгоритмы в VBA (быстрейшее решения, для сравнения):
QuickSort на VBA (простая сортировка одномерного массива) -6.8 сек.
Кликните здесь для просмотра всего текста
Visual Basic
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
Option Explicit
Const testSize = 2000000
Dim a(testSize), x$, y$
 
Sub test()
Dim i&
For i = 0 To testSize
  a(i) = Format$(Int(Rnd * testSize), "0000000")
Next
 
Dim t#
t = Timer
QuickSort 0, testSize
Debug.Print Timer - t
 
End Sub
 
Sub QuickSort(ByVal L As Long, ByVal U As Long)
Dim i As Long, j As Long
i = L: j = U: x = a((L + U) \ 2)
Do
  While a(i) < x: i = i + 1: Wend: While x < a(j): j = j - 1: Wend 'по возрастанию
'  While A(I) > X: I = I + 1: Wend: While X > A(J): J = J - 1: Wend 'по убыванию
  If i <= j Then
    y = a(i): a(i) = a(j): a(j) = y:    i = i + 1: j = j - 1
  End If
Loop Until i > j
If L < j Then QuickSort L, j
If i < U Then QuickSort i, U
End Sub


Метод 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"

Последние версии библиотек.
Миниатюры
Нажмите на изображение для увеличения
Название: BedvitCOM_VBA1.PNG
Просмотров: 348
Размер:	90.1 Кб
ID:	5523  
Метки c++, vba, winapi
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 18
Комментарии
  1. Старый комментарий
    Аватар для bedvit
    26/11/2018 - Обновления функционала
    Запись от bedvit размещена 27.11.2018 в 09:08 bedvit на форуме
  2. Старый комментарий
    подскажите, как сделать, чтобы в Ворде тоже работало? пока ошибку выдает на строке
    Visual Basic
    1
    
    Set bVBA = CreateObject("BedvitCOM.VBA")
    спс
    Запись от Ципихович Эндрю размещена 04.01.2019 в 09:50 Ципихович Эндрю вне форума
  3. Старый комментарий
    Аватар для bedvit
    Ципихович Эндрю, извините что с опозданием, дела не ждут, редко бываю. По вашему вопросу - для того, что бы использовать эту библиотеку в VBA (Word ), ее нужно зарегистрировать. И все заработает ) просто в Excel за вас это делает .xll Если тема ещё интересна, вышлю вам СОМ.DLL для использования в Word и любых других СОМ-поддерживающих программах.
    Запись от bedvit размещена 16.02.2019 в 00:22 bedvit на форуме
  4. Старый комментарий
    Если тема ещё интересна - ДА!
    вышлю вам СОМ.DLL для использования в Word - спасибо, жду
    Запись от Ципихович Эндрю размещена 16.02.2019 в 11:47 Ципихович Эндрю вне форума
  5. Старый комментарий
    Аватар для bedvit
    Выслал вам на указанную почту.
    Запись от bedvit размещена 17.02.2019 в 09:37 bedvit на форуме
  6. Старый комментарий
    А у меня ваш код ошибку выдаёт "Invalid procedure call or argument"
    Запись от FireHeadChaos размещена 26.10.2019 в 20:29 FireHeadChaos вне форума
  7. Старый комментарий
    Аватар для bedvit
    Вы открыли xll или зарегистрировали СОМ? Возможно вы передаёте неверный аргумент. Как вы используете данную библиотеку?
    Запись от bedvit размещена 27.10.2019 в 12:53 bedvit на форуме
  8. Старый комментарий
    вышлю вам СОМ.DLL для использования в Word
    Выслал вам на указанную почту

    решил вернуться к теме, приложите пжл здесь, спс
    Запись от Ципихович Эндрю размещена 27.10.2019 в 13:08 Ципихович Эндрю вне форума
  9. Старый комментарий
    Я пытаюсь использовать ваш тест: Пример тестирования и использования в VBA (элементарно через CreateObject("BedvitCOM.VBA")) . И что интересно объект создаётся. Открывал XLL
    Запись от FireHeadChaos размещена 27.10.2019 в 13:09 FireHeadChaos вне форума
  10. Старый комментарий
    Аватар для bedvit
    Ципихович Эндрю, посмотрите по ссылке Последние версии библиотек. Там всегда самая последняя.
    FireHeadChaos, можете показать код? Массив должен быть завернут в variant
    Visual Basic
    1
    
    Dim Arr1: ReDim Arr1(-5 To testSize) As String
    Есть вариант сортировки любых данных (Variant), он более универсальный:
    Библиотека COM (OLE Automation). Часть 2 - ArraySort (Variant)

    FireHeadChaos, да есть такой момент, сейчас посмотрю.
    Проблема решена. Залил новую версию.
    Запись от bedvit размещена 28.10.2019 в 00:03 bedvit на форуме
  11. Старый комментарий
    Простая сорт. 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 FireHeadChaos вне форума
  12. Старый комментарий
    Аватар для bedvit
    Цитата Сообщение от FireHeadChaos
    Вот мой результат по сортировкам, заполнил предварительно колонки листа случайными значениями и ещё заметил нагрузку процессора на все 100
    Спасибо за тест, у вас время больше, видимо машина слабее, чем тестовый стенд: ЦП-QuadCore Intel Core i7-3770, ОЗУ-16ГБ (DDR3-1600 DDR3 SDRAM), WIN7x64, MS Office2016x64
    Нагрузка на ЦП 100% - потому как использованы параллельные алгоритмы сортировки (библиотеки PPL).
    По выявленным ошибкам - прошу писать в блог или на почту.
    В блог думаю лучше, будет информация для других пользователей.
    Запись от bedvit размещена 28.10.2019 в 16:46 bedvit на форуме
  13. Старый комментарий
    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 JeyCi вне форума
  14. Старый комментарий
    и коннектилась как по примеру с 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 JeyCi вне форума
  15. Старый комментарий
    P.S. я не думаю, что надо усложнять передачей параметров через IDispatch, как здесь к Excel, или всё-таки придётся использовать DISPPARAMS?
    Запись от JeyCi размещена 01.05.2025 в 16:44 JeyCi вне форума
  16. Старый комментарий
    Аватар для bedvit
    JeyCi, приветствую. Разместите тему в профильном разделе по С++. Скиньте ссылку сюда. У меня не всегда есть время быстро ответить, а там возможно вам быстрее помогут. Если функция в других языках работает, то дело скорее всего в вашем коде на С++.
    Интерфейс метода:
    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);
    Но удобнее использовать другой метод/вариант сортировки любых данных (Variant), он более универсальный и его проще тестировать на С++, если использовать библиотеку ATL и ATL::CComVariant.
    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 на форуме
  17. Старый комментарий
    bedvit, перенесла вопрос по подключению к с++-Клиенту сюда -- можете удалить мои посты, если модерируете блог, или мне удалить?

    P.S. под рукой ATL нет,
    Запись от JeyCi размещена 01.05.2025 в 18:59 JeyCi вне форума
  18. Старый комментарий
    Аватар для bedvit
    JeyCi, ответил в вашей теме. Кратко: что бы использовать методы [in, out], нужно передавать VT_VARIANT | VT_BYREF в Invoke().
    Запись от bedvit размещена 02.05.2025 в 17:23 bedvit на форуме
 
Новые блоги и статьи
Рисование коллайдеров физического движка Box2D-WASM v3 на Three.js
8Observer8 04.06.2025
Erin Catto (автор Box2D) переписал с нуля Box2D v2 с С++ на Си и появилась версия Box2D v3. Birch-san собрал Box2D v3 в WebAssembly (WASM), чтобы можно было использовать Box2D v3 на JavaScript. В. . .
Worker Threads и многопоточность в Node.js
Reangularity 03.06.2025
Если вы когда-нибудь посещали собеседования на позицию Node. js разработчика, почти наверняка слышали заезженную фразу: "Node. js - однопоточная платформа". Звучит как неоспоримый факт, который. . .
Event-Driven CQRS на C# с паттерном Outbox
stackOverflow 03.06.2025
В традиционной модели происходит примерно следующее: вы получаете команду, обрабатываете ее, сохраняете результат в базу данных и затем пытаетесь опубликовать событие в брокер сообщений. Но что если. . .
OwenLogic: перенос сетевых переменных в панель Weintek (EasyBuilder Pro)
ФедосеевПавел 03.06.2025
ВВЕДЕНИЕ ПЕРЕД ЭКСПЕРИМЕНТАМИ - СОЗДАЙТЕ РЕЗЕРВНЫЕ КОПИИ ПРОЕКТОВ На момент написания статьи (02 июня 2025 г. ) самыми актуальными версиями ПО являются: OwenLogic v. 2. 10. 366 EasyBuilder Pro. . .
Dev-c++5.11 Покорение вершины
russiannick 02.06.2025
С утра преследовала одна мысль - вот бы выучить С++. Сказано-сделано. Окончив смену, скачал в интернете бестселлер Дэвиса Dev-C++ для чайников. Книга оказалась интересной и я скачал среду, на примере. . .
Тестирование Pull Request в Kubernetes с GitHub Actions и GKE
Mr. Docker 02.06.2025
Мы все знаем, что тестирование на локальной машине или в изолированном CI-окружении — это не совсем то же самое, что тестирование в реальном кластере Kubernetes. Контекстно-зависимые ошибки, проблемы. . .
Оптимизация CMake для ускорения сборки
bytestream 02.06.2025
Вы когда-нибудь ловили себя на мысле, что пока ваш проект компилируется, можно успеть сварить кофе, прочитать главу книги или даже сбегать в соседний офис? Если да, то добро пожаловать в клуб. . .
JS String.prototype.localeCo­mpare()
mr_dramm 02.06.2025
скопировано из этой темы чтобы не потерялось. localeCompare без указания локали для сравнения строк под капотом использует Intl. Collator , который работает согласно Unicode Collation Algorithm. . .
Облако проектов
russiannick 01.06.2025
Слава Джа, написал прогу для компиляции. Значит написал компилятор? Обьем кода 300+ строк. Язык-яву. Вводим данные, заполняем поля, тычем радиобаттоны. И по итогу в поле результат получам листинг. . .
Rust и квантовые вычисления: интеграция с Q# и Qiskit
golander 01.06.2025
Мир квантовых вычислений традиционно оставался закрытым клубом для высокоуровневых языков типа Python и специализированных DSL вроде Q#. Однако в последние годы Rust начал тихую революцию в этой. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru
OSZAR »