понедельник, 17 октября 2022 г.

1СЗаготовка Дублирование значение ячейки Ctrl+D (аналог Excel)

Готовый код для программного добавления кнопки (вызвать СоздатьКомандуДублироватьЗначение() из ПриСозданииНаСервере() формы), команды и сама процедура обработки:


&НаСервере
Функция СоздатьКомандуДублироватьЗначение()
	НоваяКоманда = Команды.Добавить("ДублироватьЗначение");
	НоваяКоманда.Действие= "ДублироватьЗначение";
	НоваяКоманда.Заголовок= "Дублировать значение";
	НоваяКоманда.ИзменяетСохраняемыеДанные = ?(найти(нрег(этаформа.ИмяФормы),"обработка")>0,Ложь,Истина);
	НоваяКоманда.Отображение= ОтображениеКнопки.Картинка;
	НоваяКоманда.Подсказка= "Дублируется значение предыдыущей ячейки, аналогично Excel. В т.ч. и выделенные строки";
	НоваяКоманда.СочетаниеКлавиш= Новый СочетаниеКлавиш(Клавиша.D, , Истина); // Ctrl+D
	
	// Опытным путем выявлено, что вызов команды сочетаниемклавиш не работает без кнопки
	// при этом кнопка должна быть на форме, Видимость=Истина
	// также замечено, что нажатие сочетанийклавишь активизирует кнопку
	// из-за чего ЭтаФорма.ТекущийЭлемент вернет кнопку
	// поэтому убираем кнопку в допМеню, этот фокус позволит получить именно текущий элемент
	НоваяКнопка=Элементы.Добавить("ДублироватьЗначение",Тип("КнопкаФормы"),ЭтаФорма.КоманднаяПанель);
	НоваяКнопка.вид=ВидКнопкиФормы.КнопкаКоманднойПанели;
	НоваяКнопка.ИмяКоманды="ДублироватьЗначение";
	НоваяКнопка.ПоложениеВКоманднойПанели=ПоложениеКнопкиВКоманднойПанели.ВДополнительномПодменю;
КонецФункции

&НаКлиенте
Функция ДублироватьЗначение()
	Если Типзнч(этаформа.ТекущийЭлемент)=Тип("ТаблицаФормы") Тогда     //работаем только с таблицами
		ИмяТФ=этаформа.ТекущийЭлемент.Имя;	// имя ТаблицыФормы
		ИмяТЗ=ПолучитьПутьКДанным(ИмяТФ);	// имя элемента формы может отличатся от имени реквизита
		ТЗнаФорме=Вычислить(ИмяТЗ);	// данные формы коллекция
		ВыделенныеСтроки=Элементы[ИмяТФ].ВыделенныеСтроки;
		// Определяем источник - строка предшествующая первой выделенной 
		// При удалении, перемещении строк, их идентификатор не меняется, и очень похож на номер строки
		// при этом индекс строки меняется
		ИндексСтрокиИсточника=9999999;
		Для каждого ИдСтроки ИЗ ВыделенныеСтроки Цикл
			ИндексСтроки=ТЗнаФорме.Индекс(ТЗнаФорме.НайтиПоИдентификатору(ИдСтроки));
			ИндексСтрокиИсточника=?(ИндексСтрокиИсточника>ИндексСтроки,ИндексСтроки,ИндексСтрокиИсточника);
		КонецЦикла;                                 
		ИндексСтрокиИсточника=ИндексСтрокиИсточника-1;
		
		Если ИндексСтрокиИсточника>=0 Тогда
			// опять же, имя элемента формы может отличатся от имени реквизита
			// при этом ПутьКДанным колонки содержит и ПутьКДанным таблицы, исключаем
			// обращатся к колонке по индексу также не стоит, т.к. порядок на форме может отличаться от порядка реквизитов
			ИмяТекКолонки=стрзаменить(ПолучитьПутьКДанным(Элементы[ИмяТФ].ТекущийЭлемент.Имя),""+ИмяТЗ+".","");

			ЗначениеИсточника=ТЗнаФорме[ИндексСтрокиИсточника][ИмяТекКолонки];
			
			Для Каждого СтрТЧ ИЗ ВыделенныеСтроки Цикл
				// ВыделенныеСтроки хранит не индекс строк, а их иденитфикаторы
				// при удалении строк из середины обновляется индекс, но не номер строки
				ТЗнаФорме.НайтиПоИдентификатору(СтрТЧ)[ИмяТекКолонки]=ЗначениеИсточника;
			КонецЦикла;
			Элементы[ИмяТФ].Обновить();  //обновляем данные в ТаблицеФормы
		КонецЕсли;
	КонецЕсли;		
КонецФункции

&НаСервере
Функция ПолучитьПутьКДанным(ИмяЭлемента)
	Возврат(Элементы[ИмяЭлемента].ПутьКДанным);
КонецФункции

Собственно комментарии рассказывают все подводные камни.

В теории можно подключить интерактивную запись и тем самым вызывать событие ПриИзменении(), но:

  1. Мне лень
  2. Нужно немного переделать код
  3. Для поддержки выделенных строк не забыть предварительно скопировать массив со строками
Собственно решение доработано и переделано уже несколько раз здесь

Комментариев нет:

Отправить комментарий