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