Have a Snippet?

Keep, track and share your code snippets with your friends



1C 7.7: Набор универсальных функций для работы с наборами данных 1С Share on Vkontakte

Для работы с таблицей значений:
- глВТЗ, глИзТЗ Вместо Установить/Получить для сокращения записи
- глПечатьТЗ Выводит на печать любую таблицу значений
- глВзятьТаблицу Интеллектуальная функция для получения таблиц значений из различных объектов
- глДобавитьКолонкуВТаблицу Добавляет колонку и заполняет её значениями, полученными из других колонок
- глСоединитьТаблицы Формирует из двух таблиц одну
- глРазлицияТаблиц Сравнивает две таблицы по списку ключевых полей. Возвращает только различия
- глРаспределитьПропорционально Название говорит само за себя
- глИндексированнаяТаблица Добавляет колонку, в которую записывает внутренние идентификаторы указанных полей
Для работы со списками значений:
- глПараметры Подобие восьмерочного конструктора структуры. Создает список значений и заполняет его параметрами
- глВыбратьЗначение Чуть более функциональтая обёртка к стандартному методу
- глТекущееЗначение Более краткая запись получения текущего значения списка
- глПомеченныеЗначения Возвращает только значения, отмеченные галочками
Служебные и универсальные
- глВнутреннийИдентификатор Возвращает внутреннее 36-ричное представление объекта
- глЗаполнитьЗначения Аналог процедуры 1С8
- глКорректноеИмяРеквизита Убирает недопустимые для идентификатора символы из строки
- глэлементОчереди Получение подстроки из строки с разделителями

//******************************************************************************
Функция глМод(числ) Экспорт //возвращает значения числа "по модулю"
        Возврат ?(числ<0,-числ,числ);
КонецФункции     

//******************************************************************************
// глЭлементОчереди(Знач Очередь,Знач Разделитель, Знач Позиция)
Функция глЭлементОчереди(Знач Очередь, Знач Разделитель, Знач Позиция) Экспорт
        Если ПустаяСтрока(Очередь)=1 Тогда
                Возврат "";
        КонецЕсли;
        Если СтрЧислоВхождений(Очередь,Разделитель)<Позиция-1 Тогда
                Возврат "";
        КонецЕсли;
        ДлинаРазделителя = СтрДлина(Разделитель)-1;
        Пока Позиция>1 Цикл
                Позиция = Позиция-1;
                ПозицияРазделителя = Найти(Очередь,Разделитель);
                Очередь = Прав(Очередь,СтрДлина(Очередь)-ПозицияРазделителя-ДлинаРазделителя);
        КонецЦикла;
        Если СтрЧислоВхождений(Очередь,Разделитель)=0 Тогда
                Возврат Очередь;
        КонецЕсли;
        Возврат Лев(Очередь,Найти(Очередь,Разделитель)-1);
КонецФункции
        
//******************************************************************************
Функция глВнутреннийИдентификатор(Объект) Экспорт
        ТипОбъекта = ТипЗначенияСтр(Объект);
        Если Найти("Строка,Число,Дата",ТипОбъекта) > 0 Тогда
                Возврат СокрЛП(Строка(Объект));
        ИначеЕсли ТипОбъекта = "Справочник" Тогда
                ВнутреннееПредставление = ЗначениеВСтрокуВнутр(Объект.ТекущийЭлемент());
        ИначеЕсли ТипОбъекта = "Документ" Тогда
                ВнутреннееПредставление = ЗначениеВСтрокуВнутр(Объект.ТекущийДокумент());
        Иначе
                ВнутреннееПредставление = ЗначениеВСтрокуВнутр(Объект);
        КонецЕсли;
        ВнутреннееПредставление = СтрЗаменить(СтрЗаменить(ВнутреннееПредставление,"{",""),"}","");
        Идентификатор = СокрЛП(СтрЗаменить(глЭлементОчереди(ВнутреннееПредставление,",",7),"""",""));
        Если Найти(Идентификатор," ") > 0 Тогда
                // если идентификатор содержит в себе идентификатор вида,
                // то последний отсекается, нужен только идентификатор объекта
                Идентификатор = СокрЛП(Сред(Идентификатор,Найти(Идентификатор," ")));
        КонецЕсли;
        Возврат СокрЛП(_IdToStr(Идентификатор));
КонецФункции // глВнутреннийИдентификатор  

//******************************************************************************
Функция глИзТЗ(тз,СтрокаТЗ=0,КолонкаТЗ) Экспорт
        СтрокаТЗ = ?(СтрокаТЗ=0,тз.НомерСтроки,СтрокаТЗ);
        Попытка
                Возврат тз.ПолучитьЗначение(СтрокаТЗ,КолонкаТЗ);
        Исключение
                Сообщить(ОписаниеОшибки()+"; Строка: " + СтрокаТЗ + "/" + тз.КоличествоСтрок()+"; колонка: "+КолонкаТЗ,"!!");
                Возврат 0;
        КонецПопытки;
КонецФункции // ПолучитьЗначениеИзТЗ

//******************************************************************************
//Множитель: 0 - заменить значение, 1 - Прибавить к значению, -1 - вычесть из значения
Процедура глВТЗ(тз,СтрокаТЗ=0,КолонкаТЗ,ЗначениеТЗ,Множитель=0) Экспорт
        СтрокаТЗ = ?(СтрокаТЗ=0,тз.НомерСтроки,СтрокаТЗ);
        Попытка
                зн = ?(ТипЗначенияСтр(ЗначениеТЗ)="Число",?(Множитель=0,ЗначениеТЗ,глИзТЗ(тз,СтрокаТЗ,КолонкаТЗ)+ЗначениеТЗ*Множитель),ЗначениеТЗ);
                тз.УстановитьЗначение(СтрокаТЗ,КолонкаТЗ,зн);
        Исключение
                Сообщить(ОписаниеОшибки()+"; Строка: " + СтрокаТЗ + "/" + тз.КоличествоСтрок()+"; колонка: "+КолонкаТЗ+"; ("+ЗначениеТЗ+"*["+Множитель+"])","!!");
        КонецПопытки;
КонецПроцедуры // УстановитьВТЗ

//******************************************************************************
Функция глПечатьТЗ(тз,Показать=0) Экспорт
        Т = СоздатьОбъект("Таблица");
        Т.ИсходнаяТаблица("ТЗ");
        зн = "";
        Т.ВывестиСекцию("Заголовок|Начало");
        Для а = 1 По тз.КоличествоКолонок() Цикл
                зн = тз.ПолучитьПараметрыКолонки(а);
                Т.ПрисоединитьСекцию("Заголовок|Колонка");
        КонецЦикла;
        тз.ВыбратьСтроки();
        Пока тз.ПолучитьСтроку() = 1 Цикл
                Т.ВывестиСекцию("Строка|Начало");
                Для а = 1 По тз.КоличествоКолонок() Цикл
                        зн = глИзТЗ(тз,,тз.ПолучитьПараметрыКолонки(а));
                        Если СокрЛП(Строка(Число(зн))) = СокрЛП(Строка(зн)) Тогда
                                зн = Формат(зн,"Ч0.,");
                        ИначеЕсли ТипЗначенияСтр(зн) = "Справочник" Тогда
                                Если зн.Вид() = "ГотоваяПродукция" Тогда
                                        зн = зн.Код + " " + зн.Наименование;
                                КонецЕсли;
                        КонецЕсли;
                        Т.ПрисоединитьСекцию("Строка|Колонка");
                КонецЦикла;
        КонецЦикла;
        Т.ТолькоПросмотр(1);
        Если Показать = 1 Тогда
                Т.Показать();
        КонецЕсли;
        Возврат Т;
КонецФункции // глПечатьТЗ

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

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

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

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

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

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

//******************************************************************************
Функция глСоединитьТаблицы(Знач тз1,тз2) Экспорт
        Если ТипЗначенияСтр(тз1) <> "ТаблицаЗначений" Тогда
                тз1 = СоздатьОбъект("ТаблицаЗначений");
        КонецЕсли;
        Если ТипЗначенияСтр(тз2) <> "ТаблицаЗначений" Тогда
                Возврат тз1;
        ИначеЕсли тз2.КоличествоКолонок() = 0 Тогда
                Возврат тз1;
        Иначе
                // Колонки могут быть в другом порядке, тогда возникает неприятность
                // Поэтому вторая таблица приводится к виду первой
                тз2 = глВзятьТаблицу(тз2,глСписокКолонок(тз1));
        КонецЕсли;
        тз1.КоличествоСтрок(тз1.КоличествоСтрок()+тз2.КоличествоСтрок());
        тз1.Заполнить(тз2,тз1.КоличествоСтрок()-тз2.КоличествоСтрок()+1);
        Возврат тз1;
КонецФункции // глСоединитьТаблицы

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

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

//******************************************************************************
// Создает список значений, используется для быстрого создания списка параметров, необходимого для передачи между формами
// Параметры:
//              - ИменаПараметров - Строка с именами параметров через запятую
//              - Значение1,...,Значение10 - Значения параметров
Функция глПараметры(Знач ИменаПараметров,Значение1="",Значение2="",Значение3="",Значение4="",Значение5="",Значение6="",Значение7="",Значение8="",Значение9="",Значение10="") Экспорт
        Результат = СоздатьОбъект("СписокЗначений");
        ИменаПараметров = СтрЗаменить(ИменаПараметров," ","");
        Для а = 1 По СтрЧислоВхождений(ИменаПараметров,",")+1 Цикл
                зн = "";
                Если а < 11 Тогда
                        Шаблон("[глПрисвоить(зн,Значение"+а+")]");
                КонецЕсли;
                Результат.Установить(глЭлементОчереди(ИменаПараметров,",",а),зн);
        КонецЦикла;
        Возврат Результат;
КонецФункции // глПараметры

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

//******************************************************************************
Функция глТекущееЗначение(СписокЗначений,Позиция=0) Экспорт
        ТекЗначение = СписокЗначений.ПолучитьЗначение(СписокЗначений.ТекущаяСтрока());
        Если Позиция > 0 Тогда
                СписокЗначений.ТекущаяСтрока(Позиция);
        КонецЕсли;
        Возврат ТекЗначение;
КонецФункции // глТекущееЗначение

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


Tag: Таблица значений, Список значений, Универсальные функции, Полезные функции

1 Comments

  1. Avatar
    QbeeQ

    4th June 2013, 01:26

    А как тут вообще корректировка осуществляется?
    В функции "глИндексированнаяТаблица" ошибка, а исправить не могу