CftClub.ru
Клуб специалистов ЦФТ-Банк

печать фин. распор. потоком в конце дня в WORD/EXCEL

 
Ответить на тему    Клуб специалистов ЦФТ-Банк (IBSO) -> Разработка в PL/PLUS. Оптимизация запросов Oracle
Предыдущая тема :: Следующая тема  
Автор Сообщение
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-отчетов.


да, здесь лучше слияние использовать. спасибо Smile
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
Показать сообщения:   
Ответить на тему    Клуб специалистов ЦФТ-Банк (IBSO) -> Разработка в PL/PLUS. Оптимизация запросов Oracle Часовой пояс: GMT + 3
Страница 1 из 1

 
Перейти:  
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Рейтинг@Mail.ru