Адрес этой странички :
http://doc-prg.narod.ru/art_00104/art_00104.htm
Дата обновления : 08.08.2009
© 08.08.2009 Сергей Попов
1Cv7.
Некоторые полезные алгоритмы.
Справочники.
Статью в виде файла (12.4 кб) можно скачать здесь: art_00104.zip
1. Получить уникальный код в
справочнике по реквизиту
//Получить СЛЕДУЮЩИЙ уникальный код (по
заданному реквизиту) в заданном
справочнике
//Реквизит может иметь типы : Строка или
ЦЕЛОЕ Число.
//Если тип = СТРОКА, то все равно, содержание
реквизита должно быть ЦИФРОВЫМ !!!
//Ест-нно, что Реквизит должен иметь атрибут
"Сортировка"
//Производится проверка на переполнение
//Функция возвращает уникальный код (строка
ненулевой длины или ненулевое число в
зависимости от типа реквзита)
//Если неудачно, то пустую строку или число 0
(в зависимости от типа реквизита)
//Функция может располагаться в глобальном
модуле.
Функция сп_ПолучитьУникКодВСправочникеПоРеквизиту(ИмяСправ="Сотрудники",ИмяРеквДляПоиска="УникальныйКод")
Экспорт
//Res - возвращаемое значение.
// Уникальный код в справочнике ИмяСправ по
Реквизиту ИмяРеквДляПоиска.
// "" или 0 - НЕ удачно
Перем Res;
Перем ТипРекв;
Res=0;
ТипРекв=0;
YesOfCouse=0;
Длина=0;
Если Метаданные.Справочник(""+ИмяСправ).Выбран()>0
Тогда
//Справочник есть
Если Метаданные.Справочник(""+ИмяСправ).Реквизит(""+ИмяРеквДляПоиска).Выбран()>0
Тогда
//Реквизит есть
Sx=Метаданные.Справочник(""+ИмяСправ).Реквизит(""+ИмяРеквДляПоиска).Тип;
Если ВРег(Sx)=ВРег("Число")
Тогда
ТипРекв=1;
Res=0;
КонецЕсли;
Если ВРег(Sx)=ВРег("Number")
Тогда
ТипРекв=1;
Res=0;
КонецЕсли;
Если ВРег(Sx)=ВРег("Строка")
Тогда
ТипРекв=2;
Res="";
КонецЕсли;
Если ВРег(Sx)=ВРег("String")
Тогда
ТипРекв=2;
Res="";
КонецЕсли;
Если ТипРекв>0
Тогда
//Приемлемый
тип реквизита
Длина =
Метаданные.Справочник(""+ИмяСправ).Реквизит(""+ИмяРеквДляПоиска).Длина;
Если
Длина>0 Тогда //Перестрахуемся на всякий
случай
Сорт = Метаданные.Справочник(""+ИмяСправ).Реквизит(""+ИмяРеквДляПоиска).Сортировка;
Если Сорт>0 Тогда //Возможна сортировка
Если ТипРекв=1 Тогда
//Число
Точность = Метаданные.Справочник(""+ИмяСправ).Реквизит(""+ИмяРеквДляПоиска).Точность;
Если Точность <=0 Тогда //Перестрахуемся на
всякий случай, что это ЦЕЛОЕ число
YesOfCouse=1;
КонецЕсли;
КонецЕсли;
Если ТипРекв=2 Тогда
//Строка
YesOfCouse=1;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Если YesOfCouse>0 Тогда
//Все OK - продолжим
ПоследнийГерой2=1; //По умолчанию,
в справочнике ничего нет
Спр=СоздатьОбъект("Справочник."+ИмяСправ);
Спр.ПорядокРеквизита(""+ИмяРеквДляПоиска);
Спр.ОбратныйПорядок(1);
Если Спр.ВыбратьЭлементы(0)>0
Тогда
Если Спр.ПолучитьЭлемент(1)>0
Тогда
//Вычислим
след.код
ПоследнийГерой = Спр.ПолучитьАтрибут(""+ИмяРеквДляПоиска);
Если
ТипРекв=1 Тогда
ПоследнийГерой2=ПоследнийГерой+1;
КонецЕсли;
Если
ТипРекв=2 Тогда
//Строка
ПоследнийГерой2=ЧИСЛО(ПоследнийГерой)+1;
КонецЕсли;
КонецЕсли;
КонецЕсли;
//Вернем найденное значение в
формате заданного реквизита
Если ТипРекв=1 Тогда
//Тип реквизита -
число
Res=ПоследнийГерой2;
Если СтрДлина(СТРОКА(Res))>Длина
Тогда //Переполнение
Res=0;
КонецЕсли;
КонецЕсли;
Если ТипРекв=2 Тогда
//Тип реквизита -
строка
Res=СТРОКА(ПоследнийГерой2);
Если СтрДлина(Res)<=Длина
Тогда //Переполнения НЕТ
Если
СтрДлина(Res)<Длина Тогда
//Добавим ведущие нули до Длины Реквизита
Count=Длина-СтрДлина(Res);
i=0;
Пока i<Count Цикл
i=i+1;
Res="0"+Res;
КонецЦикла;
КонецЕсли;
Иначе
//Переполнение
Res="";
КонецЕсли
КонецЕсли;
КонецЕсли;
Возврат Res;
КонецФункции //сп_ПолучитьУникКодВСправочникеПоРеквизиту
2. Прозрачное копирование
элементов справочника(ов).
Функция сп_КопироватьЭлементСправочника(ТекЭлОС_откуда,ТекЭлОС_куда,СписОшибок="")
Скачать (3 Кб)
//ОБЯЗАТЕЛЬНОЕ Условие :
// Оба элемента справочника должны быть
выбраны (должны существовать).
//Из элемента "откуда" копируются
только те реквизиты, что существуют
//в элементе "куда" (по идентификатору).
//Копируются периодические и
непериодические реквизиты.
//При этом, проверяется соответствие типов и
"периодичности".
//Если реквизит-приемник имеет
неопределенный тип,
//то тип ему назначается по типу конкретного
значения реквизита-источника.
//Для периодических реквизитов НЕ
копируются значения источника
неопределенного типа
//и значения, где не задана дата.
//ФУНКЦИЯ ПРОИЗВОДИТ ЗАПИСЬ СКОПИРОВАННОГО
ЭЛЕМЕНТА В СПРАВОЧНИК !!!
//Если не было ошибок, то возвращается 1, в
противном случае, 0
//Если тип переменной СписОшибок =
СписокЗначений,
//то туда размещается список ошибок.
//Значение - код ошибки, строка - описание
ошибки
3. Универсальная функция чтения
Значения из элемента справочника.
//СпрМХ - ТекущийЭлемент
справочника (должен быть выбран)
//ИмяРеквизита - Идентификатор реквизита
справочника
//ТипЗн - возвращаемое значение :
ТипЗначения (строка).
//Функция возвращает "обычные" и
периодические реквизиты.
//Для периодического реквизита возвращает
значение на Дату (Дата99)
//Если Дата99 = "", то возвращается
ПустоеЗначение (для периодич.реквизита)
//"Понимает" ИмяРекв = [Код,
Наименование, Владелец, Родитель]
Функция сп_Реквизит_ВернутьЗначениеИзСправочника(СпрМХ,ИмяРеквизита,
ТипЗн, Дата99="") Экспорт
//23.01.2003 сп_
Перем Res; //Возвращаемое значение - Значение
Реквизита справочника
//ТипЗн - возращаемое значение Типа Значения
Реквизита
Res=ПолучитьПустоеЗначение();
ТипЗн="";
Если ТипЗначения(СпрМХ)=11 Тогда
Если СпрМХ.Выбран()>0 Тогда
Если Метаданные.Справочник(""+СпрМХ.Вид()).Выбран()>0
Тогда;
Yes=1;
Если
ВРег(СокрЛП(ИмяРеквизита))="КОД" Тогда
Yes=0;
Res=СпрМХ.Код;
ТипЗн=ВРег(ТипЗначенияСтр(СпрМХ.Код));
КонецЕсли;
Если
ВРег(СокрЛП(ИмяРеквизита))="НАИМЕНОВАНИЕ"
Тогда
Yes=0;
Res=СпрМХ.Наименование;
ТипЗн=ВРег(ТипЗначенияСтр(СпрМХ.Наименование));
КонецЕсли;
Если
ВРег(СокрЛП(ИмяРеквизита))="ВЛАДЕЛЕЦ"
Тогда
Yes=0;
Res=СпрМХ.Владелец;
ТипЗн=ВРег(ТипЗначенияСтр(СпрМХ.Владелец));
КонецЕсли;
Если
ВРег(СокрЛП(ИмяРеквизита))="РОДИТЕЛЬ"
Тогда
Yes=0;
Res=СпрМХ.Родитель;
ТипЗн=ВРег(ТипЗначенияСтр(СпрМХ.Родитель));
КонецЕсли;
Если Yes>0
Тогда
Если Метаданные.Справочник(""+СпрМХ.Вид()).Реквизит(""+ИмяРеквизита).Выбран()>0
Тогда
ЭтоПериодический=Метаданные.Справочник(""+СпрМХ.Вид()).Реквизит(""+ИмяРеквизита).Периодический;
Если ЭтоПериодический<=0 Тогда
Res=СпрМХ.ПолучитьАтрибут(""+ИмяРеквизита);
ТипЗн=ВРег(ТипЗначенияСтр((Res)));
Иначе
Если ДАТА(СокрЛП(Дата99))<>ДАТА(0) Тогда
Res=СпрМХ.ПолучитьАтрибут(""+ИмяРеквизита).Получить(ДАТА(СокрЛП(Дата99)));
ТипЗн=ВРег(ТипЗначенияСтр((Res)));
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Возврат Res;
КонецФункции //сп_Реквизит_ВернутьЗначениеИзСправочника
4.Проверка, существует ли
Справочник с идентификатором ИдСпр
//Функция возвращает 1, если существует и 0 в
противном случае
//ИдСпр - Идентификатор Справочника
Функция сп_СправочникСуществует(ИдСпр)
Экспорт
//_new_ 05.04.2003 сп_
Перем Res;
Res=0;
Если Метаданные.Справочник(""+СокрЛП(ИдСпр)).Выбран()>0
Тогда
Res=1;
КонецЕсли;
Возврат Res;
КонецФункции //сп_СправочникСуществует()
//----------------------------------------------------------------------
5. Проверка, существует ли
реквизит с идентификатором ИмяРекв в
справочнике с идентификатором ИмяСпр
//Функция возвращает 1, если существует и 0 в
противном случае
Функция сп_Реквизит_СправочникаСуществует(ИмяСпр,ИмяРекв)
Экспорт
//_new_ 02.02.2003 сп_
Перем Res;
Res=0;
ИмяСпр=СокрЛП(ИмяСпр);
ИмяРекв=СокрЛП(ИмяРекв);
Если Метаданные.Справочник(""+ИмяСпр).Выбран()>0
Тогда
Если Метаданные.Справочник(""+ИмяСпр).Реквизит(""+ИмяРекв).Выбран()>0
Тогда
Res=1;
КонецЕсли;
КонецЕсли;
Возврат Res;
КонецФункции //сп_Реквизит_СправочникаСуществует
6.Функция "вычисляет" тип и
вид реквизита справочника (из метаданных)
//ИмяСпр - идентификатор справочника
//ИдРекв - идентификатор реквизита
//В параметрах ТипРекв и ВидРекв
возвращается строковое значение Типа и
Вида реквизита
//В параметре ЭтоПериодический
возвращается 1, если реквизит периодический
и 0, если нет
/Функция возвращает такое же значение, как
функция ТипЗначения()
Функция сп_ПолучитьТипРеквизитаИзМетаданных(ИмяСпр,ИдРекв,ТипРекв,ВидРекв,ЭтоПериодический)
Экспорт
//_new_ 01.04.2003 сп_
Перем Res; //Возвращаемое значение : код типа
значения
Res = 0;
ТипРекв = "";
ВидРекв = "";
ЭтоПериодический = 0;
Yes=0;
Если Метаданные.Справочник(""+СокрЛП(ИмяСпр)).Выбран()>0
Тогда
Если Метаданные.Справочник(""+СокрЛП(ИмяСпр)).Реквизит(""+СокрЛП(ИдРекв)).Выбран()>0
Тогда
Yes=1;
ТипРекв = СокрЛП(Метаданные.Справочник(""+СокрЛП(ИмяСпр)).Реквизит(""+СокрЛП(ИдРекв)).Тип);
ВидРекв = СокрЛП(Метаданные.Справочник(""+СокрЛП(ИмяСпр)).Реквизит(""+СокрЛП(ИдРекв)).Вид);
ЭтоПериодический = Метаданные.Справочник(""+СокрЛП(ИмяСпр)).Реквизит(""+СокрЛП(ИдРекв)).Периодический;
КонецЕсли;
КонецЕсли;
Если Yes>0 Тогда
Если ВРег(ТипРекв) = ВРег("Число")
Тогда
Res=1;
КонецЕсли;
Если ВРег(ТипРекв) = ВРег("Строка")
Тогда
Res=2;
КонецЕсли;
Если ВРег(ТипРекв) = ВРег("Дата")
Тогда
Res=3;
КонецЕсли;
Если ВРег(ТипРекв) = ВРег("Перечисление")
Тогда
Res=10;
КонецЕсли;
Если ВРег(ТипРекв) = ВРег("Справочник")
Тогда
Res=11;
КонецЕсли;
Если ВРег(ТипРекв) = ВРег("Документ")
Тогда
Res=12;
КонецЕсли;
Если ВРег(ТипРекв) = ВРег("Календарь")
Тогда
Res=13;
КонецЕсли;
Если ВРег(ТипРекв) = ВРег("ВидРасчета")
Тогда
Res=14;
КонецЕсли;
Если ВРег(ТипРекв) = ВРег("Счет")
Тогда
Res=15;
КонецЕсли;
Если ВРег(ТипРекв) = ВРег("ВидСубконто")
Тогда
Res=16;
КонецЕсли;
КонецЕсли;
Возврат Res;
КонецФункции //сп_ПолучитьТипРеквизитаИзМетаданных()
7. Прочитать список реквизитов
справочника в СписокЗначений
(на основании инфы из метаданных)
//Дополнительно в СписокЗначений
включаются : Код, Наименование, Владелец,
Родитель
//Возвращаемое значение: СписокЗначений
// СТРОКА : ИдРеквизита
// ЗНАЧЕНИЕ : ТипЗначения
Функция сп_ПолучитьСписокРеквизитовСправочника(ИмяСпр)
Экспорт
//_new_ 01.04.2003 сп_
Перем Res;
Res = СоздатьОбъект("СписокЗначений");
Если Метаданные.Справочник(""+СокрЛП(ИмяСпр)).Выбран()>0
Тогда
Тип99 = "?";
Res.ДобавитьЗначение(Тип99,"Код");
Тип99 = "СТРОКА";
Res.ДобавитьЗначение(Тип99,"Наименование");
Тип99 = "?";
Res.ДобавитьЗначение(Тип99,"Владелец");
Тип99 = "?";
Res.ДобавитьЗначение(Тип99,"Родитель");
Колво = Метаданные.Справочник(""+СокрЛП(ИмяСпр)).Реквизит();
Если Колво>0 Тогда
i=0;
Пока i<Колво цикл
i=i+1;
ЭтоПериодический = Метаданные.Справочник(""+СокрЛП(ИмяСпр)).Реквизит(i).Периодический;
ИдРекв=СокрЛП(Метаданные.Справочник(""+СокрЛП(ИмяСпр)).Реквизит(i).Идентификатор);
ТипРекв="";
ВидРекв="";
ЭтоП=0;
Тип99 = сп_ПолучитьТипРеквизитаИзМетаданных(""+СокрЛП(ИмяСпр),ИдРекв,ТипРекв,ВидРекв,ЭтоП);
Res.ДобавитьЗначение(Тип99,ИдРекв);
КонецЦикла;
КонецЕсли;
КонецЕсли;
Возврат Res;
КонецФункции //сп_ПолучитьСписокРеквизитовСправочника()
8. Считывание значений реквизитов
Элемента Справочника <ТекЭлСпр99>
(элемент должен быть выбран) в
ТаблицуЗначений <ТЗ99>
//Периодические реквизиты читаются на
дату Дата99 (если не задана, то ТекущаяДата())
//Кроме реквизитов считываются : Код,
Наименование, Владелец, Родитель
//Функция возвращает : 0 - если ошибка, или >0
(кол-во строк в ТЗ99), если все OK
//Колонки ТЗ99 :
// ИдРеквизита - Идентификатор Реквизита
// ЗначРеквизита - Считанное значение
Реквизита
// ТипИзМетаданных - Тип и Вид Реквизита (как
задано в конфигураторе).
// [Определение Типа для Код, Наименование,Владелец
и Родитель - не реализовно]
// ТипПоЗначению - Тип и Вид Реквизита (по
факту значения)
// Периодический - Если = 1, то периодический,
в противном случае = 0
Функция сп_ПрочитатьРеквизитыЭлементаСправочника_в_ТЗ(ТЗ99,ТекЭлСпр99,Дата99="")
Экспорт
//_new_ 01.04.2003 сп_
Перем Res;
Res=0;
ТЗ99="";
ТЗ99 = СоздатьОбъект("ТаблицаЗначений");
ТЗ99.НоваяКолонка("ИдРеквизита");
ТЗ99.НоваяКолонка("ЗначРеквизита");
ТЗ99.НоваяКолонка("ТипИзМетаданных");
ТЗ99.НоваяКолонка("ТипПоЗначению");
ТЗ99.НоваяКолонка("Периодический");
Если ДАТА(СокрЛП(Дата99))=ДАТА(0) Тогда
Дата99=ТекущаяДата();
КонецЕсли;
Если сп_ЗначениеАгрегатногоТипаВыбрано(ТекЭлСпр99)>0
Тогда
СписРекв = сп_ПолучитьСписокРеквизитовСправочника(СокрЛП(ТекЭлСпр99.Вид()));
Спр = СоздатьОбъект("Справочник."+СокрЛП(ТекЭлСпр99.Вид()));
Если Спр.НайтиЭлемент(ТекЭлСпр99)>0
Тогда
ТекЭл = Спр.ТекущийЭлемент();
КолвоРеквизитов=СписРекв.РазмерСписка();
Если
КолвоРеквизитов>0 Тогда
НомРекв=0;
Пока
НомРекв<КолвоРеквизитов Цикл
НомРекв=НомРекв+1;
ИдРекв = "";
ТипРекв99 = СписРекв.ПолучитьЗначение(НомРекв,ИдРекв);
ИдРекв = СокрЛП(ИдРекв);
ТипЗн="";
V = сп_Реквизит_ВернутьЗначениеИзСправочника(ТекЭл,ИдРекв,
ТипЗн, Дата99);
ТЗ99.НоваяСтрока();
НомСтр = ТЗ99.КоличествоСтрок();
ТЗ99.УстановитьЗначение(НомСтр,"ИдРеквизита",ИдРекв);
ТЗ99.УстановитьЗначение(НомСтр,"ЗначРеквизита",V);
ТипРекв="";
ВидРекв="";
ЭтоПериодический=0;
Тип99 = сп_ПолучитьТипРеквизитаИзМетаданных(""+ТекЭл.Вид(),""+ИдРекв,ТипРекв,ВидРекв,ЭтоПериодический);
ТипЗн=ТипРекв;
Если СтрДлина(СокрЛП(ВидРекв))>0 Тогда
ТипЗн=ТипЗн+"."+ВидРекв;
КонецЕсли;
ТЗ99.УстановитьЗначение(НомСтр,"ТипИзМетаданных",ТипЗн);
ТипЗн = сп_Значение_ПолучитьТипВидСтр(V);
ТЗ99.УстановитьЗначение(НомСтр,"ТипПоЗначению",ТипЗн);
Если ЭтоПериодический>0 Тогда
ТЗ99.УстановитьЗначение(НомСтр,"Периодический",1);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Res=ТЗ99.КоличествоСтрок();
Возврат Res;
КонецФункции //сп_ПрочитатьРеквизитыЭлементаСправочника_в_ТЗ()
© 08.08.2009 Сергей Попов