Работа с табличными частями в 1С:Предприятие — одна из самых частых задач, с которыми сталкиваются разработчики и пользователи системы. Независимо от того, занимаетесь ли вы бухгалтерией, складским учетом или торговлей, рано или поздно потребуется автоматизировать заполнение строк в документах, справочниках или отчетах. Создание специализированной обработки для этой цели экономит время, снижает риск ошибок и упрощает работу с большими объемами данных.
В этой статье мы разберем процесс создания обработки заполнения табличной части с нуля: от подготовки конфигурации до написания кода и тестирования. Особое внимание уделим типичным сценариям — заполнению по шаблону, копированию данных из других документов, а также динамическому формированию строк на основе условий. Материал актуален для платформы 1С:Предприятие 8.3 (включая последние релизы) и частично применим к версии 8.2.
Если вы никогда не писали обработки в 1С, не переживайте: мы начнем с базовых понятий и постепенно перейдем к более сложным примерам. Опытные разработчики найдут здесь полезные сниппеты кода и рекомендации по оптимизации.
1. Подготовка: что нужно знать перед созданием обработки
Прежде чем приступить к написанию кода, важно понять структуру табличной части в 1С. Табличная часть — это коллекция строк, каждая из которых содержит набор реквизитов (колонок). Она может принадлежать документу, справочнику или регистру сведений. Например, в документе РеализацияТоваровУслуг табличная часть Товары хранит информацию о продаваемых позициях: номенклатуру, количество, цену и сумму.
Обработка для заполнения табличной части может решать разные задачи:
- 📋 Копирование данных из одного документа в другой (например, перенос строк из заказа покупателя в реализацию).
- 🔄 Заполнение по шаблону (например, добавление стандартного набора услуг в акт выполненных работ).
- 📊 Динамическое формирование строк на основе условий (например, автоматическое добавление скидок при достижении определенной суммы).
- 🔗 Интеграция с внешними источниками (загрузка данных из Excel, API или других систем).
Для работы потребуется:
- 🖥️ 1С:Предприятие 8.3 (режим
Конфигуратор). - 📂 Права на редактирование конфигурации (или внешняя обработка, если прав нет).
- 📝 Понимание основ встроенного языка 1С (циклы, условия, работа с объектами).
⚠️ Внимание: Если вы работаете с типовой конфигурацией (например, 1С:Бухгалтерия 3.0 или 1С:УТ 11), создание обработки напрямую в конфигурации может нарушить поддержку. В таких случаях лучше использовать внешние обработки или расширения.
2. Способы создания обработки: встроенная vs внешняя
В 1С:Предприятие есть два основных подхода к созданию обработок для заполнения табличных частей: встроенные (внутри конфигурации) и внешние (отдельные файлы с расширением .epf или .erf). Выбор зависит от ваших прав и задач.
Встроенная обработка создается непосредственно в конфигураторе и становится частью базы данных. Она подходит, если:
- 🔧 У вас есть права на изменение конфигурации.
- 📌 Обработка нужна постоянно и только для этой базы.
- 🔄 Требуется тесная интеграция с другими объектами конфигурации.
Внешняя обработка — это отдельный файл, который можно подключить к любой базе. Ее преимущества:
- 📁 Не требует прав на изменение конфигурации.
- 🔄 Можно переносить между базами.
- 🛡️ Безопаснее для типового решения (не ломает поддержку).
| Критерий | Встроенная обработка | Внешняя обработка |
|---|---|---|
| Требуются права на конфигуратор | Да | Нет |
| Возможность переноса | Ограничена (только через выгрузку/загрузку) | Да (просто копируете файл) |
| Поддержка типового решения | Может нарушить | Не нарушает |
| Скорость работы | Выше (встроенные механизмы) | Немного ниже (зависит от реализации) |
Для большинства задач по заполнению табличных частей внешняя обработка — оптимальный выбор. Она гибкая, безопасная и не привязана к конкретной базе. В этой статье мы рассмотрим оба варианта, но основной упор сделаем на внешнюю обработку, так как она универсальна.
Если вы только учитесь программировать в 1С, начинайте с внешних обработок. Они позволяют экспериментировать без риска повредить рабочую базу.
3. Пошаговая инструкция: создаем обработку с нуля
Рассмотрим процесс создания внешней обработки для заполнения табличной части документа ЗаказПокупателя на примере добавления строк из справочника Номенклатура. Этот сценарий актуален для торговли и склада, где часто требуется быстро формировать документы на основе шаблонов.
Шаг 1: Создание новой обработки
1. Откройте 1С:Предприятие в режиме Конфигуратор.
2. Перейдите в меню Файл → Новый и выберите Внешняя обработка.
3. В открывшемся окне укажите имя обработки, например, ЗаполнениеТабличнойЧастиЗаказа.
4. Сохраните файл с расширением .epf (например, ЗаполнениеЗаказа.epf).
Шаг 2: Настройка формы обработки
1. В дереве объектов обработки найдите Формы → ОсновнаяФорма и откройте ее.
2. Добавьте на форму элементы управления:
- 📌
Поле вводадля выбора документа-шаблона (типДокументСсылка.ЗаказПокупателя). - 📌
Кнопкас названиемЗаполнить. - 📌
Табличное поледля отображения результата (реквизитТаблицаТоваров, типТаблицаЗначений).
Шаг 3: Пишем код для заполнения
Основная логика будет в процедуре, связанной с кнопкой Заполнить. Ниже приведен пример кода, который копирует строки из выбранного заказа в новую таблицу:
Процедура Заполнить(Команда)
// Получаем ссылку на документ-шаблон
ДокументШаблон = ЭлементыФормы.Шаблон.Значение;
// Проверяем, что шаблон выбран
Если НЕ ЗначениеЗаполнено(ДокументШаблон) Тогда
Предупреждение("Не выбран документ-шаблон!", 60);
Возврат;
КонецЕсли;
// Создаем новую таблицу значений для результата
ТаблицаРезультата = Новый ТаблицаЗначений;
ТаблицаРезультата.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
ТаблицаРезультата.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));
ТаблицаРезультата.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число"));
ТаблицаРезультата.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число"));
// Копируем строки из шаблона
Для Каждого Строка Из ДокументШаблон.Товары Цикл
НоваяСтрока = ТаблицаРезультата.Добавить();
НоваяСтрока.Номенклатура = Строка.Номенклатура;
НоваяСтрока.Количество = Строка.Количество;
НоваяСтрока.Цена = Строка.Цена;
НоваяСтрока.Сумма = Строка.Сумма;
КонецЦикла;
// Отображаем результат в таблице на форме
ЭлементыФормы.ТаблицаТоваров.Значение = ТаблицаРезультата;
// Опционально: предлагаем сохранить результат в новый документ
Если Вопрос("Сохранить результат в новый заказ?", Вопрос.ДаНет) = КодВопроса.Да Тогда
НовыйДокумент = Документы.ЗаказПокупателя.СоздатьДокумент();
НовыйДокумент.Дата = ТекущаяДата();
НовыйДокумент.Контрагент = ДокументШаблон.Контрагент;
// Переносим строки в табличную часть нового документа
Для Каждого СтрокаРезультата Из ТаблицаРезультата Цикл
НоваяСтрокаДок = НовыйДокумент.Товары.Добавить();
НоваяСтрокаДок.Номенклатура = СтрокаРезультата.Номенклатура;
НоваяСтрокаДок.Количество = СтрокаРезультата.Количество;
НоваяСтрокаДок.Цена = СтрокаРезультата.Цена;
НоваяСтрокаДок.Сумма = СтрокаРезультата.Сумма;
КонецЦикла;
НовыйДокумент.Записать();
ОткрытьФорму("Документ.ЗаказПокупателя.ФормаОбъекта", НовыйДокумент.Ссылка);
КонецЕсли;
КонецПроцедуры
Шаг 4: Тестирование и отладка
1. Сохраните обработку и откройте ее в режиме 1С:Предприятие.
2. Выберите документ-шаблон из списка заказов.
3. Нажмите Заполнить и проверьте, что строки скопировались корректно.
4. При необходимости отладьте код, используя Отладчик 1С (клавиша F5 в конфигураторе).
Обработка сохранена в формате .epf|Код отформатирован и читаем|Все переменные объявлены|Тестирование проведено на реальных данных|Обработка работает без ошибок-->
4. Расширенные сценарии: динамическое заполнение и условия
Базовое копирование строк — только начало. На практике часто требуется динамическое заполнение табличной части на основе условий. Рассмотрим несколько распространенных сценариев:
Сценарий 1: Заполнение по шаблону с фильтрацией
Допустим, вам нужно добавлять в заказ только те товары из шаблона, которые есть на складе. Для этого модифицируем код:
// Добавляем проверку остатков перед копированием
Для Каждого Строка Из ДокументШаблон.Товары Цикл
Остатки = ПолучитьОстаткиНаСкладе(Строка.Номенклатура, Строка.Склад);
Если Остатки >= Строка.Количество Тогда
НоваяСтрока = ТаблицаРезультата.Добавить();
НоваяСтрока.Номенклатура = Строка.Номенклатура;
НоваяСтрока.Количество = Строка.Количество;
// ... остальной код
КонецЕсли;
КонецЦикла;
Функция ПолучитьОстаткиНаСкладе() должна быть реализована отдельно. Пример:
Функция ПолучитьОстаткиНаСкладе(Номенклатура, Склад)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РегистрыНакопления.ОстаткиТоваровОрганизаций.КоличествоОстаток КАК Остаток
|ИЗ
| РегистрНакопления.ОстаткиТоваровОрганизаций КАК РегистрыНакопления.ОстаткиТоваровОрганизаций
|ГДЕ
| РегистрыНакопления.ОстаткиТоваровОрганизаций.Номенклатура = &Номенклатура
| И РегистрыНакопления.ОстаткиТоваровОрганизаций.Склад = &Склад";
Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
Запрос.УстановитьПараметр("Склад", Склад);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.Остаток;
Иначе
Возврат 0;
КонецЕсли;
КонецФункции
Сценарий 2: Автоматическое добавление скидок
Если сумма заказа превышает определенное значение, можно автоматически добавлять строку со скидкой. Например:
// После заполнения таблицы проверяем сумму
СуммаЗаказа = 0;
Для Каждого Строка Из ТаблицаРезультата Цикл
СуммаЗаказа = СуммаЗаказа + Строка.Сумма;
КонецЦикла;
Если СуммаЗаказа > 10000 Тогда
СтрокаСкидки = ТаблицаРезультата.Добавить();
СтрокаСкидки.Номенклатура = Справочники.Номенклатура.НайтиПоНаименованию("Скидка 5%");
СтрокаСкидки.Количество = 1;
СтрокаСкидки.Цена = - (СуммаЗаказа * 0.05);
СтрокаСкидки.Сумма = СтрокаСкидки.Цена;
КонецЕсли;
Сценарий 3: Заполнение из Excel
Для загрузки данных из Excel используйте объект ЧтениеXML или библиотеку OneScript.Excel (если установлена). Пример упрощенного кода:
Процедура ЗагрузитьИзExcel(ПутьКФайлу)
ТаблицаExcel = Новый ТаблицаЗначений;
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ПутьКФайлу);
// Парсим XML (упрощенно)
// ...
// Заполняем ТаблицаРезультата на основе данных из Excel
КонецПроцедуры
⚠️ Внимание: При работе с внешними файлами (Excel, CSV) всегда проверяйте формат данных. Несоответствие типов (например, текст вместо числа) может вызвать ошибки при загрузке. Используйте ТипЗнч() для приведения типов.
Как обработать ошибки при загрузке из Excel?
При загрузке данных из Excel рекомендуется добавлять обработку исключений:
Попытка
// Код загрузки
Исключение
Сообщить("Ошибка загрузки: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
Также полезно вести лог ошибок в отдельной таблице, чтобы пользователь мог увидеть, какие строки не загрузились и почему.
5. Оптимизация и типичные ошибки
Даже правильно написанная обработка может работать медленно или выдавать ошибки. Рассмотрим распространенные проблемы и способы их решения:
Проблема 1: Медленное выполнение при большом количестве строк
Если табличная часть содержит тысячи строк, цикл Для Каждого может тормозить. Решения:
- 🚀 Используйте
Запросвместо циклов для массовых операций. - 📈 Разбивайте обработку на пакеты (например, по 100 строк за итерацию).
- 🔄 Отключайте контроль транзакций на время заполнения:
НачатьТранзакцию(); ... ЗафиксироватьТранзакцию();.
Проблема 2: Ошибки привязки типов
Частая ошибка — попытка присвоить значение несовместимого типа. Например:
НоваяСтрока.Количество = "10"; // Ошибка: строка вместо числа
Исправление:
НоваяСтрока.Количество = Число("10");
Проблема 3: Некорректная работа с ссылками
Если вы копируете ссылки на объекты (например, номенклатуру), убедитесь, что они существуют в текущей базе. Пример проверки:
Если НЕ Строка.Номенклатура.Пустая() Тогда
НоваяСтрока.Номенклатура = Строка.Номенклатура;
КонецЕсли;
Проблема 4: Забытые транзакции
Если вы начинаете транзакцию (НачатьТранзакцию()), но забываете ее завершить (ЗафиксироватьТранзакцию() или ОтменитьТранзакцию()), это может заблокировать базу для других пользователей. Всегда обрабатывайте исключения:
Попытка
НачатьТранзакцию();
// Код заполнения
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
| Ошибка | Причина | Решение |
|---|---|---|
| Ошибка приведения типа | Попытка присвоить строковое значение числовому реквизиту | Использовать Число(), Дата() и другие функции приведения |
| Зависание при большом объеме данных | Долгие циклы без оптимизации | Использовать пакетную обработку или запросы |
| Ошибка "Объект не найден" | Ссылка на несуществующий объект (например, удаленную номенклатуру) | Добавить проверку Пустая() перед присвоением |
| Блокировка базы | Незавершенная транзакция | Всегда завершать транзакции в блоке Попытка-Исключение |
Самая частая ошибка при работе с табличными частями — игнорирование типов данных. Всегда проверяйте, что значения соответствуют типам реквизитов (число, строка, ссылка и т.д.).
6. Примеры готовых обработок для разных задач
Ниже приведены фрагменты кода для типовых задач. Вы можете адаптировать их под свои нужды.
Пример 1: Заполнение табличной части из справочника
Добавляем в документ все позиции из группы номенклатуры Канцтовары:
Процедура ЗаполнитьИзГруппы(Группа)
ТаблицаРезультата = Новый ТаблицаЗначений;
// Настройка колонок (аналогично предыдущим примерам)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Номенклатура
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Родитель = &Группа
| И НЕ Номенклатура.ПометкаУдаления";
Запрос.УстановитьПараметр("Группа", Группа);
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
НоваяСтрока = ТаблицаРезультата.Добавить();
НоваяСтрока.Номенклатура = Выборка.Номенклатура;
НоваяСтрока.Количество = 1;
НоваяСтрока.Цена = ПолучитьЦену(Выборка.Номенклатура); // Функция получения цены
КонецЦикла;
ЭлементыФормы.ТаблицаТоваров.Значение = ТаблицаРезультата;
КонецПроцедуры
Пример 2: Копирование строк между документами
Копируем строки из документа ЗаказПоставщику в ПоступлениеТоваров:
Процедура КопироватьСтроки(Источник, Приемник)
Приемник.Товары.Очистить();
Для Каждого Строка Из Источник.Товары Цикл
НоваяСтрока = Приемник.Товары.Добавить();
НоваяСтрока.Номенклатура = Строка.Номенклатура;
НоваяСтрока.Количество = Строка.Количество;
НоваяСтрока.Цена = Строка.Цена;
КонецЦикла;
КонецПроцедуры
Пример 3: Заполнение на основе данных регистра
Добавляем в заказ товары, которые были проданы в прошлом месяце (для повторных заказов):
Процедура ЗаполнитьПоПродажам(Контрагент)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| Продажи.Номенклатура КАК Номенклатура,
| СУММА(Продажи.Количество) КАК Количество
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК Продажи
|ГДЕ
| Продажи.Ссылка.Контрагент = &Контрагент
| И Продажи.Ссылка.Дата МЕЖДУ &ДатаНачала И &ДатаКонца
|СГРУППИРОВАТЬ ПО
| Продажи.Номенклатура";
Запрос.УстановитьПараметр("Контрагент", Контрагент);
Запрос.УстановитьПараметр("ДатаНачала", НачалоМесяца(ТекущаяДата()) - 30);
Запрос.УстановитьПараметр("ДатаКонца", КонецМесяца(ТекущаяДата()) - 30);
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
НоваяСтрока = ТаблицаРезультата.Добавить();
НоваяСтрока.Номенклатура = Выборка.Номенклатура;
НоваяСтрока.Количество = Выборка.Количество;
КонецЦикла;
КонецПроцедуры
⚠️ Внимание: При работе с регистрами накопления (например, Продажи) учитывайте, что данные в них могут изменяться ретроактивно. Для точности используйте виртуальные таблицы с указанием периода.
7. Интеграция обработки в интерфейс 1С
Готовая обработка бесполезна, если пользователи не могут ее легко запустить. Рассмотрим способы интеграции:
Способ 1: Подключение как внешняя обработка
1. Сохраните файл обработки (.epf) в доступную папку.
2. В режиме 1С:Предприятие перейдите в Файл → Открыть и выберите ваш файл.
3. Обработка откроется в отдельном окне. Пользователи смогут запускать ее вручную.
Способ 2: Добавление в панель действий документа
Если у вас есть права на изменение конфигурации, можно добавить кнопку вызова обработки прямо в форму документа:
1. Откройте форму документа (например, ЗаказПокупателя) в конфигураторе.
2. Добавьте новую команду в Команды формы (например, ЗаполнитьИзШаблона).
3. В модуле формы напишите обработчик:
Процедура ЗаполнитьИзШаблона(Команда)
ПутьКОбработке = "C:\Обработки\ЗаполнениеЗаказа.epf";
Если НЕ ФайлСуществует(ПутьКОбработке) Тогда
Предупреждение("Файл обработки не найден!");
Возврат;
КонецЕсли;
Обработка = ВнешниеОбработки.Создать(ПутьКОбработке);
Обработка.Открыть();
КонецПроцедуры
Способ 3: Автоматический запуск при создании документа
Можно настроить обработку так, чтобы она запускалась автоматически при создании нового документа. Для этого используйте событие ПриСозданииНаСервере:
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если НЕ Заполнено(ЭтотОбъект.Контрагент) Тогда
// Запускаем обработку заполнения по умолчанию
Обработка = ВнешниеОбработки.Создать("C:\Обработки\ЗаполнениеПоУмолчанию.epf");
Обработка.ЗаполнитьПоКонтрагенту(ЭтотОбъект.Контрагент, ЭтотОбъект.Товары);
КонецЕсли;
КонецПроцедуры
Способ 4: Использование расширений
Для типовой конфигурации безопаснее использовать расширения:
1. Создайте новое расширение в конфигураторе.
2. Добавьте в него свою обработку и формы.
3. Подключите расширение к базе — оно будет работать поверх типового решения без его изменения.
Если обработка используется часто, добавьте ее в панель быстрого доступа. Для этого в режиме 1С:Предприятие перейдите в Сервис → Настройка панели действий и настройте ярлык.