Урок 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
|
|
|
 |
|
|
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете голосовать в опросах
|
|