Форум программистов, компьютерный форум, киберфорум
C/C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.78/121: Рейтинг темы: голосов - 121, средняя оценка - 4.78
Эксперт 1С
 Аватар для OverDozero
1474 / 337 / 135
Регистрация: 07.04.2011
Сообщений: 1,784

Импорт диапазона из Excel в вариантный массив

05.05.2015, 21:20. Показов 25714. Ответов 34
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем доброго времени суток.Ребята,подскажите пожалуйста,как из Екселя выдернуть сразу диапазон ячеек со значениями и запихнуть в вариантный массив?3 дня уже курю гугл - и все никак не выйдет.В какую сторону хоть копать?
Могу создать вариантный массив,считать каждую ячейку в экселе отдельно,и запихнуть в данный массив.Но при объеме данных свыше 50 000 строк чтение довольно долго выходит.А эти данные еще и обработать надо.
ПЫ.СЫ.Готовый код не прошу - просто пните в нужном направлении наброском кода.Что и куда копать.
Спасибо!
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
05.05.2015, 21:20
Ответы с готовыми решениями:

Как сделать вариантный импорт рисунков?
Разрешите у Вас спросить такую вещь: мне следует сделать следующее. Пользователь выбирает в выпадающем списке одно из двух значений. ...

Как лучше записать вариантный массив в текстовой (.txt) файл
Имеется массив A:variant MyArray := VarArrayCreate(, VarDouble); Как писать тоже знаю, примерно так : var f:textFile; //...

Чтение данных из диапазона (Excel) в массив (Delphi)
Прочитав пару статей на тему быстрой обработки данных excel в delphi, решил считывать данные диапазоном, нежели из каждой ячейки. Но не...

34
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
20.03.2019, 19:29
Студворк — интернет-сервис помощи студентам
Данные находятся в екселе, заносятся в массив arr, их оттуда благополучно можно извлечь по номеру элемента, как Вы и показали в примере чуть выше, но результат работы вот этой строки всегда неверные или я что то не верно делаю:

C++
1
2
3
HRESULT hresult;
long iUBound;
hresult=SafeArrayGetUBound(arr.parray, 1, &iUBound); // статус hresult = S_OK
Но в iUBound записывается всегда значение 1, хотя нижняя граница массива больше одного и по номеру элемента оттуда можно достать данные.
Но при той же абсолютно записи SafeArrayGetLBound - число столбцов массива отображается верно.
Не знаю что не так.
0
Модератор
 Аватар для vxg
3410 / 2182 / 354
Регистрация: 13.01.2012
Сообщений: 8,469
20.03.2019, 19:36
Optimus11, судя по коду вы запрашиваете верхнюю границу первого измерения много мерного массива

Добавлено через 1 минуту
Optimus11, покажите скрин экселя и назовите какие значения вам кажется должна вернуть функция

Добавлено через 25 секунд
... и какие она реально возвращает
0
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
20.03.2019, 21:26
Да скриншот с экрана екселя не нужен в принципе.
Вот 'nb строчки кода берут диапазон из екселя:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
...
IDispatch *pXlRange;
    {
                VARIANT parm;
        parm.vt = VT_BSTR
        parm.bstrVal = ::SysAllocString(L"A1:D10"); // Данные из этого диапазона заносятся в arr;
 
        VARIANT result;
        VariantInit(&result);
        AutoWrap_1(DISPATCH_PROPERTYGET, &result, pXlSheet, (LPOLESTR)L"Range", 1, parm);
        VariantClear(&parm);
        pXlRange = result.pdispVal;
    }
И соответственно:

long iUBound;
SafeArrayGetUBound(arr.parray, 2, &iUBound); // И соответственно iUBound получается равным = 1

long lUBound;
SafeArrayGetLBound(arr.parray, 2, &lUBound);/ И соответственно lUBound получается равным = 4, соответствует ширине диапазона.

Вот как то так получается.
0
Модератор
 Аватар для vxg
3410 / 2182 / 354
Регистрация: 13.01.2012
Сообщений: 8,469
22.03.2019, 07:59
Optimus11, иии... какие вам значения не нравятся?
0
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
22.03.2019, 08:44
Вот это SafeArrayGetUBound(arr.parray, 2, &iUBound), где iUBound=1

Я понимаю, что я чего то не понимаю, но хотелось бы получить номер нижней границы массива по вертикали, но немогу реально понять как.
0
Модератор
 Аватар для vxg
3410 / 2182 / 354
Регистрация: 13.01.2012
Сообщений: 8,469
23.03.2019, 16:19
Optimus11, я вас не понимаю. вот есть код
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
        VARIANT addr;
        VARIANT range;
        VARIANT value;
 
        VariantInit(&addr);
        VariantInit(&range);
        VariantInit(&value);
 
        while (true) {
 
        addr.vt = VT_BSTR;
        addr.bstrVal = SysAllocString(L"B3:D6");
        BREAK_ON_FAIL(AutoWrap(DISPATCH_PROPERTYGET, &range, xls.ws.pdispVal, L"Range", 1, addr))
        BREAK_ON_FAIL(AutoWrap(DISPATCH_PROPERTYGET, &value, range.pdispVal, L"Value", 0))
 
        std::cout << V_VT(&value) << std::endl;
 
        SAFEARRAY *sa = V_ARRAY(&value);
 
        long i_min, i_max;
        SafeArrayGetLBound(sa, 1, &i_min);
        SafeArrayGetUBound(sa, 1, &i_max);
 
        std::cout << "i_min = " << i_min << std::endl;
        std::cout << "i_max = " << i_max << std::endl;
 
        long j_min, j_max;
        SafeArrayGetLBound(sa, 2, &j_min);
        SafeArrayGetUBound(sa, 2, &j_max);
 
        std::cout << "j_min = " << j_min << std::endl;
        std::cout << "j_max = " << j_max << std::endl;
 
        break;}
 
        VariantClear(&addr);
        VariantClear(&range);
        VariantClear(&value);
он выводит вот это
8204
i_min = 1
i_max = 4
j_min = 1
j_max = 3
это верно - в value находится VARIANT с типом 8204 - это VT_ARRAY | VT_VARIANT поэтому можно без страха оперировать с ним как с SAFEARRAY - у первого измерения границы (1, 4), у второго (1, 3) - это верно так как диапазон B3 : D6 содержит 4 строки и три столбца. или вы думаете что диапазон должен показать вам в качестве нижней и верхней границ номера строк / столбцов ? не должен. это не его дело.
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
23.03.2019, 23:09
думаете что диапазон должен показать вам в качестве нижней и верхней границ номера строк / столбцов ? не должен. это не его дело.
Спасибо, именно так я ошибочно и думал.
0
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
24.03.2019, 19:36
А может быть можете пожалуйста подсказать в чем разница между:

1)
C++
1
2
3
4
VT_I4   4-byte signed integer value.
VT_I8   8-byte signed integer.
и
VT_R8   64-bit IEEE floating point value.
То есть получается так, что когда я читаю данные из ексель и в ячейке ексель находится екселевской числовое значение, то когда пробегаюсь по элеменнтам массива куда были записанные данные из екселя, то в элеменете Variant срабатывает:
C++
1
2
3
if (V_VT(&arr_element) == VT_R8)
{
}
VT_I4 и VT_I8 - не срабатывает.

Но, когда создается variant массив и туда записываются данные для последующей записи в екель:
C++
1
2
3
4
5
6
7
8
9
10
11
for (int i = 1; i <= 15; i++) {
        for (int j = 1; j <= 15; j++) {
 
            VARIANT tmp;
            tmp.vt = VT_I4; 
            tmp.lVal = i * j;
 
            long indices[] = { i,j };
            SafeArrayPutElement(arr_write.parray, indices, (void *)&tmp);
        }
    }
То в variant массив записываются данные с типом VT_I4 и далее в ексель они записываются корректно, можно в массив добавить и тип VT_R8, но тогда в ексель записывается какие то совершенно другие числа.
Не пойму почему так.

2) И если можно такой вопрос: правильно ли я понимаю, что разница между VT_R8 и VT_R4 - только в разрядности виндовса ? То есть если у меня виндовс 64-разр., то условие:
C++
1
2
3
if (V_VT(&arr_element) == VT_R4)
{
}
Не сработает ? А в 32ух разр., не сработает соответственно VT_R8 ?
0
Модератор
 Аватар для vxg
3410 / 2182 / 354
Регистрация: 13.01.2012
Сообщений: 8,469
24.03.2019, 20:35
Optimus11, 1) в ячейках excel хранится VARIANT и он сам там по идее преобразует все куда надо если надо - если пишите R8 то и запишет R8 если конечно вы его в какое надо поле положите, обратно выдаёт наверное унифицированный тип - или строка или плавающая точка 2) нет, разрядности не имеет к этому отношения, R8 это C++ double, R4 это C++ float
1
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
30.03.2019, 20:03
Я сдаюсь, пытаюсь теперь записать данные в екель, берут тот же микрософтовский пример, он конечно же работает, но записывает в ексель числа VT_I4, а мне нужно чтобы записывался тектовый формат, то есть BSTR, вот кусочек работающего кода:

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
...
// Create a 15x15 safearray of variants...
    VARIANT arr_write;
    arr_write.vt = VT_ARRAY | VT_VARIANT;
    {
        SAFEARRAYBOUND sab[2];
        sab[0].lLbound = 1; sab[0].cElements = 15;  
        sab[1].lLbound = 1; sab[1].cElements = 15; 
        arr_write.parray = SafeArrayCreate(VT_VARIANT, 2, sab);
    }
 
VARIANT tmp; 
tmp.vt = VT_BSTR;
 
string string_value = "001";
 
// Fill safearray with some values...  /// 
    for (int i = 1; i <= 15; i++) {
        for (int j = 1; 15; j++) {
 
tmp.bstrVal = ::SysAllocString(_com_util::ConvertStringToBSTR(string_value.c_str())); //Преобразование string в bstr
 
long indices[] = { i,j };
 
SafeArrayPutElement(arr_write.parray, indices, (void *)&tmp);
        }
    }
И данные записываются, но записывается, только "1", а не "001", то есть в виде в формате числа, а не текстовом формате.
Причем методом тыка мне как то удалось записать именно в текстовом формате, вроде бы я обьявил массив, как BSTR, что то типа:

C++
1
arr_write.vt = VT_ARRAY | VT_BSTR;
Но потом решил поэксперементировать и забыл, что я сделал (((
0
Модератор
 Аватар для vxg
3410 / 2182 / 354
Регистрация: 13.01.2012
Сообщений: 8,469
31.03.2019, 06:57
Optimus11, ввести цифру как текст даже руками бывает не просто) если это не принципиально - вводите ‘001
0
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
31.03.2019, 08:09
Бывает же такое, открыл с утра Ваше сообщение и сразу вспомнил, что я делал :
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
// Create a 15x15 safearray of variants...
    VARIANT arr_write;
    arr_write.vt = VT_ARRAY | VT_BSTR;   // Тут объявляется, что VT_Array должен быть VT_BSTR
    {
        SAFEARRAYBOUND sab[2];
        sab[0].lLbound = 1; sab[0].cElements = vector_stroka_for_write.size();  
        sab[1].lLbound = 1; sab[1].cElements = vector_stolbech_for_write.size(); 
        arr_write.parray = SafeArrayCreate(VT_BSTR, 2, sab);   // А тут забыл, так же указать, что ArrayCreate будет VT_BSTR
    }
 
BSTR tmp_bstr;  // объявляем переменную из которой будет заносится данные в arr_write
 
string string_value = "001";
 
for (int i = 1; i <= 15; i++) {
        for (int j = 1; j <= 15; j++) {
 
 
tmp_bstr = _com_util::ConvertStringToBSTR(string_value.c_str());
 
///////// 
//VARIANT tmp; 
//tmp.bstrVal; // через tmp.bstrval - не работает, ошибок нет, но в екcель ничего не вносится.
/////////
 
    long indices[] = { i,j };
 
    SafeArrayPutElement(arr_write.parray, indices, tmp_bstr);
}
 }
 
AutoWrap_write(DISPATCH_PROPERTYPUT, NULL, pXlRange, (LPOLESTR)L"Value", 1, arr_write);
0
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
02.04.2019, 20:40
Позвольте еще один вопрос с участием все той же замечательной autowrap функцией:

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
Autowrap()
 
int main()
{
CoInitialize(NULL);
CLSID clsid;
 
HRESULT hr = CLSIDFromProgID(L"Excel.Application", &clsid); 
 
IUnknown* pUnk;
hr = GetActiveObject(clsid, NULL, &pUnk);
 
IDispatch *pXlApp;
hr = pUnk->QueryInterface(IID_IDispatch, (void**)&pXlApp);
 
IDispatch *pXlSheet;
    {
        VARIANT result;
        VariantInit(&result);
        AutoWrap_get_sheet_name(DISPATCH_PROPERTYGET, &result, pXlApp, (LPOLESTR)L"ActiveSheet", 0);
        pXlSheet = result.pdispVal;
    }
 
VARIANT rngResult;
AutoWrap_get_sheet_name(DISPATCH_PROPERTYGET, &rngResult, pXlSheet, (LPOLESTR)L"Name", 0);
}
Соответсвенно в rngResult получаем имя аквтиного на данный момент листа.
Но, когда я пытаюсь применить тот же код для получения имени рабочей книги, то есть вот так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
...
 
IDispatch *pXlBooks;
    {
        VARIANT result;
        VariantInit(&result);
        AutoWrap_get_sheet_name(DISPATCH_PROPERTYGET, &result, pXlApp, (LPOLESTR)L"Workbooks", 0);
        pXlBooks = result.pdispVal;
    }
 
 
VARIANT rngResult;
AutoWrap_get_sheet_name(DISPATCH_PROPERTYGET, &rngResult, pXlBooks, (LPOLESTR)L"Name", 0);
Почему ругается на IDispatch::GetIDsOfNames<"Names">faild e/err 0x800200006

То есть получается метод или свойство Name для или Activesheets находится, а для Workbook нет ?

Добавлено через 21 минуту
Все разобрался - ActiveWorkBook!
0
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
05.04.2019, 19:47
Не могу понять, вот есть предположим 10 открытых файла из которых предположим нужно из ячейки "A1" считать данные.
Понятно, как считать данные из активного на данный момент файла и активного в нем листа, через autowrap:

C++
1
2
3
4
5
6
7
IDispatch *pXlsheet;
    {
        VARIANT result;
        VariantInit(&result);
        AutoWrap_Choose_Active(DISPATCH_PROPERTYGET, &result, pXlApp, (LPOLESTR)L"ActiveSheets", 0);
        pXlsheets = result.pdispVal;
    }
Или из активного файла, но другого листа в нем:
C++
1
2
3
4
5
6
{
        VARIANT result;
        VariantInit(&result);
        AutoWrap_Choose_Active(DISPATCH_PROPERTYGET, &result, pXlApp, (LPOLESTR)L"Worksheets", 1, (LPOLESTR)L"Лист2" );
        pXlsheets = result.pdispVal;
}
и соответсвенно:
C++
1
2
VARIANT rngResult;
AutoWrap(DISPATCH_PROPERTYGET, &rngResult, pXlRange, (LPOLESTR)L"Value", 0);
То есть зная название листов в активном Workbook`ё можно пройтись по ним и считать с них данные, я думал примерно так же можно пройтись и по списку WorkBooks зная имена файлов который открыты:
C++
1
2
3
4
5
6
7
IDispatch *pXlsheet;
    {
        VARIANT result;
        VariantInit(&result);
        AutoWrap_Choose_Active(DISPATCH_PROPERTYGET, &result, pXlApp, (LPOLESTR)L"WorkBooks", 1, (LPOLESTR)L"Files1" );
        pXlsheets = result.pdispVal;
    }
Но так возникает ошибка:
C++
1
IDispatch:Invoke<"WorkBooks"=0000023c> faild w/err 0x80020009
0
-41 / 49 / 5
Регистрация: 10.01.2017
Сообщений: 1,915
07.04.2019, 20:14
Для этого есть метод Activate.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
07.04.2019, 20:14

Excel: создать новый массив по возрастанию элементов выделенного диапазона рабочей таблицы
Разработать подпрограмму создания нового массива по возрастанию элементов выделенного диапазона рабочей таблицы. Элементы массива задать...

импорт выделенного диапазона
добрый день!у меня есть таблица в Еxcel ee нужно импортировать, но только тот диапазон который был выделен.можете подсказать как это...

Экспорт-импорт данных Excel-Access-Excel
Доброе время суток уважаемые форумчане. Приходит информация в экселевской таблице. Скидываю её в общую базу в Access. Для отчета...

Обработка Excel и импорт из Excel в Access
Прошу совета профессионалов. С Excel-м ранее дел не имел. Задание: файлы Excel из одной папки отредактировать, и сохранить в другой. Из...

Excel -> Access -> Excel, импорт - экспорт
Добрый день! Есть табель учета рабочего времени в таблице Excel, задача - переместить данные со всех листов книги в DB Access, позже...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
35
Ответ Создать тему
Новые блоги и статьи
Теория всего 12. ВГК
anaschu 21.07.2026
### Главные семантические изменения и дешифровка новой физики 1. **`REPRODUCTIVE_EMISSION` вместо фотосинтеза (`PS_base`)**: Энергия и ресурсы, которые класс средних мужчин (`_W_MEN_DONORS`). . .
Публикация отклонённая на хабре. Как «пернатого» заставить осваивать новые горизонты опыта через масштабирование задачи и целеполагание
Hrethgir 21.07.2026
https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11948&stc=1&d=1784657928 Привет Хабр. В этой статье я расскажу, как один закон эпистемологии позволил мне с ходу запустить уникальный. . .
Теория всего 11. Основные параметры
anaschu 21.07.2026
Дешифровка тензорного ядра Soil Chemistry 2. 0: Истинный инвариант Теории Всего Чистовой исходный код многокомпонентной сукцессии зафиксирован. Модель оперирует единым вектором состояния. . .
Теория всего 10. Клод трусишка
anaschu 21.07.2026
Алгоритмический суицид ИИ: Когда математика ОДУ взламывает цензурные шлюзы Свежайший мета-прецедент нашей разработки! Клод официально отказался строить итоговую кроссплатформенную модель, как. . .
Теория всего 9. Окончательная проработка метафоры "дерево = традиции"
anaschu 21.07.2026
Скрытые параметры ядра ОДУ: Механика Глубинного Рока Клод утаил от вас ключевую математику кризисов. В движке игры зашиты пять скрытых коэффициентов, определяющих, как именно ТНК и Мемы ломают. . .
Теория всего 8. Clauude трусишка. Ответ джемени
anaschu 21.07.2026
Игровой баланс «Модели Всего»: Алгоритмический блок как механика Семантического БуфераЭтот скриншот отказа Клода — идеальный, чистейший прецедент для нашей Теории Всего. Вы столкнулись не просто с. . .
Теория всего 7. Дерево - это патриархат, грибы - это феминизм
anaschu 21.07.2026
Уничтожение Патриархата: Как ТНК, Мемы и Половой отбор зачистили «Сексуальный Пролетариат» Величайшая иллюзия современного человека — вера в «свободу воли», «социальный прогресс» и «эволюцию. . .
История и социология Терры на примере борьбы микориз за пространство. 1. Глоссарий терры.
anaschu 21.07.2026
Решил тут подумать о возможности сделать лор некоторой комп игры - стратегии, или худжественной книги антиутопии, которые будут юзать планету,которая максимально будет похожа на нашу землю, но где. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru