В процессе интеграции 1С с внешними системами учета или при работе с файлами поставщиков часто возникает необходимость сравнить внешние данные (например, таблицу Excel) с существующими документами в базе данных 1С. Типичный сценарий — распределение затрат на оплату труда по конкретным заказам, номенклатурным группам или аналитикам, которые становятся известны только в конце расчетного периода.
В этой статье мы подробно разберем два принципиально разных подхода к решению данной задачи. Первый подход — технический: мы научимся правильно программно сопоставлять таблицы и удалять дублирующиеся строки в 1С, избегая классических ошибок начинающих разработчиков. Второй подход — методологический: мы выясним, как решить задачу стандартными средствами конфигурации «1С:Зарплата и управление персоналом 3.1» вообще без программирования и ручного изменения проводок, что гарантирует целостность и корректность учета.
---
Представим ситуацию, когда нам все же необходимо программно сопоставить данные, полученные из Excel, с табличной частью существующего документа 1С (например, ОтражениеЗарплатыВБухучете) по полям Сотрудник и Сумма, и удалить совпадающие записи.
При реализации этой задачи в коде разработчики часто совершают критическую ошибку — удаляют строки в процессе прямого обхода коллекции. Давайте разберем, почему это опасно и как этого избежать.
Если мы обходим табличную часть обычным циклом Для каждого и внутри него удаляем строку, платформа 1С динамически перестраивает индексы элементов в коллекции. Строка, которая шла следующей за удаленной, смещается на место удаленной и получает ее индекс. В результате цикл просто перескакивает через одну строку, а программа пропускает проверку нужных данных. Это может привести к тому, что часть дублирующихся строк останется в документе.
Чтобы решить эту проблему, мы можем применить два надежных программных метода.
Это классический и самый производительный способ удаления элементов из коллекций. Поскольку мы начинаем обход с последнего элемента и движемся к началу (к нулевому индексу), удаление строки в конце коллекции никак не влияет на индексы тех элементов, которые нам еще предстоит обработать.
Рассмотрим пример реализации обратного цикла:
// Предположим, что ТаблицаИзЭксель — это ТаблицаЗначений, полученная при разборе Excel-файла,
// а ДокументОбъект — это объект нашего документа Отражение зарплаты в бухучете.
ТЧДокумента = ДокументОбъект.Начисления; // Табличная часть начислений
КоличествоСтрок = ТЧДокумента.Количество();
Индекс = КоличествоСтрок - 1;
Пока Индекс >= 0 Цикл
ТекущаяСтрока = ТЧДокумента[Индекс];
// Формируем структуру отбора для поиска совпадений в таблице из Excel
ПараметрыОтбора = Новый Структура;
ПараметрыОтбора.Вставить("Сотрудник", ТекущаяСтрока.Сотрудник);
ПараметрыОтбора.Вставить("Сумма", ТекущаяСтрока.Сумма);
// Ищем совпадающие строки в таблице Excel
НайденныеСтроки = ТаблицаИзЭксель.НайтиСтроки(ПараметрыОтбора);
// Если совпадение найдено, удаляем строку из ТЧ документа
Если НайденныеСтроки.Количество() > 0 Тогда
ТЧДокумента.Удалить(ТекущаяСтрока);
КонецЕсли;
Индекс = Индекс - 1;
КонецЦикла;
Если вам неудобно использовать обратный цикл, можно применить другой подход. Сначала мы обходим табличную часть обычным циклом Для каждого, находим нужные строки и записываем ссылки на них во временный массив. На втором этапе мы отдельно обходим полученный массив и удаляем строки из табличной части документа.
Давайте посмотрим, как выглядит этот алгоритм на практике:
ТЧДокумента = ДокументОбъект.Начисления;
СтрокиДляУдаления = Новый Массив;
// Этап 1. Поиск совпадений и наполнение массива
Для каждого СтрокаТЧ Из ТЧДокумента Цикл
ПараметрыОтбора = Новый Структура;
ПараметрыОтбора.Вставить("Сотрудник", СтрокаТЧ.Сотрудник);
ПараметрыОтбора.Вставить("Сумма", СтрокаТЧ.Сумма);
НайденныеСтроки = ТаблицаИзЭксель.НайтиСтроки(ПараметрыОтбора);
Если НайденныеСтроки.Количество() > 0 Тогда
СтрокиДляУдаления.Добавить(СтрокаТЧ);
КонецЕсли;
КонецЦикла;
// Этап 2. Безопасное удаление накопленных строк
Для каждого СтрокаДляУдаления Из СтрокиДляУдаления Цикл
ТЧДокумента.Удалить(СтрокаДляУдаления);
КонецЦикла;
Если в вашем документе и в файле Excel содержатся тысячи строк, поочередный поиск методом НайтиСтроки() внутри цикла может существенно замедлить работу системы. В таких случаях правильнее перенести операцию сравнения на сторону СУБД с помощью временных таблиц и запроса.
Давайте разберем этот процесс по шагам:
ТаблицуЗначений.Сотрудник и Сумма с помощью внутреннего соединения (ВНУТРЕННЕЕ СОЕДИНЕНИЕ).---
Хотя мы научились технически решать задачу сравнения и очистки строк, прямое вмешательство в документ ОтражениеЗарплатыВБухучете несет в себе огромные риски для учета. Давайте проанализируем, почему ручные или программные корректировки этого документа крайне нежелательны:
В программе «1С:Зарплата и управление персоналом 3.1» заложен мощный механизм, созданный специально для таких случаев. Если в течение месяца сотрудники работают по разным заказам или направлениям деятельности, а доли затрат становятся известны только в конце месяца из внешнего файла (например, Excel), мы должны использовать документ «Распределение основного заработка».
Этот документ находится в разделе Зарплата -> Бухучет -> Распределение основного заработка. Он позволяет зафиксировать, в каких пропорциях (в процентах или долях) заработок конкретных сотрудников за текущий месяц должен распределиться по различным способам отражения (статьям затрат, номенклатурным группам, заказам).
Рекомендуемый и безопасный алгоритм автоматизации:
Распределение основного заработка за нужный месяц. В документе указываются сотрудники, способы отражения в бухучете (наши заказы из Excel) и доли распределения.Отражение зарплаты в бухучете и просто нажимает стандартную кнопку «Заполнить».Если вам нужно распределять не весь заработок сотрудника за месяц, а только конкретные межрасчетные начисления (например, премии, разовые начисления или командировки), обязательно обратите внимание на настройки программы.
В разделе Настройка -> Расчет зарплаты вы можете установить флаг «Регистрировать бухучет документов как распределение». При включении этой опции непосредственно в документах начислений появится удобный переключатель «Распределить по счетам, субконто», что позволит детализировать затраты еще на этапе их первичного начисления в информационной базе.
---
При работе в среде 1С всегда важно соблюдать баланс между кастомной разработкой и использованием типовых возможностей конфигурации. Если перед вами стоит задача сопоставления таблиц общего характера — смело используйте обратный цикл обхода коллекций или запросы с временными таблицами для быстрого сравнения.
Однако, если задача касается учета расходов на оплату труда в 1С:ЗУП, лучшим решением будет отказ от ручной правки проводок в пользу загрузки данных в типовой документ «Распределение основного заработка». Это сбережет ваше время, защитит базу данных от ошибок учета и обеспечит корректность сдачи регламентированной отчетности.