Записная книжка разработчика. Штампы на документ

6 2

В нашей организации сотрудники, работающие непосредственно с документами, проставляют при необходимости на документе 3 вида штампов: штамп регистрации, электронной подписи и штамп основного документа на приложения. Все это вынесено на ленту и занимает полезное место.  Пример того, как это выглядело до недавнего времени.

Решено было внести изменения и перенести все это в один сценарий с выбором пользователем нужного вида штампа. На ленте создана группа "Штампы", и на нее добавлен простой сценарий выбора в диалоговом окне нужного действия. Пример внесенных изменений.

При выборе сотрудником данной опции появляется выбор необходимого вида штампа:

Исходный код формирования диалога: 

// Диалог выбора штампа 
 Res = InputDialogEx('*Вид:'; ; 'Pick:штамп регистрации документа,штамп электронной подписи:R'; 'Установка штампа на документ';;;;'ОК|Отмена';;'Отмена')
  
   if CharPos('Отмена'; Res) > 0  
    ShowMessage('Не выбран вид формируемого штампа документа!')    
    Exit()
   endif
  
  DialogRes = SubString(Res; '|'; 1)

  if DialogRes == 'штамп регистрации документа'
  endif 

  if DialogRes == 'штамп электронной подписи'
  endif 

Заполняем условия необходимым кодом.

1. Штамп регистрации (дата и номер)

Ранее в статье "Дата и номер на документе из РКК" был рассмотрен вопрос добавления регистрационных данных на документ в любом из журналов из регистрационно-контрольной карточки. Немного внесем изменения в код, который был представлен, и добавим ему универсальности.  В зависимости от журнала и шаблона документа, на котором ставится штамп регистрации, можно добавить настройку внешнего вида, а именно расположения даты и номера: 

//В зависимости от представления справочника меняем внешний вид проставляемого номера и даты
    
If Object.ViewName == 'РККВх'
   HTML = '<html><head> 
           <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> 
           <title>Тег TABLE</title></head> 
           <body text = "RoyalBlue">
           <table width="36%" cellpadding="2" bordercolor="#f4f4f4">
           <tr><td><big><b> '& DateReg &' </b></big></td></tr> 
           <tr><td><big><b> № '& RegNumber &' </b></big></td></tr>
           </table></body></html>' 
endif
    
If Object.ViewName == 'РККИсх'
  HTML = '<html><head> 
          <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> 
          <title>Тег TABLE</title></head> 
          <body text = "black"> 
          <table width="30%" cellpadding="2" bordercolor="#f4f4f4"> 
          <tr><td><big><b> '& DateReg &' </b></big></td><td><big><b> '& RegNumber &' </b></big</td> 
          </tr></table> 
          </body></html>'
endif
      

И точно также можно задать значения координат по умолчанию в зависимости от вида справочника, чтобы у  делопроизводителя уже были примерные координаты расположения штампа. Достаточно добавить условие по примеру выше в код, используемый в сценарии, чтобы задать координаты по умолчанию для нужного представления справочника: 

If Object.ViewName == 'InnerRRC'
  InputSh = InputDialog('Отступ по горизонтали|Отступ по вертикали';'50|800';;;;;; TRUE)
endif

Также в диалоговом окне формирования штампа регистрации добавлен ввод номера страницы, на которую ставится штамп: на первую или последнюю т. е. вместо кода выше используем:

if Object.ViewName == 'InnerRRC' 
InputSh = InputDialog('Отступ по горизонтали|Отступ по вертикали|Номер страницы (0 - 1 стр.; 1 - послед.стр.)';'135|180|0';;;;;; TRUE)		  
endif

По умолчанию, штамп ставится на  первую страницу. Весь код доступен в полной версии сценария. 

Работа сотрудника, который занимается обработкой документов будет сводиться к алгоритму действий при формировании штампа: выбор вида штампа - предварительный просмотр результата при формировании - сохранение результата или редактирование координат расположения и сохранение окончательного варианта. 

В качестве примера результат штампа для исходящих документов, а для входящих пример такого штампа представлен в вышеупомянутой статье:

2. Штамп электронной подписи

При формировании штампа ЭП в системе Directum предусмотрены штатные функции: GenerateStateStamp и GeneratePNGImageFromHTML.  

Внешний вид штампа закодирован в функции GenerateStateStamp таким образом:

HTML = MimeDecodeString('PGh0bWwgeG1sbnM9Imh0dHA6Ly9....CjwvdGFibGU+DQo8L2JvZHk+DQo8L2h0bWw+')

Раскодировав содержимое любым онлайн декодером в формате base64 в кодировке windows 1251 получим html код внешнего вида штампа, который при наличии базовых навыков  языка html, можно превратить в такой вид, например: 

Код по работе с ЭП достаточно длинный по размеру. Приведем выдержки из него. Например, формирование штампа ЭП и использование функции GenerateStateStamp. 

// Сгенерировать штамп отметки об ЭП на основе сертификата 
    StampFullFileName = ''
    ExportStamps = 1
     if ExportStamps                            
      StampFullFileName = PathForExport & '\Stamp' & EDocID & SignatureCount & '.png'
      SertNumber = Certificate.SerialNumber
      CAPICOMCertificate = CreateObject("CAPICOM.Certificate")
      CertPath = GetTempFolder() &'Cert.cer'
 // Экспортировать сертификат
      Certificate.Export(CertPath; ''; 1)         
 // Загрузить сертификат в CAPICOM.Certificate
      CAPICOMCertificate.load(CertPath)
      SubjectNameList = CreateStringList()
      SubjectNameList.Delimiter = ','
 // Получить строку с данными владельца сертификата
      SubjectNameList.DelimitedText = CAPICOMCertificate.SubjectName
 // Определить ФИО владельца сертификата
      Name = ''
      LastName = ''
            
      foreach SubjectNameListItem in SubjectNameList
       if CharPos('SN='; SubjectNameListItem) > 0
          LastName = SubString(SubjectNameListItem; '='; 2)
        else
           if CharPos('G='; SubjectNameListItem) > 0
              Name = SubString(SubjectNameListItem; '='; 2)
           endif
        endif              
       endforeach
       FIO = LastName & ' ' & Name
 // Удалить выгруженный сертификат
       if FileExists(CertPath)
          DeleteFile(CertPath)
       endif
           
 Date = Format("с %0:s по %1:s"; ArrayOf(FormatDate("D.M.YY "; Certificate.ValidFromDate); 
 FormatDate("D.M.YY "; Certificate.ValidToDate)))      
// Подключение функции GenerateStateStamp
 GenerateStateStamp(GerbFilePath; SertNumber; FIO; Date; StampFullFileName)

Недостатки реализации

Недостаток функционала, который проявляется как для даты и номера регистрации, так и штампа ЭП, в том, что если документ состоит из 3-х страниц (основной документ и приложение) в одном файле, то поставить штамп на 2-ю страницу нельзя. Можно ставить либо на все страницы, либо на первую или последнюю страницу. Для  реализации функционала по выбору страницы нужно смотреть в сторону библиотеки,  например DebenuPDFLibraryLite. Но для большинства задач текущей реализации вполне достаточно. Тем более, что выход из данной ситуации достаточно прост - оформление основного и сопутствующих документов раздельно.

Полный вариант сценария: SetStamp

Послесловие

На скриншоте выбора вида штампа приведено 3 варианта установки штампа, а код приведен для 2. Неописанный вариант предполагает установку штампа на приложение (связанный документ) вида, например "Утверждено приказом от 10.01.2023 № 02.00-55/0055",  т.е. по сути ставится штамп регистрации основного документа на приложение к нему. Возможно, тема для следующего материала.

Максим Стецук

Идея хорошая, но требует доработки по реализации.

При отмене выбора выводить еще одно окно с сообщением о выбранном пользователем действии нет необходимости:

if CharPos('Отмена'; Res) > 0  
    ShowMessage('Не выбран вид формируемого штампа документа!')  // Убрать данное сообщение.
    Exit()
endif

Пользователь уже выбрал действие "Отмена".

Диалог выбора вида штампа удобнее формировать с помощью MessageBoxEx https://club.directum.ru/webhelp/directum/5.7/index.html?om_messageboxex_vyvesti_okno_s_zagolovkom_i_tekstom_soobtchenia.htm и Стиль кнопок  cbsCommandLinks. Это уменьшает действия пользователей. (https://club.directum.ru/post/265)

 

 

Дмитрий Зайцев

Максим,  я с вами согласен. Наверно, это дело вкуса, как выводить информацию и запрашивать ее у пользователя. 

Авторизуйтесь, чтобы написать комментарий