Кроме множественного выбора, в статье присутствует информация по:
Что имеется ввиду под множественным выбором в детальном разделе? Для наглядности, сразу хочу показать как работает этот механизм в готовом виде.
1. Есть некий справочник SimpleRef. Откроем карточку записи:
2. Выберем несколько записей справочника "Места появления затрат", затем нажмем Enter:
3. В результате в детальный раздел добавились 4 новые строки, первая строка — изменилась:
Также пропорционально количеству выбранных записей разделились суммы.
4. Повторим выбор еще раз, изменив значения полей Канал затрат и *НДС, %:
В итоге: 4-я строка изменилась, 6-9 строки добавились в соответствие с выбранными записями; Сумма с НДС строки 4 разбилась пропорционально между выбранными строками.
Необходимо реализовать механизм, который будет делать следующее:
Необходимо "навесить" соответствующий код на реквизит Место появления затрат — на нем и будет работать множественный выбор. В случае необходимости, можно это проделать и с другими реквизитами.
Процесс реализации условно можно разделить на 4 части:
1. Переопределение механизма выбора (SelectMode smLike\smSelect\smCard), так как стандартный механизм уже не будет работать.
2. Обработка вычислений у других реквизитов, которые срабатывают при добавлении строк и "сбивают" указатель с текущей строки.
3. Выделение из всех реквизитов детального раздела только тех, значения которых нужно передать в новые строки.
4. Заполнение необходимыми данными вновь создаваемых строк.
Код приведу с подробными комментариями, чтобы он был понятен и тем, у кого небольшой опыт разработки.
Размер кода получился большой в силу того, что кроме множественного выбора, там присутствуют переопределение механизма выбора и работа с событиями.
А вот и код:
EMPTY_STR = ''
// Объект IDataSet
DDS2 = Object.DetailDataSet(2)
// "Запомнить" текущее значение реквизита МПЗ на случай,
// если новое значение не будет выбрано
CostOrigPlaceValue = DDS2.CostOriginationPlaceT2
// Получить набор данных справочника "CostOriginationPlaces"
// со всеми записями
Ref = References.CostOriginationPlaces.GetComponent()
// Получить главное представление справочника
View = Ref.CreateView(Ref.MainViewCode)
// Установить отображения представления в режиме "Выбор"
View.ViewMode = vmSelect
// Разрешить множественный выбор
View.MultiSelection = true
// -------------------------------------------------------
// Переопределение пользовательского выбора из справочника
// Наложить фильтр по введенному значению, когда
// введен какой-то текст и затем нажата
// клавиша "Enter"
if SelectMode = smLike
// Недостаток такой фильтрации - она происходит уже
// на локальном компьютере, т.е. не накладывает
// ограничения на данные при запросе
Ref.Filtered = true
// Наименование - реквизит, по значениям которого
// накладывается фильтр
Ref.Filter = 'Наименование like "%' & InputValue & '%"'
endif
// Установить признак восстановления значения реквизита
// МПЗ к прежнему значению, если форма была показана
// и закрыта без выбора
Flag = true
// smLike при пустом тексте ввода не имеет смысла
if (SelectMode = smLike and InputValue <<>> EMPTY_STR)
or (SelectMode = smSelect)
// Показать форму
View.MainForm.Show
else
// Так как реквизит МПЗ не является обязательным,
// здесь обрабатывается ситуация, когда текст ввода
// просто очистили и сохранили карточку.
if not (SelectMode = smCard)
DDS2.CostOriginationPlaceT2 = EMPTY_STR
Flag = false
endif
endif
// Отключить фильтрацию
Ref.Filtered = false
// Выбрана хотя бы одна запись
if View.MainForm.Result = mrOK
// Заполнить реквизит МПЗ текущей строки значением
// первой из выбранных строк
IDRec = View.SelectedRecordsID(0)
DDS2.CostOriginationPlaceT2 =
References.CostOriginationPlaces.ObjectInfo(IDRec).Code
// ***Отключить события "При изменении реквизита"***
// Отключить события всех реквизитов и событий, у
// которых есть собственные вычисления, нарушающие
// механизм работы данного вычисления.
// Сами реквизиты и события определяются опытным путем.
// Альтернативный вариант - изменить сами вычисления
// на этих реквизитах и\или в событиях.
// "Сумма с НДС"
DDS2.Requisites('Цена2Т2').Events.Events(reOnChange).Enabled = false
// "*НДС, %"
DDS2.Requisites('NDSProcentT2').Events.Events(reOnChange).Enabled = false
DDS2Events = DDS2.Events
// Отключить событие "Добавление После" для детального раздела 2
DDS2Events.Events(dseAfterInsert).Enabled = False
// Проверить обязательный реквизит "*НДС, %" на означеность
if Assigned(DDS2.NDSProcentT2)
NDSRef = References.NDSProcents.GetObjectByCode(DDS2.NDSProcentT2)
else
NDSRef = EMPTY_STR
endif
NewSumNDS = null
NewSumOutNDS = null
// Получить новое значение реквизита "Сумма с НДС",
// разделив его на количество выбранных записей,
// если записей > 1
if Assigned(DDS2.Requisites('Цена2Т2').Value)
and (View.SelectedRecordCount > 1)
NewSumNDS = DDS2.Requisites('Цена2Т2').Value / View.SelectedRecordCount
DDS2.Requisites('Цена2Т2').Value = NewSumNDS
// Заполнить реквизит "Сумма без НДС"
// Рассчитать "вручную", так как событие отключено
if Assigned(NDSRef)
NewSumOutNDS = (NewSumNDS * 100) / (NDSRef.Цена1 + 100)
DDS2.Requisites('АmountT2').Value = NewSumOutNDS
endif
endif
AccountRefID = References.SimpleRef.GetComponent().ComponentID
// Получить наименования реквизитов детального раздела 2
// справочника.
// Такие системные реквизиты, как: XRecID, Vid, Analit,
// NumStr, XRecStat в выборку не попадают
QueryText = Format("select Kod
from MBVidAnRecv
where Vid = %s and Razd = %s";
ArrayOf(AccountRefID; "'С'") // "С" - Таблица 2
)
QuerySelectList = CreateQuery()
QuerySelectList.CommandText = QueryText
// Открыть набор данных запроса
QuerySelectList.Open
// Сделать текущей первую запись набора данных
QuerySelectList.First
// Создать список, в котором будет храниться информация
// вида (наименование реквизита ; значение реквизита)
RecvList = CreateList()
// Записать данные текущей строки:
// наименование реквизита - из SQL-запроса
// значение реквизита - из детального раздела
while not QuerySelectList.EOF
RecvList.Add(QuerySelectList.Kod; DDS2.Requisites(QuerySelectList.Kod).Value)
QuerySelectList.Next
endwhile
QuerySelectList.Close
Index = 1
while Index < View.SelectedRecordCount
// При множественном выборе добавить в
// детальный раздел 2 (количество выбранных строк - 1)
// и скопировать в них значения реквизитов
// текущей строки
RecvListItem = 0
// Добавить запись в конец набора данных и открыть ее
DDS2.Append
// "Пробежаться" по всем, выбранным SQL-запросом,
// реквизитам и заполнить соответствующими данными
while RecvListItem <= (RecvList.Count - 1)
DDS2.Requisites(RecvList.Names(RecvListItem)).Value = RecvList.Values(RecvListItem)
RecvListItem = RecvListItem + 1
endwhile
// Заполнить реквизиты, значения которых необходимо переопределить
IDRec = View.SelectedRecordsID(Index)
DDS2.CostOriginationPlaceT2 = References.CostOriginationPlaces.ObjectInfo(IDRec).Code
DDS2.Requisites('Цена2Т2').Value = NewSumNDS
DDS2.Requisites('АmountT2').Value = NewSumOutNDS
Index = Index + 1
endwhile
// Включить события
DDS2.Requisites('Цена2Т2').Events.Events(reOnChange).Enabled = true
DDS2.Requisites('NDSProcentT2').Events.Events(reOnChange).Enabled = true
DDS2Events.Events(dseAfterInsert).Enabled = true
NDSRef = nil
else
// Восстановить значение реквизита МПЗ, если не было выбрано новое
if Flag
DDS2.CostOriginationPlaceT2 = CostOrigPlaceValue
endif
endif
// Обработка режима выбора формы-карточки(Ctrl+F4)
if SelectMode = smCard
SelectFromReferenceAction('CostOriginationPlaces'; SelectMode; InputValue; DDS2.Requisites('CostOriginationPlaceT2'))
endif
Этот пример реализации множественного выбора под конкретную задачу, с которой я столкнулся. Не сомневаюсь, что он может быть оптимизирован, использован частично или существенно переработан для решения разных задач.
Андрей, великодушно благодарю за статью! Очень помогли!
Авторизуйтесь, чтобы написать комментарий