Преобразование ТаблицыЗначений во Временную таблицу


Преобразование таблицы значений во временную таблицу.

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

 

Вот сами функции….

 

 

//————————————————
процедура ПреобразоватьТЗвВТ(ТЗ,МВТ,имяВТ)

    ТЗнов = ПреобразоватьТЗвТЗсОписаниемТипов(ТЗ);

    запрос = новый запрос;
   
запрос.МенеджерВременныхТаблиц = МВТ;
   
запрос.Текст = «ВЫБРАТЬ
                    | *
                    |ПОМЕСТИТЬ «
+ имяВТ+«
                    | ИЗ &ТЗнов КАК ТЗнов»
;
   
запрос.УстановитьПараметр(«ТЗнов»,ТЗнов);
   
запрос.Выполнить();

КонецПроцедуры

Функция ПолучитьТЗизВТ(МВТ,имяВТ)
   
//———————————
    // Выгружаем значение Временной таблицы(ВТ)
    // в ТаблицуЗначений (ТЗ)
    //———————————
   
запрос = новый запрос;
   
запрос.МенеджерВременныхТаблиц = МВТ;
   
запрос.Текст = «ВЫБРАТЬ * из «+имяВТ+» КАК ТЗ»;
   
ТЗ = Запрос.Выполнить().Выгрузить();
   
//———————————
   
возврат ТЗ;
КонецФункции
//————————————————

//———тех ФУНКЦИИ —————————-
функция ПреобразоватьТЗвТЗсОписаниемТипов(ТЗ)
   
//———————————————
    // Создаём новую ТЗ с описанием типов
    //———————————————
   
ТЗ_tmp2 = новый ТаблицаЗначений;
    для каждого
кол из ТЗ.Колонки Цикл
       
ОпТипов = ОпределитьОписаниеТиповПоляТЗ(ТЗ,кол.Имя);
       
ТЗ_tmp2.Колонки.Добавить(кол.Имя,ОпТипов);
    КонецЦикла;
   
//———————————————

    для каждого стр_t из ТЗ Цикл
       
стр_нов_t = ТЗ_tmp2.Добавить();
       
ЗаполнитьЗначенияСвойств(стр_нов_t,стр_t);
    КонецЦикла;
    возврат 
ТЗ_tmp2;
КонецФункции

функция ПолучитьТипы(мас)
   
//——————————————
    // Определяет все различные типы элементов
    //   встречающиеся  в массиве
    //——————————————
   
ТЗтипы = новый ТаблицаЗначений;
   
ТЗтипы.Колонки.Добавить(«Тип»);
   
ТЗтипы.Колонки.Добавить(«Индекс»);

    колво = мас.Количество();

    Если колво>0 тогда
       
стрТип = ТЗтипы.Добавить();
       
стрТип.Тип    = ТипЗнч(мас[0]);
       
стрТип.индекс = 0; // номер элемента в ТЗ с этим типом
       
предыдущ_тип  = стрТип.Тип; // предыдущее значение типа
   
КонецЕсли;

    для н = (0+1) по (колво1) Цикл
       
эл = мас[н];
       
типЭл = ТипЗнч(эл);
       
// Чтобы каждый раз не проверять тип по всему ТЗ, делаем проверку
        //   только когда он меняется
       
Если типЭл <> предыдущ_тип тогда
           
//——————-
            // теперь проверяем, есть ли у нас такой тип
           
ЦиклПрерван = 0;
            для каждого
стрТип из ТЗтипы Цикл
                Если 
стрТип.Тип = типЭл тогда
                   
ЦиклПрерван = 1;
                    Прервать;
                КонецЕсли;
            КонецЦикла;
           
//——————-
            // перебрали все наши типы и такого не нашли
           
Если ЦиклПрерван = 0 тогда
               
// добавляем в наш список
               
стрТип = ТЗтипы.Добавить();
               
стрТип.Тип    = типЭл;
               
стрТип.индекс = н; // номер элемента в ТЗ с этим типом
           
КонецЕсли;
           
//——————-
           
предыдущ_тип = типЭл;
        КонецЕсли;

    КонецЦикла;

    возврат  ТЗтипы;
конецФункции

функция ОпределитьОписаниеТиповПоляТЗ(ТЗ,имяКолонки)
   
мас1    = ТЗ.ВыгрузитьКолонку(имяКолонки);
   
тзТипов = ПолучитьТипы(мас1);

    //—————————————-
    // Собираем все типы в одином запросе
    //  для того чтобы получить составной тип
    //—————————————-
   
запрос= новый запрос;
   
н = 0;
    Если
тзТипов.Количество()>0 тогда
       
Запрос.Текст = «ВЫБРАТЬ &поле»+н+» как поле»;
       
запрос.УстановитьПараметр(«поле»+н, мас1[тзТипов[н].Индекс]);
    КонецЕсли;
   
колво = тзТипов.Количество();
    для
н = 0+1 по (колво1) Цикл
       
Запрос.Текст = Запрос.Текст + » ОБЪЕДИНИТЬ ВСЕ
                        |ВЫБРАТЬ &поле»
+н+» как поле»;
       
запрос.УстановитьПараметр(«поле»+н, мас1[тзТипов[н].Индекс]);
    КонецЦикла;

    ТЗ_tmp = запрос.Выполнить().Выгрузить();
   
//——————————-
   
возврат ТЗ_tmp.Колонки.поле.ТипЗначения;
КонецФункции

//————————————————

// Пример!!!
Процедура КнопкаВыполнитьНажатие(Кнопка)

    //———————————————-
    // Составляем произвольную ТЗ для проверки
    //———————————————-
   
ТЗ2 = новый ТаблицаЗначений;
   
ТЗ2.Колонки.Добавить(«поле1»);
   
ТЗ2.Колонки.Добавить(«поле2»);
   
ТЗ2.Колонки.Добавить(«поле3»);
   
ТЗ2.Колонки.Добавить(«поле4»);
   
стр = ТЗ2.Добавить();
   
стр.поле1 = 10.3434;
   
стр = ТЗ2.Добавить();
   
стр.поле1 = Справочники.Контрагенты.ПустаяСсылка();
   
стр = ТЗ2.Добавить();
   
стр.поле1 = Справочники.Контрагенты.ПустаяСсылка();
   
стр = ТЗ2.Добавить();
   
стр.поле1 = Справочники.Контрагенты.ПустаяСсылка();
   
стр = ТЗ2.Добавить();
   
стр.поле1 = Справочники.Номенклатура.ПустаяСсылка();
   
стр = ТЗ2.Добавить();
   
стр.поле1 = Справочники.Контрагенты.ПустаяСсылка();
   
стр.поле2 = 45.12;
   
стр.поле3 = 1;
   
стр.поле4 = 3;

    МВТ = новый МенеджерВременныхТаблиц;

    //———————————————————
    //Преобразование таблицы значений во временную таблицу
    //———————————————————
    //ПреобразоватьТЗвВТ(,,);
   
ПреобразоватьТЗвВТ(ТЗ2,МВТ,«ТЗЯху»);

    ТЗ_рез = ПолучитьТЗизВТ(МВТ,«ТЗЯху»);

    ТЗ_рез.ВыбратьСтроку();
КонецПроцедуры

 

 В качестве примера выложил обработку для 8.1, где это всё реализовано

 

50 Comments

  1. Serj1C

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

    Reply
  2. Famza

    Походу автор очень торопился выложить обработку. За оформление — минус

    Reply
  3. anton.fly7

    если ТЗ будет на 10000 строк, мне кажется замучаешься ждать

    Reply
  4. DimaP

    Авансом плюс!

    Часто сталкиваюсь с таким.

    С оформлением, конечно, лажа 🙂

    Reply
  5. Поручик

    (0) Полный атас. Тебя из какого класса церковно — приходской школы вытурили за полную безграмотность?

    Reply
  6. Поручик

    (0) Смотреть противно, как на бомжа, жрущего из помойки.

    Reply
  7. Поручик

    (0) Передо мной интереснейший бытовой материал: четыре больших тетради под общим заглавием «Дневник земского начальника».

    Автор дневника — земский начальник одной из южных губерний — вел его за свою службу с 1902 по 1909 год, записывая ежедневно перлы и адаманты поступающих бумаг.

    ……………….

    Невольно вспоминается одно ходившее по рукам в половине прошлого столетия письмо бурмистра к своему барину в Петербург, где также не было ни одного знака препинания. Письмо таково:

    — …Батюшка барин сивый жеребец Михалла Петрович помер шкуру вашу барскую содрали продали на вырученные деньги куплен хомут для вашей милости на ярмарке свиней вашей породы было много прошли хорошо жаль только что небыло самих вашей милости самолично потому соседи просили хряка на племя староста Антип.

    Далеко ли мы ушли от того времени?!

    Reply
  8. comol

    Мне лично всё равно до офрмления. за публикацию большой «+». Любую загрузку чего-либо пишу обычно преобразовывая ТЗ в ВТ (собственно как и все уже думаю) и каждый раз «убивает» очень «полезное» занятие с преобразованием типов. Автор реально помог, а вам нет чтобы «спасибо» написать…

    Reply
  9. AlexO

    (5) Поручик,

    это россиянский студент после ЕГЭ.

    Вы еще россиянских школьников не видели…

    Reply
  10. AlexO

    (7) Поручик,

    Далеко ли мы ушли от того времени?!

    деградации нет предела — до полного вымирания нации.

    Reply
  11. Поручик

    (8) Превратим инфостарт в полную помойку, чо уж там.

    Reply
  12. AlexO

    (8) comol,

    я, может, и отстал от продвинутых тру-1снигов, но всегда пользуюсь:

      Запрос.УстановитьПараметр(«ТЗ», ТЗ);
    Запрос.Текст =
    «ВЫБРАТЬ * из &ТЗ
    |ПОМЕСТИТЬ
    |    ВТ » ;
    |ВЫБРАТЬ *
    |ИЗ
    | &ВТ КАК ВТ
    |АВТОУПОРЯДОЧИВАНИЕ»;
    
    РезультатЗапроса = Запрос.Выполнить().Выгрузить(); 

    Показать

    Из ТЗ — в ВТ, потом снова в ТЗ. Кому нравится — могут и через МВТ сделать.

    Только зачем нужна ВТ из МВТ, когда есть уже готовая ТЗ??

    Reply
  13. AlexO

    (11) Поручик,

    страну же превращаем — чем инфостарт хуже? 🙁

    Reply
  14. comol

    (12) AlexO, Улыбнуло 🙂

    Reply
  15. tolyan_ekb

    Орфо рулит. )) Я когда увидел оформление, чуть не упал. Как модерацию прошла публикация?

    Reply
  16. Angeros

    Ну вообще плевое дело создать любой тип программно хоть составной хоть не составной. Есть в конфигураторе специальный конструктор. Который называется — конструктор описания типов. Изучайте мат часть, а не лепите огород на пустом месте. 🙂

    Reply
  17. AlexO

    (17) Angeros,

    я вообще не понял задачи. Так как её описания здесь нет.

    Одни восторги.

    Reply
  18. Поручик

    (16) Да так и прошла. Увидели, что есть новая, не глядя тупо нажали одобрить или разрешить.

    Reply
  19. AlexO

    да, еще оцените название — «Из ТЗ в ВТ», и описание-скрин: «таблицаЗначений из ВременнойТаблицы».

    Повторюсь, может я что-то упустил.

    Reply
  20. alexk-is

    Добавил в заметочки «Про таблицу значений«

    Reply
  21. i132

    (21), Мне кажется мой код будет быстрее работать и его легче читать:

       ТипизированнаяТЗ = Новый ТаблицаЗначений;
    Для й=1 По Тз.Количество() Цикл ТипизированнаяТЗ.Добавить(); //Создаем строки
    КонецЦикла;
    
    ДЗТипов = Новый ДеревоЗначений;
    ДЗТипов.Колонки.Добавить(«ИмяКолонки»);
    ДЗТипов.Колонки.Добавить(«ТипЗначений»);
    
    Для Каждого Колонка из Тз.Колонки Цикл
    СтрокаКолонки = ДЗТипов.Строки.Добавить();
    СтрокаКолонки.ИмяКолонки = Колонка.Имя;
    
    ТекСТрокаТипа = СтрокаКолонки.Строки.Добавить();
    ТекСТрокаТипа.ИмяКолонки = Колонка.Имя; //Заполняется для красоты
    ТекСТрокаТипа.ТипЗначений = ТипЗнч(тз[0][Колонка.Имя]);
    Для Каждого СтокаТЗ из Тз Цикл
    ТекТип = ТипЗнч(СтокаТЗ[Колонка.Имя]);
    Если НЕ ТекТип = ТекСТрокаТипа.ТипЗначений Тогда
    Если СтрокаКолонки.Строки.Найти(ТекТип, «ТипЗначений»)=Неопределено Тогда
    ТекСТрокаТипа = СтрокаКолонки.Строки.Добавить();
    ТекСТрокаТипа.ИмяКолонки = Колонка.Имя;//Заполняется для красоты
    ТекСТрокаТипа.ТипЗначений = ТекТип;
    КонецЕслИ;
    КонецЕслИ;
    КонецЦикла;
    
    МассивТипов = СтрокаКолонки.Строки.ВыгрузитьКолонку(«ТипЗначений»);
    ТипизированнаяТЗ.Колонки.Добавить(Колонка.Имя, Новый ОписаниеТипов(МассивТипов),Колонка.Заголовок);
    ТипизированнаяТЗ.ЗагрузитьКолонку(Тз.ВыгрузитьКолонку(Колонка),Колонка.Имя);
    КонецЦикла;
    

    Показать

    -зачем давать имена со смешанными англоРусскими буквами? (процедура ПреобразоватьТЗвТЗсОписаниемТипов(ТЗ) — ТЗ_tmp2) — это не уважение к тому кто будет перерабатывать код.

    орфографических ошибок не заметил.

    Reply
  22. Поручик

    (22) Модератор за него отредактировал. Первоначальный текст здесь, под датой 22.06.2012 07:12

    Reply
  23. sashapere

    (1) Serj1C, Извени Сергей но сайт посвящен 1с

    Reply
  24. sashapere

    (3) anton.fly7, Думаю 10000 прокатит нормально, просто перебрать разок нужно будет штобы все типы определить.

    Reply
  25. sashapere

    (5) Поручик, Слушайте умники здесь не русский язык изучаем.

    Reply
  26. sashapere

    (8) comol, Просто когда тоже столкнулся с очень увлекательным описанием типов, то понял что это дело лутше автоматизировать чем каждый раз мучатся

    Reply
  27. sashapere

    (12) AlexO, Если было былобы всё так просто то ваш код

    «ВЫБРАТЬ *

    |ПОМЕСТИТЬ ВТ

    |из &ТЗ КАК таблТЗ » ;

    ужебы давно работал, но втом-то !!!! вся и фишка , што вродебы должно работать но выдаёт следующюю ощибку:

    {Форма.Форма(221)}: Ошибка при вызове метода контекста (Выполнить): {(3, 4)}: Тип не может быть выбран в запросе

    из <<?>>&ТЗ КАК таблТЗ

    РезультатЗапроса = Запрос.Выполнить().Выгрузить();

    по причине:

    {(3, 4)}: Тип не может быть выбран в запросе

    из <<?>>&ТЗ КАК таблТЗ

    Reply
  28. sashapere

    (17) Angeros, Можно примерчик с конструктором описания типов???

    Reply
  29. Поручик

    (29) Ты гордишься своей безграмотностью? Это сейчас модно. Привет, Фурсенко!

    Reply
  30. sashapere

    (22) i132, ПРОВЕРИЛ!!!!, спасибо за пример, реально получилось, и в запрос таблица загналась, Буду разбираться как вы это сделали.

    Reply
  31. sashapere

    ————

    Reply
  32. Поручик

    (33) Комментарии про таких, как ты http://news.mail.ru/society/9361488/comments/?&thread=104866#comment_105788

    Reply
  33. sashapere

    (34) Поручик, Ладно впринцыпе согласен, с русским у меня косяк, даже на работе проблемы с этим, но я лучше попрограмирую на 1с вечерок чем буду сидеть и пить пиво в беседке.

    Reply
  34. ksnik

    (12) AlexO, хорошее решение, а я сразу не догадался(

    Запрос.УстановитьПараметр(«ТЗ», ТЗ);
    Запрос.Текст =
    «ВЫБРАТЬ * из &ТЗ
    |ПОМЕСТИТЬ
    |    ВТ » ;
    |ВЫБРАТЬ *
    |ИЗ
    | &ВТ КАК ВТ
    |АВТОУПОРЯДОЧИВАНИЕ»;
    
    РезультатЗапроса = Запрос.Выполнить().Выгрузить(); 

    Показать

    Reply
  35. Шёпот теней

    … при составления запроса из ТЗ — в конструкторе при изменении временной таблицы выскакивает форма, у которой можно, якобы, указывать ТИП колонки ВТ, но установленные типы при сохранении запроса не сохраняются и никак не запоминаются …

    … кто знает: просвятите — как этим пользоваться где и как ? … или для чего это существует ? …

    … вот …

    кстати: http://www.nastroy-ka.ru/mgeneral/12—1.html

    … хмВОТхм …

    Reply
  36. alexk-is

    (22) Добавил в заметочки Пример 10. Теперь можно поиграть вариантами заполнения, объемами данных и сравнить результаты на цифрах. 🙂

    Reply
  37. alexk-is

    (40) Это используется только в текущей сессии Конструктора. Помогает конструктору разбираться с типами данных и предлагать контекстно зависимые варианты разыменования, условий соединения и т.д.

    Reply
  38. sashapere

    (41) alexk-is, Спасибо за заметочки! чувствуется что не зря делал

    Reply
  39. Rustig

    (0)напишите, пожалуйста, несколько примеров, когда ТЗ надо засунуть в ВТ?

    у меня на практике пару раз возникало такое желание, но я его обходил как-то… а вот примеры из жизни уже вспомнить не могу.

    по поводу орфографии 🙂 — попробуйте перед публикацией писать в Word’е — чтоб другие не злились…

    Reply
  40. sashapere

    (45) Rustig, Был реальный пример когда, есть регистр сведений со списком всех загруженных файлов в базу и есть таблица с именами файлов на фтп которые нужно обработать причём там их много и старые и новые,так перегонял эту таблицу во временную и уже в запросе по этой таблице и регистру сведений отфильтровывал что загружалось а что нет.

    Reply
  41. Rustig

    (46) а чем способ использовать запросы лучше перебора ТЗ в цикле?

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

    пусть эта папка будет там же на фтп-шнике, можно назвать как угодно, например «Загруженные».

    метод в 1С для этого есть: Переместить(<Имя файла источника>, <Имя файла приемника>)

    а если структуру папок и файлов нельзя менять, непонятно зачем еще в 1С загружать?

    и что получается: что ваш запрос ежедневно обрабатывает все больше и больше записей? и через год система зависнет, дойдя до «критической массы»?

    Reply
  42. sashapere

    (47) Rustig, Там были свои особенности, ftp был открыт толко для чтения и периодически подчищался сам независимо от меня, проверить по отдельности каждый файл можно-былобы но скорость не та (пробовал так тоже)(список файлов большой порядка 50000 а список в регистре сведений ещё больше около пару милионов), поэтому и стал копать в сторону запроса чтобы за один проход сразу всё отсеять.

    Reply
  43. Rustig

    (48) Нагромождение на пустом месте… или пока на пустом месте? чем обусловлено «ftp был открыт только для чтения»?

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

    а если уже реализовано, что «ftp периодически подчищался сам независимо от меня», тогда надо этих админов (или программистов) попросить периодически переносить часть файлов, чтобы они наверняка не попадали в твой запрос.

    И самое главное, ты не ответил,

    «и что получается: что ваш запрос ежедневно обрабатывает все больше и больше записей? и через год система зависнет, дойдя до «критической массы»?»

    и на всякий случай, хочу узнать какого формата файлы?

    Reply
  44. Rustig

    (4), (8), (21) коллеги, помогите с примерами к вопросу (45)

    Reply
  45. alexk-is

    (51) Если есть необходимость в дальнейшем использовать в запросе таблицу значений, то её необходимо поместить во временную таблицу.

    Может быть, вопрос об использовании менеджера временных таблиц?

    Reply
  46. jobkostya1c8

    Я считаю вполне приличная идея для разработки средств контроля (и быстрой проверки результата), т.к. часто сталкиваюсь с задачами загрузки в ТЗ при переносе баз из разчиных АИС в 1С 8.2. Одно плохо, достаточно трудно создать универсальную функцию, которая еще бы правильно писала квалификаторы в ОписанииТипов. Поскольку у меня во входных файлах содержатся кучи ошибок пользователей «простому» автоматическому (как-бы назвать) подбору типа я не доверяю.

    Reply
  47. alex_shkut

    Многие задают вопрос: а зачем Вам это нужно?

    Нужно это затем, когда данные, полученные из БД запросом нужно обработать несколько раз.

    В моем случае. в таблицу-выборку добавлено еще 13 колонок. Это показатели, которые рассчитываются на основании друг-друга и данных исходной ТЗ.

    Например, средневзвешенные значения и производные. Короче говоря. посчитать такое в Одном вычисляемом поле нереально.

    Попробуйте подсчитать запросом трудодни при постоянной текучке…

    (Это я пример более понятный написал, в моем случае — кормодни в животноводстве)

    Или рассчитать формулу «Пока остаток больше нуля идем назад по событиям и подсчитываем те-же трудо- кормодни между событиями до нулевого остатка но не более месяца назад»

    Создайте пожалуйста мне в 1С такой запрос… уж мне проще циклами.

    А потом передать это все в СКД объектом.

    Если пытаться все это в СКД выполнить то:

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

    А что будет в 10-м вычисляемом поле? Вот поэтому я все вычисления произвожу с ТЗ.

    А запрос к ТЗ позволяет также отсортировать ТЗ по нужному мне для дальнейших вычислений полю.

    Выполнять расчеты, сворачивать ТЗ. снова сортировать запросом и снова обрабатывать.

    Reply
  48. alex_shkut

    Подписался на ответы…

    Reply
  49. dusha0020

    У меня не взлетело. Проверка на тип, чтобы не повторяться обрезает длины. В итоге у меня для всех строковых типов устанавливается длина последнего строкового реквизита, что обрезает данные во временной таблице и работать в запросе как нужно она уже не может. Придется писать преобразователь самому… 🙁

    Reply
  50. n_spb

    Спасибо, статья здорово помогла.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *