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