|  08.01.2007, 13:30 | #1 | 
| Участник | Построчный импорт из 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(); // ошибка! X++: COM range, worksheet; COMVariant value; ... range = worksheet.range('A1:E1'); value = range.value(); // тип - VT_SAFEARRAY // и что делать дальше?   | 
|  | 
|  08.01.2007, 17:43 | #2 | 
| Участник | 
			
			Посмотрите класс ComExcelDocument_RU
		 | 
|  | 
|  08.01.2007, 18:33 | #3 | 
| Moderator | 
			
			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 | 
| Участник | Цитата:  Если для дела, то куда быстрее, как показала практика, импортировать данные через ADO (скромно так). | 
|  | 
|  09.01.2007, 09:43 | #5 | 
| Участник | Цитата: 
		
			Сообщение от gl00mie
			   Зачем, если не секрет? Из спортивного интереса?   Если для дела, то куда быстрее, как показала практика, импортировать данные через ADO (скромно так). 2. Иногда, требуется и читать, и писать в один и тот же файл. С ADO не очень понятно про то, как определяется тип данных в столбце (как я понял, по нескольким первым строкам). И если, скажем, среди строк встретится число (строка из одних цифр + формат ячейки = число, пример - каталожные номера), то ADO вернет пустую строку.Вроде бы так, когда параметр IMEX не 1. | 
|  | 
|  10.01.2007, 10:47 | #6 | 
| Участник | Цитата: 
		
			Сообщение от gl00mie
			   Зачем, если не секрет? Из спортивного интереса?   Если для дела, то куда быстрее, как показала практика, импортировать данные через ADO (скромно так). Правда, для работы с двухмерными массивами SafeArray в Axapta пришлось написать свой COM-класс. 
				__________________ Axapta v.3.0 sp5 kr2 | 
|  | 
|  10.01.2007, 16:45 | #7 | 
| Участник | Цитата:  Давайте только для чистоты эксперимента выложим тестовый файл для считывания... Цитата: 
		
			Правда, для работы с двухмерными массивами SafeArray в Axapta пришлось написать свой COM-класс.
		
	   | 
|  | 
|  10.01.2007, 17:02 | #8 | 
| Moderator | |
|  | 
|  10.01.2007, 17:37 | #9 | 
| Участник | 
			
			Это я к тому, что на чистой Axapta не получилось работать с такими массивами
		 
				__________________ Axapta v.3.0 sp5 kr2 | 
|  | 
|  10.01.2007, 18:01 | #10 | 
| Участник | Цитата:  Впрочем, это, конечно, не принципиально... Последний раз редактировалось gl00mie; 10.01.2007 в 18:03. | 
|  | 
|  10.01.2007, 22:41 | #11 | 
| Участник | 
			
			Вот код загрузки/выгрузки в 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));
}PS М-да. Попробовал на другой машине. Общее время - 38 сек. Время загрузки в Excel 23 сек. Дохлый у меня комп дома   
				__________________ Axapta v.3.0 sp5 kr2 Последний раз редактировалось AndyD; 11.01.2007 в 08:32. | 
|  | 
|  11.01.2007, 13:02 | #12 | 
| Участник | 
			
			А, в принципе, можно обойтись и средаствами 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 | 
| Участник | |
|  | 
|  11.01.2007, 14:55 | #14 | 
| Участник | 
			
			Про 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 | 
| Участник | 
			
			Тьфу, опять забыл про value2   спасибо | 
|  | 
|  20.10.2008, 17:19 | #16 | 
| Участник | 
			
			Не подскажете, какая библиотека нужна для использования SafeArray При запучке job`а выдается сообщение: COM-объект класса "AxSafeArray.SafeArray" не удалось создать. Убедитесь, что объект был должным образом зарегистрирован на компьютере "USER". | 
|  | 
|  20.10.2008, 17:59 | #17 | 
| Участник | 
			
			Так я, наверное, не выкладывал файл. Если надо, то он во вложении. Надо будет зарегистрировать его вызовом Код: regsvr32 AxSafeArray.dll" 
				__________________ Axapta v.3.0 sp5 kr2 Последний раз редактировалось AndyD; 23.10.2008 в 11:29. | 
|  | |
| За это сообщение автора поблагодарили: Stainless (1). | |
|  23.10.2008, 11:08 | #18 | 
| Участник | 
			
			Появилась ошибка в строчке  X++: ... k = SafeArray.AddArrayCol(v1, var); ... | 
|  | 
|  23.10.2008, 11:26 | #19 | 
| Участник | 
			
			Упс.  Прошу прощения, выложил старую версию библиотеки PS А можно попросить удалить вложение в предыдущем письме. Я не могу его отредактироваить PPS Вопрос снимается  Я через кабинет удалил. 
				__________________ Axapta v.3.0 sp5 kr2 Последний раз редактировалось AndyD; 23.10.2008 в 14:01. | 
|  | 
|  23.10.2008, 13:15 | #20 | 
| Участник |  Ошибка все равно сохранилась. Версия обоих файлов 1.0.0.1   | 
|  | 
| Теги | 
| ax3.0 | 
|  | 
| Опции темы | Поиск в этой теме | 
| Опции просмотра | |
| 
 |