Имя: Пароль:
1C
 
Как из дерева значений сделать таблицу значений?
0 Чаппи
 
28.06.06
11:19
Как из дерева значений сделать таблицу значений?
1 clappa
 
28.06.06
11:23
// Выгружает колонки из дерева значений в таблицу значений, с возможностью иерархической выгрузки (с подчиненными строками)
//
// Параметры
//  Источник     – ДеревоЗначений, СтрокаДереваЗначений – объект-источник для выгрузки
//  Иерархически - Булево - признак необходимости выгружать подчиненные строки. По умолчанию - Истина
//  Колонки      - Перечень колонок для выгрузки
//                 Вариант 1: Значение Неопределено или "*" (по умолчанию) - в этом случае выгружаются все колонки
//                 Вариант 2: Строка - перечень имен колонок через запятую
//                 Вариант 3: Массив строк - имен колонок для выгрузки
//  ДобавитьКолонкуИсходнаяСтрока - Булево - Если Истина, то в результирующую таблицу значений будет добавлена колонка
//                 "ИсходнаяСтрока", значениями которой будут строки исходного дерева значений из которых заполнены соответствующе строки таблицы
//  КолонкиИсточника - Если в качестве источника в функцию передан объект "СтрокаДереваЗначений", то необходимо в данный параметр передать коллекцию колонок
//                 дерева значений, которому принадлежит строка. Это позволит программе настроить колонки результирующей таблицы значений
//                 в соответствии с настройками соответствующих колонок дерева, а также получить полный перечень имен колонок, если необходимо
//                 выгрузить все колонки (т.е. в параметре Колонки передано значение "*" или Неопределено)
//
// Возвращаемое значение:
//  Объект типа "ТаблицаЗначений"
//
Функция оВыгрузитьДеревоВТаблицуЗначений(Источник, Иерархически = Истина, Колонки = "*", ДобавитьКолонкуИсходнаяСтрока = Ложь, КолонкиИсточника = Неопределено, СЛУЖЕБНЫЙРезультат = Неопределено) Экспорт
   Перем КолонкиСтрокой, МассивКолонок, ИмяКолонки, ИсточникКолонка, Строка, ИсточникСтрока;
   Перем Результат;
   
   //Если передано дерево значений, можем получить настройки колонок, иначе необходимо, чтобы пользователь указал колонки в параметре "КолонкиИсточника"
   Если (КолонкиИсточника = Неопределено) и (ТипЗнч(Источник) = Тип("ДеревоЗначений")) Тогда
       КолонкиИсточника = Источник.Колонки
   КонецЕсли;
   
   КоолонкиСтрокой = "";
   Если (Колонки = "*") или (Колонки = Неопределено) Тогда
       //Необходимо заполнить полный список колонок по переданному описанию
       Если КолонкиИсточника <> Неопределено Тогда
           Для каждого ИсточникКолонка Из КолонкиИсточника Цикл
               КолонкиСтрокой = КолонкиСтрокой + "," + ИсточникКолонка.Имя
           КонецЦикла;
       КонецЕсли;
   ИначеЕсли ТипЗнч(Колонки) = Тип("Строка") Тогда
       КолонкиСтрокой = Колонки
   ИначеЕсли ТипЗнч(Колонки) = Тип("Массив") Тогда
       КолонкиСтрокой = ВСтрокуСРазделителями(Колонки, ",")
   КонецЕсли;
   
   Результат = СЛУЖЕБНЫЙРезультат;
   Если Результат = Неопределено Тогда
       Результат = Новый ТаблицаЗначений;
       МассивКолонок = ИзСтрокиСРазделителями(КолонкиСтрокой, ",");
       Для каждого ИмяКолонки Из МассивКолонок Цикл
           //Если есть определение для колонок источника, установим аналогичные параметры для колонок приемника,
           //иначе просто добавим нетипизированные колонки с определенными именами
           Если (КолонкиИсточника <> Неопределено) и (КолонкиИсточника.Найти(ИмяКолонки) <> Неопределено) Тогда
               ИсточникКолонка = КолонкиИсточника.Найти(ИмяКолонки);
               Результат.Колонки.Добавить(ИсточникКолонка.Имя, ИсточникКолонка.ТипЗначения, ИсточникКолонка.Заголовок, ИсточникКолонка.Ширина)
           Иначе
               Результат.Колонки.Добавить(ИмяКолонки)
           КонецЕсли;
       КонецЦикла;
       Если ДобавитьКолонкуИсходнаяСтрока Тогда
           Результат.Колонки.Добавить("ИсходнаяСтрока")
       КонецЕсли;
   КонецЕсли;
   
   Для каждого ИсточникСтрока Из Источник.Строки Цикл
       Строка = Результат.Добавить();
       Если КолонкиСтрокой <> "" Тогда
           ЗаполнитьЗначенияСвойств(Строка, ИсточникСтрока, КолонкиСтрокой)
       КонецЕсли;
       Если ДобавитьКолонкуИсходнаяСтрока Тогда
           Строка.ИсходнаяСтрока = ИсточникСтрока
       КонецЕсли;
       Если Иерархически и (ИсточникСтрока.Строки.Количество() > 0) Тогда
           оВыгрузитьДеревоВТаблицуЗначений(ИсточникСтрока, Иерархически, КолонкиСтрокой, ДобавитьКолонкуИсходнаяСтрока, КолонкиИсточника, Результат)
       КонецЕсли;
   КонецЦикла;
   
   Возврат Результат
КонецФункции

// Преобразует строку значений, перечисленных через символ-разделитель в массив или список значений
//
// Параметры
//  Строка - исходная строка
//  Разделитель - символ-разделитель значений в строке (по умолчанию - ",")
//  УдалятьОбрамляющиеКавычки - Булево или Неопределено - определяет режим обработки кавычек, обрамляющих значения (символы ' и ")
//         Если "Истина" - Функция проверяет наличие кавычек. Все символы, (в т.ч. символы-разделители),
//                         оказавшиеся внутри кавычек, считаются принадлежащими к значению.
//                         В итоговую коллекцию значения попадают без обрамляющих кавычек.
//         Если "Ложь"   - Функция проверяет наличие кавычек. Все символы, (в т.ч. символы-разделители),
//                         оказавшиеся внутри кавычек, считаются принадлежащими к значению.
//                         В итоговую коллекцию значения попадают вместе с обрамляющими кавычками.
//         Если "Неопределено" (по умолчанию) - Символы кавычек обрабатываются так же, как и все другие символы.
//                         Никакого специального контроля не производится.
//  ВернутьСписокЗначений - Булево - Если Ложь (по умолчанию), функция вернет объект типа "Массив", иначе
//                         функция вернет объект типа "СписокЗначений"
//
// Возвращаемое значение:
//  Массив или СписокЗначений
//
Функция ИзСтрокиСРазделителями(Знач Строка, Разделитель = ",", УдалятьОбрамляющиеКавычки = Неопределено, ВернутьСписокЗначений = Ложь) Экспорт
   Перем Результат, Поз, Имя, Имя2, ОткрытаКавычка;
   Результат = ?(ВернутьСписокЗначений = Ложь, Новый Массив(), Новый СписокЗначений());
   ОткрытаКавычка = "";
   Пока СтрДлина(Строка) > 0 Цикл
       Поз = Найти(Строка + Разделитель, Разделитель);
       Если (УдалятьОбрамляющиеКавычки <> Истина) и (УдалятьОбрамляющиеКавычки <> Ложь) Тогда
           //Не нужно контролировать наличие кавычек
           Результат.Добавить(СокрЛП(Лев(Строка, Поз - 1)));
           Строка = Сред(Строка, Поз + СтрДлина(Разделитель));
       Иначе
           Если ОткрытаКавычка = "" Тогда
               Имя = СокрЛ(Лев(Строка, Поз - 1)) //Начинаем чтение нового значения
           Иначе
               Имя = Имя + Лев(Строка, Поз - 1) //Продолжаем чтение предыдущего значения
           КонецЕсли;
           Строка = Сред(Строка, Поз + СтрДлина(Разделитель));
           //Проверим, не начинается ли новая строка с кавычки
           Если (ОткрытаКавычка = "") и ((Лев(Имя, 1) = """") или (Лев(Имя, 1) = "'")) Тогда
               ОткрытаКавычка = Лев(Имя, 1)
           КонецЕсли;
           //Проверим, есть ли закрывающая кавычка (двойные вхождения удалим)
           Если ОткрытаКавычка = "" Тогда
               Имя = СокрП(Имя)
           Иначе
               Имя2 = СтрЗаменить(Сред(Имя, СтрДлина(ОткрытаКавычка)+1), ОткрытаКавычка+ОткрытаКавычка, "");
               Если Найти(Имя2, ОткрытаКавычка) > 0 Тогда
                   Если (УдалятьОбрамляющиеКавычки = Истина) и (Прав(СокрП(Имя2), 1) = ОткрытаКавычка) Тогда
                       Имя = СтрЗаменить(Сред(Имя, СтрДлина(ОткрытаКавычка)+1, СтрДлина(СокрП(Имя))-2*СтрДлина(ОткрытаКавычка)), ОткрытаКавычка+ОткрытаКавычка, ОткрытаКавычка)
                   Иначе
                       Имя = СокрП(Имя)
                   КонецЕсли;
                   ОткрытаКавычка = "";
               КонецЕсли;
           КонецЕсли;
           //Если значение прочитано полностью - добавим к результату, иначе приплюсуем разделитель к значению
           Если (ОткрытаКавычка = "") или (Строка = "") Тогда
               Результат.Добавить(Имя)
           Иначе
               Имя = Имя + Разделитель
           КонецЕсли;
       КонецЕсли;
   КонецЦикла;
   Возврат Результат
КонецФункции

// Преобразует массив, список значений, структуру или соответствие в строку (перечисляя значения коллекции через символ-разделитель)
//
// Параметры
//  Коллекция - исходная коллекция
//  Разделитель - символ-разделитель значений в строке (по умолчанию - ",")
//
// Возвращаемое значение:
//  Строка
//
Функция ВСтрокуСРазделителями(Коллекция, Разделитель = ",") Экспорт
   Перем Результат, Элемент, ТипЗн;
   Результат = "";
   ТипЗн = ТипЗнч(Коллекция);
   Если (ТипЗн = Тип("Структура")) или (ТипЗн = Тип("Соответствие")) или (ТипЗн = Тип("СписокЗначений")) Тогда
       Для каждого Элемент Из Коллекция Цикл
           Результат = Результат + Разделитель + Элемент.Значение
       КонецЦикла
   Иначе
       Для каждого Элемент Из Коллекция Цикл
           Результат = Результат + Разделитель + Элемент
       КонецЦикла
   КонецЕсли;
   Возврат Сред(Результат, СтрДлина(Разделитель) + 1)
КонецФункции