Имя: Пароль:
1C
1С v8
Запрос к внешней таблице. Использование результата запроса из другой базы.
0 CAPITALIST
 
06.09.11
08:08
нужно сверить соответствие счетов-фактур в двух разных базах. Не получается использовать таблицу, в которую выгружен результат запроса из внешней базы

ЗапросУПП = БазаУПП.NewObject("Запрос");

   ЗапросУПП.Текст = "ВЫБРАТЬ ПЕРВЫЕ 10 //чтоб быстрее

   |    СчетФактураВыданный.Ссылка КАК СчетФактура,

   |    СчетФактураВыданный.СуммаДокумента КАК Сумма,

   |    СчетФактураВыданный.ДокументОснование,

   |    ПОДСТРОКА(СчетФактураВыданный.Номер, 4, 8) КАК Номер, //а хорошо былобы в число преобразовать!

   |    НАЧАЛОПЕРИОДА(СчетФактураВыданный.Дата, День) КАК Дата

   |ИЗ

   |    Документ.СчетФактураВыданный КАК СчетФактураВыданный

   |ГДЕ

   |    СчетФактураВыданный.Проведен

   |    И СчетФактураВыданный.Дата МЕЖДУ &ДатаНач И &ДатаКон

   |    И СчетФактураВыданный.Грузополучатель = &Грузополучатель



   |УПОРЯДОЧИТЬ ПО

   |    СчетФактураВыданный.Дата";

   

ЗапросУПП.УстановитьПараметр("ДатаНач", НачалоГода(ТекущаяДата()));

ЗапросУПП.УстановитьПараметр("ДатаКон", КонецДня(ТекущаяДата()));

ЗапросУПП.УстановитьПараметр("Грузополучатель", БазаУПП.Справочники.Контрагенты.НайтиПоКоду("000000381"));

   

ТабУПП = ЗапросУПП.Выполнить().Выгрузить();
//Нормально выгружается, просмотреть результат можно
МенеджерВТ = Новый МенеджерВременныхТаблиц;



Запрос = Новый Запрос;

Запрос.Текст = "ВЫБРАТЬ

   |    Таб.Номер

   |ПОМЕСТИТЬ ТЧУПП

   |ИЗ

   |    &Таблица КАК Таб //РУГАЕТСЯ НА ЭТУ СТРОЧКУ!!!

   |;

   |ВЫБРАТЬ

   |    ТЧУПП.Номер";

//Пока возьмем только Номер    

Запрос.МенеджерВременныхТаблиц = МенеджерВТ;



Запрос.УстановитьПараметр("Таблица", ТабУПП);



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



БазаУПП = Null;
1 ZanderZ
 
06.09.11
08:13
(0) т.е. у тебя "СчетФактураВыданный.Ссылка" нормально передается ????
2 CAPITALIST
 
06.09.11
08:14
Передается как СОМ объект. но я же все равно во втором запросе это поле не беру. у Номера простейший тип Строка по-идее. Поэтому проблем не должно возникать!
3 ZanderZ
 
06.09.11
08:17
(2) ну так ты в запрос ВСЮ таблицу передаешь, а потом уже выбираешь номер строки
4 CAPITALIST
 
06.09.11
08:20
Только что убрал из первого запроса все поля кроме Номер. т.е. результат внешнего запроса теперь содержит поле базового типа. Та же ошибка. Может я вообще не тем путем пошел? а как по-другому взять доки из другой базы? да еще потом связать их по номеру и дате с доками текущей базы?
5 ZanderZ
 
06.09.11
08:23
(4) что за ошибка то ??
6 CAPITALIST
 
06.09.11
08:27
Ошибка при вызове метода методе выполнить. Неверные параметры "Таблица" <<?>>&Таблица КАК Таб.
Вот только если подставить табличку созданую в этой базе, с полем Номер, 10 строк. значения от 1 до 10, такой ошибки не возникает! но там я явно указываю тип поля у таблицы источника
7 zender
 
06.09.11
08:27
8 CAPITALIST
 
06.09.11
08:34
В принципе все я это делал. Мои действия не противоречат данной статье.
9 CAPITALIST
 
06.09.11
08:38
Как еще можно дернуть доки из другой базы?
далее я буду их связывать с докам текущей базы по Номер = НомерВходДока И Дата = ДатаВходДока
10 zender
 
06.09.11
08:59
(9) была похожая проблема, решал созданием отдельной ТЗ, с указанием типов колонок, в нее грузил данные из внешнего источника и засовывал в МВТ
11 CAPITALIST
 
06.09.11
09:08
сейчас также делаю. вот только у меня около 20000 строк в результате...
хорошо, а возможно ли преобразовать целую колонку в заполненной таблице? там что-то есть такое, только не разобрался как использовать

ТабУПП.Колонка.ИмяПоля.ТипЗначения
12 zender
 
06.09.11
09:11
Нет:

КолонкаТаблицыЗначений.ТипЗначения (ValueTableColumn.ValueType)
КолонкаТаблицыЗначений (ValueTableColumn)
ТипЗначения (ValueType)
Использование:

Только чтение.
Описание:

Тип: ОписаниеТипов. Содержит объект, описывающий допустимые типы значений для колонки.

Доступность:

Сервер, толстый клиент, внешнее соединение.
13 CAPITALIST
 
06.09.11
09:15
Хорошо, а можно в запросе (не к внешней базе, а к текущей) преобразовать Строку к числу?

ПОДСТРОКА(СчетФактураВыданный.Номер, 4, 8) КАК Номер,

убераю префикс, а дальше возможно в этом же запросе к числу преобразовать?
14 zender
 
06.09.11
09:17
можно, через конструкцию ВЫРАЗИТЬ
15 CAPITALIST
 
06.09.11
09:20
Эта функция работает только для полей, имеющих составной тип. Т.е. в данном случае Номер должен иметь тип и Строки и Числа, тогда бы работало
16 zender
 
06.09.11
09:31
17 VVi3ard
 
06.09.11
09:32
(10) прав нужно задать тип колонки.
Альтернатива это делать запрос к SQL данным но в твоем случае
(2000 строк) это из пушки по воробьям, 2000 строк добавятся в новую ТЗ секунд за 15 поэтому создавай Новую ТЗ с указанием типов колонок и с помощью ВыгрузитьКолонку/ЗагрузитьКолонку перекидывай данные из ТабУПП в новую ТЗ.

Если бы у тебя было 1,5-2 миллиона строк нужно было бы использовать ЗапросУПП.Выполнить().Выбрать() и по выборке формировать ТЗ. По сути Выгрузить() тоже по выборке бегает и формирует ТЗ по крайней мере в тестовых примерах
Выгрузить() или Выбрать + Цикл по Выборке с добавлением строк занимает сравнимое время.

А если больше то лучше написать SQL запрос.
18 Синий зуб
 
06.09.11
09:33
Вот проблема то. Добавь новую колонку с нужным типом в твою готовую ТЗ, заполни ее в цикле, грохни старую.
19 VVi3ard
 
06.09.11
09:35
(18) я о том же, человек считает что 2000 записей это много :)

У меня в принципе ТЗ меньше 20 000 редко встречаются :) 2000 строк в ТЧ это стандартный документ.
20 CAPITALIST
 
06.09.11
10:12
Нолик потеряли))) не 2000 а 20 тыщ. И таких запроса 3. И это не единственное поле которое нужно преобразовать! Видите как увеличиться время обработки!

Ахигеть, zender!!! Вот это настоящий изврат))) Но работает!!!
Спасибо!
21 zender
 
06.09.11
10:18
(20) пож-та)
22 VVi3ard
 
06.09.11
10:53
Процедура КнопкаВыполнитьНажатие(Кнопка)
   ТЗ=Новый ТаблицаЗначений;
   ОТСтрока = Новый КвалификаторыСтроки(8, ДопустимаяДлина.Фиксированная);
   НовКолонкаС=ТЗ.Колонки.Добавить("Колонка1",Новый ОписаниеТипов("Строка", ,ОТСтрока));
   Сообщить("Старт: "+ТекущаяДата());                                          
   Для сч=0 По 2000000 Цикл
       НовСтрТЗ=ТЗ.Добавить();        
       НовСтрТЗ.Колонка1=Строка(сч);
       сч=сч+1;
   КонецЦикла;    
   Сообщить("Финиш: "+ТекущаяДата());
КонецПроцедуры

Сколько у тебя выполняется код?
23 Serdolik55
 
06.09.11
11:01
У меня была похожая задача, делал так:


Процедура Соответствие_СФНажатие(Элемент)
   
   Соединение(СтрокаСоединения);
   ЗапросУд_ПоСФ = Соединение.NewObject("Запрос");
   ЗапросУд_ПоСФ.УстановитьПараметр("ДатаНачала",НачалоДня(ДатаНачала));
   ЗапросУд_ПоСФ.УстановитьПараметр("ДатаОкончания",КонецДня(ДатаОкончания));
   ЗапросУд_ПоСФ.УстановитьПараметр("ОрганизацияИНН", Контрагент.ИНН);
   ЗапросУд_ПоСФ.УстановитьПараметр("КонтрагентИНН",Организация.ИНН);
   
   ЗапросУд_ПоСФ.Текст = "ВЫБРАТЬ
                         |    НАЧАЛОПЕРИОДА(ДокСФ.Дата, ДЕНЬ) КАК Дата,
                         |    ДокСФ.Номер,
                         |    ДокСФ.СуммаДокумента
                         |ИЗ
                         |    Документ.СчетФактураВыданный КАК ДокСФ
                         |ГДЕ
                         |    ДокСФ.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания
                         |    И ДокСФ.Проведен
                         |    И ДокСФ.Организация.ИНН = &ОрганизацияИНН
                         |    И ДокСФ.Контрагент.ИНН = &КонтрагентИНН";
   
   Результат_СФ = ЗапросУд_ПоСФ.Выполнить();
   
   ТЗ_ПоСФ = Новый ТаблицаЗначений;
   //опишим типы данных колонок
   Массив_ПоСФ = Новый Массив;
   КД = Новый КвалификаторыДаты(ЧастиДаты.Дата);
   КЧ = Новый КвалификаторыЧисла(10,2);
   КС = Новый КвалификаторыСтроки(150);
   Массив_ПоСФ.Добавить(Тип("Дата"));
   Массив_ПоСФ.Добавить(Тип("Число"));
   Массив_ПоСФ.Добавить(Тип("Строка"));
   ОписаниеТиповТаблицы = Новый ОписаниеТипов(Массив_ПоСФ,КД ,КС ,КЧ);
   ТЗ_ПоСФ.Колонки.Добавить("Дата_Уд",ОписаниеТиповТаблицы);
   ТЗ_ПоСФ.Колонки.Добавить("Номер_Уд",ОписаниеТиповТаблицы);
   ТЗ_ПоСФ.Колонки.Добавить("СуммаДокумента_Уд",ОписаниеТиповТаблицы);
   
   //Сделаем выборку из результата запроса и заполним ТЗ
   ВыборкаУд_СФ = Результат_СФ.Выбрать();
   Пока ВыборкаУд_СФ.Следующий() Цикл
       НовСтр = ТЗ_ПоСФ.Добавить();
       НовСтр.Дата_Уд = ВыборкаУд_СФ.Дата;
       НовСтр.Номер_Уд = ВыборкаУд_СФ.Номер;
       НовСтр.СуммаДокумента_Уд = ВыборкаУд_СФ.СуммаДокумента;
   КонецЦикла;
   
   ТЗ_2 = ЗапросНаСоответсвиеСФ(ТЗ_ПоСФ).Выгрузить();
   ЭлементыФормы.ТЗ_2.СоздатьКолонки();
   
КонецПроцедуры

Функция ЗапросНаСоответсвиеСФ(ТЗ_ПоСФ)
   
   ЗапросРезультирующий = Новый Запрос;
   
   МВТ = Новый МенеджерВременныхТаблиц;
   ЗапросРезультирующий.МенеджерВременныхТаблиц = МВТ;
   ЗапросРезультирующий.УстановитьПараметр("ДатаНачала",НачалоДня(ДатаНачала));
   ЗапросРезультирующий.УстановитьПараметр("ДатаОкончания",КонецДня(ДатаОкончания));
   ЗапросРезультирующий.УстановитьПараметр("Организация",Организация);
   ЗапросРезультирующий.УстановитьПараметр("Контрагент",Контрагент);
   ЗапросРезультирующий.УстановитьПараметр("ТЗ_ПоСФ",ТЗ_ПоСФ);
   
   ЗапросРезультирующий.Текст =
   "ВЫБРАТЬ
   |ТЗ_ПоСФ.Дата_Уд КАК Дата_Уд,
   |ТЗ_ПоСФ.Номер_Уд КАК Номер_Уд,
   |ТЗ_ПоСФ.СуммаДокумента_Уд КАК СуммаДокумента_Уд
   |ПОМЕСТИТЬ
   |ТЗ_ПоСФ
   |ИЗ
   |&ТЗ_ПоСФ КАК ТЗ_ПоСФ";
   
   ЗапросРезультирующий.Выполнить();
   
   ЗапросРезультирующий.Текст = "ВЫБРАТЬ
                                |    ДокСФ.Ссылка,
                                |    НАЧАЛОПЕРИОДА(ДокСФ.Дата,ДЕНЬ) КАК Дата_Лок,
                                |    ТЗ_ПоСФ.Дата_Уд КАК ДатаВходящегоДокумента,
                                |    ДокСФ.СуммаДокумента КАК СуммаДокумента_Лок,
                                |    ТЗ_ПоСФ.СуммаДокумента_Уд КАК СуммаДокумента_Уд,
                                |    ТЗ_ПоСФ.Номер_Уд КАК НомерВходящегоДокумента,
                                |    ДокСФ.ДатаВходящегоДокумента,
                                |    ДокСФ.НомерВходящегоДокумента
                                |ИЗ
                                |    ТЗ_ПоСФ КАК ТЗ_ПоСФ
                                |        ЛЕВОЕ СОЕДИНЕНИЕ Документ.СчетФактураПолученный КАК ДокСФ
                                |        ПО ТЗ_ПоСФ.СуммаДокумента_Уд = ДокСФ.СуммаДокумента
                                |      И  ТЗ_ПоСФ.Дата_Уд = ДокСФ.Дата
                                |ГДЕ
                                |    ДокСФ.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания
                                |    И ДокСФ.Проведен
                                |    И ДокСФ.Организация = &Организация
                                |    И ДокСФ.Контрагент = &Контрагент
                                |
                                |УПОРЯДОЧИТЬ ПО
                                |    Дата_Лок";
                               
                                Рез = ЗапросРезультирующий.Выполнить();
                                Возврат Рез;
   
КонецФункции

Процедура ЗаполнитьВСФНажатие(Элемент)
   Выборка_СФ = ЗапросНаСоответсвиеСФ(ТЗ_ПоСФ).Выбрать();
   Пока Выборка_СФ.Следующий() Цикл
       ТекСФ = Выборка_СФ.Ссылка.ПолучитьОбъект();
       ТекСФ.ДатаВходящегоДокумента = Выборка_СФ.ДатаВходящегоДокумента;
       ТекСФ.НомерВходящегоДокумента = Выборка_СФ.НомерВходящегоДокумента;
       ТекСФ.Записать();
       Сообщение = Новый СообщениеПользователю;
       Сообщение.Текст = "Произошла замена реквизитов! Документ записан: " + ТекСФ.Ссылка;
       Сообщение.Сообщить();
   КонецЦикла;
   Сообщить("Обработка счет-фактур завершена!!!");
КонецПроцедуры
24 zender
 
06.09.11
11:03
(23) - это пример того, что я описал в (10)
25 Serdolik55
 
06.09.11
11:05
(24) Собственно да, более развёрнутый
26 VVi3ard
 
06.09.11
11:06
Через выборку как я писал в (17) более оптимально по памяти, но даже если через ТЗ то на таких смешных объёмах даже тупой код работает мгновенно.

Вот можно потестить:

Процедура КнопкаВыполнитьНажатие(Кнопка)
   ТЗ=Новый ТаблицаЗначений;
   ОТСтрока = Новый КвалификаторыСтроки(8, ДопустимаяДлина.Фиксированная);
   НовКолонкаС=ТЗ.Колонки.Добавить("Колонка1",Новый ОписаниеТипов("Строка", ,ОТСтрока));
   Сообщить("Старт: "+ТекущаяДата());                                          
   Для сч=0 По 2000000 Цикл
       НовСтрТЗ=ТЗ.Добавить();        
       НовСтрТЗ.Колонка1=Строка(сч);
       сч=сч+1;
   КонецЦикла;    
   Сообщить("Финиш: "+ТекущаяДата());
   
   ТЗ2=Новый ТаблицаЗначений;
   ОТЧисло = Новый ОписаниеТипов("Число",
             Новый КвалификаторыЧисла(10, 0, ДопустимыйЗнак.Неотрицательный));
   НовКолонкаС=ТЗ2.Колонки.Добавить("Колонка1",ОТЧисло);
   
   Сообщить("Старт выгрузка колонки: "+ТекущаяДата());                                          
   Тз2.ЗагрузитьКолонку(ТЗ.ВыгрузитьКолонку("Колонка1"),"Колонка1");
   Сообщить("Финиш выгрузка колонки: "+ТекущаяДата());                                          
КонецПроцедуры

У меня:
Старт: 06.09.2011 11:02:21
Финиш: 06.09.2011 11:02:29
Старт выгрузка колонки: 06.09.2011 11:02:29
Финиш выгрузка колонки: 06.09.2011 11:02:30