Export To Excel (v.2)

И снова возвращаемся к построению отчетов в Excel из Lotus‘а.
Задача сводится к тому, чтобы в отчете были отображены выделенные документы из представления, или все документы из представления.
Также убрал наличие файла-пустышки, куда будут формироваться данные, и путь к которому мы жестко задаем в коде.
Также, к этому отчету можно присовокупить другие документы из других баз, если они связаны по ключевым позициям. Но это в том случае, если того требует ваша задача и логика баз-приложений в Лотусе построена должным образом.

Исходные данные: в базе есть представление с документами. Из этого представления необходимо выполнить экспорт данных выделенных документов в Excel. Экспортом у нас будет заниматься программный агент, которого мы и будем описывать в этой статье. Если документы не выделены, то при вызове агента в Excel будут передаваться данные по ВСЕМ документам нашего представления.
В свойствах программного агента в группе Runtime указываем триггер запуска «Trigger: On Event». Событие у нас «Action Menu Selection», агент применим ко всем выделенным документам (Target: All selected documents).

>>Листинг программного агента Export To Excel<<
>>Listing of Lotus Notes agent for Export to MS Excel documents from Lotus<<

Давайте попробуем разобрать этот код.

Листинг программного агента.
Комментарии - по коду движения пьесы 🙂
комментарии к разбору кода

%REM
  Agent Экспорт в Excel
  Created Apr 20, 2016 by Maksym Gluschenko/DOMAINLOTUSNOTES
  Description: Comments for Agent
%END REM

Option Public
Option Declare

Объявление глобальных переменных и констант в программном агенте.
Dim nc As Long
Dim nmore As Long
Dim i As Long
Dim x As Long
Dim nchar As String
Dim remarks As String

' Excel
Dim xlApp As Variant
Dim xlWorkSheet As Variant

Const DEBAG = False
Const SendToAddr = {<e-mail_addreses@lst&rt;}

Инициализация агента.
Sub Initialize
  Dim ses As New NotesSession

Так как мы работаем с выделенными документами текущего представления, то небоходимо определить классы NotesUIWorkspace и NotesUIView.
  Dim UIws As New NotesUIWorkspace
  Dim db As NotesDatabase
  Dim UiView As NotesUIView
  Dim currentView As NotesView
  Dim viewName
  Dim viewAlias
  Dim coll As NotesDocumentCollection
  Dim countSelectedDocs As Long
  Dim gowithselection As Integer
  Dim goonall As Integer
  Dim doc As NotesDocument
  Dim countall As Long
  Dim ViewEntryColl As NotesViewEntryCollection
  Dim ViewEntry As NotesViewEntry

  On Error GoTo Handler

  remarks = ""
  i = 0
  Set db = ses.Currentdatabase
  Set UiView = UIws.CurrentView
  viewName = UiView.ViewName
  viewAlias = UiView.ViewAlias
  Set currentView = db.getView(viewAlias)
  Set coll = db.UnprocessedDocuments
  countSelectedDocs = coll.Count

Определяем, будет ли агент обрабатывать только выделенные документы представления, или все документы из текущего представления.

  gowithselection = 0
  goonall = 0
  If countSelectedDocs >1 Then
   gowithselection = UIws.Prompt(PROMPT_YESNO, "Есть выбранные документы!", "Экспортировать только выбранные документы?")
   Set doc=coll.getfirstdocument
   'Check if there is really a doc selected
   If (doc Is Nothing) And (gowithselection=1) Then
    MsgBox "Выбраны некорректные документы"
    Exit Sub
   End If
   Set doc = Nothing
  Else
   goonall = UIws.Prompt(PROMPT_YESNO, "Выбранных документов нет!", "Экспортировать все документы в представлении?" _
   + Chr$(13) + "Подсказка:" _
   + Chr$(13) + "Для экспорта только выбранных документов," _
   + Chr$(13) + "сделайте отметки перед экспортом.")
   If goonall=0 Then
    Print "Выход ..."
    Exit Sub
   End If
   Set coll = Nothing
  End If

Работает с Excel объектом.

' Создаем Excel объект
  Set xlApp = CreateObject("Excel.Application")
  If xlApp Is Nothing Then
   MsgBox "Не удалось создать открыть приложение Excel"
   GoTo ex
  End If
  xlApp.Visible = True ' Приложение Excel запустится сразу
  Call xlApp.Workbooks.Add
  Set xlWorkSheet = xlApp.ActiveSheet
' Формируем 1-ю строчку с шапкой
  'Add the table labels

Глобальные переменные nc и nmore. Определяются их начальные значения перед использованием в ф-ции countcol(nchar), которая формирует горизонтальный порядок столбцов.

  nc=64
  nmore=0

nchar - переменная с порядковым номером столбца в документе MS Excel.

  nchar = 0

Значение переменной nchar (столбец) определяется в функции countcol(nchar). Порядок горизонтальной нумерации в MS Excel буквенный, т.е. идут буквы латинского алфавита: A, B, C, D,...... После достижения 26-ой позиции, нумерация продолжается добавлением второго регистра "числа" ...Y, Z, AA, AB, AC,..... - и так до 3-го регистра - 26^2 (26 во 2-ой степени) позиций. Затем добавляется 3-ий регистр буквенного числа ...ZX, ZY, ZZ, AAA, AAB,...., и т.д.

Формируем шапку нашего документа. Количество столбцов в шапке (если она предусмотрена ТЗ) должно соответствовать количеству столбцов в экспортируемых данных.

  nchar = countcol(nchar)
  xlWorkSheet.Range(nchar + "1").Value = "№" ' 1 - Value 01
'xlWorkSheet.Range("A1").Value = "№" ' 1
  ' Документ сотрудника

  nchar = countcol(nchar)
  xlWorkSheet.Range(nchar + "1").Value = "Value 02" ' 2
'xlWorkSheet.Range("B1").Value = "Value 02" ' 2
  nchar = countcol(nchar)
  xlWorkSheet.Range(nchar + "1").Value = "Value 03" ' 3
  nchar = countcol(nchar)
  xlWorkSheet.Range(nchar + "1").Value = "Value 04" ' 4
  nchar = countcol(nchar)
  xlWorkSheet.Range(nchar + "1").Value = "Value 05" ' 5
  nchar = countcol(nchar)
  xlWorkSheet.Range(nchar + "1").Value = "Value 06" ' 6
  nchar = countcol(nchar)
  xlWorkSheet.Range(nchar + "1").Value = "Value 07" ' 7
  nchar = countcol(nchar)
  xlWorkSheet.Range(nchar + "1").Value = "Value 08" ' 8
  nchar = countcol(nchar)
  xlWorkSheet.Range(nchar + "1").Value = "Value 09" ' 9
  nchar = countcol(nchar)
  xlWorkSheet.Range(nchar + "1").Value = "Value 10" ' 10

  If gowithselection = 1 Then
   countall = countSelectedDocs
  Else
   countall = currentView.AllEntries.Count
  End If

В зависимости от типа выбора документов для экспорта (только выделенные или все документы из представления), в цикле перебора документов запускаем процедуру ExportDoc(doc), которая наполняет наш MS Excel документ согласно предусмотренной в процедуре логикой.

  If countSelectedDocs > 1 AND gowithselection = 1 Then
   ' Работаем с коллекцией выделенных документов
   Set doc = coll.getFirstDocument
   While Not (doc Is Nothing)
    Call ExportDoc(doc)
    Set doc = coll.getNextDocument(doc)
   Wend
  Else
   ' Работаем со всеми документами представления
   ' (!!!) Все документы представления обрабатываются, если при выборанных документах
   ' выполнить отказ от выполнения только выбранных - тогда будут обработаны
   ' ВСЕ документы.

   Set ViewEntryColl = currentView.Allentries
   Set ViewEntry = ViewEntryColl.Getfirstentry()
   While Not (ViewEntry Is Nothing)
    Set doc = ViewEntry.Document
    Call ExportDoc(doc)
    Set ViewEntry = ViewEntryColl.GetnextEntry(ViewEntry)
   Wend

  End If

  remarks = {Обработано документов: } & Chr(014) & i & { шт.}
  MsgBox {Обработано документов: } & i & { шт.}
  GoTo ex

Handler:
  Print "Ошибка в строке " + CStr(Erl) + " : " + CStr(Error)
  xlApp.DisplayAlerts = False
  xlApp.Quit
  GoTo ex

ex:
  If Not remarks = "" Then
   If DEBAG Then
    ' Отправляем ошибку на почту если DEBAG = True,
    Dim maildoc As NotesDocument
    Set maildoc = New NotesDocument(db)
    Dim rtItem As NotesRichTextItem
    maildoc.Form="Memo"
    maildoc.SendTo = SendToAddr
    maildoc.Subject = " - remark"
    Set rtItem = maildoc.Createrichtextitem({Body})
    Call rtItem.Appendtext(" ")
    Call rtItem.Addnewline(1)
    Call rtItem.Appendtext("export.excel.full - remark")
    Call rtItem.Addnewline(2)
    Call rtItem.Appendtext(remarks)
    Call maildoc.ConvertToMIME(CONVERT_RT_TO_HTML)
    Call maildoc.Send( False )
   End If
  End If
  Exit Sub
End Sub

Функция countcol(nchar), которая выполняет горизонтальную нумерацию столбцов в документе MS Excel.

Function countcol(nchar As String)
  nc=nc+1
  If nc=91 Then
   nmore = nmore+1 'PreChar = Axx (AC23)
   nc=65 'reset to A
  End If
  If nmore > 0 Then
   nchar = CStr(Chr(nmore+64))+Cstr(Chr(nc))
  Else
   nchar = CStr(Chr(nc))
  End If
'Print {nchar = } & nchar
  countcol = nchar
End Function

Процедура ExportDoc(doc), которая как раз выполняет экспорт данных из полей документа, передаваемого в качестве параметров этой процедуры, в MS Excel.

%REM
  Sub ExportDoc
  Description: Comments for Sub
%END REM

Sub ExportDoc(doc As NotesDocument)

  On Error GoTo Handler

' Заполняем Excel файл
  nc=64
  nmore=0
  nchar = 0
  i = i + 1
  x = i + 1 ' Строка в Excel файле_
  ' Потому что i начинается с 0, а 1-я строка в файле_
  ' уже заполнена шапкой
  ' 1 - value 01 - № П/п

  nchar = countcol(nchar)
  xlWorkSheet.Range(nchar + CStr(x)).Value = CStr(i)
  If Not (doc Is Nothing) Then
   ' 2 - value 02
   nchar = countcol(nchar)
   xlWorkSheet.Range(nchar + CStr(x)).Value = Evaluate({@Text(@Year(@Created)) + "." + @Right(@Text(@Power(10;2) +@Month(@Created));2)},doc)
   ' 3 - value 03
   nchar = countcol(nchar)
   xlWorkSheet.Range(nchar + CStr(x)).Value = Trim(CStr(doc.NAME(0))) ' value 03
   ' 4 - value 04
   nchar = countcol(nchar)
   xlWorkSheet.Range(nchar + CStr(x)).Value = Evaluate({@Text(@Name([CN];@Trim(Remote_User:CurrentUser)))},doc) ' value 04 - LN User name, saved doc (field)
   ' 5 - value 05
   nchar = countcol(nchar)
   xlWorkSheet.Range(nchar + CStr(x)).Value = Evaluate({@Text(@Trim(Remote_Addr:CurrentComputer))},doc) ' From saved doc IP address
   ' 6 - value 06
   nchar = countcol(nchar)
   xlWorkSheet.Range(nchar + CStr(x)).Value = Trim(CStr(doc.DATESAVE(0))) ' value 06
   ' 7 - value 07
   nchar = countcol(nchar)
   xlWorkSheet.Range(nchar + CStr(x)).Value = Trim(CStr(doc.DATEAPP(0))) ' value 08
   ' 8 - value 08
   nchar = countcol(nchar)
   xlWorkSheet.Range(nchar + CStr(x)).Value = Trim(CStr(doc.DTDISM(0))) ' value 08
   ' 9 - value 09
   nchar = countcol(nchar)
   xlWorkSheet.Range(nchar + CStr(x)).Value = Trim(CStr(doc.LOCATIONNAME(0))) ' value 09
   ' 10 - value 10
   nchar = countcol(nchar)
   xlWorkSheet.Range(nchar + CStr(x)).Value = Evaluate({@Text(@If(_Field_A_="2";@Trim(_Field_B_);""))},doc) ' value 10
   ' _Field_A_ - <key_field_name>
   ' _Field_B_ - <a_particular_field_name>

  Else
   ' 2 - value 01
   nchar = countcol(nchar)
   xlWorkSheet.Range(nchar + CStr(x)).Value = "Is NaN"
   ' 3 - value 02
   nchar = countcol(nchar)
   xlWorkSheet.Range(nchar + CStr(x)).Value = "Is NaN"
   ' 4 - value 03
   nchar = countcol(nchar)
   xlWorkSheet.Range(nchar + CStr(x)).Value = "Is NaN"
   ' 5 - value 04
   nchar = countcol(nchar)
   xlWorkSheet.Range(nchar + CStr(x)).Value = "Is NaN"
   ' 6 - value 05
   nchar = countcol(nchar)
   xlWorkSheet.Range(nchar + CStr(x)).Value = "Is NaN"
   ' 7 - value 06
   nchar = countcol(nchar)
   xlWorkSheet.Range(nchar + CStr(x)).Value = "Is NaN"
   ' 8 - value 07
   nchar = countcol(nchar)
   xlWorkSheet.Range(nchar + CStr(x)).Value = "Is NaN"
   ' 9 - value 08
   nchar = countcol(nchar)
   xlWorkSheet.Range(nchar + CStr(x)).Value = "Is NaN"
   ' 10 - value 09
   nchar = countcol(nchar)
   xlWorkSheet.Range(nchar + CStr(x)).Value = "Is NaN"
  End If
  GoTo ex

Handler:
  Print {итерация цикла : } & i
  Print "\ExportDoc - Ошибка в строке " + CStr(Erl) + " : " + CStr(Error)
  Resume ex

ex:
  Exit Sub
End Sub

Если у вас возникли вопросы по данному материалу, требующие дополнительных пояснений, пишите на e-mail: maximke@ukr.net

Comments are closed.