печать фин. распор. потоком в конце дня в WORD/EXCEL
|
Предыдущая тема :: Следующая тема |
Автор |
Сообщение |
vtar Эксперт
Вступление в Клуб: 20.03.2009
|
Чт Май 06, 2010 19:02  печать фин. распор. потоком в конце дня в WORD/EXCEL |
|
Полезность: Нет оценки
|
Уважаемые коллеги!
Кто нибудь реализовывал такое:
печать однотипных фин. распоряжений потоком в конце дня в WORD/EXCEL ?
пока наметился способ с клиент скриптом:
( проблема - надо формировать отдельно екселовский
файл со всеми значениями , и главная проблема, что вылезает окошко "выделить таблицу" с этим файлом, указание Листа1 источником почему -то не помогло, и это сильно мешает ... )
Dim docNew As Document
Set WrdDoc = Documents.Add("c:\TEST.doc")
WrdDoc.MailMerge.MainDocumentType = wdCatalog
WrdDoc.MailMerge.OpenDataSource Name:="c:\DATA.xls", ReadOnly:=True, ConfirmConversions:=False, Connection:="'Лист1$'"
WrdDoc.MailMerge.DataSource.FirstRecord = wdDefaultFirstRecord
WrdDoc.MailMerge.DataSource.LastRecord = wdDefaultLastRecord
WrdDoc.MailMerge.Destination = wdSendToNewDocument
WrdDoc.MailMerge.Execute
Test.doc - шаблон ФР
Data.xls - набор значений кодиков для заполнения шаблона |
|
 |
timochev Эксперт
Вступление в Клуб: 02.07.2007
|
Пт Май 07, 2010 07:50   |
|
Полезность: Нет оценки
|
А чем не подходит дистрибутивный способ печати? Есть операция "Печать распоряжения (Excel)". Она позволяет печатать список распоряжений. У нас этот механизм используется для печати списков распоряжений по овердрафтам. |
|
 |
vtar Эксперт
Вступление в Клуб: 20.03.2009
|
Пт Май 07, 2010 10:11   |
|
Полезность: Нет оценки
|
Ну скажем так, нужна общая технология потоковой печати документов по шаблонам в WORD/EXCEL, чтобы все печатаемые документы попадали в одно приложение .
Дистрибутивная технология , похоже требует наличия именно ФР (прошу прощения, не совсем корректно сформулировал тему)
Думаю в сторону выводить в отдельные приложения WORD , потом копировать /вставлять - собирать в одно. Если кто-то реализовал подобные схемы, просьба поделиться опытом. |
|
 |
vtar Эксперт
Вступление в Клуб: 20.03.2009
|
Пн Июн 07, 2010 15:36   |
|
Полезность: Нет оценки
|
vtar пишет: |
Думаю в сторону выводить в отдельные приложения WORD , потом копировать /вставлять - собирать в одно. |
Как оказалось, принципиально работает. Но медленно - 50 одностраничных документов по 4 шаблонам сгенерировалось примерно за минуту. Таким образом можно нашлепать тучу документов (думаю порядка нескольких сотен, дальше либо будет некомфортно юзеру, либо WORDу ) по разным шаблонам в один многостраничный файл в WORDe. |
|
 |
zinovjeva_n Участник - экстремал
Вступление в Клуб: 15.10.2008
|
Ср Июн 09, 2010 15:07   |
|
Полезность: 2
|
Я подобное реализовывала следующим образом:
Шаблон Word с Braket (например [НОМЕР])
в шаблоне Word писала макрос, который копирует содержимое первой страницы при этом добавляя к наименованию полей порядковый номер, переданный в параметре:
Код: | Sub CopyPage(lCount As Integer)
Dim strBookmark As String
Dim i As Integer
Dim n As Integer
i = ActiveDocument.Range.End
ActiveDocument.Range(0, i).Select
Selection.Copy
For n = 2 To lCount
ActiveDocument.Sections.Add
ActiveDocument.Sections.Last.Range.Select
Selection.Paste
With ActiveDocument.Sections.Last.Range.Find
.Text = "[НОМЕР]"
.Replacement.Text = "[НОМЕР" & Trim(Str(n)) & "]"
.Execute Replace:=wdReplaceOne, Forward:=True, _
Wrap:=wdFindContinue
' И так по всем полям
End With
Next n
End Sub |
Далее данные для печати загоняла во временную таблицу, определяла количество страниц, которые должны быть напечатаны и копировала страницу-шаблон столько раз, сколько это было нужно, передавая порядковый номер записи из курсора, которая будет распечатана на этой странице:
Код: | lCount = GetData("COUNT")
WrdApp.Run "CopyPage" , lCount |
Далее поля устанавливаются следующим образом:
Код: | For i = 1 To CInt(lCount)
Call SetBracketsFields(WrdApp, WrdDoc, "НОМЕР" & CInt(i))
Next |
При этом в проверке значения полей вычисляются по номеру в таблице, номер берется от поля:
Код: | if p_info like 'НОМЕР%' then
P_DATA := ' ';
ind := to_number(nvl(substr(p_info, length('СЧЕТ_ПЛАТ') + 1), '1'));
P_DATA := rc_table(ind).doc_rc_ref.[PAYER].[ACC];
end if; |
Не знаю на сколько это будет быстрее, но вроде наши довольны. _________________ Coding for food |
|
 |
vtar Эксперт
Вступление в Клуб: 20.03.2009
|
Ср Июн 09, 2010 16:51   |
|
Полезность: Нет оценки
|
zinovjeva_n пишет: | который копирует содержимое первой страницы при этом добавляя к наименованию полей порядковый номер, переданный в параметре: |
Вот это хорошая идея, пожалуй я ее использую если будут жалобы на тормоза. Во временной таблице собирал ссылки на объекты, по которым каждый раз вычислялись кодики в шаблоне при очередной вставке. Если кодики рассчитать сразу для всех объектов, думаю можно снизить торможение процентов на 20 - 40 ... |
|
 |
svn Профи
Вступление в Клуб: 04.02.2008
|
Ср Июн 09, 2010 17:32   |
|
Полезность: Нет оценки
|
тормоза будут расти в геометрической прогрессии от количества фин. распоряжений. - в ворде очень тупой внутренний поиск закладок. |
|
 |
vtar Эксперт
Вступление в Клуб: 20.03.2009
|
Чт Июн 10, 2010 08:15   |
|
Полезность: Нет оценки
|
svn пишет: | в ворде очень тупой внутренний поиск закладок. |
я делал не через закладки, а стандартным методом ЦФТ через ActiveDocument.FormFields , с полями ворд работает по моему быстро, тормоза у моем случае обусловлены дерганием расчета кодиков (Select'ы к базе) из клиент скрипта, о чем писал, а вот если их заранее посчитать то наверно тормоза уменьшатся. |
|
 |
Volod Эксперт
Вступление в Клуб: 19.09.2007
|
Чт Июн 10, 2010 11:49   |
|
Полезность: Нет оценки
|
На самом деле при копировании страницы с закладками в WORD, наименования закладок остаются в источнике. Таким образом, заполняем страницу-шаблон с закладками - делаем ее копию и т.д.
В конце можно удалить страницу с закладками, или не копировать ее.
Код: | NumLetter = CInt(GetData("КОЛ_ПИСЕМ")) ' кол-во писем
' в цикле заполняем раздел 1 шаблона и делаем его копию
For x = 1 To NumLetter
TextData = "@@@" & CStr(x) 'передаем номер строки в Проверку для индекса таблицы
Call Form1.ScriptServerValidate( TextData, "####" )
' заполняем Закладки в шаблоне
Call SetFormField(WrdApp, WrdDoc, "ДОЛЖНОСТЬ_БОССА")
Call SetFormField(WrdApp, WrdDoc, "ФИО_БОССА")
..... ' копируем в новый раздел
' при копировании Закладки остаются в разделе 1
Call CopySection(WrdApp, WrdDoc)
Next
WrdDoc.Sections(1).Range.Delete ' удаляем раздел 1, чтобы не было повторения |
|
|
 |
dumpino Участник со стажем
Вступление в Клуб: 13.12.2011
|
Пт Фев 03, 2012 13:41   |
|
Полезность: 1
|
Добавлю свои 3 копейки. Возможно кому будет полезно.
Спасибо zinovjeva_n за идею, собственно её я и использовал в реализации, только вместо Bracket взял FormFields.
Задача стояла следующая. Вывести потоком вордовские листы с заявлением на открытие карточек. Одна такая операция могла затронуть до 2500 карточек, а это 2500 вордовских листов.
Если делать методом Bracket, то слишком долго идет поиск данного "брекета" в файле, тратилось порядка 2-5 секунд на один параметр. На одном листе у меня 11 параметров, вот и думайте...
Схема такая
1. Делаем шаблон заявления (*.dot), заполняем formfields (причем имя закладки можно и не указывать, будем работать со значеним по умолчанию), пишем макрос генерации страниц
Код: | Sub CopyPage(lCount As Integer)
Dim i As Integer
Dim n As Integer
Dim f
i = ActiveDocument.Range.End
ActiveDocument.Range(0, i).Select
Selection.Copy
For n = 2 To lCount
ActiveDocument.Sections.Add
ActiveDocument.Sections.Last.Range.Select
Selection.Paste
With ActiveDocument.Sections.Last.Range.FormFields
For f = 1 To 11 'количество параметров
Select Case (.Item(f).Result)
Case "C1_PAN1"
.Item(f).Result = "C1_PAN" & Trim(Str(n))
... перечисляем все параметры на странице
End Select
Next f
End With
Next n
End Sub |
2. Вызываем макрос
Код: | if (lCount > 0) then
WrdApp.Run "CopyPage" , lCount
end if |
3. Когда страницы сгенерированы, заменим их на каждом листе на реальные данные
Код: | set FormFields = WrdApp.ActiveDocument.FormFields
j = 0
For i = 1 To CInt(lCount)
for k = 1 to 11
FormFields(j+k).Result = GetData(FormFields(j+k).Result)
next
j = j + 11
Next |
Замена с помощью FormFields происходит в разы быстрее. |
|
 |
maestro Профи
Вступление в Клуб: 12.10.2010
|
Чт Фев 09, 2012 15:40   |
|
Полезность: Нет оценки
|
dumpino пишет: | Добавлю свои 3 копейки. Возможно кому будет полезно.
Спасибо zinovjeva_n за идею, собственно её я и использовал в реализации, только вместо Bracket взял FormFields.
Задача стояла следующая. Вывести потоком вордовские листы с заявлением на открытие карточек. Одна такая операция могла затронуть до 2500 карточек, а это 2500 вордовских листов.
|
На 2500 вордовских листов я бы использовал слияние. Самый быстрый способ генерации WORD-отчетов. |
|
 |
Volod Эксперт
Вступление в Клуб: 19.09.2007
|
Чт Фев 09, 2012 16:15   |
|
Полезность: Нет оценки
|
Есть реализация слияния? |
|
 |
vtar Эксперт
Вступление в Клуб: 20.03.2009
|
Чт Фев 09, 2012 16:22   |
|
Полезность: Нет оценки
|
Для более-менее однотипных документов есть реализация потоковой печати в EXCEL, очень быстро . Делал уважаемый SVN.
Печатались ФР текстом, без картинок. |
|
 |
dumpino Участник со стажем
Вступление в Клуб: 13.12.2011
|
Пт Фев 10, 2012 13:15   |
|
Полезность: Нет оценки
|
maestro пишет: |
На 2500 вордовских листов я бы использовал слияние. Самый быстрый способ генерации WORD-отчетов. |
да, здесь лучше слияние использовать. спасибо  |
|
 |
maestro Профи
Вступление в Клуб: 12.10.2010
|
Пн Фев 13, 2012 10:08   |
|
Полезность: 2
|
Volod пишет: | Есть реализация слияния? |
Попробую привести клочки кода.
1. Валидатор. Готовим CSV-файл с данными:
Код: |
if p_info = 'CREATE_CSV' then
V_ERROR := null;
begin
Create_CSV( ... );
-- Заполняем структуру для копирования
[DOCUMENT]::[COPYFILES].idx := 0;
[DOCUMENT]::[COPYFILES].tbl_F$L.delete;
[DOCUMENT]::[COPYFILES].tbl_F$L(1).[SRC_NAME] := &filename;
[DOCUMENT]::[COPYFILES].tbl_F$L(1).[SRC_PATH] := ::[SYSTEM_PARAMS].GET('PATH',True);
[DOCUMENT]::[COPYFILES].tbl_F$L(1).[SRC_TYPE] := true;
[DOCUMENT]::[COPYFILES].tbl_F$L(1).[SRC_DELETE] := true;
[DOCUMENT]::[COPYFILES].tbl_F$L(1).[DST_NAME] := &filename;
[DOCUMENT]::[COPYFILES].tbl_F$L(1).[DST_PATH] := V_FOLDER;
[DOCUMENT]::[COPYFILES].tbl_F$L(1).[DST_TYPE] := false;
[DOCUMENT]::[COPYFILES].tbl_F$L(1).[DST_DELETE] := false;
exception
when others then
V_ERROR := sqlerrm;
end;
end if;
|
Код: |
-- Функция оборачивает значение кавычками
function wrap(p_str varchar2(4000)) return varchar2(1024) is
begin
p_str := '"'||replace(p_str, '"', '""')||'"';
return p_str;
end;
--
procedure Create_CSV(....) is
path varchar2(1024);
op_date date := [SYSTEM]::[OP_DATE];
file integer;
str varchar2(4000);
i integer := 0;
begin
-- Создаем файл
path := ::[SYSTEM_PARAMS].GET('PATH',True);
file := stdio.open(path, &filename, 'w');
-- Заголовок CSV-файла
stdio.PUT_LINE(file, convert('head_1; head_2; head_3', 'utf8'), false, null, stdio.unxtext);
-- Выборка данных
for ( select x(...)
) loop
-- Подготавливаем файл с данными для печати (слияние)
str := wrap(x.[...])||';'||wrap(x.[...])||';'||wrap(x.[...])||';';
stdio.PUT_LINE(file, convert(str, 'utf8'), false, null, stdio.unxtext);
i := i + 1;
end loop;
stdio.close(file);
end;
|
2. Клиент-скрипт
Код: |
' Migunov S. 26/03/2011 REQDEV-3887
if LastControl is OK Then
Runtime.ShowMonitor
' Создаем CSV-файл и копируем его на клиента
Call Form1.ScriptServerValidate( OK, "CREATE_CSV")
' Обработаем ошибки сервера.
if len(V_ERROR.Text) > 0 then
Main = false
Exit Function
end if
'Вызываем операцию копирования файла с данными на клиента
Call Runtime.PlayEx("<% PLPCALL [DOCUMENT].[COPYFILES]() %>")
'Инициализируем Word
if not OpenWordDoc(WrdApp, WrdDoc, GetData("REPORTFILE")) then
Main = False
Exit Function
end if
'Линкуем файл с данными
dataFileName = GetData("DATAFILE")
WrdDoc.MailMerge.OpenDataSource v_folder & "\" & dataFileName
'Выполняем слияние
WrdDoc.MailMerge.Destination = wdSendToNewDocument
WrdDoc.MailMerge.SuppressBlankLines = True
WrdDoc.MailMerge.Execute
'Гасим лишние документы
WrdApp.Windows("Документ1").Close wdDoNotSaveChanges
WrdApp.Windows("Ошибки слияния1").Close wdDoNotSaveChanges
Set WrdDoc = WrdApp.Windows("Формы1")
'Удаляем файл с данными
set fso = CreateObject("Scripting.FileSystemObject")
if fso.FileExists(v_folder & "\" & dataFileName) then
fso.DeleteFile(v_folder & "\" & dataFileName)
end if
'Сохраняем результат
WrdApp.ChangeFileOpenDirectory v_folder & "\"
departCode = GetData("DEPART_CODE")
saveFileName = "NOM_SETNULLLIMIT" & departCode & ".doc"
WrdApp.ActiveDocument.SaveAs saveFileName
msgbox "Информация сохранена в файле: "& v_folder & "\" & saveFileName, vbInformation
WrdApp.Visible = true
'Печать
If bPrintOut.Text = "1" then
WrdDoc.PrintOut
End If
end if
' /Migunov S. 26/03/2011 REQDEV-3887
|
|
|
 |
|
|
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете голосовать в опросах
|
|