Здесь можно прочитать первую часть статьи: ссыль.
Нужно больше универсальности!
Начинающий разработчик Василий не так давно начал свой путь универсализации всего и вся.
И теперь не собирается останавливаться.
На данный момент Вася имеет метод, который открывает значение текущей ячейки. Но что, если расширить функционал? Методы, которые позволят не только открывать текущее значение, но и присваивать его… И независимо от того, находимся ли мы на клиенте или сервере…
Василий берёт блокнот и записывает:
-
программно получить значение текущей ячейки (на клиенте и на сервере)
-
программно установить значение текущей ячейки (на клиенте и на сервере)
-
интерактивно показать значение текущей ячейки (на клиенте)
-
чистить кэш
-
сохранять сессию открытых окон…
Почесав затылок, наш начинающий универсальщик скрепя когтями решает отложить часть пунктов «на потом» и сократить список:
-
программно получить значение текущей ячейки (на клиенте и на сервере)
-
программно установить значение текущей ячейки (на клиенте и на сервере)
-
интерактивно показать значение текущей ячейки (на клиенте)
Для всего этого нужна хорошая обёртка. Василий переворачивает страницу блокнота и пишет:
-
Возможность передать в метод любую таблицу. Ведь, если на текущем инструменте несколько таблиц, то нужно обеспечить возможность работы со всеми.
-
Работать как «&НаСервере», так и «&НаКлиенте». Естественно, где это возможно.
-
Изолированность — методы должны быть вынесены так, чтобы их было несложно перенести в другой инструмент.
Разработчик окидывает взглядом текущий функционал, который он написал в первой статье
&НаСервере Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка) ПутиКДаннымЭлементовФормы = Новый Структура; Для Каждого ЭлементФормы Из ЭтаФорма.Элементы Цикл Если ТипЗнч(ЭлементФормы) = Тип("ПолеФормы") ИЛИ ТипЗнч(ЭлементФормы) = Тип("ТаблицаФормы") Тогда ПутиКДаннымЭлементовФормы.Вставить(ЭлементФормы.Имя, ЭлементФормы.ПутьКДанным); КонецЕсли; КонецЦикла; КонецПроцедуры &НаКлиенте Функция ПутьКДаннымЭлементаФормы(ИмяЭлемента) ПутьКДаннымЭлемента = Неопределено; ПутиКДаннымЭлементовФормы.Свойство(ИмяЭлемента, ПутьКДаннымЭлемента); Возврат ПутьКДаннымЭлемента; КонецФункции &НаКлиенте Процедура ОткрытьЗначениеЯчейки(Команда) ТаблицаФормы = Элементы.Валюты; Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда Возврат; КонецЕсли; ИмяПоляКолонки = ТаблицаФормы.ТекущийЭлемент.Имя; ПутьКДаннымКолонки = ПутьКДаннымЭлементаФормы(ИмяПоляКолонки); СоставПутиКДанным = СтрРазделить(ПутьКДаннымКолонки, ".", Ложь); ИмяКолонкиТаблицы = СоставПутиКДанным[СоставПутиКДанным.ВГраница()]; ЗначениеЯчейки = Неопределено; ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТаблицы, ЗначениеЯчейки); ПоказатьЗначение(Новый ОписаниеОповещения, ЗначениеЯчейки); КонецПроцедуры
Первое, что попадается на глаза разработчику Васе — метод «ПриСозданииНаСервере». Его используют очень часто для разного рода действий и загромождать своим кодом будет не очень удобно.
— Нужно вынести в новый метод!
И Василий решает содержимое события «ПриСозданииНаСервере» вынести в отдельный метод. А заодно и протестировать возможность конфигуратора, о которой он вроде бы слышал, но никогда не пробовал — рефакторинг кода.
Начинающий разработчик выделяет нужный код, нажимает правую кнопку мыши и выбирает «Рефакторинг» → «Выделить фрагмент»
В появившемся окошке он вводит название своего нового метода: ОбновитьПутиКДаннымЭлементовФормы
И в результате получает то, что хотел. Конфигуратор сам создал новую процедуру и сделал вызов на неё
&НаСервере Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка) ОбновитьПутиКДаннымЭлементовФормы(); КонецПроцедуры &НаСервере Процедура ОбновитьПутиКДаннымЭлементовФормы() ПутиКДаннымЭлементовФормы = Новый Структура; Для Каждого ЭлементФормы Из ЭтаФорма.Элементы Цикл Если ТипЗнч(ЭлементФормы) = Тип("ПолеФормы") ИЛИ ТипЗнч(ЭлементФормы) = Тип("ТаблицаФормы") Тогда ПутиКДаннымЭлементовФормы.Вставить(ЭлементФормы.Имя, ЭлементФормы.ПутьКДанным); КонецЕсли; КонецЦикла; КонецПроцедуры
— Не зря я учился в Великой Школе Одинэсников Имени Желтого Чайника!
В результате, если Вася захочет поделиться наработками, то применить их в другом инструменте будет теперь чуточку проще. Есть ещё один приятный бонус — возможность дополнительно вызывать этот метод по мере необходимости (Василий пока ещё не понял зачем, но об этом позднее…).
Для этого сразу же ранее написанный метод «ПутьКДаннымЭлементаФормы» делаем &НаКлиентеНаСервереБезКонтекста. Таким образом один и тот же метод будет доступен и на сервере и на клиенте.
&НаКлиентеНаСервереБезКонтекста Функция ПутьКДаннымЭлементаФормы(ИмяЭлемента) ПутьКДаннымЭлемента = Неопределено; ПутиКДаннымЭлементовФормы.Свойство(ИмяЭлемента, ПутьКДаннымЭлемента); Возврат ПутьКДаннымЭлемента; КонецФункции
Василий знает, что при такой директиве метод «теряет» контекст формы, а значит больше не видит её свойств, элементов, реквизитов и так далее. Но как же теперь с этим работать?
Наш разработчик будет просто передавать форму напрямую.
&НаКлиентеНаСервереБезКонтекста Функция ПутьКДаннымЭлементаФормы(ЭтаФорма, ИмяЭлемента) ПутьКДаннымЭлемента = Неопределено; ЭтаФорма.ПутиКДаннымЭлементовФормы.Свойство(ИмяЭлемента, ПутьКДаннымЭлемента); Возврат ПутьКДаннымЭлемента; КонецФункции
Получается, что, независимо от того, находимся ли мы сейчас на клиенте или же сервере, можно вызвать один и тот же метод и просто передать в него текущую форму:
&НаКлиенте Процедура ОткрытьЗначениеЯчейки(Команда) ТаблицаФормы = Элементы.Валюты; Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда Возврат; КонецЕсли; ИмяПоляКолонки = ТаблицаФормы.ТекущийЭлемент.Имя; ПутьКДаннымКолонки = ПутьКДаннымЭлементаФормы(ЭтаФорма, ИмяПоляКолонки); СоставПутиКДанным = СтрРазделить(ПутьКДаннымКолонки, ".", Ложь); ИмяКолонкиТаблицы = СоставПутиКДанным[СоставПутиКДанным.ВГраница()]; ЗначениеЯчейки = Неопределено; ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТаблицы, ЗначениеЯчейки); ПоказатьЗначение(Новый ОписаниеОповещения, ЗначениеЯчейки); КонецПроцедуры
Почва подготовлена. Теперь Василий может использовать этот код для реализации наших новых методов.
— Ну-с, приступим!
&НаКлиентеНаСервереБезКонтекста Функция ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы) КонецФункции
Этот метод вернёт значение текущей ячейки. На клиент, на сервер — не важно. А дальше уже мы сможем использовать это по своему усмотрению.
Начинаем с классической проверки:
&НаКлиентеНаСервереБезКонтекста Функция ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы) Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда Возврат Неопределено; КонецЕсли; КонецФункции
И сразу же при помощи волшебного копипаста переносим написанный в прошлой статье код, в наш новый метод:
&НаКлиентеНаСервереБезКонтекста Функция ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы) Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда Возврат Неопределено; КонецЕсли; ИмяПоляКолонки = ТаблицаФормы.ТекущийЭлемент.Имя; ПутьКДаннымКолонки = ПутьКДаннымЭлементаФормы(ЭтаФорма, ИмяПоляКолонки); СоставПутиКДанным = СтрРазделить(ПутьКДаннымКолонки, ".", Ложь); ИмяКолонкиТаблицы = СоставПутиКДанным[СоставПутиКДанным.ВГраница()]; ЗначениеЯчейки = Неопределено; ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТаблицы, ЗначениеЯчейки); Возврат ЗначениеЯчейки; КонецФункции
Написанная функция вернёт нам значение текущей ячейки. Что с ним делать? Именно. Открывать.
&НаКлиенте Процедура ОткрытьЗначениеТекущейЯчейки(ТаблицаФормы) ЗначениеТекущейЯчейки = ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы); Если НЕ ЗначениеТекущейЯчейки = Неопределено Тогда ПоказатьЗначение(Новый ОписаниеОповещения, ЗначениеТекущейЯчейки); КонецЕсли; КонецПроцедуры
А в нашей команде просто вызываем этот метод:
&НаКлиенте Процедура ОткрытьЗначениеЯчейки(Команда) ОткрытьЗначениеТекущейЯчейки(Элементы.Валюты); КонецПроцедуры
Замечательно, теперь наш код стал значительно красивее.
//Обработчик команды формы &НаКлиенте Процедура ОткрытьЗначениеЯчейки(Команда) ОткрытьЗначениеТекущейЯчейки(Элементы.Валюты); КонецПроцедуры //Процедура открывает значение текущей ячейки &НаКлиенте Процедура ОткрытьЗначениеТекущейЯчейки(ТаблицаФормы) ЗначениеТекущейЯчейки = ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы); Если НЕ ЗначениеТекущейЯчейки = Неопределено Тогда ПоказатьЗначение(Новый ОписаниеОповещения, ЗначениеТекущейЯчейки); КонецЕсли; КонецПроцедуры //Функция возвращает значение текущей ячейки &НаКлиентеНаСервереБезКонтекста Функция ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы) Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда Возврат Неопределено; КонецЕсли; ИмяПоляКолонки = ТаблицаФормы.ТекущийЭлемент.Имя; ПутьКДаннымКолонки = ПутьКДаннымЭлементаФормы(ЭтаФорма, ИмяПоляКолонки); СоставПутиКДанным = СтрРазделить(ПутьКДаннымКолонки, ".", Ложь); ИмяКолонкиТаблицы = СоставПутиКДанным[СоставПутиКДанным.ВГраница()]; ЗначениеЯчейки = Неопределено; ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТаблицы, ЗначениеЯчейки); Возврат ЗначениеЯчейки; КонецФункции
— Рано ликовать!
У Васи готовы методы
-
программно получить значение текущей ячейки (на клиенте и на сервере)
-
интерактивно показать значение текущей ячейки (на клиенте)
Осталось сделать ещё один
-
программно установить значение текущей ячейки (на клиенте и на сервере)
И снова мы начинаем с проверки. Метод, естественно, будет &НаКлиентеНаСервереБезКонтекста
&НаКлиентеНаСервереБезКонтекста Процедура УстановитьЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы, Значение) Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда Возврат; КонецЕсли; КонецПроцедуры
Теперь Василию нужно как-то получить не значение в текущей ячейке, а именно саму эту «ячейку», чтобы установить значение.
Но на самом деле , ранее это уже было сделано. В методе ЗначениеТекущейЯчейки() :
//Функция возвращает значение текущей ячейки &НаКлиентеНаСервереБезКонтекста Функция ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы) Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда Возврат Неопределено; КонецЕсли; ИмяПоляКолонки = ТаблицаФормы.ТекущийЭлемент.Имя; ПутьКДаннымКолонки = ПутьКДаннымЭлементаФормы(ЭтаФорма, ИмяПоляКолонки); СоставПутиКДанным = СтрРазделить(ПутьКДаннымКолонки, ".", Ложь); ИмяКолонкиТаблицы = СоставПутиКДанным[СоставПутиКДанным.ВГраница()]; ЗначениеЯчейки = Неопределено; ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТаблицы, ЗначениеЯчейки); Возврат ЗначениеЯчейки; КонецФункции
Да, именно этот кусочек кода нужно выполнить в нашем новом методе. Можно было, конечно, скопировать его и вставить в наш новый метод, но…
Не этому меня учили в Великой Школе Одинэсников Имени Желтого Чайника!
И Василий снова берётся за «рефакторинг». Выделяет наш кусочек кода и выносит в специальный новый метод «ИмяКолонкиТекущейЯчейки»:
&НаКлиентеНаСервереБезКонтекста Функция ИмяКолонкиТекущейЯчейки(ЭтаФорма, ТаблицаФормы) ИмяПоляКолонки = ТаблицаФормы.ТекущийЭлемент.Имя; ПутьКДаннымКолонки = ПутьКДаннымЭлементаФормы(ЭтаФорма, ИмяПоляКолонки); СоставПутиКДанным = СтрРазделить(ПутьКДаннымКолонки, ".", Ложь); ИмяКолонкиТаблицы = СоставПутиКДанным[СоставПутиКДанным.ВГраница()]; Возврат ИмяКолонкиТаблицы; КонецФункции
А в ранее написанной функции теперь просто вызов этого нового метода. Красота. В результате функция стала ещё нагляднее:
&НаКлиентеНаСервереБезКонтекста Функция ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы) Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда Возврат Неопределено; КонецЕсли; ИмяКолонкиТекущейЯчейки = ИмяКолонкиТекущейЯчейки(ЭтаФорма, ТаблицаФормы); ЗначениеЯчейки = Неопределено; ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТекущейЯчейки, ЗначениеЯчейки); Возврат ЗначениеЯчейки; КонецФункции
Прекрасно. Теперь у Васи есть метод, который возвращает имя нужно колонки. Осталось только присвоить значение:
&НаКлиентеНаСервереБезКонтекста Процедура УстановитьЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы, Значение) Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда Возврат; КонецЕсли; ИмяКолонкиТекущейЯчейки = ИмяКолонкиТекущейЯчейки(ЭтаФорма, ТаблицаФормы); Если ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТекущейЯчейки) Тогда ТаблицаФормы.ТекущиеДанные[ИмяКолонкиТекущейЯчейки] = Значение; КонецЕсли; КонецПроцедуры
Василий довольный оглядывает весь свой получившийся код.
Спойлер
&НаСервере Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка) ОбновитьПутиКДаннымЭлементовФормы(); КонецПроцедуры //Процедура обновляет пути для определения реквизита текущей ячейки &НаСервере Процедура ОбновитьПутиКДаннымЭлементовФормы() ПутиКДаннымЭлементовФормы = Новый Структура; Для Каждого ЭлементФормы Из ЭтаФорма.Элементы Цикл Если ТипЗнч(ЭлементФормы) = Тип("ПолеФормы") ИЛИ ТипЗнч(ЭлементФормы) = Тип("ТаблицаФормы") Тогда ПутиКДаннымЭлементовФормы.Вставить(ЭлементФормы.Имя, ЭлементФормы.ПутьКДанным); КонецЕсли; КонецЦикла; КонецПроцедуры //Обработчик команды формы &НаКлиенте Процедура ОткрытьЗначениеЯчейки(Команда) ОткрытьЗначениеТекущейЯчейки(Элементы.Валюты); КонецПроцедуры //Процедура открывает значение текущей ячейки &НаКлиенте Процедура ОткрытьЗначениеТекущейЯчейки(ТаблицаФормы) ЗначениеТекущейЯчейки = ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы); Если НЕ ЗначениеТекущейЯчейки = Неопределено Тогда ПоказатьЗначение(Новый ОписаниеОповещения, ЗначениеТекущейЯчейки); КонецЕсли; КонецПроцедуры //Процедура устанавливает значение текущей ячейки &НаКлиентеНаСервереБезКонтекста Процедура УстановитьЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы, Значение) Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда Возврат; КонецЕсли; ИмяКолонкиТекущейЯчейки = ИмяКолонкиТекущейЯчейки(ЭтаФорма, ТаблицаФормы); Если ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТекущейЯчейки) Тогда ТаблицаФормы.ТекущиеДанные[ИмяКолонкиТекущейЯчейки] = Значение; КонецЕсли; КонецПроцедуры //Функция возвращает значение текущей ячейки &НаКлиентеНаСервереБезКонтекста Функция ЗначениеТекущейЯчейки(ЭтаФорма, ТаблицаФормы) Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда Возврат Неопределено; КонецЕсли; ИмяКолонкиТекущейЯчейки = ИмяКолонкиТекущейЯчейки(ЭтаФорма, ТаблицаФормы); ЗначениеЯчейки = Неопределено; ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТекущейЯчейки, ЗначениеЯчейки); Возврат ЗначениеЯчейки; КонецФункции //Функция возвращает имя колонки текущей ячейки &НаКлиентеНаСервереБезКонтекста Функция ИмяКолонкиТекущейЯчейки(ЭтаФорма, ТаблицаФормы) ИмяПоляКолонки = ТаблицаФормы.ТекущийЭлемент.Имя; ПутьКДаннымКолонки = ПутьКДаннымЭлементаФормы(ЭтаФорма, ИмяПоляКолонки); СоставПутиКДанным = СтрРазделить(ПутьКДаннымКолонки, ".", Ложь); ИмяКолонкиТаблицы = СоставПутиКДанным[СоставПутиКДанным.ВГраница()]; Возврат ИмяКолонкиТаблицы; КонецФункции
Замечтательно! Довольный программист потирает лапки и идёт наслаждаться победой. Но не полной. Осталось придумать, как теперь завернуть это в удобный механизм. Но об этом он подумает завтра.
Понравилась статья?
Дамы и господа 1Сники. Не будьте равнодушными. Каждая ваша "звёздочка" порадует и автора и программиста Васю. Ведь это показатель того, что кому-то текст зашёл, а значит и время было потрачено не зря.
Ну а после переходите к другим работам.
"Меньше копипаста!", или как Вася универсальную процедуру писал
Не провоцируйте СКД, или пример "как не надо"
Чем расщепить или "СтрРазделить() VS РазложитьСтрокуВМассивПодстрок()"
Кстати. Забыл сказать, что Василий — кот.
Могу ошибаться, но мне кажется, если путь к данным колонки таблицы содержит 2 и более точки, то будет ошибка. То есть, например, есть у нас колонка с ссылкой на элемент справочника и мы дополнительно выводим в таблицу колонку с его кодом. В БСП, кажется, есть соответствующие методы. Либо проверять наличие 2-х и больше точек в пути к данным при формировании переменной ПутиКДаннымЭлементовФормы.
(1) а об этом в следующих сериях 👍
Так вот для чего эта кнопка! (рефакторинг)
А меня учили в других заведениях, и про рефакторинг не рассказали. Зато теперь знаю.
А в EDT рефакторинг ещё доработали и стало ещё лучше. Схему модуля, например, можно делать проще.