К статье
Практический материал

Разработка и Конфигурация · 12 мин

Как изменить значение в таблице значений 1С

Как изменить значение в таблице значений 1С: прямое присвоение, Найти, НайтиСтроки, перебор строк, обработка результата запроса. Примеры кода и типичные ошибки.

Таблица значений — один из самых используемых объектов встроенного языка 1С: в неё выгружаются результаты запросов, в ней собираются данные для отчётов, обменов и печатных форм. Задача изменить значение в конкретной ячейке возникает постоянно: пересчитать сумму, подставить ставку НДС, заменить пустую ссылку, скорректировать количество перед проведением документа.

Главное, что нужно понимать: таблица значений не хранит «ячейки» как самостоятельные объекты. Изменение происходит через строку таблицы — сначала вы получаете нужную строку (объект типа «СтрокаТаблицыЗначений»), затем присваиваете новое значение её свойству, имя которого совпадает с именем колонки. Никаких специальных методов «УстановитьЗначение» у таблицы нет.

Дальше разобраны все рабочие способы: прямое обращение по индексу, поиск через Найти() и НайтиСтроки(), массовое изменение в цикле, особенности таблиц, полученных из запроса, и типичные ошибки, из-за которых изменения «не сохраняются».

Как устроено изменение данных в таблице значений

Таблица значений (объект ТаблицаЗначений) состоит из коллекции строк и коллекции колонок. Колонки описывают структуру — имя, тип, заголовок. Строки содержат сами данные. Когда вы пишете Строка.Сумма = 1000, вы меняете значение в конкретной строке по имени колонки.

Доступ к ячейке возможен двумя синтаксическими формами: через точку (Строка.Сумма) и через квадратные скобки со строковым именем (Строка["Сумма"]). Второй вариант незаменим, когда имя колонки хранится в переменной или содержит символы, недопустимые для идентификатора.

Важно помнить о типизации. Если колонка объявлена с типом «Число», попытка присвоить строку приведёт либо к ошибке, либо к неявному преобразованию — в зависимости от того, задан ли составной тип. Поэтому перед массовыми изменениями полезно проверить описание типов колонки, особенно если таблица создана вручную через Новый ТаблицаЗначений.

Изменение значения по индексу строки

Самый простой случай — вы точно знаете позицию нужной строки. Индексация строк начинается с нуля, поэтому первая строка имеет индекс 0, а последняя — Таблица.Количество() - 1.

Таблица = Новый ТаблицаЗначений;

Таблица.Колонки.Добавить("Номенклатура");

Таблица.Колонки.Добавить("Цена");

Строка = Таблица.Добавить();

Строка.Номенклатура = "Товар А";

Строка.Цена = 100;

// Изменим цену в первой строке

Таблица[0].Цена = 150;

// Альтернативный вариант через переменную

ПерваяСтрока = Таблица[0];

ПерваяСтрока.Цена = 150;

Обращение по индексу быстрое, но опасное: если строк в таблице нет или индекс выходит за границы, произойдёт ошибка выполнения. Перед обращением проверяйте Таблица.Количество() > 0 либо работайте внутри цикла, где границы гарантированы.

Обратите внимание: переменная ПерваяСтрока — это не копия данных, а ссылка на строку таблицы. Изменения через неё сразу отражаются в самой таблице, дополнительно «записывать строку обратно» не нужно.

Изменение значения через Найти и НайтиСтроки

На практике индекс строки обычно неизвестен — строку нужно сначала найти по значению в одной из колонок. Для этого служат методы Найти() и НайтиСтроки().

Метод Найти — первая подходящая строка

Метод Найти(Значение, ИмяКолонки) возвращает первую строку, где в указанной колонке находится искомое значение. Если совпадений нет — возвращает Неопределено. Пропуск проверки на Неопределено — самая частая причина ошибки «Поле объекта не обнаружено».

Строка = Таблица.Найти(ИскомыйТовар, "Номенклатура");

Если Строка <> Неопределено Тогда

Строка.Цена = НоваяЦена;

Иначе

Сообщить("Строка не найдена — изменение не выполнено");

КонецЕсли;

Метод НайтиСтроки — все подходящие строки

Если критерию соответствует несколько строк, используйте НайтиСтроки(Отбор), где отбор — структура: ключ — имя колонки, значение — искомое значение. Метод возвращает массив строк, и изменить можно каждую из них.

Отбор = Новый Структура;

Отбор.Вставить("Склад", ОсновнойСклад);

Отбор.Вставить("Отгружено", Ложь);

НайденныеСтроки = Таблица.НайтиСтроки(Отбор);

Для Каждого Строка Из НайденныеСтроки Цикл

Строка.Отгружено = Истина;

Строка.ДатаОтгрузки = ТекущаяДатаСеанса();

КонецЦикла;

Порядок изменения значения через поиск
  1. 1
    Сформируйте критерий поиска: значение и имя колонки или структуру отбора
  2. 2
    Вызовите Найти() для одной строки или НайтиСтроки() для нескольких
  3. 3
    Проверьте результат: Найти() не вернул Неопределено, НайтиСтроки() вернул непустой массив
  4. 4
    Присвойте новое значение свойству строки — Строка.ИмяКолонки = Значение
  5. 5
    Проверьте результат, повторно прочитав значение или выведя таблицу

Массовое изменение значений в цикле

Когда изменить нужно все строки или строки по вычисляемому условию, используется обычный перебор. Внутри цикла доступны любые проверки и расчёты — это самый гибкий способ.

Для Каждого Строка Из Таблица Цикл

Если Строка.Количество = 0 Тогда

Строка.Сумма = 0;

Иначе

Строка.Сумма = Строка.Количество * Строка.Цена;

КонецЕсли;

КонецЦикла;

Два практических замечания. Во-первых, не удаляйте и не добавляйте строки внутри цикла Для Каждого по той же таблице — это нарушает обход коллекции. Если нужно удалять, соберите строки в отдельный массив и удаляйте после цикла. Во-вторых, для больших таблиц перебор с Найти() внутри цикла работает медленно: лучше заранее построить соответствие или индекс.

Для ускорения поиска на больших объёмах добавьте индекс по колонке: Таблица.Индексы.Добавить("Номенклатура"). После этого Найти() и НайтиСтроки() по этой колонке выполняются заметно быстрее.

Если в цикле по таблице на каждой итерации вызывается Найти() или НайтиСтроки() по другой таблице, добавьте индекс по колонке поиска — на таблицах в десятки тысяч строк разница по времени может быть кратной.
ПЗ
Практическое замечание

Особенности изменения таблицы, полученной из запроса

Часто таблица значений появляется как результат Запрос.Выполнить().Выгрузить(). Такая таблица полностью редактируется описанными способами — это обычный объект в памяти, не связанный с базой данных. Изменения в ней никак не затрагивают данные информационной базы, пока вы явно не запишете их в документы или регистры.

Типичный сценарий — выгрузить результат запроса, дозаполнить вычисляемые колонки и передать таблицу дальше, например в СКД или в табличную часть документа:

РезультатЗапроса = Запрос.Выполнить();

Таблица = РезультатЗапроса.Выгрузить();

Для Каждого Строка Из Таблица Цикл

Строка.СуммаСНДС = Строка.Сумма + Строка.СуммаНДС;

КонецЦикла;

Если нужна колонка, которой нет в результате запроса, её добавляют после выгрузки: Таблица.Колонки.Добавить("Признак", Новый ОписаниеТипов("Булево")). Учтите, что новая колонка во всех строках будет содержать значение по умолчанию (для Булево — Ложь), и его нужно заполнить отдельно.

Изменение значений в таблице значений на форме

Отдельный случай — реквизит формы типа «ТаблицаЗначений». На клиенте (в тонком или веб-клиенте) объект ТаблицаЗначений недоступен напрямую: при передаче на форму он преобразуется в ДанныеФормыКоллекция. У этой коллекции другой набор методов — НайтиСтроки() работает, а Найти() отсутствует.

Изменение значения в строке данных формы выглядит так же — через присвоение свойству строки:

Отбор = Новый Структура("Код", ИскомыйКод);

Строки = ТаблицаНаФорме.НайтиСтроки(Отбор);

Если Строки.Количество() > 0 Тогда

Строки[0].Наименование = НовоеНаименование;

КонецЕсли;

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

Типичные ошибки
01
Обращение к результату Найти() без проверки на Неопределено — ошибка «Поле объекта не обнаружено» при отсутствии строки
02
Использование метода Найти() для ДанныеФормыКоллекция на форме — метода нет, нужен НайтиСтроки()
03
Изменение копии таблицы: таблица, полученная через Выгрузить() или Скопировать(), не связана с исходной — правки в ней не влияют на оригинал
04
Присвоение значения несовместимого типа в типизированную колонку — ошибка преобразования или потеря данных
05
Изменение таблицы на сервере без ЗначениеВРеквизитФормы() — на форме данные визуально не обновляются

Проверка результата и отладка

После изменения полезно убедиться, что значение действительно записалось. Самый быстрый способ в отладчике — поставить точку останова после присвоения и посмотреть таблицу через «Вычислить выражение» (Shift+F9): таблицы значений раскрываются построчно.

Программно результат проверяется повторным чтением: Если Строка.Цена = НоваяЦена Тогда .... Для массовых операций удобно считать количество фактически изменённых строк и выводить его в сообщение — это сразу показывает, сработал ли отбор.

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

Контрольные точки

Как проверить результат

Строка найдена
Норма

Найти() вернул строку, НайтиСтроки() — непустой массив

Тревожный признак

Найти() вернул Неопределено, массив пуст — критерий отбора не совпал ни с одной строкой

Значение записалось
Норма

Повторное чтение свойства строки возвращает новое значение

Тревожный признак

Значение старое — изменялась копия таблицы или другая строка

Данные на форме
Норма

После изменения реквизит формы отображает новые значения

Тревожный признак

На форме старые данные — не выполнено ЗначениеВРеквизитФормы()

Часто задаваемые вопросы

Можно ли изменить значение ячейки напрямую, без получения строки?

Нет. Встроенный язык не предоставляет адресации «строка-колонка» напрямую. Минимальная запись — обращение к строке по индексу с присвоением: Таблица[0].Цена = 150. Здесь строка всё равно получается, просто в одном выражении.

Почему Найти() не находит строку, хотя значение в таблице точно есть?

Чаще всего причина в несовпадении типов: в колонке хранится ссылка на справочник, а ищется строка с наименованием, или число сравнивается со строкой. Также проверьте регистр и пробелы в строковых значениях — сравнение выполняется точное.

Как изменить значения сразу в нескольких колонках одной строки?

Получите строку один раз и присвойте значения каждому свойству последовательно: Строка.Цена = 100; Строка.Сумма = 500;. Метода «заполнить строку из структуры» нет, но можно использовать ЗаполнитьЗначенияСвойств(Строка, СтруктураСДанными), если имена свойств совпадают с именами колонок.

Изменения в таблице значений сохранятся в базе данных?

Нет. Таблица значений — объект в оперативной памяти. Чтобы данные попали в базу, нужно явно перенести их в запись объекта: табличную часть документа, набор записей регистра, реквизит справочника — и вызвать метод записи этого объекта.

Как изменить значение в свёрнутой таблице после метода Свернуть()?

Точно так же — через поиск и присвоение. Но учтите, что после свёртки в таблице остаются только колонки группировок и суммируемые колонки; обращение к удалённой колонке вызовет ошибку. Свернутую таблицу нельзя «развернуть» обратно — исходные строки теряются.

Что быстрее для массовых изменений: цикл с условием или НайтиСтроки()?

Для однократного изменения по простому равенству НайтиСтроки() обычно удобнее и читабельнее. Если условие сложное (сравнения, вычисления, несколько колонок), один проход циклом с проверкой внутри эффективнее, чем многократные вызовы поиска по таблице.

Итог

Что важно запомнить

Значение в таблице значений меняется через строку: получите её по индексу, через Найти() или НайтиСтроки() и присвойте новое значение свойству с именем колонки. Всегда проверяйте результат поиска на Неопределено, помните про типы колонок и различие между ТаблицаЗначений на сервере и ДанныеФормыКоллекция на форме. Изменения в таблице не затрагивают базу данных, пока данные явно не записаны в объекты конфигурации.