Имя: Пароль:
1C
 
Таблица.ИсходнаяТаблица(...), Вызов из другого модуля.
0 twilight5023
 
10.03.06
14:23
Имеется внешний отчет report.ert, в нем есть таблица table, которая заполняется согласно определенному алгоритму. Пытаюсь запустить процедуру формирования этого отчета из другого модуля (call_report.ert), соответственно открываю форму ОткрытьФорму("Отчет",СписокПараметров,"report.ert");, в списке параметров передаю параметр "Автозапуск" = 1, который анализируется в report.ert, т.е. если это запуск из другого модуля, то формируем все автоматически и сохраняем файл. Однако при запуске на строке Таб.ИсходнаяТаблица("table"); он пишет не найден файл "table". Я так понимаю что поиск таблицы идет в вызвавшем модуле, а потом в общих таблицах? Можно ли как-нибудь указать чтобы таблица "table" искалась в report.ert, а не в call_report.ert?
1 Вильям
 
10.03.06
14:28
Приведи текст report.ert.
По крайней мере кусок, где ты создаешь таблицу и процедуру ПриОткрытии()
2 GrayT
 
10.03.06
14:32
На всякий случай проверь имя таблицы в report.ert
3 twilight5023
 
10.03.06
14:33
[report.ert]

Процедура Сформировать()
<...>
Таб = СоздатьОбъект("Таблица");
Таб.ИсходнаяТаблица("table");
Таб.ВывестиСекцию("Заголовок");
Таб.Опции(0, 0, Таб.ВысотаТаблицы());
<...>

< дальнейшее не ПриОткрытии(), а в коде после всех процедур в report.ert >

гПараметрыВызова = Форма.Параметр;
ПутьДляВыгрузки  = гПараметрыВызова.Получить("ПутьДляВыгрузки");
ФайлДляВыгрузки  = гПараметрыВызова.Получить("ФайлДляВыгрузки");
КодГруппы        = гПараметрыВызова.Получить("КодГруппы");
Автозапуск       = гПараметрыВызова.Получить("Автозапуск");
ФайлЛога         = гПараметрыВызова.Получить("ФайлЛога");
ДатаКонца        = гПараметрыВызова.Получить("ДатаКонца");
ДатаНачала       = гПараметрыВызова.Получить("ДатаНачала");
Номенклатура = СоздатьОбъект("Справочник.Номенклатура");
Номенклатура.НайтиПоКоду(КодГруппы);
ВыбТМЦ = Номенклатура.ТекущийЭлемент();

<...>

// Если форма была вызвана из другой (запущено роботом) - запускаем формирование
Если ПустоеЗначение(Автозапуск)=0 Тогда
   Если Автозапуск = 1 Тогда
       Сформировать();
       Форма.Закрыть(0);
   КонецЕсли;
КонецЕсли;


[call_report.ert]
СписокПараметров = СоздатьОбъект("СписокЗначений");
<...>
СписокПараметров.ДобавитьЗначение(1, "Автозапуск");
ОткрытьФорму("Отчет",СписокПараметров,"report.ert");
4 twilight5023
 
10.03.06
14:35
(2) Имя таблицы правильно, если просто ткнуть кнопку на которую привязано Сформировать() - все работает, а вот если вызывать из call_report.ert, то он почему-то ищет таблицу с именем table сначала в call_report.ert, потом в общих таблицах, а потом в файле. Естественно не находит, т.к. она находится в вызываемом report.ert, в принципе не проблема, можно вынести таблицу во внешний файл или перенести в общие, но как-то нехорошо это ;)
5 twilight5023
 
10.03.06
14:36
Просто не пойму почему он ищет таблицу в вызвавшем модуле, а не в том код которого исполняется на данный момент. Можно как-то в ИсходнаяТаблица(...) указать чтобы таблица бралась именно из report.ert?
6 Тык
 
10.03.06
14:40
Определи Таб на уровне модуля
7 twilight5023
 
10.03.06
14:44
(6)

[report.ert]
Перем Таб;
<...>
Процедура Сформировать()
<...>
Таб = СоздатьОбъект("Таблица");
Таб.ИсходнаяТаблица("table");
Таб.ВывестиСекцию("Заголовок");
Таб.Опции(0, 0, Таб.ВысотаТаблицы());
<...>

Результат тот же самый. Не там он ищет.
8 Shaman100M
 
10.03.06
14:45
(7) Перенеси "код после всех процедур" в процедуру ПриОткрытии() - она выполняется последней.
9 twilight5023
 
10.03.06
14:47
(8) А смысл? Код после всех процедур выполняется, Сформировать() запускается. Только он таблицу не там ищет.
10 twilight5023
 
10.03.06
14:48
(8) Оп-па... Ты гений ;) Если перенести все это в ПриОткрытии(), то работает. Интересно, а почему так? Разницы ведь вроде никакой?
11 Shaman100M
 
10.03.06
14:49
(9) ИМХО, может это связано именно с последовательностью событий при открытии формы?
12 Shaman100M
 
10.03.06
14:50
(11) Но ПриОткрытии() выполняется самой последней, после ВводНового(), ВводНаОсновании() и операторов в конце модуля.
13 twilight5023
 
10.03.06
14:52
(11) Ты прав... оказалось связано, но как-то уж очень неявно. Из описания метода исходная таблица: "Переназначает в качестве исходной таблицы-шаблона одну из таблиц той формы, в программном модуле которой запущена данная процедура. Имя таблицы сначала ищется в форме модуля, потом в общих таблицах. Если такой таблицы нет, то переданное имя будет рассматриваться как имя файла, содержащего данную таблицу" ... Все равно не понимаю, ведь и в том и в том случае Сформировать() по-идее должна запускаться в контексте report.ert, однако если мы запускаем ее из операторов в конце модуля, то на исполняется как бы от call_report.ert, а если из ПриОткрытии(), то в контексте report.ert. Фича наверное ;)
14 Shaman100M
 
10.03.06
14:55
(13) я уже не предполагаю, что - где, а принял за правило - "свободных операторов" не писать вообще.
15 Вильям
 
10.03.06
14:57
Использовать "код после всех процедур" - не очень хорошо с точки зрения хорошего стиля программирования. Не факт, что программу писать будете только Вы. Лучше, имхо, такие куски запихивать все же в ПриОткрытии(). Разбираться будет проще...
16 twilight5023
 
10.03.06
14:58
(14),(15) Да все вообщем-то правильно, просто до этого момента думал что между "свободными операторами" и ПриОткрытии() разница только в порядке исполнения. А оказывается еще и на контекст исполнения влияет. Теперь будем знать.
17 GrayT
 
10.03.06
14:59
Что то у меня не получилось смоделировать ситуацию. Нашел таблицу согласно 13
Движок какой?
18 twilight5023
 
10.03.06
15:00
20-й, SQL.
19 twilight5023
 
10.03.06
15:01
(17) Сейчас допишу, ради интереса на 25-м попробую...
20 twilight5023
 
10.03.06
15:26
(17) На 25-м то же самое, смотри как проще смоделировать... делаем две обработки, r1.ert в ней таблицу с именем r1, текст модуля:

//*******************************************
Процедура Сформировать()
Таб = СоздатьОбъект("Таблица");
Таб.ИсходнаяТаблица("r1");
Таб.Показать();
КонецПроцедуры

гПараметрыВызова = Форма.Параметр;
Автозапуск       = гПараметрыВызова.Получить("Автозапуск");
Если ПустоеЗначение(Автозапуск)=0 Тогда
   Если Автозапуск = 1 Тогда
       Сформировать();
       Форма.Закрыть(0);
   КонецЕсли;
КонецЕсли;

И файл r2.ert:

СписокПараметров = СоздатьОбъект("СписокЗначений");
СписокПараметров.ДобавитьЗначение(1, "Автозапуск");
ОткрытьФорму("Отчет",СписокПараметров,"r1.ert");

Таблицу r1 он не найдет.
21 twilight5023
 
10.03.06
15:28
+20: Однако если запихнуть код после процедур (r1.ert) в ПриОткрытии(), то все заработает.
22 GrayT
 
10.03.06
15:48
Хм, действительно.
Причем для встроенных в конфу отчета, такого не наблюдается.
Видимо проблема с тем, что пока проходит инициализация Таб. как объекта еще не существует :(
23 twilight5023
 
10.03.06
15:51
(22) В смысле "как объекта не существует"? Если ты сделаешь таблицу с именем "r1" в модуле r2.ert, то он ее оттуда и покажет. Здесь какой-то баг с контекстом исполнения.
24 twilight5023
 
10.03.06
15:53
+23: Согласно определению в (13) он ищет таблицу "программном модуле которой запущена данная процедура", только вот почему-то он считает что запуск произошел из r2.
25 GrayT
 
10.03.06
16:01
(23)Согласен, я даже попытался с контекстом поиграться - ни чего путного не получилось.
26 twilight5023
 
10.03.06
16:04
(25) Может это в 1С или в базу знаний?
27 АЛьФ
 
модератор
10.03.06
16:04
Могу объяснить подобное поведение на уровне движка. Интересует?
28 GrayT
 
10.03.06
16:05
(27)Да
29 twilight5023
 
10.03.06
16:05
(27) Конечно.
30 АЛьФ
 
модератор
10.03.06
16:23
Делов том, что открытие встроенной формы и внешней обработки реализовано разными функциями внутри движка. При этом для того, чтобы модуль воспринимал таблицы-шаблоны в нужном контексте необходим вызов метода "void CGetDoc7::SetTableSourceForms(class CWorkBookDoc *,unsigned int)".
Далее. Вызов на исполнение операторов "тела" модуля происходит после компиляции методом "int CBLModule::Execute(void)", а предопределенный процедур далее после некоторой дополнительной инициализации.
Суммируем и получаем. Для внешних обработок "SetTableSourceForms" вызывается после вызова "Execute", а для встроенных формы до.
Соответственно если запускается открытие внешней обработки из другой внешней, то в момент исполнения "тела" модуля второй обработки "SetTableSourceForms" уже вызвана для первой, но еще не вызвана для текущей исполняемой и движок настроен на поиск таблиц в первой внешней. И, наконец, если открытие второй внешней идет из "тела" первой, то и для первой еще не вызвана "SetTableSourceForms" и поиск таблиц будет только в общих таблицах.
Фух... Вроде так...
31 GrayT
 
14.03.06
11:42
(30)Сенкс. К сожалению с Си не силен, но общую идею, кажись, понял. (22) было относительно верным предположением :)