15.06.2006, 20:40 | #41 |
Moderator
|
Замерил способ "через 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 процентов.
Мне он, однако, понравился другим, в частности: - возможностью писать "почти как на VBA c многими точками" (см. комментарии в тексте джоба), - писать нормально Value, а не Value2 (при этом класс SysExcelCell сам берет на себя ответственность за обработку value - "до XP или после" ). |
|
15.06.2006, 21:09 | #42 |
Moderator
|
Цитата:
Сообщение от Gustav
Результат "1228 сек" ниже "1060 сек"
Редактировать прямо там боюсь, так как съедет форматирование кода X++. Кстати, почему такое происходит с тегом XPP? Т.е. пишу сообщение, делаю предварительный просмотр - пока всё хорошо, пишу дальше, делаю повторный предварительный просмотр - и всё разрушается - код сливается с текстом, отступы пропадают - в общем, беда какая-то... Последний раз редактировалось Gustav; 15.06.2006 в 23:08. |
|
16.06.2006, 09:00 | #43 |
1C
|
и все же не есть правильно не использовать средства прямого доступа :-)
|
|
16.06.2006, 09:18 | #44 |
Moderator
|
Цитата:
Сообщение от Dolter
и все же не есть правильно не использовать средства прямого доступа :-)
Поясните, пожалуйста, что Вы имеете в виду конкретно? |
|
20.06.2006, 14:18 | #45 |
Участник
|
Продолжим
Выгрузка в текстовый файл с последующей загрузкой в 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 |
Moderator
|
Цитата:
Сообщение от AndyD
Продолжим
Выгрузка в текстовый файл с последующей загрузкой в Excel... 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 |
Moderator
|
Цитата:
Сообщение от AndyD
Почему такой путь - для передачи типов данных в столбцах функция требует передачи в кач-ве одного из параметров массива массивов.
К сожалению, не знаю как это организовать в Axapta без привлечения сторонних средств Итак, как я понимаю, проблема заключается в том, что в операторе VBA вида PHP код:
PHP код:
Код: Номер Тип --------- 1 1 2 2 3 2 4 2 5 1 6 1 7 1 8 1 9 1 10 1 PHP код:
то потом можно заменить FieldInfo:=Array... на FieldInfo:=Worksheets("Sheet1").Range("A1:B10") и получится: PHP код:
Попробуете? Только прошу, ни в коем случае не убирайте предыдущую версию. Пусть она останется в ветке. А новую можно назвать типа "ExportExcelTXT_2" |
|
|
За это сообщение автора поблагодарили: AndyD (4). |
21.06.2006, 15:14 | #48 |
Участник
|
Не работает такой вариант ч/з интерфейсы.
Я думаю, причина в том, что при вызове из 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 |
Участник
|
Не слушайте его. Он все врет.
В общем моя ошибка - пропустил один из параметров, в результате 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)); }
__________________
Axapta v.3.0 sp5 kr2 Последний раз редактировалось AndyD; 22.06.2006 в 17:26. |
|
|
За это сообщение автора поблагодарили: NataLee (1). |
21.06.2006, 16:43 | #50 |
Moderator
|
Цитата:
Сообщение от 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 |
Moderator
|
Остается как-то взять под контроль сепараторы колонок и строк массива...
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 |
Участник
|
Excel 2003 - ситуация противоположная
__________________
Axapta v.3.0 sp5 kr2 |
|
21.06.2006, 17:10 | #53 |
Участник
|
Вот кусок 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 |
Moderator
|
Цитата:
Сообщение от AndyD
Excel 2003 - ситуация противоположная
Мой маленький джобик Test_OpenText_FormulaArray прогонялся с 2003. P.S. (млин... С каждой новой версией хелп Офиса выглядит как изощренный тест на дебильность, ей Богу! ) Последний раз редактировалось Gustav; 21.06.2006 в 17:35. |
|
21.06.2006, 17:33 | #55 |
Участник
|
У меня работает, как написано в хелпе. Ситуация противоположная вашей - в первом случае ругается, во втором все OK
Кстати, когда пробовал - написал код в VBA и в нем передавал строку с разделителями запятая и точка с запятой. Массив формировался нормально.
__________________
Axapta v.3.0 sp5 kr2 |
|
21.06.2006, 17:50 | #56 |
Moderator
|
Цитата:
Сообщение от 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 |
Участник
|
Шутники, однако...
__________________
Axapta v.3.0 sp5 kr2 |
|
21.06.2006, 18:01 | #58 |
Moderator
|
Цитата:
Сообщение от 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 |
Moderator
|
А, собственно говоря, чччо мы мучаемся... Пусть 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 |
Участник
|
Не мучаемся, а препарируем
Еще один вариант с разделителями 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)); А как это будет выглядеть на английской версии? Если все Ok, то исправлю выгрузку
__________________
Axapta v.3.0 sp5 kr2 Последний раз редактировалось AndyD; 22.06.2006 в 10:05. |
|
Теги |
benchmark, download, excel, faq, xml, законченный пример, производительность, экспорт/импорт |
|
|