Часто при работе с расчетными документами в решениях «1С:Зарплата и управление персоналом» или «1С:ERP Управление предприятием» пользователи и разработчики сталкиваются со следующей проблемой. При создании корректирующего документа «Табель» (когда в нем заполнен реквизит ИсправленныйДокумент) кнопка «Удалить» на форме становится недоступной, а нажатие клавиши Del на клавиатуре не дает никаких результатов. Более того, при попытке отладить этот процесс выясняется, что программа даже не заходит в обработчик события ПередУдалением табличной части.
В этой статье мы подробно разберем, почему так происходит, выясним технические и методологические причины этого ограничения, а также рассмотрим практические способы обхода данного запрета — как для обычных пользователей, так и для программистов 1С.
Для того чтобы понять, почему платформа игнорирует попытки удаления строк, проанализируем свойства управляемой формы документа. В управляемом интерфейсе 1С:Предприятие 8 у элемента формы типа «Таблица», который связан с табличной частью документа, существует стандартное свойство «Изменять состав строк» (в коде оно доступно как ИзменятьСоставСтрок или ChangeRowSet).
Рассмотрим, как это свойство влияет на поведение интерфейса:
Истина, пользователь может свободно добавлять, копировать и удалять строки табличной части.Ложь, платформа полностью блокирует любые интерактивные действия с составом строк на уровне самого интерфейса.В типовом коде формы документа «Табель» при открытии выполняется проверка заполненности реквизита исправления. Если это корректирующий документ, срабатывает программная инструкция:
Элементы.ДанныеОВремени.ИзменятьСоставСтрок = Ложь;
Поскольку действие заблокировано платформой на уровне отображения формы, кнопки добавления и удаления становятся неактивными. По этой же причине событие ПередУдалением на клиенте физически не вызывается — платформа пресекает действие пользователя еще до того, как управление передается обработчикам событий.
Прежде чем обходить данный запрет, давайте разберем, почему разработчики фирмы 1С внедрили такое поведение. Это не ошибка системы, а жестко заложенная методология учета рабочего времени.
При создании корректирующего табеля (по ссылке «Исправить» в закрытом периоде) система автоматически копирует весь состав сотрудников из исходного документа. В корректирующем документе должны оставаться абсолютно все те же физические лица, что и в первичном. Это нужно для корректного сторнирования начислений:
Однако на практике возникают ситуации, когда документ-исправление был создан ошибочно или состав сотрудников в нем действительно требует ручной корректировки. Рассмотрим, как решить эту задачу.
Если вам нужно разово отредактировать состав строк без изменения программного кода и снятия конфигурации с поддержки, можно использовать следующую последовательность действий:
ИсправленныйДокумент.ИсправленныйДокумент на форме табеля. Если это поле заблокировано для редактирования на форме, воспользуйтесь стандартной обработкой «Групповое изменение реквизитов» (ее можно открыть через меню «Администрирование» — «Обслуживание» — «Корректировка данных»).ИсправленныйДокумент в пустое значение для вашего табеля.ИсправленныйДокумент ссылкой на первичный табель (вручную или через групповое изменение реквизитов) и проведите документ.Если ваша база данных находится на поддержке, но вам регулярно требуется корректировать состав строк в исправлениях, лучшим решением будет использование механизма расширений. Мы можем программно вернуть доступность элементам управления формы в момент ее инициализации.
Разберем по шагам, как это сделать:
ФормаДокумента).Напишем следующий код в модуле формы расширения:
&После("ПриЧтенииНаСервере")
Процедура Ист_ПриЧтенииНаСервере(ТекущийОбъект)
// Снимаем блокировку изменения состава строк, установленную типовым кодом
Если ЗначениеЗаполнено(Объект.ИсправленныйДокумент) Тогда
Элементы.ДанныеОВремени.ИзменятьСоставСтрок = Истина;
КонецЕсли;
КонецПроцедуры
Этот простой код гарантирует, что даже при заполненном реквизите исправления табличная часть формы останется доступной для редактирования, а кнопка удаления строк станет активной. При этом отладчик начнет корректно заходить в процедуру ДанныеОВремениПередУдалением.
Свойство ИзменятьСоставСтрок накладывает ограничения исключительно на интерактивные действия пользователя непосредственно в интерфейсе формы. Оно никак не мешает программному изменению табличных частей на уровне встроенного языка 1С.
Мы можем написать внешнюю обработку, которая будет программно находить и удалять ненужные строки из табеля, обходя любые ограничения формы. Посмотрим на пример серверного кода для удаления строки по определенному сотруднику:
&НаСервере
Процедура УдалитьСтрокуИзТабеляНаСервере(СсылкаНаТабель, СсылкаНаСотрудника)
// Получаем объект документа для редактирования
ДокОбъект = СсылкаНаТабель.ПолучитьОбъект();
// Создаем массив для сбора строк, подлежащих удалению
СтрокиДляУдаления = Новый Массив;
// Обходим табличную часть документа
Для Каждого СтрокаТЧ Из ДокОбъект.ДанныеОВремени Цикл
Если СтрокаТЧ.Сотрудник = СсылкаНаСотрудника Тогда
СтрокиДляУдаления.Добавить(СтрокаТЧ);
КонецЕсли;
КонецЦикла;
// Удаляем найденные строки из коллекции
Для Каждого ТекущаяСтрока Из СтрокиДляУдаления Цикл
ДокОбъект.ДанныеОВремени.Удалить(ТекущаяСтрока);
КонецЦикла;
// Записываем документ напрямую в базу данных, минуя интерфейсные ограничения
Попытка
ДокОбъект.Записать(РежимЗаписиДокумента.Запись);
Сообщить("Строки успешно удалены, документ перезаписан.");
Исключение
ВызватьИсключение "Не удалось записать документ: " + ОписаниеОшибки();
КонецПопытки;
КонецПроцедуры
Этот способ является максимально безопасным, так как не требует изменения типовой конфигурации и позволяет точечно решать проблему с ошибочно заполненными строками в корректирующих табелях.