22.06.2006, 12:03 | #61 |
Moderator
|
AndyD... Есть ощущение, что мы несколько перестарались с массивами...
Сейчас проверил - работает и обычный Range, без всяких FormulaArray... Просто выстраиваем наш "массив массивов" из 10 строк и 2 столбцов в диапазоне A1:B10 и передаем его OpenText... о блин! X++: static void Test_OpenText_NoArray_3(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:A10 COM::createFromVariant( cells.Item( 1, 1) ).Value2( 1); COM::createFromVariant( cells.Item( 2, 1) ).Value2( 2); COM::createFromVariant( cells.Item( 3, 1) ).Value2( 3); COM::createFromVariant( cells.Item( 4, 1) ).Value2( 4); COM::createFromVariant( cells.Item( 5, 1) ).Value2( 5); COM::createFromVariant( cells.Item( 6, 1) ).Value2( 6); COM::createFromVariant( cells.Item( 7, 1) ).Value2( 7); COM::createFromVariant( cells.Item( 8, 1) ).Value2( 8); COM::createFromVariant( cells.Item( 9, 1) ).Value2( 9); COM::createFromVariant( cells.Item(10, 1) ).Value2( 10); // второй СТОЛБЕЦ листа - типы полей B1:B10 COM::createFromVariant( cells.Item( 1, 2) ).Value2( 1); COM::createFromVariant( cells.Item( 2, 2) ).Value2( 2); COM::createFromVariant( cells.Item( 3, 2) ).Value2( 2); COM::createFromVariant( cells.Item( 4, 2) ).Value2( 2); COM::createFromVariant( cells.Item( 5, 2) ).Value2( 2); COM::createFromVariant( cells.Item( 6, 2) ).Value2( 1); COM::createFromVariant( cells.Item( 7, 2) ).Value2( 1); COM::createFromVariant( cells.Item( 8, 2) ).Value2( 1); COM::createFromVariant( cells.Item( 9, 2) ).Value2( 1); COM::createFromVariant( cells.Item(10, 2) ).Value2( 2); // !!!!!! обычный Range без всяких FormulaArray :) rng = wks.Range('A1:B10'); 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, 12:07 | #62 |
Moderator
|
Цитата:
Сообщение от AndyD
PS 2 Gustav.
А как это будет выглядеть на английской версии? Если все Ok, то исправлю выгрузку На английской версии проверю чуть позже. Обязательно сообщу. P.S. иех, почему я не проверил сразу просто Range?.. наверное, слово Array меня смутило... В общем, "Болван... - Согласен!" (с) Операция Ы Последний раз редактировалось Gustav; 22.06.2006 в 12:11. |
|
|
За это сообщение автора поблагодарили: oip (2). |
22.06.2006, 16:57 | #63 |
Moderator
|
Цитата:
Сообщение от AndyD
А как это будет выглядеть на английской версии? Если все Ok, то исправлю выгрузку
Всё - ОК! OpenText отрабатывает, файл загружается. Строка для FormulaArray формируется корректно. Когда в региональных настройках Windows "Десятичный разделитель" - "запятая", то в виде (содержимое любой входящей в массив ячейки Excel): Код: ={1\1; 2\2; 3\2; 4\2; 5\2; 6\2; 7\4; 8\2; 9\1; 10\2} Код: ={1,1; 2,2; 3,2; 4,2; 5,2; 6,2; 7,4; 8,2; 9,1; 10,2} P.S.Forward Цитата:
Сообщение от AndyD
Выгрузку исправил.
Последний раз редактировалось Gustav; 22.06.2006 в 20:20. |
|
22.06.2006, 17:25 | #64 |
Участник
|
Выгрузку исправил
__________________
Axapta v.3.0 sp5 kr2 |
|
29.06.2006, 01:57 | #65 |
Коллективное бессознательn ое
|
Завтра забуду, поэтому предложу еще вариант
Сразу извиняюсь, что тестирование не по правилам - ночь на дворе, предлагаю просто в качестве идеи.
Выгрузку ниже делал дома, подключившись через интернет к терминальному серверу. Файл "111.xls" лежит у меня дома на диске "С", т.е. файл пишется через интернет. Код ниже прошел за 59 секунд. Тут использовались "самодельные" классы-оболочки АДО, но идея проста - берем АДОКомманд и пишем запрос "INSERT INTO". Единственный момент - видимо, придется до начала процедуры задать имена столбцов обычным способом, а потом уже грузить данные. CREATE COLUMN я не пербовал, но может и пройдет, зависит от драйвера, если пройдет, будет быстрее. Код: static void Job122(Args _args) { ADOConnection connection; ADOCommand command; int i; int timeFullStart, timeFullFinish, timeFullTotal; ; timeFullStart = timenow(); connection = ADODB::establishConnection("C:\\111.xls", false); command = new ADOCommand(); command.ActiveConnection(connection); while(i<50000) { command.CommandText(strFmt("INSERT INTO [Лист1$] (Field1, Field2) VALUES (100000000000000000000, 20000000000000000)")); command.Execute(); i++; } connection.Close(); timeFullFinish = timenow(); timeFullTotal = timeFullFinish - timeFullStart; info('Время выполнения, сек'); info(int2str(timeFullTotal)); }
__________________
Жизнь такова, какова она есть и больше никакова. |
|
29.06.2006, 10:02 | #66 |
Moderator
|
Цитата:
Сообщение от KSS
Сразу извиняюсь, что тестирование не по правилам - ночь на дворе, предлагаю просто в качестве идеи…
идея проста - берем АДОКомманд и пишем запрос "INSERT INTO"…. Но зачОт пока поставить не могу. В первую очередь, конечно, потому, что далековато от «Условий конкурса»: фактически у Вас в цикле 50 тыс. раз вставляется одна и та же запись, т.е. нет фетча по таблицам Аксы, а на фетч тратится довольно большой процент времени. В вторую очередь - это даже не "очередь", а мое очень субъективное "ИМХО" - потому что Ваш вариант несколько тяжеловат – существует, опять же ИМХО, более элегантное решение, приведенное здесь (Господи, не дай возгордиться и захвалиться!). Там на стороне Axapta данные загружаются в ADODB.Recordset в оперативной памяти (без связи с БД, как в массив), а на стороне Excel вставляются – не устаю восхищаться! – одной единственной командой Range.CopyFromRecordset. Посмотрите, сравните. Это не может не понравиться. Хотя по скорости, конечно, несколько уступает быстрокрылым способам AndyD-а, но не на порядок (чуть позже я выложу свою «конкурсную» версию). Зато прозрачность реализации подкупает. Однако, я совсем не отговариваю Вас от Вашего подхода. Оформите джобик «по правилам» и выкладывайте – будем его хронометрировать на моей «эталонной» машине и сохранять для благодарных потомков. |
|
14.07.2006, 20:43 | #67 |
Коллективное бессознательn ое
|
Цитата:
Сообщение от Wamr
Вот такой код отрабатывает за 35 сек на
Celeron-2,5/ 512Mb Excel-2000 Win2000 Оно позволяло выгружать в экселевские файлы данные из стандартного диалога печати аксапты. Колумбус, помнится, его продавал...
__________________
Жизнь такова, какова она есть и больше никакова. |
|
22.09.2006, 16:45 | #68 |
Участник
|
[QUOTE=Wamr;110027]Вот такой код отрабатывает за 35 сек на
Celeron-2,5/ 512Mb Excel-2000 Win2000 QUOTE] Здесь, кстати, не мешало бы использовать функцию, как в одном из методов, предоставленных AndyD - для смены раскладки. |
|
23.09.2006, 00:40 | #69 |
Moderator
|
2 kashperuk: Иван, как приятно Ваш комментарий
Цитата:
Спасибо. Очень рад, что вы такой бескорыстный
|
|
24.09.2006, 00:32 | #70 |
Участник
|
Цитата:
Сообщение от Gustav
2 kashperuk: Иван, как приятно Ваш комментарий к репутации AndyD'у за этот его пост контрастирует с Спасибо! В общем, "Can't Buy Me Love", короче!
Побольше бы таких вот бескорыстных. Работа бы была - просто в кайф. Она и щас ничего, конечно. |
|
09.07.2007, 18:18 | #71 |
Участник
|
Цитата:
Нам очень понадобилось, поэтому переделал в класс. Собственно, выкладываю класс. В нем из любого места можно вызвать - просто посмотреть в коде пример использования - это ExXML::Test(). |
|
10.07.2007, 09:57 | #72 |
Участник
|
Лично я взял вариант, использующий ADO, склеил его с COM, и получил класс, который мы сейчас используем повсеместно.
Вариант через XML мне очень нравиться. В приведенном выше посте неплохой JOB - но, во-первых, не полностью компилируется (метода salesTotals нету на таблице SalesTable в стандарте), а во-вторых, код ну уж очень трудно-читаемый. Вариант с использованием Dynamic data exchange (DDE) тоже быстр. Его не пробовал сильно. По скорости эти три варианты получились приблизительно одинаковы.Разница несущественна, по сути. Поэтому, это уже что кому больше нравиться. думаю, технологию здесь стоит выбирать по тем ограничениям, которые присущи каждому из подходов (они также описаны в этой теме) |
|
10.07.2007, 10:02 | #73 |
Участник
|
Цитата:
По-моему, лучше не искать в данной теме "самый лучший" способ, а изучить все рассмотренные, чтобы затем можно было использовать тот или иной способ, в зависимости от ситуации. |
|
10.07.2007, 10:10 | #74 |
Участник
|
|
|
10.07.2007, 11:24 | #75 |
Участник
|
«Специализация парализует, ультраспециализация - убивает»
|
|
10.07.2007, 11:26 | #76 |
Участник
|
Цитата:
1. Способов <<1000 2. Каждый способ это компромисс между скоростью легкостью в реализации и пр. Например, XML не поддерживается версиями Excel раньше XP, а ADO не поддерживает вывод форматирования. |
|
10.07.2007, 11:49 | #77 |
MCT
|
Цитата:
2. Каждый способ это компромисс между скоростью легкостью в реализации и пр. Например, XML не поддерживается версиями Excel раньше XP, а ADO не поддерживает вывод форматирования.
А оформить задачки можно так Задача выгрузки в excel. 1 Условия: продвинутое форматирование, с шаблоном.... Реализация. ..... Пример... 2 Условия: продвинутое форматирование, без шаблона.... Реализация. ..... Пример... |
|
|
За это сообщение автора поблагодарили: belugin (4). |
10.07.2007, 14:54 | #78 |
Moderator
|
Продолжаю наслаждаться комбинацией несвязанного ADODB.Recordset в оперативной памяти и последующего Range.CopyFromRecordset в Excel. Пристегиваю этот способ ко всем новым задачкам, в которых требуется вывод в Excel.
Способ не наибыстрейший, но вполне комфортный по скорости. Тестовое задание этой ветки (50 тыс.строк X 10 полей) выполняется примерно за 80 сек. Это уже не просто джобом, а классом, который сам настраивает Recordset и может резать выводимую выборку как по критерию "65 тыс строк" на лист, так и по произвольно задаваемому групповому критерию - типа "все сотрудники на А на первый лист, на Б - на второй и т.д." - т.е. сам процесс вывода продирается через эти "рогатки". Основная причина же этой моей симпатии - возможность управления типами данных выводимых столбцов. Ради этой возможности я согласен ждать 50-60 лишних секунд Форматирую, если требуется, после вывода. Сразу большими Range'ми (целыми строками, столбцами, заголовками, областью данных), необходимые ссылки на которые создаются и запоминаются классом в процессе вывода. Это что касается спискообразных "автоотчетов". Для развесистых стандартных шаблонов (типа акта ОС-1) теперь тоже использую такой вывод с CopyFromRecordset. В файле шаблона создаю еще один лист, можно скрытый, на который вывожу одну строку с необходимыми данными. А в ячейках самого шаблона прописываю формулы-ссылки на ячейки этой выводимой строки. Подход родился в процессе решения задачи по пакетной печати нескольких тысяч актов ОС-1. Один CopyFromRecordset вместо многих присваиваний Range.Value(...) увеличил скорость процесса примерно в 30 раз (иначе можно было бы тихо загнуться на этой печати). |
|
|
За это сообщение автора поблагодарили: player (1). |
20.01.2010, 18:04 | #79 |
Участник
|
Цитата:
Сообщение от AndyD
Опробовал еще на одной машине
Конфигурация клиента - Celeron 2800, 256Мб Сеть - сервер б/д тот-же, что и в предыдущем случае, но подключение ч/з 3 хаба. Excel 2003 Время через файл 40-45 с, напрямую в Excel - 35 c Почему через файл дольше - на мой взгляд из-за версии XML (на первой машине XML 6.0) и способа выгрузки во втором случае - передаются не все данные сразу, а по несколько тысяч строк. По всей видимости, XML 4 хуже работает с большими по размеру документами (в данном случае - больше 30 Мб) Ну и в завершение - тестовый джоб У меня при использовании этого механизма для выгрузки в Excel, если количество полей больше определенного порога, выдается ошибка X++: "value" COM- "Range" 0x800A03EC (<>), : <>. |
|
13.02.2014, 13:18 | #80 |
Участник
|
я ищу причину ошибки:
Цитата:
Метод "item" в COM-объекте класса "Range" возвратил код ошибки 0x800A03EC (<неизвестно>), который означает: <неизвестно>.
в ходе поиска получил близкую ошибку: Цитата:
Метод "value" в COM-объекте класса "Range" возвратил код ошибки 0x80004005 (E_FAIL), который означает: Общий сбой.
Именно этот job на больших данных мне конкретно пишет: Цитата:
Ошибка времени выполнения: Недостаточно памяти для исполнения кода.
Цитата:
Exception of type `SystemOutMemoryException` was thrown
Пытался добиться своей ошибки выводом в xml строк больше1 048 576 но система спокойно выводит последнюю строку, а остальные "скромно" пропускает. |
|
Теги |
benchmark, download, excel, faq, xml, законченный пример, производительность, экспорт/импорт |
|
|