gifts2017

Выгрузка таблицы значений в Excel

Опубликовал Яков Коган (Yashazz) в раздел Обмен - Загрузка и выгрузка в Excel

Примитивно, грубо, без дизайна, но очень быстро.

Честно говоря, это не столько публикация, сколько антисклерозник для меня самого. Вот как Трактор делает - собрал свои наработки, укомпоновал и выложил, удобно отовсюду доставать. А поскольку я этот блок свой уже пару раз про...любил и заново написал, то во избежание - пусть будет таким образом. Как говорится, "в копипасте - щастье".

 

// Внимание! Исходная таблица тДанных должна содержать только данные простых типов!!!
Процедура БыстроВывестиТаблицуЗначенийВExcel(тДанных,рПутьИмяФайла,рОткрыватьДляПросмотра=Ложь) Экспорт
Попытка
    Если
тДанных.Количество()=0 Или ПустаяСтрока(рПутьИмяФайла) Тогда Возврат КонецЕсли;

   
// если таблица для экселя спецслужебная, то выводим в двумерный массив, и теперь уже знаем его размеры
   
квоКолонокДЭ=тДанных.Колонки.Количество();
   
квоСтрокДЭ=тДанных.Количество()+1; // припуск на заголовок
   
РезДокумент=Новый Массив(квоКолонокДЭ,квоСтрокДЭ);

   
// заголовки
   
мКолонокДат=Новый Массив;
    Для
итерКолонок=1 По квоКолонокДЭ Цикл
       
кол=тДанных.Колонки[итерКолонок-1];
       
РезДокумент[итерКолонок-1][0]=кол.Заголовок;
        Если
кол.ТипЗначения.СодержитТип(Тип("Дата")) Тогда мКолонокДат.Добавить(кол.Имя) КонецЕсли;
    КонецЦикла;

   
// основные данные
   
квоиз=" из "+СокрЛП(квоСтрокДЭ-1);
    Для
й=0 По квоСтрокДЭ-2 Цикл
       
#Если Клиент Тогда
           
ОбработкаПрерыванияПользователя();
           
Состояние("Вывод в Excel: "+Строка(й+1)+квоиз);
       
#КонецЕсли
       
стро=тДанных.Получить(й);
        Для
итерКолонок=1 По квоКолонокДЭ Цикл
           
знч=стро[итерКолонок-1];
            Если
мКолонокДат.Найти(тДанных.Колонки[итерКолонок-1])<>Неопределено Тогда
               
// выгрузка в эксель через COMSafeArray не понимает совсем пустые даты, поэтому надо это учесть!!!
               
знч=?(ЗначениеЗаполнено(знч),знч,Дата(1900,1,1));
            КонецЕсли;
           
РезДокумент[итерКолонок-1][й+1]=знч;
        КонецЦикла;
    КонецЦикла;

   
// сохраняем все в произвольный тип, подробнее см. типизацию в описании конструктора "По типу элемента 1"
   
рТипМассива="VT_VARIANT";
   
рМассив=Новый COMSafeArray(РезДокумент,рТипМассива,квоКолонокДЭ,квоСтрокДЭ);
   
Ексель=Новый COMОбъект("Excel.Application");
   
Книга=Ексель.Workbooks.Add();
    Если
Книга.WorkSheets.Count=0 Тогда
       
Лист=Книга.WorkSheets.Add();
    Иначе
       
Лист=Книга.WorkSheets.Item(1); // нумерация с 1
   
КонецЕсли;
   
// самое главное: диапазону ячеек можно просто присвоить SafeArray со значениями
   
рНачало=Лист.Cells(1,1);
   
рКонец=Лист.Cells(квоСтрокДЭ,квоКолонокДЭ);
   
Лист.Range(рНачало,рКонец).Value=рМассив;
   
//
    // соответствие форматов: xlOpenXMLWorkbook=51 это xlsx, xlExcel12=50 это xlsb, xlExcel8=56 это xls
   
стрпф=Новый Структура("xls,xslx,xlsb",56,51,50);
   
рФайл=Новый Файл(СокрЛП(рПутьИмяФайла));
   
расш=СтрЗаменить(рФайл.Расширение,".","");
   
рФормат=?(стрпф.Свойство(расш),стрпф[расш],51); // по умолчанию xlsx
   
Книга.SaveAs(СокрЛП(рПутьИмяФайла),рФормат);

    Если
рОткрыватьДляПросмотра Тогда
       
#Если Клиент Тогда
           
Ексель.Visible=Истина;
       
#КонецЕсли
   
КонецЕсли;
   
//
   
Ексель=Null;

Исключение
   
Сообщить("БыстроВывестиТаблицуЗначенийВExcel, ошибка: "+ОписаниеОшибки(),СтатусСообщения.ОченьВажное);
КонецПопытки;
КонецПроцедуры


 

Желающим плюсить - сюда: http://infostart.ru/public/269846/

Ну а первоисточник, который применял я, здесь: http://kb.mista.ru/article.php?id=707

Поскольку моё тут только конкретное воплощение, публикацию особо плюсить не стоит, и вообще она life.

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Сергей Семченков (BigClock) 29.06.15 10:03
ТабЗнч = РезЗапроса.Выгрузить();
ПострПечать = Новый ПостроительОтчета;
ПострПечать.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТабЗнч);
ТабДок = Новый ТабличныйДокумент;                  
ПострПечать.Вывести(ТабДок);
ТабДок.Записать("ИмяФайла.xls");
...Показать Скрыть
pikabu; androgin; mvsemenov; fancy; webester; the1; dolter; Zeskord; vasyak319; +9 1 Ответить 4
2. Василий Коровин (vasyak319) 29.06.15 10:15
Всего вторую публикацию за сегодня читаю и уже второй способ удаления гланд через задницу. Сегодня "День проктолога" что ли?
andy23; DoctorRoza; +2 1 Ответить
3. Алексей Роза (DoctorRoza) 29.06.15 10:48
Вопрос в автору, как у гуру: можно в предложенном коде сделать "Попытку .." не в блоке загрузки данных? То бишь, я хочу в начале проверить, что все загрузиться, а уже потом точно загружать данные! Спасибо!
4. Яков Коган (Yashazz) 29.06.15 11:24
(1) BigClock, господин "пионэр", вы, вероятно, не поняли фишку, что, возможно, ввиду малого опыта простительно. Я ведь написал - это вариант быстрого способа. Да ещё и не подвешивающего клиентскую машину. Флаг вам в руки сохранять моксель на 300 тысяч строк методом Записать() при небольшой оперативке, тогда поймёте.

(3) Что будет являться критерием "успешной загрузки" при проверке, и чем тогда, на ваш взгляд, загрузка будет отличаться от проверки оной?
5. Яков Коган (Yashazz) 29.06.15 13:50
(1) Вот мне интересно, сколько ещё ламеров, полагающих себя Кэпами Очевидность, плюсанут неработающий код из (1)? Прям хоть ставки делай)))
6. Xer shi (Xershi) 29.06.15 14:07
(5) Yashazz, так работает типовой механизм. Куда не поставь 1С везде создаст файл эксель. Ваш вариант предполагает установку экселя на сервер с 1С. Что может быть и вообще не быстро, т.к. просто не создастся наш файл.
7. Maxim Kolkin (the1) 29.06.15 14:11
(5) Yashazz, вполне все работает. (не про производительность речь)
8. Яков Коган (Yashazz) 29.06.15 14:25
(6), (7), мы с вами на разных 1С работаем, видимо, или у вас эксели ооочень сильно продвинутые. Позволю себе процитировать СП:
ТабличныйДокумент (SpreadsheetDocument)
Записать (Write)
Синтаксис:
Записать(<ИмяФайла>, <ТипФайлаТаблицы>)
Параметры:
<ИмяФайла> (обязательный)
Тип: Строка.
Имя файла, в котором сохраняется табличный документ.
<ТипФайлаТаблицы> (необязательный)
Тип: ТипФайлаТабличногоДокумента.
Формат, в котором будет сохранен табличный документ.
Значение по умолчанию: MXL.

А теперь скажите мне, в приведённом фрагменте кода явно указан второй параметр, определяющий формат документа? Нет, не указан. А это означает, что эксель нихрена не откроет файл, сделанный таким образом. Желающие приглашаются проверить.

Вообще это напоминает старый анекдот, как преобразовать pdf в вордовский файл - взять да и поменять расширение файла)))
9. Василий Коровин (vasyak319) 29.06.15 14:30
(8) Yashazz, а вот хамить не надо. Я понимаю, обидно, когда сидишь тут, ваяешь супермегастатью про свой убергиперспособ, а тут первый же комментатор пишет шесть строк кода, которые делают то же самое. И - о, чудо! о, подарок судьбы! - допускает мелкую ошибку. В коде, набитом на коленке чисто ради примера.
Движок сайта не даёт ставить минусы чаще, чем раз в пять минут, но я никуда не тороплюсь.
Патриот; alest; CyberCerber; +3 Ответить 1
10. Роман Ложкин (webester) 29.06.15 14:46
(8) в (1) Действительно ошибка, но сам способ я использую тоже, не могу сказать про 300тыщ, это реально много, но я регулярно сохраняю таким образом в экселевккий файлик результат СКД отчета размером в 80К строк и десяток колонок, на стареньком ноуте со старым процом и 2гигами памяти. Занимает секунд 10-20 гдето, не могу сказать точнее.
11. Xer shi (Xershi) 29.06.15 15:00
(8) Yashazz, то, что там не указано расширение. Это косяк поста 1, но метод рабочий и расширение явно зададим и получим результат без тонны кода.
Естественно для вывода простого отчета это то что нужно, ваш метод как раз таки не для таких случаем.
Так что вопрос в задаче, а не быстроте/простоте!
12. Дмитрий Ко (zikonza) 29.06.15 15:04
Очень странно читать некоторые комментарии, с производительностью кто нибудь сталкивался вообще? С нагрузкой? С требованиями оптимизировать код? Автору плюс. Практически так же записываю.
13. Дмитрий Ко (zikonza) 29.06.15 15:06
(3) DoctorRoza, Не проще тогда все делать в транзакции?
14. Яков Коган (Yashazz) 29.06.15 15:09
(13) zikonza, туманно представляю, чем может помочь транзакция. 1С ведь не будет откатывать изменения в стороннем клиентском приложении при отказе транзакции.
15. Яков Коган (Yashazz) 29.06.15 15:13
(9) vasyak319, эти 6 строчек кода я юзал ещё когда только вышла 8.0, и не надо считать себя первооткрывателями. Мне не обидно, т.к. и способ этот не я придумал, и воплощение до меня делали. "Мегастатью" ваял минут 5, спасибо автору "разукрашки" кода)
Меня возмущает манера выдать общеизвестный баян в виде истины "а мужыки-то не знают", да ещё ошибку посадить, и совершенно не подумать о производительности.

Насчёт "набитом на коленке" - знаете, вот клиенту потом трудно объяснить, что ошибка-то ерундовая. Потому что деление ошибок на ерундовые и серьёзные это признак неграмотного подхода. Любая ошибка, не позволяющая решить задачу - это серьёзная ошибка. И допущенная в цитируемом коде именно такова, сорри.

Минусуйте, если вам делать нечего. Я вот пока лучше новую интересную задачу порешаю, а результаты потом выложу.
16. Дмитрий Ко (zikonza) 29.06.15 15:51
(14) Yashazz, не сохраню его так же,как и при попытке. По сути смысл тотже
17. Яков Коган (Yashazz) 29.06.15 15:56
(16) zikonza, а, это да. Это вариант.
18. Сергей Семченков (BigClock) 29.06.15 16:03
Yashazz,
Да, в (1) есть косяк.
Но в статье не было приведено никаких цифр (хотя бы ориентировочных) по сравнению Вашего способа с очевидным.
Становится непонятным: стоит ли городить огород с такой большой процедурой?
В (10) были приведены цифры. Очевидно, что для большинства применений этого простейшего способа из 6 строк более, чем достаточно.

Насчёт "набитом на коленке" - знаете, вот клиенту потом трудно объяснить, что ошибка-то ерундовая. Потому что деление ошибок на ерундовые и серьёзные это признак неграмотного подхода. Любая ошибка, не позволяющая решить задачу - это серьёзная ошибка. И допущенная в цитируемом коде именно такова, сорри.

Речь идет о подходе к решению задачи, а не о том, что именно этот код я буду внедрять у клиента. Тем более, что перед внедрением я обязательно проведу тестирование решения, в результате которого эта ошибка будет обнаружена.

Патриот; Diego_Iv; alest; klinval; Yashazz; vasyak319; +6 Ответить 1
19. Яков Коган (Yashazz) 29.06.15 17:09
(18) BigClock,
Но в статье не было приведено никаких цифр (хотя бы ориентировочных) по сравнению Вашего способа с очевидным.
Не ставил такой цели. Я русским по белому написал, что это за публикация и зачем, а некоторые с таким жаром накинулись, будто я ноу-хау анонсировал. Прямо жаль, что того автора, ссылку на публикацию которого я привёл, так не комментили, потому что вон он понты раскидывал - не мне чета)

Становится непонятным: стоит ли городить огород с такой большой процедурой?
В моих случаях, в решениях промышленного масштаба, ещё как стоит.
В (10) были приведены цифры. Очевидно, что для большинства применений этого простейшего способа из 6 строк более, чем достаточно.
Согласен. Более того, если условия задачи допускают простое решение, то именно городить сложный огород и есть ошибка. Можно сделать просто - нужно сделать просто.
20. Геннадий Николаев (genayo) 29.06.15 18:58
(4) А 300 тысяч строк в Екселе нужны чтобы что с ними делать?
21. Андрей Осин (anosin) 01.07.15 09:03
(20) genayo, Например загрузить в другую систему, которая умеет грузить только из файла эксела
22. Андрей Осин (anosin) 01.07.15 09:04
ячейки с датами как сохранятся в экселе в приведнном коде? к примеру результат выводя СКД?
23. Яков Коган (Yashazz) 01.07.15 10:16
(21) Именно.
(22) anosin, как даты сохраняются. Или это не ко мне вопрос?
24. Дмитрий Дрейцер (MadDAD) 03.07.15 11:51
Как отлавливаете незакрывшиеся процессы экселя на сервере?
25. Яков Коган (Yashazz) 06.07.15 00:22
(24) MadDAD, правду сказать - никак. Всё руки не доходят заняться этой частью задачи.
26. Виктор Назаров (androgin) 08.07.15 20:47
(8) Yashazz, Эксель отлично открывает формат MXL !
27. Яков Коган (Yashazz) 09.07.15 14:25
(26) androgin, это в вас говорит или малый опыт, или большой оптимизм. Далеко не все версии и далеко не всегда способны открыть mxl. А иногда вроде и открывают, но лучше бы отказались, таков бывает результат.
28. Ivon (Ivon) 14.03.16 23:09
Не понимаю восторгов автора от собственного творения. Метод не самый быстрый, хотя и не самый медленный. Но самый главный минус - использование Excel для выгрузки просто таблицы значений без форматирования. Копайте в сторону ADO и будет вам счастье - там можно выгружать и в Excel и в Access не имея установленного офиса.
29. Яков Коган (Yashazz) 15.03.16 10:36
(28) Ivon, во-первых, восторгов особых вроде не вижу. Покажите, где вы их нашли, а? Уж не фраза ли "публикацию особо плюсить не стоит" это восторг?
Во-вторых, спасибо, но механикой ADO я владею в достаточной мере.
В третьих, если кто-то справедливо раскритиковал вашу разработку, ползать по ИС и цепляться к его работам - ну, несколько странно выглядит.
30. Ivon (Ivon) 15.03.16 11:44
(29) Yashazz, Если вы так хорошо во всем разбираетесь, зачем постить подобный шлак. И это тоже справедливая критика
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа