среда, 20 августа 2014 г.

Проблема сохранения в Excel больших таблиц 1С 7.7

Проблема: При попытке сохранить в Excel большой таблицы 1С "подвисает", нагружая процессор на 100%.
Под "большой" имеется в виду таблица 5-6 тыс. строк и более. Сохранение при этом может идти 30-40 минут.

Теория, решение, технические подробности от romix: Исправление ошибки при экспорте в Excel (патчинг Moxel.dll)

Еще одна реализация решения:  [MXLtoXLS] Сохранение больших таблиц в EXCEL

Копия статьи от ув. romix на память:


При попытке сохранить в Excel большой таблицы 1С "подвисает", нагружая процессор на 100%. Попытаемся исправить этот недостаток 1С 7.7. Компонента протестирована только для 1С:Предприятие 7.7, 25 релиз.
Автор статьи: romix | Редакторы:
Последняя редакция №14 от 27.12.06 | История
URL: http://kb.mista.ru/article.php?id=219


Внешняя компонента с тестовым примером конфигурации:
http://x-romix.narod.ru/MXL_DOCTOR.rar (Скачивать ЛЕВОЙ кнопкой мыши, ~75К).


Замечание для пользователей Windows 2003 в терминале
romix - есть вопрос по мхл-доктору...
Т.е. если есть такая ошибка, ставьте плагин:
Книга знаний: Перехват API-вызовов и альтернативные плагины для 1С:Предприятие

См. также:
Книга знаний: Сохранение данных MXL->XLS через HTML

Назначение
Приведенная выше компонента позволяет без торможения сохранять большие файлы в формат XLS. 

Дополнение от 10.10.2006: Теперь компонента перехватывает и случай записи из меню "Сохранить как".

Установка таблицы стилей (дополнение от 10.10.2006)
Позволяет производить "чистку" файла HTML и назначение ему таблицы стилей CSS.

Для этого служит свойство:
mxl_doctor.ФайлCSS=КаталогИБ()+"1.css";

Вычищаются подстроки: ' BORDERCOLOR=#ffffff', ' ALIGN=LEFT', ' SIZE=2', ''..''
Если таблица стилей не назначена, то с файлом HTML ничего не делается.


Технические подробности

Отладчик SoftICE позволяет находить подобные "узкие места" в производительности программы, если просто запустить подопытную программу, сделать так, чтобы она начала тормозить (я создал большую таблицу, и стал сохранять ее в Excel), и нажать Ctrl-D. Велика (близка к 100%) вероятность, что указатель команды микропроцессора будет находиться в "грузящем" систему потоке, и таким образом, несколькими нажатиями F10, мы выйдем на цикл, который загружает нашу систему.

Вот этот цикл:

00029875: 57                           push        edi
00029876: 8BCE                         mov         ecx,esi
00029878: E813010000                   call        000029990  --- (1)
0002987D: 8B54247C                     mov         edx,[esp][7C]
00029881: 85D2                         test        edx,edx
00029883: 7E08                         jle         00002988D  --- (2)
00029885: 895C2464                     mov         [esp][64],ebx
00029889: 03D8                         add         ebx,eax
0002988B: EB0C                         jmps        000029899  --- (3)
0002988D: 8B4C2464                     mov         ecx,[esp][64]
00029891: 8BD9                         mov         ebx,ecx
00029893: 2BC8                         sub         ecx,eax
00029895: 894C2464                     mov         [esp][64],ecx
00029899: 3B7C2478                     cmp         edi,[esp][78]
0002989D: 7404                         je          0000298A3  --- (4)
0002989F: 03FA                         add         edi,edx
000298A1: EBD2                         jmps        000029875  --- (5)

Это был дамп из программы Hiew.
В SoftICE вызов call выглядит так:
call Moxel!?GetRowHeight@CSheetGDI@@QAEHH@Z

Отладчик показывает, что вызов GetRowHeight() выполняется N-факториал раз. Поэтому
Для малого числа строк (100, 500) ничего особенного пользователь не замечает, но для большого числа строк (например, 10000) все "подвисает" (хотя, за ночь бурной работы, наверное, может, с грехом пополам, и выполниться).

Эта ошибка, кстати, достаточно распространенная и коварная: на малом числе итераций (повторений цикла) проблему не видно, а на большом - она растет экспоненциально.

Некоторое (приблизительное) решение проблемы дает следующая правка (в последней строке приведенного дампа):

000298A1: EBE2                         jmps        000029885  --- (5)

Внешняя компонента, которая реализует эту правку при сохранении в Excel, приведена в начале
статьи.

Другие варианты действий:
  • Поскольку в цикле вызывается GetRowHeight(), установить всем строкам отчета фиксированную (заранее прописанную) высоту. Недостаток - не будет работать "красивое" выравнивание ячеек по высоте.
  • Записывать в формат HTML (там этой ошибки почему-то нет).
    Хинт: создание табличного HTML и последующее переименование этого файла
    в XLS, кстати, позволяет простым способом сгенерировать XLS-документ (Excel не будет
    задавать никаких лишних вопросов, как будто это "родной" формат Excel).
    Это удобно, в частности, для Web-дизайнеров, которые хотят выгружать своим посетителям XLS-документы, но не знают, как это проще и правильнее всего сделать. :-)
  • Использовать программу "1С:Предприятие - Работа с файлами" для просмотра MXL и прочих
    файлов, которая распространяется фирмой 1С бесплатно, и подходит для файлов 7.7/8.0.
    http://v8.1c.ru/metod/fileworkshopdownload.htm
  • Переходить на 1С:Предприятие 8.0. :-)

Комментариев нет: