Хочу универсально! Часть 1
Начинающий разработчик проходит путь от простой задачки к созданию своего механизма
Жил-был начинающий разработчик Вася. И было у него три «пунктика»:
- Писать по стандартам
- Делать универсально
- Перепроверять, что все соответствует п.1 и п.2
И в зависимости от расположения звёзд на небе, у Василия активизировались те или иные пункты. Например.
Есть на форме обработки таблица с колонками. Разработчик столкнулся с, на первый взгляд, примитивной задачей — сделать кнопку, которая будет открывать значение в текущей колонке. Пользователь становится курсором на валюту «Руб.» и нажимает кнопку. Карточка валюты «руб.» открывается. Пользователь становится на другую ячейку и нажимает на кнопку — открывается значение из этой ячейки.
И вот программист Вася, вдохновившись тем, что сможет моментально решить задачу, добавляет команду.
- А вдруг пользователь нажмёт кнопку в тот момент, когда в таблице вообще не будет строк?
И прилежный программист сразу же (как учили) в процедуре делает стандартную проверку.
1
2
3
4
5
ТаблицаФормы = Элементы.Валюты;
Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
- Ну вот! Уже лучше. Начинаем эксперименты
И вот Василий берётся за определение текущей колонки. А так как наш разработчик любит сначала всё проверять, то выводит её сообщением.
1
2
ТекущаяКолонка = ТаблицаФормы.ТекущийЭлемент;
Сообщить("Имя текущего поля: " + ТекущаяКолонка.Имя);
Открывает свой любимый тонкий клиент и проверяет:
- Но ведь сама колонка в таблице называется «Валюта», а не «ВалютыВалюта».
Взмахнув мышкой, Василий открывает редактор формы и видит, что на самом деле происходит.
«Валюты» - это имя таблицы, в которой хранятся данные. «Валюта» - имя колонки этой таблицы. А «ВалютыВалюта» - это имя поля на форме. Оно не хранит данные, а лишь выводит их. На самом деле данные хранятся в строке таблицы «Валюты» в колонке «Валюта».
Так происходит, когда имя поля было сгенерировано автоматически. Например, разработчик вынес его «вручную» на форму обработки. Имя автоматически присвоелось по формуле:
имя таблицы + имя колонки
- И как же мне определить реальное имя колонки у текущего элемента?
Чему зачастую учат программистов в этих ваших интернетах? Прежде чем создавать свой велосипед, нужно поискать чужие. Естественно, в интернете.
Недолго думая гугля, Вася находит несколько примеров.
- А где-то я уже это видел…
Флэшбеки вспышками имен методов и переменных пролетают в сознании разработчика 1С и, погрузившись в океан жёлтых воспоминаний, он хватает за хвост имя обработки, в которой видел нечто подобное.
- Точно, я уже такое видел!
И действительно, в одной из завалявшихся в конфигурации обработок есть это:
1
ТаблицаФормы.ТекущиеДанные[Сред(ТаблицаФормы.ТекущийЭлемент.Имя, СтрДлина(ТаблицаФормы.Имя) + 1)]
Всё просто. Автор этого кода полагает, что имена элементов в его инструменте всегда будут строиться по приведенной ранее формуле: имя таблицы + имя колонки. И вроде бы ничего страшного, ведь так чаще всего и бывает, но:
- Я хочу универсальное решение!
Звёзды сошлись. Сегодня Василий решается на серьёзный поступок — не денег ради, но во имя высокой цели, сделать кнопку не «как можно быстрее», а «как можно круче». Естественно, степень крутости определяется им самим.
Нужно решение, которое можно будет скопировать в другой инструмент, не заботясь о том, чтобы имена элементов соответствовали какому-то там шаблону.
Порывшись в гугле синтаксис помощнике, Василий находит свойство у поля: ПутьКДанным
ПолеФормы (FormField) ПутьКДанным (DataPath) Использование: Чтение и запись. Описание: Тип: Строка. Содержит путь к реквизиту, с которым связан объект. Доступность: Сервер, мобильное приложение(сервер).
И вроде бы вот оно решение, однако есть загвоздка — свойство доступно только на сервере.
Можно, конечно, написать серверную функцию, которая будет возвращать путь к данным формы:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
&НаКлиенте
Процедура ОткрытьЗначениеЯчейки(Команда)
ТаблицаФормы = Элементы.Валюты;
Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
ТекущаяКолонка = ТаблицаФормы.ТекущийЭлемент;
Сообщить("Имя текущего поля: " + ТекущаяКолонка.Имя);
Сообщить("Путь к данным текущего поля: " + ПутьКДаннымЭлементаФормы(ТекущаяКолонка.Имя));
КонецПроцедуры
&НаСервере
Функция ПутьКДаннымЭлементаФормы(ИмяЭлемента)
ПутьКДаннымЭлемента = Неопределено;
НайденныйЭлемент = Элементы.Найти(ИмяЭлемента);
Если НЕ НайденныйЭлемент = Неопределено Тогда
ПутьКДаннымЭлемента = НайденныйЭлемент.ПутьКДанным;
КонецЕсли;
Возврат ПутьКДаннымЭлемента;
КонецФункции
Но…
Но…
Вспомнив, что каждое излишнее обращение к серверу — это зло, за которое его ругали в Великой Школе Одинэсников Имени Желтого Чайника, разработчик Вася решает попробовать не плодить серверные вызовы. Тем более с передачей всей формы.
Программист добавляет на форму обработки реквизит произвольного типа «ПутиКДаннымЭлементовФормы»
А при создании формы заполняем эту структуру именами полей и адресами их значений, хранящихся в свойстве «ПутьКДанным»
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ПутиКДаннымЭлементовФормы = Новый Структура;
Для Каждого ЭлементФормы Из ЭтаФорма.Элементы Цикл
Если ТипЗнч(ЭлементФормы) = Тип("ПолеФормы")
ИЛИ ТипЗнч(ЭлементФормы) = Тип("ТаблицаФормы") Тогда
ПутиКДаннымЭлементовФормы.Вставить(ЭлементФормы.Имя, ЭлементФормы.ПутьКДанным);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Теперь остаётся лишь сделать клиентский метод, который будет возвращать соответствующее значение свойства «ПутьКДанным»
1
2
3
4
5
6
7
8
&НаКлиенте
Функция ПутьКДаннымЭлементаФормы(ИмяЭлемента)
ПутьКДаннымЭлемента = Неопределено;
ПутиКДаннымЭлементовФормы.Свойство(ИмяЭлемента, ПутьКДаннымЭлемента);
Возврат ПутьКДаннымЭлемента;
КонецФункции
Разработчик оглядывает код и радуется проделанной работе. А заодно и проверяет насколько правильно всё работает:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ПутиКДаннымЭлементовФормы = Новый Структура;
Для Каждого ЭлементФормы Из ЭтаФорма.Элементы Цикл
Если ТипЗнч(ЭлементФормы) = Тип("ПолеФормы")
ИЛИ ТипЗнч(ЭлементФормы) = Тип("ТаблицаФормы") Тогда
ПутиКДаннымЭлементовФормы.Вставить(ЭлементФормы.Имя, ЭлементФормы.ПутьКДанным);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ОткрытьЗначениеЯчейки(Команда)
ТаблицаФормы = Элементы.Валюты;
Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
ТекущаяКолонка = ТаблицаФормы.ТекущийЭлемент;
Сообщить("Имя текущего поля: " + ТекущаяКолонка.Имя);
Сообщить("Путь к данным текущего поля: " + ПутьКДаннымЭлементаФормы(ТекущаяКолонка.Имя));
КонецПроцедуры
&НаКлиенте
Функция ПутьКДаннымЭлементаФормы(ИмяЭлемента)
ПутьКДаннымЭлемента = Неопределено;
ПутиКДаннымЭлементовФормы.Свойство(ИмяЭлемента, ПутьКДаннымЭлемента);
Возврат ПутьКДаннымЭлемента;
КонецФункции
Вернувшись в тонкий клиент, Василий смотрит на результат:
Уже лучше. Теперь мы можем на клиенте узнать путь к данным формы. Для проверки, что всё на самом деле так, как планировалось, разработчик Вася переименовал элемент формы на «КолонкаСВалютой». Теперь путь к данным и имя элемента непохожи между собой, что поможет понять разницу. Вася любит всё перепроверять.
Ну вот. Всё хорошо. Но что теперь делать с этим? Нужно же определить имя колонки из полного пути к данным формы. Василий берёт самый прямой способ - расщепить полный путь на массив и взять его последний элемент:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ПутиКДаннымЭлементовФормы = Новый Структура;
Для Каждого ЭлементФормы Из ЭтаФорма.Элементы Цикл
Если ТипЗнч(ЭлементФормы) = Тип("ПолеФормы")
ИЛИ ТипЗнч(ЭлементФормы) = Тип("ТаблицаФормы") Тогда
ПутиКДаннымЭлементовФормы.Вставить(ЭлементФормы.Имя, ЭлементФормы.ПутьКДанным);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Функция ПутьКДаннымЭлементаФормы(ИмяЭлемента)
ПутьКДаннымЭлемента = Неопределено;
ПутиКДаннымЭлементовФормы.Свойство(ИмяЭлемента, ПутьКДаннымЭлемента);
Возврат ПутьКДаннымЭлемента;
КонецФункции
&НаКлиенте
Процедура ОткрытьЗначениеЯчейки(Команда)
ТаблицаФормы = Элементы.Валюты;
Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
ИмяПоляКолонки = ТаблицаФормы.ТекущийЭлемент.Имя; //КолонкаСВалютой
ПутьКДаннымКолонки = ПутьКДаннымЭлементаФормы(ИмяПоляКолонки); //Валюты.Валюта
СоставПутиКДанным = СтрРазделить(ПутьКДаннымКолонки, ".", Ложь); //Валюты; Валюта
ИмяКолонкиТаблицы = СоставПутиКДанным[СоставПутиКДанным.ВГраница()]; //Валюта
Сообщить("Имя колонки таблицы: " + ИмяКолонкиТаблицы);
КонецПроцедуры
- Сейчас проверим
Осталось немного — просто взять значение из колонки и открыть его:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ПутиКДаннымЭлементовФормы = Новый Структура;
Для Каждого ЭлементФормы Из ЭтаФорма.Элементы Цикл
Если ТипЗнч(ЭлементФормы) = Тип("ПолеФормы")
ИЛИ ТипЗнч(ЭлементФормы) = Тип("ТаблицаФормы") Тогда
ПутиКДаннымЭлементовФормы.Вставить(ЭлементФормы.Имя, ЭлементФормы.ПутьКДанным);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Функция ПутьКДаннымЭлементаФормы(ИмяЭлемента)
ПутьКДаннымЭлемента = Неопределено;
ПутиКДаннымЭлементовФормы.Свойство(ИмяЭлемента, ПутьКДаннымЭлемента);
Возврат ПутьКДаннымЭлемента;
КонецФункции
&НаКлиенте
Процедура ОткрытьЗначениеЯчейки(Команда)
ТаблицаФормы = Элементы.Валюты;
Если ТаблицаФормы.ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
ИмяПоляКолонки = ТаблицаФормы.ТекущийЭлемент.Имя;
ПутьКДаннымКолонки = ПутьКДаннымЭлементаФормы(ИмяПоляКолонки);
СоставПутиКДанным = СтрРазделить(ПутьКДаннымКолонки, ".", Ложь);
ИмяКолонкиТаблицы = СоставПутиКДанным[СоставПутиКДанным.ВГраница()];
ЗначениеЯчейки = Неопределено;
ТаблицаФормы.ТекущиеДанные.Свойство(ИмяКолонкиТаблицы, ЗначениеЯчейки);
ПоказатьЗначение(Новый ОписаниеОповещения, ЗначениеЯчейки);
КонецПроцедуры
Замечательно! Инструмент заработал. И теперь уже значение будет открываться независимо от того, как называется наш элемент формы.
Василий уже прикинул в голове способы применения этого кода. Например, у нас есть табличная часть документа, которую нельзя редактировать. Наш разработчик ставит на таблицу ТолькоПросмотр, а так же подвязывает событие «Выбор», в котором открывает текущее значение.
И как только наш начинающий программист подумал об этом, в голову пришла мысль.
- Недостаточно удобно!
Да, этого мало. Василий хочет сделать ещё круче! Он решает переспать с этой мыслью, чтобы уже позже продолжить свой путь от простой задачи к универсальному механизму…