Способы выбора нескольких записей из списка

11 1

 

Одной из наиболее часто встречающихся задач является выбор ограниченного списка записей из некоторого множества (например: выбор нескольких организаций из справочника; выбор нескольких дел из номенклатуры дел; выбор нескольких населенных пунктов из всего множества населенных пунктов и т.п.)

Сразу оговорюсь: в статье рассматриваются способы выбора, при этом выбранные значения могут храниться как списком - в табличных частях, так и в реквизитах - перечислением через разделитель. Подробно способы хранения выбранных значений в этой статье не рассматриваются.

Итак, задачка не самая редкая и способов её решения существует несколько. Рассмотрим их:

 

Поля множественного выбора

Один из самых «красивых» способов решения задачи. Вся задача сводится к созданию и настройке на форме поля множественного выбора. Хорошо и подробно о полях множественного выбора написано в статье DIRECTUM 4.9. Поля множественного выбора

 

Однако использовать данную возможность можно начиная с версии 4.9. В более старых версиях такой возможности нет, поэтому придется использовать один из перечисленных ниже вариантов.

 

CSelectSQL

Используя функцию CSelectSQL (ПВыборSQL) можно вернуть список выбранных пользователем значений, предварительно загрузив в список для выбора необходимое множество.

 

Коды выбранных записей можно, допустим, поместить в некоторый строковый реквизит перечисленные через разделитель. Однако заранее необходимо просчитать сколько кодов сможет храниться в реквизите. Иначе может возникнуть ситуация когда, например, в строковый реквизит из 50 символов будут записываться коды 500 записей (плюс разделители), в итоге в реквизит запишутся только первые несколько кодов.

Пример на ISBL:

  DELIMITER = ';' & CR
  SELECTION_CANCELED = 'НЕУДАЧА: ESC!' 
  
  // Определить параметры диалога
  WindowTitle = 'Укажите подчиненные наши организации'
  OurOrgRefID = ИДТипСпр('НОР')
  Query = Format("
    select 
      NameAn
    from 
      MBAnalit
    where 
      Vid = %s"; 
    ArrayOf(OurOrgRefID))
	
  OurOrgs = CreateStringList()
  OurOrgs.Delimiter = DELIMITER 

  // Открываем окно для выбора организаций
  ChoiseResult = ПВыборSQL(WindowTitle; Query; DELIMITER; OurOrgs.DelimitedText)

  // Если выбор успешно завершен
  if ChoiseResult <<>> SELECTION_CANCELED 
    OurSelectedOrgs = CreateStringList()

    foreach OurOrgName in CSubString(ChoiseResult; DELIMITER)
      OurSelectedOrgs = AddSubString(OurOrgName; OurOrgs; DELIMITER)
    endforeach 
  endif 

Заполнение табличной части из справочника

Если множество значений для выбора являются записями некоторого справочника, то выбирать нужные записи можно прямо из справочника, а затем передать выбранные записи например в табличную часть.

 

Плюсом данного решения является использование всех возможностей справочников (фильтры, иерархии, like-ввод и т.д.)

Пример на ISBL:

  // Получить набор данных справочника "НОР" со всеми записями
  Reference = References.НОР.GetComponent()
  // Создать View для справочника 
  RefView = Reference.CreateView(Reference.MainViewCode)
  // Установить отображения представления в режиме "Выбор"
  RefView.ViewMode = vmSelect  
  // Разрешить выбор нескольких записей
  RefView.MultiSelection = TRUE
  RefViewFrom = RefView.MainForm  
  // Показать форму справочника
  RefViewFrom.Show
  
  // Если выбрана хотя бы одна запись
  if RefViewFrom.Result == mrOK     
    // Открыть набор данных перед началом работы
    Reference.Open()
    Reference.OpenRecord()
    // Получить детальный набор данных - таблицу подчиненных организаций
    OrgTable = Object.DetailDataSet(1)
    // Отключить обновление элементов управления (если записей много - чтоб не мерцало)
    OrgTable.DisableControls
    FreeException()
    ExceptionsOff()    

    // Создать индикатор 
    Progress = CreateProgress('Добавление подчиненных организаций'; RefView.SelectedRecordCount; False)
    Progress.Show   
    I = 0
    
    // Занести выбранные записи справочника в таблицу подчин.организаций
    while I < RefView.SelectedRecordCount
      IDRec = RefView.SelectedRecordsID(I)
      RecCode = References.НОР.ObjectInfo(IDRec).Code                           
      
      // Если выбранной строки нет в таблице подчин.организаций, то вставить её 
      if not OrgTable.Locate('НашиОрг'; RecCode)
        OrgTable.Append             
        OrgTable.Requisites('НашиОрг').Value = RecCode
      endif 
      I = I + 1
      Progress.Next
    endwhile 
    Progress.Hide
    // Включить обновление элементов управления
    ExceptionsOn()
    OrgTable.EnableControls
    LastException = GetLastException()
    
    // Если возникло исключение во время отключения обновления элементов управ-я
    if not VarIsClear(LastException)
      Exit(LastException.Message)
    endif
    // Закрыть набор данных после работы
    Reference.CloseRecord
    Reference.Close  
  endif 

DualListDialog

Используя функцию DualListDialog (СоздатьДиалогВыбораИзДвухСписков) можно создать диалог с двумя списками. В один из которых занести множество записей для выбора, а второй список вернёт выбранные пользователем значения.

Пример на ISBL:

  // Создать двойной список
  DualList = CreateDualListDialog('Выбор организаций')
  DualList.Title = 'Выбор организаций'
  DualList.AvailableItemsTitle = 'Все организаций'
  DualList.SelectedItemsTitle = 'Выбранные организации'
  
  Orgs = CreateReference('НОР') 
  
  // Заполнить список выбора значениями
  foreach Org in Orgs
    DualList.AvailableItems.Add(Org.Requisites('Наименование').Value)
  endforeach
  
  // Показать список
  DualList.Execute()
  
  // Отобразить выбранные значения списка 
  EditText(DualList.SelectedItems.Text)

Иерархии

По сути это решение представляет собой модификацию одного из предыдущих решений. Суть заключается в выборе не нескольких значений из списка, а только одного, узлового значения в иерархии. В этом случае не придется хранить весь список значений в таблице или в реквизите через разделители. Достаточно одного родителя, все остальные, дочерние записи можно вычислить.

Минусы: Иерархии появились только в версии 4.8. Использовать решение можно будет только применяя справочники.

 

Возможно существуют еще способы решения этой задачи, я ничего не упустил?

Отредактировал Алексей Тутаев, 16.04.2013 в 11:47
Отредактировал Алексей Тутаев, 16.04.2013 в 11:50
Отредактировал Алексей Тутаев, 16.04.2013 в 12:05
Отредактировал Алексей Тутаев, 16.04.2013 в 12:24
Отредактировал Елена Питомцева, 16.04.2013 в 12:43
11
Авторизуйтесь, чтобы оценить материал.
1
Дмитрий Гойнаш

Заполнение табличной части из справочника

Пример не совсем корректен. Я строчки

Reference.Open()
Reference.OpenRecord() 

переставил сразу после Reference = References.НОР.GetComponent()

 

 

Авторизуйтесь, чтобы написать комментарий