AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 08.01.2007, 13:30   #1  
olesh is offline
olesh
Участник
 
58 / 26 (1) +++
Регистрация: 02.04.2002
Адрес: Москва
Построчный импорт из Excel через COM
Что-то никак не пойму, возможен ли импорт строки целиком из Excel через массив? Типа, операция обратная экспорту с помощью массивов http://www.axforum.info/forums/showt...5729#post35729

Через sysExcelRange не получается вообще никогда, ругается то на многомерность safe array, то на некорректность его же.

X++:
Array arr;
....
sysExcelRange = sysExcelWorksheet.range('A1:E1');
arr = sysExcelRange.value(); // ошибка!
Если через COM, тоже не понятно, как, получив из range.value() многомерный массив, его прочитать.

X++:
COM range, worksheet;
COMVariant value;
...
range = worksheet.range('A1:E1');
value = range.value(); // тип - VT_SAFEARRAY

// и что делать дальше?
Понятно, что есть куча других вариантов импорта, но хочется разобраться с этим
Старый 08.01.2007, 17:43   #2  
Delfins is offline
Delfins
Участник
 
320 / 39 (2) +++
Регистрация: 20.09.2005
Адрес: Riga, Latvia
Посмотрите класс ComExcelDocument_RU
Старый 08.01.2007, 18:33   #3  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от Delfins Посмотреть сообщение
Посмотрите класс ComExcelDocument_RU
1. Необходимо уточнить, что смотреть можно, начиная с версии Ax 3.0 SP4. Там действительно в этом классе появляются несколько методов, посвященных именно ИМПОРТУ из Excel. В SP3 про импорт еще "ни слова".

2. Не думаю, что методы эти устроят olesh : _comRange.text() (см. ниже) возвращает содержательный "текст" только для диапазона, состоящего из одной ячейки, например, для A1. Для диапазона из нескольких ячеек, например, для A1:E1 вернется НЕ Null только тогда, когда все ячейки диапазона будут иметь одно и то же неНулл-значение. И вернется, конечно же, как видно из кода ниже, только одно значение (никакой не массив).
Цитата:
Сообщение от ComExcelDocument_RU (Ax 3.0 SP4)
Код:
protected anyType GetValueFromRange(COM _comRange)
{
     //anyType _anyType;
     str _anyType;
 
     _anyType = this.convertVariant2Str(_comRange.text());
     return _anyType;
}
 
str convertVariant2Str(COMVariant cv)
{
    str     retVal;
    switch (cv.variantType())
    {
        case COMVariantType::VT_BSTR:
            retVal = cv.bStr();
            break;
        case COMVariantType::VT_R8:
            retVal =  num2str(cv.double(),-1,-1,-1,-1);
            break;
        case COMVariantType::VT_DATE:
            retval = date2str(cv.date(), -1, -1, -1, -1, -1, 4); //Year as 4 digits
            break;
        case COMVariantType::VT_EMPTY:
            retVal = '';
            break;
        default:
            error("@SYS59922");
            throw Exception::Error;
    }
    return retVal;
}
Старый 09.01.2007, 01:30   #4  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5798 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Цитата:
Сообщение от olesh Посмотреть сообщение
Что-то никак не пойму, возможен ли импорт строки целиком из Excel через массив? Понятно, что есть куча других вариантов импорта, но хочется разобраться с этим
Зачем, если не секрет? Из спортивного интереса? Если для дела, то куда быстрее, как показала практика, импортировать данные через ADO (скромно так).
Старый 09.01.2007, 09:43   #5  
olesh is offline
olesh
Участник
 
58 / 26 (1) +++
Регистрация: 02.04.2002
Адрес: Москва
Цитата:
Сообщение от gl00mie Посмотреть сообщение
Зачем, если не секрет? Из спортивного интереса? Если для дела, то куда быстрее, как показала практика, импортировать данные через ADO (скромно так).
1. Ну, в основном, да, из-за интереса. Для импортов, где объемы данных большие, планирую ADO использовать. Хотя попробовать ускорить поячеечный импорт тоже интересно.
2. Иногда, требуется и читать, и писать в один и тот же файл. С ADO не очень понятно про то, как определяется тип данных в столбце (как я понял, по нескольким первым строкам). И если, скажем, среди строк встретится число (строка из одних цифр + формат ячейки = число, пример - каталожные номера), то ADO вернет пустую строку.Вроде бы так, когда параметр IMEX не 1.
Старый 10.01.2007, 10:47   #6  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Цитата:
Сообщение от gl00mie Посмотреть сообщение
Зачем, если не секрет? Из спортивного интереса? Если для дела, то куда быстрее, как показала практика, импортировать данные через ADO (скромно так).
Не знаю, как насчет скорости через ADO, но у меня считывание данных из Excel в массив 20*50'000 ячеек (причем, содержащие как строки, так и цифири) и получение к ним доступа из Axapta (для каждого столбца - отдельный массив Array) занимает порядка 17 секунд.

Правда, для работы с двухмерными массивами SafeArray в Axapta пришлось написать свой COM-класс.
__________________
Axapta v.3.0 sp5 kr2
Старый 10.01.2007, 16:45   #7  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5798 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Цитата:
Сообщение от AndyD Посмотреть сообщение
Не знаю, как насчет скорости через ADO, но у меня считывание данных из Excel в массив 20*50'000 ячеек (причем, содержащие как строки, так и цифири) и получение к ним доступа из Axapta (для каждого столбца - отдельный массив Array) занимает порядка 17 секунд.
Можно начать очередной коллективный эксперимент Давайте только для чистоты эксперимента выложим тестовый файл для считывания...
Цитата:
Правда, для работы с двухмерными массивами SafeArray в Axapta пришлось написать свой COM-класс.
Всего-то делов
Старый 10.01.2007, 17:02   #8  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от gl00mie Посмотреть сообщение
Давайте только для чистоты эксперимента выложим тестовый файл для считывания
Ну дык, первым шагом выгрузить 10 полей x 50 тыс.записей из того эксперимента, а потом читать обратно
Старый 10.01.2007, 17:37   #9  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Цитата:
Сообщение от gl00mie Посмотреть сообщение
Всего-то делов
Это я к тому, что на чистой Axapta не получилось работать с такими массивами
__________________
Axapta v.3.0 sp5 kr2
Старый 10.01.2007, 18:01   #10  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5798 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Цитата:
Сообщение от Gustav Посмотреть сообщение
Ну дык, первым шагом выгрузить 10 полей x 50 тыс.записей из того эксперимента, а потом читать обратно
У AndyD уже, видимо, есть и файл, и код для чтения данных, и даже контрольное время считывания. Хотелось бы, если данные не шибко секретные, тренироваться именно на них Впрочем, это, конечно, не принципиально...

Последний раз редактировалось gl00mie; 10.01.2007 в 18:03.
Старый 10.01.2007, 22:41   #11  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Вот код загрузки/выгрузки в Excel - 10 колонок * 50 т. строк
X++:
{
    ComExcelDocument_RU excel = new ComExcelDocument_RU();
    Com doc;
    Com app;
    Com sheet;
    Com range;
    COMVariant var;
    ComVariant v, v1;
    Array arr;
    Container c;
    int i, j, k;

    Com SafeArray = new Com ("AxSafeArray.SafeArray");
    int rowCount;
    int colCount;
    int tm = winapi::getTickCount();
    ;

    v = ComVariant::createNoValue();
    v1 = new ComVariant(ComVariantInOut::In, ComVariantType::VT_VARIANT);
    v1.variant(v);
    arr = new Array(Types::Class);
    for (j=1;j<=10;j++)
    {
        for (i=1;i<=50000;i++)
            switch (j mod ((i mod 3)+1))
            {
                case 0:
                    arr.value(i, ComVariant::createFromStr(strfmt("??? %1", i)));
                    break;
                case 1:
                    arr.value(i, ComVariant::createFromInt(i));
                    break;
                case 2:
                    arr.value(i, ComVariant::createFromReal(i));
                    break;
            }
        var = ComVariant::createFromArray(arr);
        k = SafeArray.AddArrayCol(v1, var);
    }

    var = v;

    excel.newFile("", false);
    doc = excel.getComDocument();
    app = doc.Application();
    sheet = app.activeSheet();
    range = sheet.range("A1:J50000");
    c += [strfmt("%1", winapi::getTickCount()-tm)];
    range.value2(var);

    c += [strfmt("%1", winapi::getTickCount()-tm)];

    var = range.value2();
    rowCount = SafeArray.GetArrayRowCount(var);
    colCount = SafeArray.GetArrayColCount(var);
    c += [strfmt("%1", winapi::getTickCount()-tm)];
    for (j=1;j<=colCount;j++)
    {
        v1 = SafeArray.GetArrayCol(var, j);
        arr = v1.safeArray();
        for (i=1;i<=rowCount;i++)
            v = arr.value(i);
    }
    excel.visible(true);
    c += [strfmt("%1", winapi::getTickCount()-tm)];

    for (i=1;i<=conlen(c);i++)
        info(conpeek(c, i));
}
Общее время - 58-60 сек. Время загрузки в Excel 35 сек.

PS М-да. Попробовал на другой машине. Общее время - 38 сек. Время загрузки в Excel 23 сек.

Дохлый у меня комп дома
__________________
Axapta v.3.0 sp5 kr2

Последний раз редактировалось AndyD; 11.01.2007 в 08:32.
Старый 11.01.2007, 13:02   #12  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
А, в принципе, можно обойтись и средаствами Axapta, если считывать по одной строке или колонке.
X++:
{
    ComExcelDocument_RU excel = new ComExcelDocument_RU();
    Com doc;
    Com app;
    Com sheet;
    Com range;
    Array arr;
    int j;
    COMVariant v;

    Array GetArrayFromVariant(COMVariant var)
    {
        Binary bin = new Binary(100);
        int dims;
        Array   ret = null;
        int cols, rows;
        int lBound;
        int i;
        int locks;
        ;
        if (var && var.variantType() == COMVariantType::VT_SAFEARRAY)
        {
            bin.attach(var.int(), 24);
            dims = bin.word(0);
            if (dims == 2)
            {
                bin.attach(var.int(), 16 + dims * 8);

                cols = bin.dWord(16);
                rows = bin.dWord(24);
                if (rows == 1)
                {
                    locks = bin.dWord(8);
                    if (locks == 0)
                    {
                        bin.dWord(8, locks+1);
                        bin.word(0, 1);
                        try
                        {
                            ret = var.safeArray();
                            bin.word(0, dims);
                            bin.dWord(8, locks);
                        }
                        catch
                        {
                            bin.word(0, dims);
                            bin.dWord(8, locks);
                        }
                    }
                }
                else if (cols == 1)
                {
                    locks = bin.dWord(8);
                    if (locks == 0)
                    {
                        bin.dWord(8, locks+1);
                        lBound = bin.dWord(20);
                        bin.dWord(16, rows);
                        bin.dWord(20, bin.dWord(28));
                        bin.word(0, 1);
                        try
                        {
                            ret = var.safeArray();
                            bin.word(0, dims);
                            bin.dWord(16, cols);
                            bin.dWord(20, lBound);
                            bin.dWord(8, locks);
                        }
                        catch
                        {
                            bin.word(0, dims);
                            bin.dWord(16, cols);
                            bin.dWord(20, lBound);
                            bin.dWord(8, locks);
                        }
                    }
                }
            }
            else if (dims == 1)
                ret = var.safeArray();
        }
        return ret;
    }
    ;
    excel.open("Имя файла Excel для загрузки.xls",true);
    doc = excel.getComDocument();
    app = doc.Application();
    sheet = app.activeSheet();
    range = sheet.range("D1:D100");

    arr = GetArrayFromVariant(range.value2());

    if (arr)
    {
        for (j=1;j<=arr.lastIndex();j++)
        {
            v = arr.value(j);
            switch (v.variantType())
            {
                case COMVariantType::VT_BSTR:
                    info(v.bStr());
                    break;
                case COMVariantType::VT_INT:
                    info(strfmt("%1", v.int()));
                    break;
                case COMVariantType::VT_R8:
                    info(strfmt("%1", v.double()));
                    break;
            }
        }
    }
}
__________________
Axapta v.3.0 sp5 kr2

Последний раз редактировалось AndyD; 11.01.2007 в 13:12.
За это сообщение автора поблагодарили: olesh (1), belugin (14), alex55 (2).
Старый 11.01.2007, 13:51   #13  
olesh is offline
olesh
Участник
 
58 / 26 (1) +++
Регистрация: 02.04.2002
Адрес: Москва
Цитата:
Сообщение от AndyD Посмотреть сообщение
А, в принципе, можно обойтись и средаствами Axapta, если считывать по одной строке или колонке.
О, то что надо, в принципе! Импорта достаточно построчного. Андрей, а где можно почитать про побайтную структуру safearray? Туда бы еще добавить обработку типов дата/время.
Старый 11.01.2007, 14:55   #14  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Про SAFEARRAY можно посмотреть здесь SAFEARRAY Data Type

С датой/временем можно сделать так
1. Для получения значения из ячеек использовать range.value(10) вместо range.value2() (value2 для даты возвращает число с плавающей точкой)
2. Добавить в обработчик массива
X++:
case COMVariantType::VT_DATE:
    info(strfmt("%1 %2", date2str(v.date(), 123, 2, 1, 2, 1, 4), time2str(v.time(), 1, 1)));
    break;
Здесь есть такой момент: если формате ячейки указать вывод только для времени (например, такой "ч:мм:сс"), то вернется число с плавающей точкой
__________________
Axapta v.3.0 sp5 kr2
Старый 11.01.2007, 15:24   #15  
olesh is offline
olesh
Участник
 
58 / 26 (1) +++
Регистрация: 02.04.2002
Адрес: Москва
Тьфу, опять забыл про value2 спасибо
Старый 20.10.2008, 17:19   #16  
Stainless is offline
Stainless
Участник
MCBMSS
Columbus IT
 
34 / 114 (4) +++++
Регистрация: 26.01.2007
Не подскажете, какая библиотека нужна для использования SafeArray
При запучке job`а выдается сообщение:
COM-объект класса "AxSafeArray.SafeArray" не удалось создать. Убедитесь, что объект был должным образом зарегистрирован на компьютере "USER".
Старый 20.10.2008, 17:59   #17  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Так я, наверное, не выкладывал файл.
Если надо, то он во вложении. Надо будет зарегистрировать его вызовом
Код:
regsvr32 AxSafeArray.dll"
__________________
Axapta v.3.0 sp5 kr2

Последний раз редактировалось AndyD; 23.10.2008 в 11:29.
За это сообщение автора поблагодарили: Stainless (1).
Старый 23.10.2008, 11:08   #18  
Stainless is offline
Stainless
Участник
MCBMSS
Columbus IT
 
34 / 114 (4) +++++
Регистрация: 26.01.2007
Появилась ошибка в строчке
X++:
...
k = SafeArray.AddArrayCol(v1, var);
...
COM Объект не имеет метода "AddArrayCol".
Старый 23.10.2008, 11:26   #19  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Упс.
Прошу прощения, выложил старую версию библиотеки

PS А можно попросить удалить вложение в предыдущем письме. Я не могу его отредактироваить
PPS Вопрос снимается Я через кабинет удалил.
__________________
Axapta v.3.0 sp5 kr2

Последний раз редактировалось AndyD; 23.10.2008 в 14:01.
Старый 23.10.2008, 13:15   #20  
Stainless is offline
Stainless
Участник
MCBMSS
Columbus IT
 
34 / 114 (4) +++++
Регистрация: 26.01.2007
Ошибка все равно сохранилась. Версия обоих файлов 1.0.0.1
Теги
ax3.0

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Импорт из 'офисной БД' (Excel, Access) Gustav DAX: База знаний и проекты 4 07.06.2008 17:17
Импорт строк PurchLine (через функционал) kaw DAX: Функционал 8 20.03.2008 14:49
Помогите сделать действие в Excel через COM kashperuk DAX: Программирование 25 10.09.2007 15:59
Импорт из Excel через шаблон стандартными средствами аксапты NV DAX: Функционал 5 20.01.2005 12:26
Импорт бюджета из Excel OliaM DAX: Функционал 16 13.01.2005 21:56

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 09:15.