Есть несколько мест, на которых необходимо обратить внимание:
1. Алгоритм опирается на нерекомендуемую ИТС функцию "ЗначениеВСтрокуВнутр";
2. Работоспособность зависит от начальных действий - необходимо "для начала" руками изменить настройки формы;
3. В самом общем случае - когда используются пользовательские поля и синонимы - шаг "разбираем их" существенно усложняется;
4. Если имена колонок содержат "." или "_", шаг "разбираем их" усложняется еще больше.
&НаКлиенте
Процедура СдвинутьКолонку(Команда)
ТекущаяКолонка = ЭтаФорма.ТекущийЭлемент.ТекущийЭлемент.Имя;
КлючОбъекта = ЭтотОбъект.ИмяФормы + "/НастройкиФормы";
Пользователь = Строка(ПользователиКлиент.ТекущийПользователь());
СдвинутьКолонкуНаСервере(ТекущаяКолонка, КлючОбъекта, Пользователь);
КонецПроцедуры
&НаСервере
Процедура СдвинутьКолонкуНаСервере(Знач ТекущаяКолонка, Знач КлючОбъекта, Знач Пользователь)
НастройкиФормы = ПолучитьНастройкиФормы(КлючОбъекта, Пользователь);
Если НастройкиФормы = "" Тогда
ОбщегоНазначения.СообщитьПользователю("Перед началом иллюстрации работы механизма необходимо
|зайти в настройки формы и передвинуть одну из колонок.");
Возврат;
КонецЕсли;
ОригинальнаяСекцияПорядкаКолонок = СекцияПорядкаПолей(НастройкиФормы);
СтараяСекцияИзменений = ЭлементыСекцииПорядкаПолей(ОригинальнаяСекцияПорядкаКолонок)[8];
НоваяСекцияИзменений = ПереместитьКолонку(ОригинальнаяСекцияПорядкаКолонок, ТекущаяКолонка, -1);
НовыеНастройкиФормы = СтрЗаменить(НастройкиФормы, СтараяСекцияИзменений, НоваяСекцияИзменений);
СохранитьНастройкиФормы(КлючОбъекта, Пользователь, НовыеНастройкиФормы);
ИзменитьРеквизиты();
КонецПроцедуры
Разложим текущие настройки формы в строку "скобочного формата". Порядок колонок динамического списка хранится в последней секций описания. (Еще раз - описываем простой случай).
Описание порядка делится на две части - "изменения" и "порядок по умолчанию". Секция изменений содержит пары "имя поля + новое положение".
{"Список",
{
{0,0,1,1,
{1,0},
{1,0},0,1,0,0,60,0,1,0,0,2,0,0,1,0,
{0}
},
{
{3,"ОбъектУчета",1,"Поле6",7,"Поле8",9},
{11,"Картинка","ОбъектУчета","Поле1","Поле2","Поле3","Поле4","Поле5","Поле6","Поле7","Поле8","Поле9"}
}
}
}
Готовим "виртуальный обновленный порядок" и сверяем с порядком по умолчанию. Для построения списка изменений применяется следующая эвристика:
"если индекс поля не соответствует позиции по умолчанию, то поле заносится в список перемещенных колонок".
Пример реализации в приложенной обработке.
P.S.
#Область СдвинутьКолонку
&НаКлиенте
Процедура СдвинутьКолонку(Команда)
ТекущаяКолонка = ЭтаФорма.ТекущийЭлемент.ТекущийЭлемент.Имя;
КлючОбъекта = ЭтотОбъект.ИмяФормы + "/НастройкиФормы";
Пользователь = Строка(ПользователиКлиент.ТекущийПользователь());
СдвинутьКолонкуНаСервере(ТекущаяКолонка, КлючОбъекта, Пользователь);
КонецПроцедуры
&НаСервере
Процедура СдвинутьКолонкуНаСервере(Знач ТекущаяКолонка, Знач КлючОбъекта, Знач Пользователь)
НастройкиФормы = ПолучитьНастройкиФормы(КлючОбъекта, Пользователь);
Если НастройкиФормы = "" Тогда
ОбщегоНазначения.СообщитьПользователю("Перед началом иллюстрации работы механизма необходимо
|зайти в настройки формы и передвинуть одну из колонок.");
Возврат;
КонецЕсли;
ОригинальнаяСекцияПорядкаКолонок = СекцияПорядкаПолей(НастройкиФормы);
СтараяСекцияИзменений = ЭлементыСекцииПорядкаПолей(ОригинальнаяСекцияПорядкаКолонок)[8];
НоваяСекцияИзменений = ПереместитьКолонку(ОригинальнаяСекцияПорядкаКолонок, ТекущаяКолонка, -1);
НовыеНастройкиФормы = СтрЗаменить(НастройкиФормы, СтараяСекцияИзменений, НоваяСекцияИзменений);
СохранитьНастройкиФормы(КлючОбъекта, Пользователь, НовыеНастройкиФормы);
ИзменитьРеквизиты();
КонецПроцедуры
// важный нюанс - без контекста!
&НаСервереБезКонтекста
Процедура СохранитьНастройкиФормы(Знач КлючОбъекта, Знач Пользователь, Знач НовыеНастройкиФормы)
НоваяНастройкаФормы = ЗначениеИзСтрокиВнутр(НовыеНастройкиФормы);
ХранилищеСистемныхНастроек.Сохранить(КлючОбъекта,, НоваяНастройкаФормы,, Пользователь);
КонецПроцедуры
&НаСервере
Функция ПолучитьНастройкиФормы(Знач КлючОбъекта, Знач Пользователь)
НастройкиФормы = ХранилищеСистемныхНастроек.Загрузить(КлючОбъекта,,, Пользователь);
НастройкиФормыСтрокой = ЗначениеВСтрокуВнутр(НастройкиФормы);
Возврат НастройкиФормыСтрокой;
КонецФункции
&НаСервере
Функция СекцияПорядкаПолей(Знач НастройкиФормыСтрокой, Знач ИмяДинамическогоСписка = "Список")
СтрокаПоиска = "{""" + ИмяДинамическогоСписка + """,";
НачалоСекции = СтрНайти(НастройкиФормыСтрокой, СтрокаПоиска, НаправлениеПоиска.СКонца);
Если НЕ НачалоСекции = 0 Тогда
СекцияОписанияПорядкаПолей = ПрочитатьСекцию(НастройкиФормыСтрокой, НачалоСекции);
Иначе
СекцияОписанияПорядкаПолей = "";
КонецЕсли;
Возврат СекцияОписанияПорядкаПолей;
КонецФункции
&НаСервере
Функция ЭлементыСекцииПорядкаПолей(Знач СекцияПорядкаПолей)
РазделительЭлементовСекции = "{}" + Символы.ПС;
Возврат СтрРазделить(СекцияПорядкаПолей, РазделительЭлементовСекции, ЛОЖЬ);
КонецФункции
&НаСервере
Функция ПорядокПолейПоУмолчанию(СекцияПорядкаПолей)
РазделительДанныхСекции = """,""";
ПорядокПолейПоУмолчанию = 10;
Возврат СтрРазделить(СекцияПорядкаПолей[ПорядокПолейПоУмолчанию], РазделительДанныхСекции, ЛОЖЬ);
КонецФункции
&НаСервере
Функция ПеремещенныеПоля(Знач СекцияПорядкаПолей)
РазделительДанныхСекции = """,""";
ПеремещенныеПоля = 8;
Возврат СтрРазделить(СекцияПорядкаПолей[ПеремещенныеПоля], РазделительДанныхСекции, ЛОЖЬ);
КонецФункции
&НаСервере
Функция ПереместитьКолонку(Знач СекцияПорядкаКолонок, Знач ИмяКолонки, Знач Сдвиг)
СекцияПорядкаПолей = ЭлементыСекцииПорядкаПолей(СекцияПорядкаКолонок);
ПорядокПоУмолчанию = ПорядокПолейПоУмолчанию(СекцияПорядкаПолей);
Перемещения = ПеремещенныеПоля(СекцияПорядкаПолей);
АктуальныйПорядок = ПостроитьАктуальныйСписок(ПорядокПоУмолчанию, Перемещения);
АктуальныйПорядок.Удалить(0);
АктуальнаяПозиция = АктуальныйПорядок.Найти(ИмяКолонки);
НоваяПозиция = АктуальнаяПозиция + Сдвиг;
ПеремещениеНеВызоветПереполнения = (НоваяПозиция >= 0)
И (НоваяПозиция <= АктуальныйПорядок.ВГраница());
Если ПеремещениеНеВызоветПереполнения Тогда
СписокПеремещений = ПостроитьСписокПеремещений(Перемещения, ИмяКолонки, НоваяПозиция);
КонецЕсли;
Возврат СписокПеремещений;
КонецФункции
&НаСервере
Функция ПостроитьАктуальныйСписок(Знач ПорядокПоУмолчанию, Знач Перемещения)
МассивВозврата = Новый Массив;
Для Каждого ЭлементМассива Из ПорядокПоУмолчанию Цикл
МассивВозврата.Добавить(ЭлементМассива);
КонецЦикла;
ГраницаМассива = Перемещения.ВГраница();
Итератор = 1;
Пока Итератор <= ГраницаМассива Цикл
МестоВШаблоне = МассивВозврата.Найти(Перемещения[Итератор]);
Если МестоВШаблоне = Неопределено Тогда
МассивВозврата.Добавить(Перемещения[Итератор]);
МестоВШаблоне = МассивВозврата.ВГраница();
КонецЕсли;
СдвинутьВМассиве(МассивВозврата, МестоВШаблоне, Число(Перемещения[Итератор + 1]) + 1);
Итератор = Итератор + 2;
КонецЦикла;
Возврат МассивВозврата;
КонецФункции
&НаСервере
Функция ПостроитьСписокПеремещений(Знач Перемещения, Знач ИмяКолонки, Знач НоваяПозиция)
ФорматнаяСтрока = "ЧГ=";
ВПеремещениях = Перемещения.Найти(ИмяКолонки);
Если ВПеремещениях = Неопределено Тогда
Перемещения.Добавить(ИмяКолонки);
Перемещения.Добавить(Формат(НоваяПозиция, ФорматнаяСтрока));
Перемещения[0] = Формат(Число(Перемещения[0]) + 1, ФорматнаяСтрока);
Иначе
Перемещения[ВПеремещениях + 1] = (Формат(НоваяПозиция, ФорматнаяСтрока));
КонецЕсли;
Для Итератор = 0 По Перемещения.ВГраница() Цикл
Если НЕ СтроковыеФункцииКлиентСервер.ТолькоЦифрыВСтроке(Перемещения[Итератор]) Тогда
Перемещения[Итератор] = """" + Перемещения[Итератор] + """";
КонецЕсли;
КонецЦикла;
Возврат СтрСоединить(Перемещения, ",");
КонецФункции
&НаСервере
Процедура СдвинутьВМассиве(МассивЗначений, Знач ЧтоДвигать, Знач КудаДвигать)
Перем БуферЗначения, Двигатель, ШагИтерации;
Если ЧтоДвигать = КудаДвигать Тогда
Возврат;
КонецЕсли;
БуферЗначения = МассивЗначений[ЧтоДвигать];
Двигатель = ЧтоДвигать;
ШагИтерации = ?(КудаДвигать > ЧтоДвигать, 1, -1);
Пока Двигатель <> КудаДвигать Цикл
МассивЗначений[Двигатель] = МассивЗначений[Двигатель + ШагИтерации];
Двигатель = Двигатель + ШагИтерации;
КонецЦикла;
МассивЗначений[КудаДвигать] = БуферЗначения;
КонецПроцедуры
&НаСервере
Функция ПрочитатьСекцию(Знач СтрокаОписанияНастроек, Знач ПозицияНачалаСекции)
СтекСкобок = 1;
Сдвиг = 1;
Пока СтекСкобок <> 0 Цикл
РабочийСимвол = Сред(СтрокаОписанияНастроек, ПозицияНачалаСекции + Сдвиг, 1);
Если РабочийСимвол = "{" Тогда
СтекСкобок = СтекСкобок + 1;
ИначеЕсли РабочийСимвол = "}" Тогда
СтекСкобок = СтекСкобок - 1;
КонецЕсли;
Сдвиг = Сдвиг + 1;
КонецЦикла;
Возврат Сред(СтрокаОписанияНастроек, ПозицияНачалаСекции, Сдвиг);
КонецФункции
#КонецОбласти
Проверено на следующих конфигурациях и релизах:
- 1С:Зарплата и кадры бюджетного учреждения, релизы 1.0.121.2
Вступайте в нашу телеграмм-группу Инфостарт