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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 15.06.2006, 20:40   #41  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Замерил способ "через SysExcel":
X++:
static void SpeedTest_Job3_SysExcel(Args _args)
{
     
    LedgerTrans             ledgerTrans;
    LedgerTable             ledgerTable;
    
    int row;
    int timeFullStart, timeFullFinish, timeFullTotal;
    
    SysExcelCells          cells;
    
    COM rng, xlApp;
    
    ;
    
    timeFullStart = timenow();
    
    // обратите внимание, что если нам нужны, например, только ячейки рабочего листа 1,
    // то нет необходимости выделять отдельные переменные для всех вышестоящих объектов
    // можно всё указать в одной строке через точки - почти как в VBA :)
        
    cells = SysExcelApplication::construct().workbooks().add().worksheets().itemFromNum(1).cells();
        
    // но нам потребуется объект Application - хотя бы для того, чтобы сделать Excel видимым
    // в рамках примера получим его как "COM от COM-а" любой ячейки, например, А1
        
    rng = cells.range('A1').comObject(); // Range
    xlApp = rng.Application();           // Excel.Application
        
    xlApp.Visible(true); // в эсперименте на скорость - комментировался/раскомментировался этот оператор
        
    // повторяю - этот "изврат" выше сделан для целей примера
    // без использования COM-переменных можно было бы последовательно оформить вот так:
    //    SysExcelApplication  xlApp;
    //    SysExcelCells        cells;
    //    ................................
    //    xlApp = SysExcelApplication::construct();
    //    cells = xlApp.workbooks().add().worksheets().itemFromNum(1).cells();
    // и дальше спокойно распоряжаться этими двумя переменными
    // для работы с ячейками первого рабочего листа новой рабочей книги
    
    row = 0;
    
    while select  ledgerTrans
            join  ledgerTable
            where ledgerTrans.AccountNum == ledgerTable.AccountNum
    {
        row++;
        if (row > 50000) break;
    
        cells.item( row,  1).value( ledgerTrans.RecId                       );
        cells.item( row,  2).value( ledgerTrans.AccountNum                  );
        cells.item( row,  3).value( ledgerTable.AccountName                 );
        cells.item( row,  4).value( strfmt('%1', ledgerTable.AccountPlType) );
        cells.item( row,  5).value( ledgerTrans.BondBatchTrans_RU           );
        cells.item( row,  6).value( ledgerTrans.BondBatch_RU                );
        cells.item( row,  7).value( ledgerTrans.TransDate                   );
        cells.item( row,  8).value( ledgerTrans.Txt                         );
        cells.item( row,  9).value( ledgerTrans.AmountMST                   );
        cells.item( row, 10).value( strfmt('%1', ledgerTrans.Crediting)     );
    
    }
    
    xlApp.visible(true);
    
    timeFullFinish = timenow();
    
    timeFullTotal = timeFullFinish - timeFullStart;
    
    info('Время выполнения, сек');
    info(int2str(timeFullTotal));
    
}
Результата привожу два:
1. 1228 сек - т.е. чуть больше 20 минут - когда сразу делаем видимым окно Excel в начале процедуры (см. в коде "xlApp.Visible(true); // в эсперименте на скорость...")
2. 1060 сек - т.е. чуть меньше 18 минут - когда показываем Excel только в конце (см. в коде "// xlApp.Visible(true); // в эсперименте на скорость...")

Делать Visible(true) в начале - плохая практика, AndyD абсолютно прав! Но в рамках эксперимента, конечно, можно посмотреть и так, и сяк

С джобами SpeedTest_Job1 и SpeedTest_Job2 имеет смысл сравнивать только первый результат, поскольку и они тоже прогонялись при начальном Visible(true). Результат "1228 сек" несколько больше, чем у _Job2 (1090 сек), и это объяснимо: представители семейства системных классов SysExcel оформлены как "обертки" над COM и, соответственно, часть времени тратится на "продирание" через эти "обертки", в то время, как _Job2 фактически использует чистый COM.

Результат "1228 сек" ниже "1060 сек" примерно на (1228-1060)/1228 = около 14 % - что я и обещал:
Цитата:
Сообщение от Gustav
Да, разница в скорости порядка 10-15 процентов.
Конечно, с точки зрения скорости способ "через SysExcel" также оставляет желать гораздо более лучшего и в качестве широкого использования "как быстрый способ" рекомендоваться не может.

Мне он, однако, понравился другим, в частности:
- возможностью писать "почти как на VBA c многими точками" (см. комментарии в тексте джоба),
- писать нормально Value, а не Value2 (при этом класс SysExcelCell сам берет на себя ответственность за обработку value - "до XP или после" ).
Старый 15.06.2006, 21:09   #42  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от Gustav
Результат "1228 сек" ниже "1060 сек"
ВЫШЕ, конечно (в смысле: ВЫШЕ - по значению, НИЖЕ - по скорости... ну, вы меня поняли )

Редактировать прямо там боюсь, так как съедет форматирование кода X++.

Кстати, почему такое происходит с тегом XPP? Т.е. пишу сообщение, делаю предварительный просмотр - пока всё хорошо, пишу дальше, делаю повторный предварительный просмотр - и всё разрушается - код сливается с текстом, отступы пропадают - в общем, беда какая-то...

Последний раз редактировалось Gustav; 15.06.2006 в 23:08.
Старый 16.06.2006, 09:00   #43  
Dolter is offline
Dolter
1C
1C
 
83 / 18 (1) ++
Регистрация: 18.11.2005
и все же не есть правильно не использовать средства прямого доступа :-)
Старый 16.06.2006, 09:18   #44  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от Dolter
и все же не есть правильно не использовать средства прямого доступа :-)
Dolter, Ваша фраза подкупает своей неопровержимостью, может быть, чуть-чуть уступая бесспорным утверждениям типа "по телефону можно звонить" или "в море можно плавать"
Поясните, пожалуйста, что Вы имеете в виду конкретно?
Старый 20.06.2006, 14:18   #45  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Продолжим

Выгрузка в текстовый файл с последующей загрузкой в Excel

В кач-ве особенности - в книге Excel создается макрос для загрузки текстового файла с помощью функции OpenText. Затем этот макрос запускается и происходит открытие этого файла с учетом типов данных в столбцах.

Почему такой путь - для передачи типов данных в столбцах функция требует передачи в кач-ве одного из параметров массива массивов. К сожалению, не знаю как это организовать в Axapta без привлечения сторонних средств

Время полета - 20 с

PS Для того, что бы этот код выполнился, необходимо включить в Excel параметр "Доверять доступ к Visual Basic Project" в форме управления безопасностью макросов

Еще информация по этой теме
Axapta программирует Excel на VBA

X++:
static void ExportExcelTXT(Args _args)
{
    LedgerTrans ledgerTrans;
    LedgerTable ledgerTable;
    int timeFullStart, timeFullFinish, timeFullTotal;
    int cnt = 0;
    str Buf, s;
    ComExcelDocument_Ru excel;
    COM                 doc;
    COM                 app;
    TextBuffer          tb;

    COM Workbook;
    COM prj;
    COM comp;
    COM module;
    COM code;
    Array fields;

    #define.vbext_ct_StdModule(1)
    #define.fileName("d:\\temp\\demo.txt")

    void AddField(int fldNum, TableId tbl, FieldId fld)
    {
        DictField   dictField;
        Array field;
        #define.xlGeneralFormat(0x00000001)
        #define.xlTextFormat(0x00000002)
        #define.xlMDYFormat(0x00000003)
        #define.xlDMYFormat(0x00000004)
        #define.xlYMDFormat(0x00000005)
        #define.xlMYDFormat(0x00000006)
        #define.xlDYMFormat(0x00000007)
        #define.xlYDMFormat(0x00000008)
        #define.xlSkipColumn(0x00000009)
        ;
        if (!fields)
            fields = new Array(Types::Class);
        dictField = new dictField( tbl, fld );
        field = new Array(Types::Integer);
        field.value(1, fldNum);
        if (dictField)
        {
            switch (dictField.baseType())
            {
                case Types::Date:
                    field.value(2, #xlDMYFormat);
                    break;
                case Types::Enum, Types::String:
                    field.value(2, #xlTextFormat);
                    break;
                default:
                    field.value(2, #xlGeneralFormat);
            }
        }
        else
            field.value(2, #xlGeneralFormat);

        fields.value((fields.lastIndex()+1), field);
    }
    str getFields()
    {
        str ret = "";
        int i;
        Array field;
        ;
        if (!fields) return "";
        for (i=1; i<= fields.lastIndex(); i++)
        {
            field = fields.value(i);
            if (field)
                ret += (ret ? ", " : "") + strfmt("Array(%1,%2)", field.value(1), field.value(2));
        }
        if (ret)
            return "FieldInfo:=Array(" + ret + "), ";
        return "";
    }
    // засекаем время
    timeFullStart = timenow();

    excel = new ComExcelDocument_Ru();
    excel.newFile("", false);
    doc = excel.getComDocument();
    app = doc.application();

    buf = "RecId\tAccountNum\tAccountName\tAccountPlType\tBondBatchTrans_RU\tBondBatch_RU\tTransDate\tTxt\tAmountMST\tCrediting\n";

    cnt++;
    while select  ledgerTrans
            join  ledgerTable
            where ledgerTrans.AccountNum == ledgerTable.AccountNum
                && ledgerTrans.TransDate >= str2date('dd.mm.yy',123) && ledgerTrans.TransDate <= str2date('DD.MM.YY',123)
    {
            // 10 полей
        buf +=
            strfmt(
                "%1\t%2\t%3\t%4\t%5\t%6\t%7\t%8\t%9\t%10\n",
                ledgerTrans.RecId, ledgerTrans.AccountNum, ledgerTable.AccountName, ledgerTable.AccountPlType,
                ledgerTrans.BondBatchTrans_RU, ledgerTrans.BondBatch_RU,
                date2str(ledgerTrans.TransDate, 123, 2, 2, 2, 2, 4), ledgerTrans.Txt,
                strltrim(strrem(num2str(ledgerTrans.AmountMST, 10, 2, 2, 3), "+")), ledgerTrans.Crediting);

        cnt++;
        if (cnt >=65000) break;
    }
    tb = new TextBuffer();
    tb.setText(buf);
    tb.toFile(#fileName);

    Workbook = app.ActiveWorkbook();
    prj = Workbook.VBProject();
    comp = prj.VBComponents();
    comp.add(#vbext_ct_StdModule);
    module = comp.item(comp.count());
    code = module.CodeModule();

    addField( 1, ledgerTrans.TableId, fieldnum(ledgerTrans, RecId));
    addField( 2, ledgerTrans.TableId, fieldnum(ledgerTrans, AccountNum));
    addField( 3, ledgerTable.TableId, fieldnum(ledgerTable, AccountName));
    addField( 4, ledgerTable.TableId, fieldnum(ledgerTable, AccountPlType));
    addField( 5, ledgerTrans.TableId, fieldnum(ledgerTrans, BondBatchTrans_RU));
    addField( 6, ledgerTrans.TableId, fieldnum(ledgerTrans, BondBatch_RU));
    addField( 7, ledgerTrans.TableId, fieldnum(ledgerTrans, TransDate));
    addField( 8, ledgerTrans.TableId, fieldnum(ledgerTrans, Txt));
    addField( 9, ledgerTrans.TableId, fieldnum(ledgerTrans, AmountMST));
    addField(10, ledgerTrans.TableId, fieldnum(ledgerTrans, Crediting));

    s = strfmt( "sub OpenDemo()\n" +
                "    Workbooks.OpenText Filename:=\"%1\", Origin:=1251, StartRow:= 1, _\n" +
                "        DataType:=xlDelimited, TextQualifier:=xlDoubleQuote, Tab:=True, _\n" +
                "        %2TrailingMinusNumbers:=True, _\n" +
                "        DecimalSeparator:=\",\", ThousandsSeparator:=\" \"\n" +
                "End Sub", #fileName, getFields());
    code.addFromString(s);

    app.Run(strfmt("%1.OpenDemo", module.name()));
    App.DisplayAlerts(false);
    Workbook.Close();
    App.DisplayAlerts(true);

    excel.visible(true);

    timeFullFinish = timenow();
    timeFullTotal = timeFullFinish - timeFullStart;
    info('Время выполнения, сек');
    info(int2str(timeFullTotal));
}
__________________
Axapta v.3.0 sp5 kr2

Последний раз редактировалось AndyD; 20.06.2006 в 14:25.
За это сообщение автора поблагодарили: Gustav (3).
Старый 20.06.2006, 16:34   #46  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от AndyD
Продолжим
Выгрузка в текстовый файл с последующей загрузкой в Excel...
Супер. Высший пилотаж. У меня на всё той же "эталонной" машине (AMD,2.5,4) трижды подряд получилось "время полета" = 14 сек для "эталонных" 50 тыс. записей, т.е. при "if (cnt > 50000) break". Типы полей - всё как надо. Полный зачОт!

P.S. Спасибо! Дал именно "троечку" - не "раскрутки маховика инфляции репутации ради", а "своей симпатии к круглым числам из-за". Поздравляю с достижением 150! (честно говоря, думал, появится еще один зеленый "кирпичик"...)

P.P.S. AndyD, ну и надо наконец закомментарить или удалить строку " && ledgerTrans.TransDate >= str2date('dd.mm.yy',123) && ledgerTrans.TransDate <= str2date('DD.MM.YY',123)", а то чел, не вдающийся в подробности всей ветки, запустит джоб и обнаружит пустой набор, а ошибку компиляции эта строка не дает.

Последний раз редактировалось Gustav; 20.06.2006 в 16:58.
Старый 21.06.2006, 13:29   #47  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от AndyD
Почему такой путь - для передачи типов данных в столбцах функция требует передачи в кач-ве одного из параметров массива массивов.
К сожалению, не знаю как это организовать в Axapta без привлечения сторонних средств
AndyD, есть мысль - использовать формулу массива, во всяком случае в Excel у меня получилось...

Итак, как я понимаю, проблема заключается в том, что в операторе VBA вида
PHP код:
...
Workbooks.OpenText Filename:="C:\demo.txt"Origin:=1251StartRow:=1_
DataType
:=xlDelimitedTextQualifier:=xlDoubleQuoteConsecutiveDelimiter _
:=FalseTab:=TrueSemicolon:=FalseComma:=FalseSpace:=False_
Other
:=FalseFieldInfo:=Array(Array(11), Array(22), Array(32), Array(42), _
Array(51), Array(61), Array(71), Array(81), Array(91), Array(101)), _
TrailingMinusNumbers
:=True
... 
присутствует неудобный для нас фрагмент:
PHP код:
...
FieldInfo:=Array(Array(11), Array(22), Array(32), Array(42), _
Array(51), Array(61), Array(71), Array(81), Array(91), Array(101)),
... 
По жизни это не что иное, как двумерный массив "Номер поля - Тип поля" (в данном контексте задачи):
Код:
Номер Тип
---------
    1   1
    2   2
    3   2
    4   2
    5   1
    6   1
    7   1
    8   1
    9   1
   10   1
Так вот, если перед вызовом Workbooks.OpenText... выполнить оператор VBA:
PHP код:
...
Worksheets("Sheet1").Range("A1:B10").FormulaArray "={1,1;2,2;3,2;4,2;5,1;6,1;7,1;8,1;9,1;10,1}"
... 
(запятые разделяют элементы в строке, точка с запятой - строки),
то потом можно заменить FieldInfo:=Array... на FieldInfo:=Worksheets("Sheet1").Range("A1:B10") и получится:
PHP код:
...
Workbooks.OpenText Filename:="C:\demo.txt"Origin:=1251StartRow:=1_
DataType
:=xlDelimitedTextQualifier:=xlDoubleQuoteConsecutiveDelimiter _
:=FalseTab:=TrueSemicolon:=FalseComma:=FalseSpace:=False_
Other
:=FalseFieldInfo:=Worksheets("Sheet1").Range("A1:B10"), _
TrailingMinusNumbers
:=True
... 
Соответственно, от функции VBA.Array избавляемся и получается, что всё можно сделать из Аксы, не вызывая код VBA.

Попробуете? Только прошу, ни в коем случае не убирайте предыдущую версию. Пусть она останется в ветке. А новую можно назвать типа "ExportExcelTXT_2"
За это сообщение автора поблагодарили: AndyD (4).
Старый 21.06.2006, 15:14   #48  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Не работает такой вариант ч/з интерфейсы.
Я думаю, причина в том, что при вызове из VBA Excel неявно подставляет значения из Range и передает в функцию уже массив, а при вызове из интерфейсов такого преобразования не происходит и функция не обрабатывает эти значения.
Пробовал передать как непосредственно com-интерфейс, так и variant с помощью класса COMVariant::CreateFromCOM(range)

Кстати, если кому интересно, значения для FormulaArray ч/з COM-интерфейс надо передавать так
X++:
FormulaArray("={1;1:2;2:3;2:4;2:5;1:6;2:7;4:8;2:9;1:10;2}");
__________________
Axapta v.3.0 sp5 kr2
Старый 21.06.2006, 16:11   #49  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Не слушайте его. Он все врет.

В общем моя ошибка - пропустил один из параметров, в результате Range передавался не как FieldInfo, а как OtherChar.

Время выгрузки - 20с

X++:
static void ExportExcelTXT1(Args _args)
{
    LedgerTrans ledgerTrans;
    LedgerTable ledgerTable;
    int timeFullStart, timeFullFinish, timeFullTotal;
    int cnt = 0;
    str Buf, s;
    ComExcelDocument_Ru excel;
    COM                 doc;
    COM                 app;
    TextBuffer          tb;

    COM Workbook;
    COM Workbooks;
    Array fields;
    Com sheet;
    Com range;
    str leftBrace;
    str rightBrace;
    str columnSeparator;
    str rowSeparator;

    #define.xlDelimited(0x00000001)
    #define.xlDoubleQuote(0x00000001)

    #define.fileName("d:\\temp\\demo.txt")

    void AddField(int fldNum, TableId tbl, FieldId fld)
    {
        DictField   dictField;
        Array field;
        #define.xlGeneralFormat(0x00000001)
        #define.xlTextFormat(0x00000002)
        #define.xlMDYFormat(0x00000003)
        #define.xlDMYFormat(0x00000004)
        #define.xlYMDFormat(0x00000005)
        #define.xlMYDFormat(0x00000006)
        #define.xlDYMFormat(0x00000007)
        #define.xlYDMFormat(0x00000008)
        #define.xlSkipColumn(0x00000009)
        ;
        if (!fields)
            fields = new Array(Types::Class);
        dictField = new dictField( tbl, fld );
        field = new Array(Types::Integer);
        field.value(1, fldNum);
        if (dictField)
        {
            switch (dictField.baseType())
            {
                case Types::Date:
                    field.value(2, #xlDMYFormat);
                    break;
                case Types::Enum, Types::String:
                    field.value(2, #xlTextFormat);
                    break;
                default:
                    field.value(2, #xlGeneralFormat);
            }
        }
        else
            field.value(2, #xlGeneralFormat);

        fields.value((fields.lastIndex()+1), field);
    }
    str getFields()
    {
        str ret = "";
        int i;
        Array field;
        ;
        if (!fields) return "";
        for (i=1; i<= fields.lastIndex(); i++)
        {
            field = fields.value(i);
            if (field)
                ret += (ret ? strfmt("%1 ", rowSeparator) : "") +
                        strfmt("%1%3%2", field.value(1), field.value(2), columnSeparator);
        }
        return ret;
    }
    void ArrayLocal(COM xlApp)
    {
        COMVariant var;
        str alternateArraySeparator;
        str decimalSeparator;
        #define.xlDecimalSeparator(0x00000003)
        #define.xlLeftBrace(0x0000000C)
        #define.xlRightBrace(0x0000000D)
        #define.xlColumnSeparator(0x0000000E)
        #define.xlRowSeparator(0x0000000F)
        #define.xlAlternateArraySeparator(0x00000010)
        ;
        if (!xlApp)
        {
            leftBrace = "{";
            rightBrace = "}";
            columnSeparator = ";";
            rowSeparator = ":";
            return;
        }
        var = xlApp.International(#xlDecimalSeparator);
        if (var)
            decimalSeparator = var.bStr();
        else
            decimalSeparator = ",";
        var = xlApp.International(#xlLeftBrace);
        if (var)
            leftBrace = var.bStr();
        else
            leftBrace = "{";
        var = xlApp.International(#xlRightBrace);
        if (var)
            rightBrace = var.bStr();
        else
            rightBrace = "}";
        var = xlApp.International(#xlColumnSeparator);
        if (var)
            columnSeparator = var.bStr();
        else
            columnSeparator = ";";
        var = xlApp.International(#xlRowSeparator);
        if (var)
            rowSeparator = var.bStr();
        else
            rowSeparator = ":";
        var = xlApp.International(#xlAlternateArraySeparator);
        if (var)
            alternateArraySeparator = var.bStr();
        else
            alternateArraySeparator = "&";
        columnSeparator = (columnSeparator == decimalSeparator ? alternateArraySeparator : columnSeparator);
        rowSeparator = (rowSeparator == decimalSeparator ? alternateArraySeparator : rowSeparator);
    }
    // засекаем время
    timeFullStart = timenow();

    excel = new ComExcelDocument_Ru();
    excel.newFile("", false);
    doc = excel.getComDocument();
    app = doc.application();
    ArrayLocal(app);

    buf = "RecId\tAccountNum\tAccountName\tAccountPlType\tBondBatchTrans_RU\tBondBatch_RU\tTransDate\tTxt\tAmountMST\tCrediting\n";

    cnt++;
    while select  ledgerTrans
            join  ledgerTable
            where ledgerTrans.AccountNum == ledgerTable.AccountNum
                && ledgerTrans.TransDate >= str2date('dd.mm.yy',123) && ledgerTrans.TransDate <= str2date('DD.MM.YY',123)
    {
            // 10 полей
        buf +=
            strfmt(
                "%1\t%2\t%3\t%4\t%5\t%6\t%7\t%8\t%9\t%10\n",
                ledgerTrans.RecId, ledgerTrans.AccountNum, ledgerTable.AccountName, ledgerTable.AccountPlType,
                ledgerTrans.BondBatchTrans_RU, ledgerTrans.BondBatch_RU,
                date2str(ledgerTrans.TransDate, 123, 2, 2, 2, 2, 4), ledgerTrans.Txt,
                strltrim(strrem(num2str(ledgerTrans.AmountMST, 10, 2, 2, 3), "+")), ledgerTrans.Crediting);

        cnt++;
        if (cnt >=65000) break;
    }
    tb = new TextBuffer();
    tb.setText(buf);
    tb.toFile(#fileName);

    addField( 1, ledgerTrans.TableId, fieldnum(ledgerTrans, RecId));
    addField( 2, ledgerTrans.TableId, fieldnum(ledgerTrans, AccountNum));
    addField( 3, ledgerTable.TableId, fieldnum(ledgerTable, AccountName));
    addField( 4, ledgerTable.TableId, fieldnum(ledgerTable, AccountPlType));
    addField( 5, ledgerTrans.TableId, fieldnum(ledgerTrans, BondBatchTrans_RU));
    addField( 6, ledgerTrans.TableId, fieldnum(ledgerTrans, BondBatch_RU));
    addField( 7, ledgerTrans.TableId, fieldnum(ledgerTrans, TransDate));
    addField( 8, ledgerTrans.TableId, fieldnum(ledgerTrans, Txt));
    addField( 9, ledgerTrans.TableId, fieldnum(ledgerTrans, AmountMST));
    addField(10, ledgerTrans.TableId, fieldnum(ledgerTrans, Crediting));

    Workbook = app.ActiveWorkbook();
    sheet = app.ActiveSheet();
    range = sheet.range("A1:B10");
    s = strfmt("=%1%3%2", leftBrace, rightBrace, getFields());
    range.FormulaArray(s);

    Workbooks = app.Workbooks();
    Workbooks.OpenText(#fileName, COMVariant::createFromInt(1251), 1,
        #xlDelimited, #xlDoubleQuote, False, True, False, False, False, False, "",
        range, True, ",", " ");

    App.DisplayAlerts(false);
    Workbook.Close();
    App.DisplayAlerts(true);

    excel.visible(true);

    timeFullFinish = timenow();
    timeFullTotal = timeFullFinish - timeFullStart;
    info('Время выполнения, сек');
    info(int2str(timeFullTotal));
}
PS Исправил для поддержки английской и русской версий Excel
__________________
Axapta v.3.0 sp5 kr2

Последний раз редактировалось AndyD; 22.06.2006 в 17:26.
За это сообщение автора поблагодарили: NataLee (1).
Старый 21.06.2006, 16:43   #50  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от AndyD
Не слушайте его. Он все врет.
Гы! Самокритично!

Ага, я сам тоже поковырялся, и ТОЖЕ в процессе сначала пропустил параметр и почти расстроился... Потом стал считать параметры, загибая пальцы...

Прикладываю свою простенькую процедурку, которая только открывает и чуть форматирует ранее сформированный файл:
X++:
static void Test_OpenText_FormulaArray(Args _args)
{
    COM xlApp;
    COM rng;
    COM wbks, wbk;
    COM wkss, wks;   
    ;
    
    xlApp = new COM('Excel.Application');
    xlApp.Visible(true);
    
    wbks = xlApp.Workbooks();
    wbk = wbks.Add();
    
    wkss = wbk.Worksheets();
    wks = wkss.Item(1);
    
    rng = wks.Range('A1', 'B10');
    
    rng.FormulaArray(@'={1\1;2\2;3\2;4\2;5\2;6\1;7\1;8\1;9\1;10\1}'); 
    
    wbks.OpenText
    (
    'C:\\demo.txt', //FileName
    1251, // Origin,
    1, // StartRow,
    1, // DataType
    1, // TextQualifier
    false, // ConsecutiveDelimiter,
    true, // Tab,
    false, // Semicolon,
    false, // Comma,
    false, // Space,
    false, // Other,
    '', // OtherChar,
    rng // FieldInfo
    );
    
}
Старый 21.06.2006, 16:55   #51  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Остается как-то взять под контроль сепараторы колонок и строк массива...
X++:
//у меня работает вот так
rng.FormulaArray(@'={1\1; 2\2; 3\2; 4\2; 5\2; 6\1; 7\1; 8\1; 9\1; 10\1}');
     
//и НЕ работает вот так:
rng.FormulaArray(@'={1;1: 2;2: 3;2: 4;2: 5;2: 6;1: 7;1: 8;1: 9;1: 10;1}');
Старый 21.06.2006, 17:07   #52  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Excel 2003 - ситуация противоположная
__________________
Axapta v.3.0 sp5 kr2
Старый 21.06.2006, 17:10   #53  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Вот кусок help'а из Excel
Цитата:
Формат констант массива
Константы массива заключены в фигурные скобки ( { } ).

Столбцы разделяются точкой с запятой (; ). Например, чтобы представить значения 10, 20, 30 и 40, введите {10;20;30;40}. Такой массив констант является матрицей размерности 1 на 4 и соответствует ссылке на 1 строку и 4 столбца.

Строки разделяются двоеточиями (: ). Например, чтобы представить значения 10, 20, 30, 40 и 50, 60, 70, 80, находящиеся в расположенных друг под другом ячейках, можно создать массив констант размерностью 2 на 4, причем строки будут отделены друг от друга двоеточиями, а значения в столбцах — точкой с запятой: {10;20;30;40:50;60;70;80}.
__________________
Axapta v.3.0 sp5 kr2

Последний раз редактировалось AndyD; 21.06.2006 в 17:14.
Старый 21.06.2006, 17:24   #54  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от AndyD
Excel 2003 - ситуация противоположная
Противоположная - чему? XP?
Мой маленький джобик Test_OpenText_FormulaArray прогонялся с 2003.



P.S. (млин... С каждой новой версией хелп Офиса выглядит как изощренный тест на дебильность, ей Богу! )

Последний раз редактировалось Gustav; 21.06.2006 в 17:35.
Старый 21.06.2006, 17:33   #55  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
У меня работает, как написано в хелпе. Ситуация противоположная вашей - в первом случае ругается, во втором все OK

Кстати, когда пробовал - написал код в VBA и в нем передавал строку с разделителями запятая и точка с запятой. Массив формировался нормально.
__________________
Axapta v.3.0 sp5 kr2
Старый 21.06.2006, 17:50   #56  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от AndyD
Вот кусок help'а из Excel
Цитата:
Формат констант массива
Константы массива заключены в фигурные скобки ( { } ).
Столбцы разделяются точкой с запятой (; ). Например, чтобы представить значения 10, 20, 30 и 40, введите
{10;20;30;40}. Такой массив констант является матрицей размерности 1 на 4 и соответствует ссылке на 1
строку и 4 столбца.
Строки разделяются двоеточиями (: ). Например, чтобы представить значения 10, 20, 30, 40 и 50, 60, 70, 80,
находящиеся в расположенных друг под другом ячейках, можно создать массив констант размерностью 2 на 4,
причем строки будут отделены друг от друга двоеточиями, а значения в столбцах — точкой с запятой:
{10;20;30;40:50;60;70;80}.
Сравним с английской версией (у меня - английская):
Цитата:
The format of array constants
Array constants are enclosed in braces ( { } ).
Separate values in different columns with commas (, ). For example, to represent the values 10, 20, 30, and
40, enter {10,20,30,40}. This array constant is known as a 1-by-4 array and is equivalent to a
1-row-by-4-column reference.
Separate values in different rows with semicolons (; ) . For example, to represent the values 10, 20, 30,
and 40 in one row and 50, 60, 70, and 80 in the row immediately below, you would enter a 2-by-4 array
constant: {10,20,30,40;50,60,70,80}.
Ой, йооо...
Старый 21.06.2006, 17:56   #57  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Шутники, однако...
__________________
Axapta v.3.0 sp5 kr2
Старый 21.06.2006, 18:01   #58  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
Цитата:
Сообщение от AndyD
Кстати, когда пробовал - написал код в VBA и в нем передавал строку с разделителями запятая и точка с запятой. Массив формировался нормально.
Аналогично. Это, получается, международный формат, который следует применять в макросах.
С суффиксом Local свойства FormulaArray у Range не увидел (в отличие от других Formula...).

Пока не понятно только, почему Акса в этом случае требует не запятую, а обратный слэш...

P.S. Так... чуть теплее... у меня запятая используется в качестве десятичного разделителя...
AndyD, а Вы можете прогнать у себя свой джоб, заменив свою точку с запятой на обратный слэш?
т.е. с FormulaArray(@'={1\1: 2\2: 3\2: 4\2: 5\2: 6\1: 7\1: 8\1: 9\1: 10\1}');

Последний раз редактировалось Gustav; 21.06.2006 в 18:07.
Старый 21.06.2006, 18:57   #59  
Gustav is offline
Gustav
Moderator
Аватар для Gustav
SAP
Лучший по профессии 2009
 
1,858 / 1152 (42) ++++++++
Регистрация: 24.01.2006
Адрес: Санкт-Петербург
Записей в блоге: 19
А, собственно говоря, чччо мы мучаемся... Пусть Excel сам всё и определяет для себя - все свои сепараторы, семиколоны, комасы и прочие бэкслэши - используем эксельную функцию TRANSPOSE :
X++:
static void Test_OpenText_FormulaArray_2(Args _args)
{
    COM xlApp;
    COM rng;
    
    COM wbks, wbk;
    COM wkss, wks;
    COM cells;
    ;
    
    xlApp = new COM('Excel.Application');   
    xlApp.Visible(true);
    
    wbks = xlApp.Workbooks();   
    wbk = wbks.Add();
    
    wkss = wbk.Worksheets();
    wks = wkss.Item(1);
    
    cells = wks.Cells();
    
    // первая строка листа - номера полей A1:J1
    COM::createFromVariant( cells.Item(1,  1) ).Value2(  1);
    COM::createFromVariant( cells.Item(1,  2) ).Value2(  2);
    COM::createFromVariant( cells.Item(1,  3) ).Value2(  3);
    COM::createFromVariant( cells.Item(1,  4) ).Value2(  4);
    COM::createFromVariant( cells.Item(1,  5) ).Value2(  5);
    COM::createFromVariant( cells.Item(1,  6) ).Value2(  6);
    COM::createFromVariant( cells.Item(1,  7) ).Value2(  7);
    COM::createFromVariant( cells.Item(1,  8) ).Value2(  8);
    COM::createFromVariant( cells.Item(1,  9) ).Value2(  9);
    COM::createFromVariant( cells.Item(1, 10) ).Value2( 10);
    
    // вторая строка листа - типы полей A2:J2
    COM::createFromVariant( cells.Item(2,  1) ).Value2(  1);
    COM::createFromVariant( cells.Item(2,  2) ).Value2(  2);
    COM::createFromVariant( cells.Item(2,  3) ).Value2(  2);
    COM::createFromVariant( cells.Item(2,  4) ).Value2(  2);
    COM::createFromVariant( cells.Item(2,  5) ).Value2(  2);
    COM::createFromVariant( cells.Item(2,  6) ).Value2(  1);
    COM::createFromVariant( cells.Item(2,  7) ).Value2(  1);
    COM::createFromVariant( cells.Item(2,  8) ).Value2(  1);
    COM::createFromVariant( cells.Item(2,  9) ).Value2(  1);
    COM::createFromVariant( cells.Item(2, 10) ).Value2(  1);
    
    rng = wks.Range('A11:B20');
    
    rng.FormulaArray('=TRANSPOSE(A1:J2)');
    // используем формулу выше вместо формулы ниже :)
    // rng.FormulaArray(@'={1\1; 2\2; 3\2; 4\2; 5\2; 6\1; 7\1; 8\1; 9\1; 10\1}');
    
        
    wbks.OpenText
    (
    'C:\\demo.txt', //FileName
    1251, // Origin,
    1, // StartRow,
    1, // DataType
    1, // TextQualifier
    false, // ConsecutiveDelimiter,
    true, // Tab,
    false, // Semicolon,
    false, // Comma,
    false, // Space,
    false, // Other,
    '', // OtherChar,
    rng // FieldInfo
    );
    
}
Старый 22.06.2006, 09:41   #60  
AndyD is offline
AndyD
Участник
КОРУС Консалтинг
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
2,560 / 2479 (88) +++++++++
Регистрация: 20.08.2005
Не мучаемся, а препарируем

Еще один вариант с разделителями
X++:
    str leftBrace;
    str rightBrace;
    str columnSeparator;
    str rowSeparator;
    str alternateArraySeparator;
    str decimalSeparator;
    COMVariant var;

    #define.xlDecimalSeparator(0x00000003)
    #define.xlLeftBrace(0x0000000C)
    #define.xlRightBrace(0x0000000D)
    #define.xlColumnSeparator(0x0000000E)
    #define.xlRowSeparator(0x0000000F)
    #define.xlAlternateArraySeparator(0x00000010)
    ;
...
    var = xlApp.International(#xlDecimalSeparator);
    if (var) 
        decimalSeparator = var.bStr();
    else 
        decimalSeparator = ",";
    var = xlApp.International(#xlLeftBrace);
    if (var) 
        leftBrace = var.bStr();
    else 
        leftBrace = "{";
    var = xlApp.International(#xlRightBrace);
    if (var) 
        rightBrace = var.bStr();
    else 
        rightBrace = "}";
    var = xlApp.International(#xlColumnSeparator);
    if (var) 
        columnSeparator = var.bStr();
    else
        columnSeparator = ";";
    var = xlApp.International(#xlRowSeparator);
    if (var) 
        rowSeparator = var.bStr();
    else
        rowSeparator = ":";
    var = xlApp.International(#xlAlternateArraySeparator);
    if (var) 
        alternateArraySeparator = var.bStr();
    else
        alternateArraySeparator = "&";
    if (columnSeparator == decimalSeparator)
        columnSeparator = alternateArraySeparator;
    if (rowSeparator == decimalSeparator)
        rowSeparator = alternateArraySeparator;

    rng.FormulaArray(
        strfmt("=%1 1 %3 1 %4 2 %3 2 %4 3 %3 2 %4 4 %3 2 %4 5 %3 2 %4 6 %3 2 %4 7 %3 4 %4 8 %3 2 %4 9 %3 1 %4 10 %3 2%2",
        leftBrace, rightBrace, columnSeparator, rowSeparator));
PS 2 Gustav.
А как это будет выглядеть на английской версии? Если все Ok, то исправлю выгрузку
__________________
Axapta v.3.0 sp5 kr2

Последний раз редактировалось AndyD; 22.06.2006 в 10:05.
Теги
benchmark, download, excel, faq, xml, законченный пример, производительность, экспорт/импорт

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Axapta программирует Excel на VBA Gustav DAX: База знаний и проекты 10 13.03.2006 11:42
Использование OWC.Spreadsheet для ускорения экспорта/импорта в/из Excel. storer DAX: Программирование 24 28.03.2005 19:10
Передача данных из 1С в Axapta 3.0 через COM Connector isbist DAX: Программирование 10 03.12.2004 10:58
Особенности экспорта данных в Excel Roman-sp DAX: Функционал 18 01.03.2004 12:07
Введение в Аксапту Роман Кошелев DAX: Прочие вопросы 0 18.12.2001 14:00

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

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

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