Как сохранить данные в Excel из макета 1С без вывода шапки и лишних строк шаблона

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При работе с табличными документами в платформе 1С:Предприятие разработчики часто сталкиваются с необходимостью выгрузки данных во внешние форматы, такие как Excel. Типичная задача — сформировать чистый список данных (например, для отправки в государственные информационные системы, такие как ЕГИССО) без лишних декоративных элементов, заголовков или пустых строк, которые присутствуют в исходном макете конфигурации.

В этой статье мы подробно разберем, почему возникает проблема дублирования или вывода лишних строк макета, почему популярные «обходные пути» (костыли) только вредят стабильности системы, и как реализовать выгрузку правильно и профессионально с точки зрения стандартов разработки 1С.

Почему возникает проблема: разбираем физику процесса в 1С

Рассмотрим классическую ошибку начинающего разработчика. Код инициализации и выгрузки в первом сообщении темы выглядел следующим образом:


&НаСервере
Процедура ВыгрузитьНаСервере()
    Об = РеквизитФормыВЗначение("Объект");
    ТабДок = Об.ПолучитьМакет("Макет");
    ОбластьПараметров = ТабДок.ПолучитьОбласть("Строки");
    
    Для Каждого Стр Из Объект.СписокЛюдей Цикл
        ОбластьПараметров.Параметры.Контрагент = Стр.Контрагент;
        ОбластьПараметров.Параметры.Сумма = Стр.Сумма;
        ТабДок.Вывести(ОбластьПараметров);
    КонецЦикла;
    
    ТабДок.Записать("C:\Выгрузка.xls", ТипФайлаТабличногоДокумента.XLS);
КонецПроцедуры

Давайте проанализируем, что происходит в памяти сервера при выполнении этого кода. Метод ПолучитьМакет("Макет") возвращает не пустой лист, а полную копию оригинального макета со всеми его статическими текстами, оформлением, рамками и шапкой, которые были нарисованы в конфигураторе. Этот объект уже содержит заполненную визуальную часть.

Когда мы вызываем метод ТабДок.Вывести(ОбластьПараметров), платформа 1С не перезаписывает существующие строки, а последовательно добавляет (копирует) новые строки в самый конец уже существующего документа-шаблона. В результате итоговый файл Excel содержит сначала оригинальный шаблон макета (включая шапку и пустые строки параметров), а затем — заполненные строки из цикла. Это приводит к появлению «мусорных» данных в начале файла.

Неудачные способы решения (почему метод с удалением области — плохая практика)

Иногда разработчики пытаются решить эту проблему «в лоб», удаляя ненужные строки из итогового документа перед сохранением. Для этого используется метод УдалитьОбласть() со смещением ячеек. Пример такого кода:


Смещать = ТипСмещенияТабличногоДокумента.ПоВертикали;
Область = ТабДок.Область("R1C1:R8C56"); // Удаляем первые 8 строк макета
ТабДок.УдалитьОбласть(Область, Смещать);

Несмотря на то, что визуально задача кажется решенной, данный подход крайне не рекомендуется к использованию на практике по следующим причинам:

  1. Появление фантомных строк в Excel. При удалении строк со смещением по вертикали платформа 1С сдвигает ячейки вверх. Однако при конвертации результирующей таблицы в формат .xls или .xlsx в конце файла часто образуются невидимые пустые строки с неопределенным форматированием. Внешние парсеры и автоматические системы импорта данных (например, портал ЕГИССО) считывают эти строки как пустые записи с ошибками заполнения и отклоняют весь файл целиком.
  2. Нарушение структуры объединенных ячеек. Если в вашей шапке макета или в строках данных присутствуют объединенные ячейки (по горизонтали или вертикали), метод УдалитьОбласть с высокой долей вероятности вызовет ошибку времени выполнения или непредсказуемо исказит ширину колонок во всем документе.
  3. Низкая масштабируемость. Если в будущем структура макета изменится (например, добавится строка описания или изменится высота шапки), жестко прописанные координаты области (R1C1:R8C56) станут неверными, и программа начнет удалять полезные данные клиентов.

Единственно правильное решение: разделение макета и приемника

Единственным архитектурно верным и надежным решением является строгое разделение макета-шаблона и результирующего документа-приемника. Рассмотрим этот алгоритм пошагово:

  1. Мы создаем абсолютно новый, чистый табличный документ, который будет выступать в роли контейнера для записи в файл.
  2. Из оригинального макета мы получаем исключительно нужную нам область строк (без шапки и заголовков).
  3. В цикле заполняем параметры этой области данными из табличной части.
  4. Выводим заполненную область в наш новый чистый табличный документ.
  5. Сохраняем новый документ в файл Excel.

Посмотрим на практический пример реализации этого алгоритма:


&НаСервере
Процедура ВыгрузитьНаСервере()
    
    // Получаем объект и макет-источник
    Об = РеквизитФормыВЗначение("Объект");
    МакетИсточник = Об.ПолучитьМакет("Макет");
    
    // Создаем абсолютно чистый результирующий документ
    ТабДокДляЗаписи = Новый ТабличныйДокумент;
    
    // Получаем область строки параметров из макета
    ОбластьСтроки = МакетИсточник.ПолучитьОбласть("Строки");
    
    // Заполняем результирующий документ в цикле
    Для Каждого Стр Из Объект.СписокЛюдей Цикл
        
        // Заполняем параметры области
        ОбластьСтроки.Параметры.Контрагент = Стр.Контрагент;
        ОбластьСтроки.Параметры.Сумма = Стр.Сумма;
        
        // Выводим заполненную область в чистый документ
        ТабДокДляЗаписи.Вывести(ОбластьСтроки);
        
    КонецЦикла;
    
    // Безопасная запись на диск с обработкой исключений
    ПутьКФайлу = "C:\" + Объект.Организация + "_" + Формат(Объект.Дата, "ДЛФ=ДД") + ".xlsx";
    
    Попытка
        ТабДокДляЗаписи.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.XLSX);
        Сообщить("Выгрузка успешно завершена! Файл сохранен: " + ПутьКФайлу);
    Исключение
        ЗаписьЖурналаРегистрации("Выгрузка в Excel", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
        ВызватьИсключение "Не удалось записать файл Excel. Обратитесь к администратору. Причина: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
    КонецПопытки;
    
КонецПроцедуры

В данном коде мы полностью исключили появление старых статических надписей макета в готовом файле. Итоговый документ будет содержать исключительно те строки, которые мы вывели программно в цикле обработки.

Повышение надежности и современные стандарты выгрузки

Чтобы ваша выгрузка работала быстро, надежно и не вызывала сбоев на сервере, рекомендуем придерживаться нескольких профессиональных правил разработки в среде 1С:Предприятие 8.3.

1. Переход с устаревшего формата XLS на современный XLSX

В старых примерах кода часто можно встретить использование формата ТипФайлаТабличногоДокумента.XLS. Это формат Excel 97-2003, который имеет ряд критических ограничений:

Использование ТипФайлаТабличногоДокумента.XLSX снимает ограничение по строкам (до 1 048 576 строк на лист), существенно ускоряет процесс генерации файла на стороне платформы 1С и уменьшает итоговый вес файла за счет современного сжатия zip-контейнера.

2. Альтернативный способ прямой выгрузки (без использования макетов)

Если перед вами стоит задача выгрузить абсолютно «чистые» сырые данные (без рамок, специфических шрифтов и раскраски ячеек), то создавать макет в конфигураторе вообще не имеет смысла. Это избыточная работа, которая к тому же уязвима к человеческому фактору (любой другой разработчик может случайно отредактировать макет и сломать выгрузку).

Заполнить ячейки табличного документа можно напрямую по координатам. Рассмотрим пример такой выгрузки:


ТабДок = Новый ТабличныйДокумент;
НомерСтроки = 1;

Для Каждого Стр Из Объект.СписокЛюдей Цикл
    // Заполняем первую колонку (Контрагент)
    ТабДок.Область(НомерСтроки, 1).Текст = Строка(Стр.Контрагент);
    
    // Заполняем вторую колонку (Сумма)
    ТабДок.Область(НомерСтроки, 2).Текст = Строка(Стр.Сумма);
    
    НомерСтроки = НомерСтроки + 1;
КонецЦикла;

ТабДок.Записать("C:\ЧистаяВыгрузка.xlsx", ТипФайлаТабличногоДокумента.XLSX);

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

3. Использование встроенного метода ВывестиСписок()

Если ваши данные уже выведены на форму в виде таблицы или находятся в объекте типа ТаблицаЗначений, платформа 1С предоставляет мощный штатный механизм быстрого построения отчетов — метод ВывестиСписок(). Он позволяет выгрузить всю таблицу в табличный документ буквально одной строкой кода:


ТабДок = Новый ТабличныйДокумент;
// Выводим только элементы строк без оформления дерева и иерархии
ТабДок.ВывестиСписок(Объект.СписокЛюдей.Выгрузить());
ТабДок.Записать("C:\БыстраяВыгрузка.xlsx", ТипФайлаТабличногоДокумента.XLSX);

4. Очистка серверной памяти при работе с большими объемами данных

При частых выгрузках больших массивов данных (десятки тысяч строк) сервер 1С (процесс rphost) может испытывать повышенную нагрузку на оперативную память. Табличные документы являются «тяжелыми» объектами. Чтобы избежать утечек памяти, перед уничтожением локальных переменных в коде рекомендуется явно очищать табличный документ методом ТабДок.Очистить(). Это помогает сборщику мусора платформы 1С оперативно освобождать ресурсы сервера.

← На главную