| 
 
  
	| Урок PL/PLUS. Печать в Word На страницу 1, 2  След.
 
 |  
	
		| Предыдущая тема :: Следующая тема |  
		| Автор | Сообщение |  
		| German Профи
 
 
 Вступление в Клуб: 25.06.2007
 
 | 
			
				|  Чт Июн 30, 2011 21:05   Урок PL/PLUS. Печать в Word |   |  
				| Полезность: 5 
 |  
				| Недавно в новом банке делал операцию, печатающую в Word. Собственного шаблона под рукой (в который раз! ) не оказалось, поэтому решил (в который раз :) ) написать "с нуля". Попутно законспектировал пройденные шаги, и получился вот такой урок с минимальным набором действий для печати в Word.
 
 1. Сначала лучше сразу сделать шаблон Word (.dot)
 В принципе, можно обойтись и без шаблона, но это скорее исключение. Обычно печать в Word предполагает наличие шаблона, в котором ЦФТ просто заполняет текстовые поля.
 
 1.1. Добавить в документ Word текстовые поля
 С созданием простых текстовых полей в свежих навороченных версиях Word есть заморочки (надо включать какую-то доп. панель, использовать какой-то "старый режим" и т.п.), поэтому я просто открыл первый попавшийся дистрибутивный шаблон (из каталога отчетности, если не знаете где это - см. ниже п. 1.3) и скопировал оттуда первое встреченное текстовое поле в свой новый аккуратный шаблончик.
 Дальше остаётся лишь зайти в "Свойства" текстового поля и указать нужное имя, например "test_word"
 
 1.2. Документ сохранить с расширением .dot
 Это не требование программы ЦФТ, а просто принятый удобный способ.
 Можно сохранить шаблонный файл и с расширением .doc (.docx), но тогда будет открываться именно этот файл и при дальнейшем сохранении Вы можете случайно перезаписать шаблонный документ (при наличии прав на каталог с шаблонами).
 Поэтому спокойнее и удобнее сохранять с расширением .dot, например "test.dot"
 
 1.3. Полученный шаблон выложить в каталог, указанный в справочнике "Системные параметры" в настройке РАТН_PRINT_DOC
 Опять же, это просто принятое соглашение о едином месте хранения шаблонов Word, но не техническое ограничение ЦФТ.
 Программа может открыть файл из любого доступного на чтение каталога, более того, при разработке я обычно работаю с шаблоном из локального каталога.
 Но, чтобы не усложнять урок, сразу выложим шаблон в "правильный" каталог.
 
 2. Теперь можно приступить к созданию операции
 
 2.1. Дополнительные свойства
 При смене элемента управления: "Сервер, Клиент"
 И, разумеется, флаг "Может быть активизирована пользователем"
 
 2.2. Переменные
 Нужна служебная переменная, обычно её объявляют так: "Строка для передачи данных" – V_DATA – Строка_2000
 
 2.3. Экранная форма
 На экранную форму вывести переменную V_DATA, присвоить ей ValidateName = TextData (это техническое требование клиентскрипта, именно TextData и ни как иначе). Обычно переменную делают невидимой, чтобы никого не смущать, но иногда на время отладки оставляют видимой.
 Для кнопки ОК, разумеется, задать CheckValidate = True
 
 2.4. Клиент-скрипт
 
 
  	  | Код: |  	  | ' подгружаем библиотеку "Библиотека VBA функций для печати в Word" '#include ::[RUNTIME].[MSWORD SCRIPT]
 
 Public Function Main(LastControl)
 On Error Resume Next
 If LastControl Is ОК Then
 ' Действия при загрузке формы
 
 if not OpenWordDoc(WrdApp, W, GetData("REPORTFILE")) then
 Msgbox "Невозможно открыть файл!"
 Main = False
 Exit Function
 end if
 
 Call SetAIIFormFields(WrdApp, W) 'заполним только имеющиеся в шаблоне поля
 Call SetWordVisible(WrdApp, W)
 
 Else
 'Действия при потере фокуса валидируемого контрола LastControl
 End If
 
 Main = True 'Результат валидатора (True, False, NULL)
 End Function
 | 
 
 "Закомментированную" строку '#include ::[RUNTIME].[MSWORD SCRIPT] оставить обязательно!
 Как работает этот компактный скрипт, написано ниже
 Либо можно подсмотреть детали как раз в ::[RUNTIME].[MSWORD SCRIPT]
 
 2.5. Локальные описания
 В режиме VALIDATE клиент-скрипт по очереди считывает из документа содержащиеся в нем текстовые поля и по каждому из найденных полей обращается с "вопросом" чем заполнить поле.
 Но сначала клиент-скрипт задаст два обязательных вопроса: 'REPORTFILE' и 'REPORTPATH', чтобы понять, какой файл открывать.
 
 
  	  | Код: |  	  | begin if p_message = 'VALIDATE' then
 V_DATA := '';
 if p_info = 'REPORTFILE' then
 V_DATA := 'test.dot';
 elsif p_info = 'REPORTPATH' then
 V_DАТА := [SYSTEM PARAMS]::[GET]('РАТН_PRINT_DOC',null);
 elsif p_info = 'test_word' then -- первое и единственное поле примера
 V_DATA := 'РАБОТАЕТ!!!';
 -- и т.д. для каждого из текстовых полей шаблона
 end if;
 end if;
 end;
 | 
 
 Готово. Буду рад комментариям/дополнениям.
 _________________
 Homo homini
 |  |  
		|  |  
		| lexus Профи
 
 
 Вступление в Клуб: 28.09.2007
 
 | 
			
				|  Пт Июл 01, 2011 04:59    |   |  
				| Полезность: Нет оценки 
 |  
				| Добавьте еще пример заполнения одного конкретного поля в шаблоне. Для завершенности картины
  |  |  
		|  |  
		| vadim.corostelev Участник
 
 
 Вступление в Клуб: 06.05.2011
 
 | 
			
				|  Пт Июл 01, 2011 06:08    |   |  
				| Полезность: Нет оценки 
 |  
				| Хороший материал. Для начала "возни" - самое то. |  |  
		|  |  
		| hicap Участник
 
 
 Вступление в Клуб: 13.10.2010
 
 | 
			
				|  Ср Июл 13, 2011 10:10    |   |  
				| Полезность: Нет оценки 
 |  
				|  	  | lexus пишет: |  	  | Добавьте еще пример заполнения одного конкретного поля в шаблоне. Для завершенности картины
  | 
 
 Пример для РКО, возвращает должность с признаком руководителя. На договоре РКО запускаем новую созданную операцию описанную выше.
 
 
  	  | Код: |  	  | if p_info = 'test_word' then
 begin
 for x in [CL_CORP] all
 where x%id = this.[client]%id
 loop
 for y in x.[ALL_BOSS]
 where y.[CHIEF] = true
 loop
 v_data:=v_data||'; '||y.[RANGE].[VALUE];
 end loop;
 end loop;
 exception when OTHERS then
 v_data:='';
 end;
 end if;
 
 | 
 |  |  
		|  |  
		| ggrey Участник со стажем
 
 
 Вступление в Клуб: 01.10.2007
 
 | 
			
				|  Ср Июл 13, 2011 11:17    |   |  
				| Полезность: Нет оценки 
 |  
				|  	  | hicap пишет: |  	  |  	  | lexus пишет: |  	  | Добавьте еще пример заполнения одного конкретного поля в шаблоне. Для завершенности картины
  | 
 
 Пример для РКО, возвращает должность с признаком руководителя. На договоре РКО запускаем новую созданную операцию описанную выше.
 
 
  	  | Код: |  	  | if p_info = 'test_word' then
 begin
 for x in [CL_CORP] all
 where x%id = this.[client]%id
 loop
 for y in x.[ALL_BOSS]
 where y.[CHIEF] = true
 loop
 v_data:=v_data||'; '||y.[RANGE].[VALUE];
 end loop;
 end loop;
 exception when OTHERS then
 v_data:='';
 end;
 end if;
 
 | 
 | 
 
 Немного покритикую.
 Несмотря на то, что именно при решении этой задачи, можно написать любой код и никто не пострадает от потери производительности, использовать в этой ситуации два курсора очень плохой стиль. Так же exception when OTHERS здесь не нужен.
 |  |  
		|  |  
		| hicap Участник
 
 
 Вступление в Клуб: 13.10.2010
 
 | 
			
				|  Ср Июл 13, 2011 11:22    |   |  
				| Полезность: Нет оценки 
 |  
				|  	  | ggrey пишет: |  	  |  	  | hicap пишет: |  	  |  	  | lexus пишет: |  	  | Добавьте еще пример заполнения одного конкретного поля в шаблоне. Для завершенности картины
  | 
 
 Пример для РКО, возвращает должность с признаком руководителя. На договоре РКО запускаем новую созданную операцию описанную выше.
 
 
  	  | Код: |  	  | if p_info = 'test_word' then
 begin
 for x in [CL_CORP] all
 where x%id = this.[client]%id
 loop
 for y in x.[ALL_BOSS]
 where y.[CHIEF] = true
 loop
 v_data:=v_data||'; '||y.[RANGE].[VALUE];
 end loop;
 end loop;
 exception when OTHERS then
 v_data:='';
 end;
 end if;
 
 | 
 | 
 
 Немного покритикую.
 Несмотря на то, что именно при решении этой задачи, можно написать любой код и никто не пострадает от потери производительности, использовать в этой ситуации два курсора очень плохой стиль. Так же exception when OTHERS здесь не нужен.
 | 
 
 Напиши как ты считаешь правильным. Можно и через обычный селект конечно вывести все должности с признаком руководителя.
 |  |  
		|  |  
		| hicap Участник
 
 
 Вступление в Клуб: 13.10.2010
 
 | 
			
				|  Ср Июл 13, 2011 11:27    |   |  
				| Полезность: Нет оценки 
 |  
				| и даже через селект все равно придется в цикл входить, что бы вывести все должности с признаком руководителя, а от этого получится слишком громоздкий код чем с двойным циклом. |  |  
		|  |  
		| ggrey Участник со стажем
 
 
 Вступление в Клуб: 01.10.2007
 
 | 
			
				|  Ср Июл 13, 2011 11:35    |   |  
				| Полезность: Нет оценки 
 |  
				| ленивый вариант 
  	  | Код: |  	  | if p_info = 'test_word' then
 for x in this.[client].[ALL_BOSS] where x.[CHIEF] = true
 loop
 v_data:=v_data||'; '||x.[RANGE].[VALUE];
 end loop;
 end if;
 
 | 
 
 более быстрый вариант (не максимально)
 
  	  | Код: |  	  | if p_info = 'test_word' then
 for (select x(x.[RANGE].[VALUE] : val)
 in this.[client].[ALL_BOSS] where x.[CHIEF] = true)
 loop
 v_data:=v_data||'; '||x.val;
 end loop;
 end if;
 
 | 
 |  |  
		|  |  
		| hicap Участник
 
 
 Вступление в Клуб: 13.10.2010
 
 | 
			
				|  Ср Июл 13, 2011 11:48    |   |  
				| Полезность: Нет оценки 
 |  
				|  	  | ggrey пишет: |  	  | ленивый вариант 
  	  | Код: |  	  | if p_info = 'test_word' then
 for x in this.[client].[ALL_BOSS] where x.[CHIEF] = true
 loop
 v_data:=v_data||'; '||x.[RANGE].[VALUE];
 end loop;
 end if;
 
 | 
 
 более быстрый вариант (не максимально)
 
  	  | Код: |  	  | if p_info = 'test_word' then
 for (select x(x.[RANGE].[VALUE] : val)
 in this.[client].[ALL_BOSS] where x.[CHIEF] = true)
 loop
 v_data:=v_data||'; '||x.val;
 end loop;
 end if;
 
 | 
 | 
 
 я вроде написал, что операцию запускаю на договоре РКО. This это РКО. ALL_BOSS есть только на CL_CORP
 |  |  
		|  |  
		| ggrey Участник со стажем
 
 
 Вступление в Клуб: 01.10.2007
 
 | 
			
				|  Ср Июл 13, 2011 11:53    |   |  
				| Полезность: Нет оценки 
 |  
				| Я заметил, и в чем проблема с моим кодом для договора РКО? Попробуйте вставить в свою операцию.
 |  |  
		|  |  
		| hicap Участник
 
 
 Вступление в Клуб: 13.10.2010
 
 | 
			
				|  Ср Июл 13, 2011 11:55    |   |  
				| Полезность: Нет оценки 
 |  
				|  	  | ggrey пишет: |  	  | Я заметил, и в чем проблема с моим кодом для договора РКО? Попробуйте вставить в свою операцию.
 | 
 ALL_BOSS есть только на CL_CORP в client его нет
 |  |  
		|  |  
		| ggrey Участник со стажем
 
 
 Вступление в Клуб: 01.10.2007
 
 | 
			
				|  Ср Июл 13, 2011 12:02    |   |  
				| Полезность: Нет оценки 
 |  
				| На моей схеме в РКО идет ссылка на CL_CORP. Извините. Но это не сильно меняет мой код, просто обращение к ALL_BOSS будет выглядеть вот так:
 this.[client]->(CL_CORP)[ALL_BOSS]
 |  |  
		|  |  
		| hicap Участник
 
 
 Вступление в Клуб: 13.10.2010
 
 | 
			
				|  Ср Июл 13, 2011 12:08    |   |  
				| Полезность: Нет оценки 
 |  
				|  	  | ggrey пишет: |  	  | На моей схеме в РКО идет ссылка на CL_CORP. Извините. Но это не сильно меняет мой код, просто обращение к ALL_BOSS будет выглядеть вот так:
 this.[client]->(CL_CORP)[ALL_BOSS]
 | 
 
  	  | Код: |  	  | if p_info = 'test_word' then for (select x(x.[RANGE].[VALUE] : val)
 in this.[client]->(CL_CORP)[ALL_BOSS] where x.[CHIEF] = true)
 loop
 v_data:=v_data||'; '||x.val;
 end loop;
 end if;
 | 
 Отличный код! Тема ветки ведь уроки для начинающих, вот и учимся. Спасибо!
 |  |  
		|  |  
		| ggrey Участник со стажем
 
 
 Вступление в Клуб: 01.10.2007
 
 | 
			
				|  Ср Июл 13, 2011 12:12    |   |  
				| Полезность: Нет оценки 
 |  
				| И Вам спасибо, за конструктивный подход  |  |  
		|  |  
		| gens Участник со стажем
 
 
 Вступление в Клуб: 21.06.2011
 
 | 
			
				|  Чт Июл 21, 2011 10:43    |   |  
				| Полезность: Нет оценки 
 |  
				| Возможно я что-то делал не так, но заполнить все поля *(Call SetAllFormFields(wrdApp, WordDoc)) у меня не получилось. 
 Пришлось прокрутить по другому:
 
 
  	  | Код: |  	  | ' подгружаем библиотеку "Библиотека VBA функций для печати в Word" '#include ::[RUNTIME].[MSWORD_SCRIPT]
 
 Public Function Main(LastControl)
 
 if not OpenWordDoc(WrdApp, WrdDoc, GetData("REPORTFILE")) then
 Msgbox "Невозможно открыть файл!"
 Main = False
 Exit Function
 end if
 
 Call SetFormField(WrdApp, WrdDoc, "test_word")
 Call SetWordVisible(wrdApp, WrdDoc)
 
 Main = True 'Результат валидатора (True, False, NULL)
 End Function
 
 | 
 |  |  
		|  |  
		|  |  
  
	| 
 
 | Вы не можете начинать темы Вы не можете отвечать на сообщения
 Вы не можете редактировать свои сообщения
 Вы не можете удалять свои сообщения
 Вы не можете голосовать в опросах
 
 |  |