RSS Подписка на статьи RSS Подписка на комментарии Панель инструментов

Блог профессионалов стал частью сайта технической поддержки DocsVision http://support.docsvision.com. Новые материалы будут появляться уже на этом сайте.

Поиск

Ярлыки

авто генерация кода (1) Администрирование DocsVision (60) Атрибутивный поиск (3) База данных (24) Базы знаний (1) Безопасность (1) Бизнес-процессы (20) Блог (2) Вы увидите это первыми (1) Групповые политики (1) Диаграммы (2) Задания (2) Интеграция (2) Карточки DocsVision (14) Конструктор Решений (11) Маркетинг и продажи (4) Навигатор (3) Новое (3) Новости (32) Опрос (4) Опросы DocsVision (4) Оптимизация (3) Отчеты (2) Ошибки (1) Поддержка (14) Полезные ссылки (1) Представления (4) Производительность (5) Разбор полетов (18) Разработка для Workflow (7) разработка карточек (2) Разработка на платформе DocsVision (41) Разработка решений (43) Расширение платформы (1) Расширенные отчеты (9) Решения на платформе DocsVision (6) Сервисы DocsVision (3) Сканеры (3) Справочник сотрудников (1) Справочник типов (1) Установка (1) Утилиты (13) Шлюз в SharePoint (8) Штрихкод (2) Cкрипты карточек (7) DocsVision внутри (1) DocsVision Live (1) FileStream (1) FireFox (2) Opera (1) Powershell (5) Safari (1) SharePoint2007 (1) SharePoint2010 (2) Silverlight (1) UltraViews (1) Vista (1)

Еще один пример работы с правами

Еще один пример работы с правами и DocsVision API. Приложение которое ищет карточки бизнес-процесса, на которые исполнитель не имеет прав, и назначает соответствующие права.
Ссылки установлены на библиотеки DocsVision 3.6

Скачать (VS 2008, vb.net) Читать дальше

Оставить комментарий (всего: 4)

Еще 7 эккаунтов Google Wave

У меня тоже появились к раздаче 7 эккаунтов. Как уже писал Михаил, чтобы с этим работать надо иметь эккаунт в Gmail.
Обращайтесь на skurjanov(собака)gmail.com.
Читать дальше

Оставить комментарий (всего: 0)

Синхронизация данных карточки и формы InfoPath

Продолжая тему интеграции с офисными приложениями из VBS-скриптов (см. пост про работу с Word), привожу скрипт, работающий с формой InfoPath, вложенной в карточку документа в виде файла. Пафос слова "интеграция" несколько спадает если вспомнить, что форма InfoPath - это всего лишь XML файл.
Итак, что требовалось от скрипта:
  • записывать значения заданных полей карточки документа в файл формы;
  • записывать значения заданных полей формы InfoPath в карточку;
  • производить указанные действия при открытии карточки и ее сохранении.
Алгоритм работы скрипта прост:
  1. получить первый вложенный в карточку документа файл и выгрузить его на файловую систему во временный файл;
  2. прочитать из файла значения заданных полей формы и записать их в поля (и/или пользовательские свойства) карточки документа;
  3. записать в файл значения других заданных полей карточки в поля формы;
  4. сохранить файл в карточке и удалить его с файловой системы.
Соответствие полей карточки и полей формы задается в скрипте в виде двух массивов (ReadMappings и WriteMappings). Поля формы задаются с помощью выражений XPath (что дает некоторую гибкость и универсальность). Поля карточки задаются по именам, которые интерпретируются в скрипте в функциях GetPropValue, GetPropDisplayValue и процедурах SetPropValue, SetPropDisplayValue. В этой интерпретации допущен некоторый произвол, благодаря которому в скрипте появились "псевдополя" типа поля "текущий пользователь открывший карточку" (@CurrentUser).
Для пользовательских свойств карточки отдельно синхронизируется значение и отдельно отображаемое значение.
А вот, собственно, и сам скрипт:


Function DoEvent(UserSession, CardFrame, CardData, ActivateFlags, ModeID, FolderID)
StoreProps CardData, UserSession
LoadProps CardData, UserSession
DoEvent = 1
End Function


' Синхронизировать свойства из файла в карточку
Sub LoadProps(CardData, UserSession)
Dim File, Path
Set File = FirstFile(CardData, UserSession)
If FIle Is Nothing Then Exit Sub
Path = SaveFileOnFs(File)
ReadPropsFromFile Path, CardData
DeleteFileFromFs Path
End Sub

' Синхронизировать свойства из карточки в файл
Sub StoreProps(CardData, UserSession)
Dim File, Path
Set File = FirstFile(CardData, UserSession)
If FIle Is Nothing Then Exit Sub
Path = SaveFileOnFs(File)
WritePropsToFile UserSession, Path, CardData
File.Upload Path
DeleteFileFromFs Path
End Sub

' Соответствие свойста карточки и полей xml-файла
Class PropMapping
Public PropName
Public ValueXPath
Public DisplayValueXPath
End Class

' Создать соответствие свойста карточки и полей xml-файла
Function Map(PropName, ValueXPath, DisplayValueXPath)
Set Map = New PropMapping
With Map
.PropName = PropName
.ValueXPath = ValueXPath
.DisplayValueXPath = DisplayValueXPath
End With
End Function

' Соответствия свойств карточки и полей xml-файла для передачи из файла в карточку
Dim ReadMappings : ReadMappings = Array( _
Map("Тема", "/my:Protocol/my:Subject", "/my:Protocol/my:Subject"), _
Map("Номер", "/my:Protocol/my:Number", "/my:Protocol/my:Number"), _
Map("Место совещания", "/my:Protocol/my:Place", "/my:Protocol/my:Place"), _
Map("Подписанты", "/my:Protocol/my:AllSigners", "/my:Protocol/my:AllSigners"), _
Map("Участники", "/my:Protocol/my:AllAttendees", "/my:Protocol/my:AllAttendees"), _
Map("Присутствовали от контрагентов", "/my:Protocol/my:AllContragents", "/my:Protocol/my:AllContragents"), _
Map("Дата", "/my:Protocol/my:Date", "/my:Protocol/my:Date"), _
Map("Филиал", "/my:Protocol/my:BranchID", "/my:Protocol/my:BranchName") _
)

' Соответствия свойств карточки и полей xml-файла для передачи из карточки в файл
Dim WriteMappings : WriteMappings = Array( _
Map("Регистратор", "/my:Protocol/my:RegistratorID", "/my:Protocol/my:RegistratorName"), _
Map("Состояние", "/my:Protocol/my:State", "/my:Protocol/my:State"), _
Map("Вид протокола", Null, "/my:Protocol/my:Type"), _
Map("ConfirmationStartProcessTempl", "/my:Protocol/my:ConfirmationStartProcessTempl", Null), _
Map("ConfirmationStartProcessFolder", "/my:Protocol/my:ConfirmationStartProcessFolder", Null), _
Map("ResolutionTemplateID", "/my:Protocol/my:ResolutionTemplateID", Null), _
Map("ResolutionFolderID", "/my:Protocol/my:ResolutionFolderID", Null), _
Map("DeliveryStartProcessTempl", "/my:Protocol/my:DeliveryStartProcessTempl", Null), _
Map("DeliveryStartProcessFolder", "/my:Protocol/my:DeliveryStartProcessFolder", Null), _
Map("@Card", "/my:Protocol/my:CardID", Null), _
Map("@CurrentUser", "/my:Protocol/my:CurrentUserID", Null) _
)

' Прочитать свойства из xml-фала в карточку
Sub ReadPropsFromFile(Path, CardData)
Dim XDoc, Mapping, CardProp
Set XDoc = CreateObject("Msxml2.DOMDocument.3.0")
XDoc.async = False
XDoc.load Path
For Each Mapping In ReadMappings
If Not IsNull(Mapping.ValueXPath) Then
SetPropValue CardData, Mapping.PropName, XDoc.selectSingleNode(Mapping.ValueXPath).Text
If Not IsNull(Mapping.DisplayValueXPath) Then
SetPropDisplayValue CardData, Mapping.PropName, XDoc.selectSingleNode(Mapping.DisplayValueXPath).Text
End If
End If
Next
End Sub

' Записать свойства из карточки в xml-файл
Sub WritePropsToFile(UserSession, Path, CardData)
Dim XDoc, Mapping, CardProp
Set XDoc = CreateObject("Msxml2.DOMDocument.3.0")
XDoc.async = False
XDoc.load Path
For Each Mapping In WriteMappings
If Not IsNull(Mapping.ValueXPath) Then
XDoc.selectSingleNode(Mapping.ValueXPath).Text = GetPropValue(UserSession, CardData, Mapping.PropName)
End If
If Not IsNull(Mapping.DisplayValueXPath) Then
XDoc.selectSingleNode(Mapping.DisplayValueXPath).Text = GetPropDisplayValue(UserSession, CardData, Mapping.PropName)
End If
Next
XDoc.save Path
End Sub

' Получение первого приложенного к карточке файла
Function FirstFile(CardData, UserSession)
Dim FileList, FileRefs, VerFile, VersionID, FileID
Set FileList = UserSession.CardManager.CardData(MainInfo(CardData).Value("FilesID"))
Set FileRefs = Sect(FileList, "FileReferences")
If FileRefs.Rows.Count = 0 Then
Set FirstFile = Nothing
Exit Function
End If
Set VerFile = UserSession.CardManager.CardData(FileRefs.Rows(0).Value("FileID"))
VersionID = Sect(VerFile, "MainInfo").FirstRow.Value("CurrentID")
FileID = Sect(VerFile, "Versions").GetRow(VersionID).Value("FileID")
Set FirstFile = UserSession.FileManager.File(FileID)
End Function

' Сохранение файла на файловой системе во временный файл (возвращает путь к файлу)
Function SaveFileOnFs(File)
Dim Fso, Fld
Set Fso = CreateObject("Scripting.FileSystemObject")
Set Fld = Fso.GetSpecialFolder(2)
SaveFileOnFs = Fso.BuildPath(Fld.Path, Fso.GetTempName)
File.Download SaveFileOnFs
End Function

' Удаление файла с файловой системы
Sub DeleteFileFromFs(Path)
Dim Fso
Set Fso = CreateObject("Scripting.FileSystemObject")
Fso.DeleteFile Path, True
End Sub

' Получение секции карточки по имени
Function Sect(CardData, Alias)
Set Sect = CardData.Sections(CardData.Type.AllSections.GetByAlias(Alias).ID)
End Function

' Нулевая строка секции MainInfo
Function MainInfo(CardData)
Set MainInfo = Sect(CardData, "MainInfo").FirstRow
End Function

' Строка свойства
Function Prop(CardData, Alias)
Set Prop = Nothing
Dim Row: For Each Row In Sect(CardData, "Properties").Rows
If Row.Value("Name") = Alias Then
Set Prop = Row
Exit Function
End If
Next
End Function

' Получение значения свойства
Function GetPropValue(UserSession, CardData, PropName)
Select Case PropName
Case "@Card"
GetPropValue = CardData.ID
Case "@CurrentUser"
GetPropValue = StaffObject(UserSession).GetCurrentUserID
Case Else
Dim PropRow
Set PropRow = Prop(CardData, PropName)
GetPropValue = PropRow.Value("Value")
End Select
End Function

' Получение отображаемого значения свойства
Function GetPropDisplayValue(UserSession, CardData, PropName)
Select Case PropName
Case "@Card"
GetPropDisplayValue = CardData.Description
Case "@CurrentUser"
Dim Staff
Set Staff = StaffObject(UserSession)
GetPropDisplayValue = Staff.GetEmployeeName(Staff.GetCurrentUserID)
Case Else
Dim PropRow
Set PropRow = Prop(CardData, PropName)
GetPropDisplayValue = PropRow.Value("DisplayValue")
End Select
End Function

' Установка значения свойства
Sub SetPropValue(CardData, PropName, Value)
Select Case PropName
Case "Дата"
Value = CDate(Value)
End Select
Dim PropRow
Set PropRow = Prop(CardData, PropName)
PropRow.Value("Value") = Value
End Sub

' Установка отображаемого значения свойства
Sub SetPropDisplayValue(CardData, PropName, DisplayValue)
Select Case PropName
Case "@Card"
CardData.Description = CStr(DisplayValue)
Case Else
Select Case PropName
Case "Дата"
DisplayValue = FormatDateTime(CDate(DisplayValue), 2)
End Select
Dim PropRow
Set PropRow = Prop(CardData, PropName)
PropRow.Value("DisplayValue") = CStr(DisplayValue)
End Select
End Sub

' Получение StaffObject
Function StaffObject(UserSession)
Set StaffObject = CreateObject("TOHelperObjects.StaffObject")
Set StaffObject.UserSession = UserSession
End Function
Читать дальше

Оставить комментарий (всего: 0)

GoogleWave

Коллеги, у меня есть 7 инвайтов на GoogleWave. Кому необходимо, напишите мне mikhail.zakharov[cобаka)gmail.com

upd. закончились.

Сам wave полезен в коллективной работе, и лучше его тестировать совместно с кем то, кто уже имеет аккаунт. 


Читать дальше

Оставить комментарий (всего: 1)

Методический материал "Создание распределенных решений"

Службой консалтинга DocsVision выпущен новый методический материал «Создание распределенных решений на базе DocsVision». Данный вопрос особенно актуален для территориально-распределенных организаций-заказчиков. Материал включает в себя:
1. Документ, в котором рассмотрены существующие в системе DocsVision механизмы построения распределенных решений, принципы выбора архитектуры таких решений и пример решения для распределенной обработки задач в распределенной многосерверной системе.
2. XML-файлы бизнес-процессов DocsVision, реализующих рассматриваемый пример.
Этот методический материал поможет Вам лучше понять возможности cоздания распределенных решений на базе DocsVision, эффективно использовать эти знания в продажах и внедрениях в территориально-распределенных организациях.
Материал можно скачать в разделе «Внедрение» Комплекта Партнера DocsVision на нашем сайте. Читать дальше

Оставить комментарий (всего: 0)

Ещё один способ развернуть клиента DV в сети

Уверен, что многие из читателей занимались установкой клиентской части DV. Способов инсталляции существует немало. Я хочу предложить ещё один, который, на мой взгляд, будет достаточно востребован при установке на n-ое количество компьютеров.

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

Кто-то из читателей наверняка слышал про утилиту psexec. С её помощью можно выполнять команды на удалённом компьютере(-ах). Вот ею мы и воспользуемся.

Ставить будем клиента версии 4.3. Для полноценной его работы требуется .NET Framework 3.5 SP1. По своему опыту могу сказать, что далеко не всегда он установлен, поэтому его тоже включим в скрипт.

Для начала нужно создать два ресурса: один с пакетами инсталляции, второй для журналов установки.
К примеру такие:

\\SERVERNAME\dv_install
\\SERVERNAME\dv_install_logs

Минимальные права для первого - чтение для учётной записи из-под которой будет происходит установка, для второго - чтение\запись для этой же учётной записи.

Если нужно, скачиваем полный дистрибутив NET Framework 3.5 SP1 (231 мб) и кладём его в папку с пакетами клиента DV.

Далее, при помощи генератора преобразований (в консоли настройки) нужно создать преобразования для пакетов DocsVision TakeOffice и DocsVision Client.
В первом пакете, в общем случае, нужно откорректировать значения свойств: BASE_NAME, SERVER_NAME, SITE_URL, SOAP_SERVICE_URL. Во втором - DV_URL. Преобразования сохранить в директории с целевым пакетом.

Теперь нужно создать bat-файлы для установки пакетов.

Файл InstallDVClient.bat

\\SERVERNAME\dv_install\dotnetfx35_wSP1.exe /quiet /norestart

msiexec /i \\SERVERNAME\dv_install\Prerequisites\Prerequisites.msi /quiet /norestart /l* \\SERVERNAME\dv_install_logs\Prerequisites_%COMPUTERNAME%.log
msiexec /i \\SERVERNAME\dv_install\DocsVisionClient\DocsVisionClient1848.msi TRANSFORMS="\\SERVERNAME\dv_install\DocsVisionClient\dv43.mst" ALLUSERS=1 /quiet /norestart /l* \\SERVERNAME\dv_install_logs\Client_%COMPUTERNAME%.log
msiexec /i \\SERVERNAME\dv_install\TakeOfficeClient\TakeOfficeClient1848.msi TRANSFORMS="\\SERVERNAME\dv_install\TakeOfficeClient\dv43.mst" ALLUSERS=1 /quiet /norestart /l* \\SERVERNAME\dv_install_logs\TakeOffice_%COMPUTERNAME%.log
msiexec /i \\SERVERNAME\dv_install\WorkflowClient\WorkflowClient1848.msi ALLUSERS=1 /quiet /norestart /l* \\SERVERNAME\dv_install_logs\Workflow_%COMPUTERNAME%.log
msiexec /i \\SERVERNAME\dv_install\DocsVisionManagedClient\DocsVisionManagedClient1848.msi ALLUSERS=1 /quiet /norestart /l* \\SERVERNAME\dv_install_logs\ManagedClient_%COMPUTERNAME%.log

del %WINDIR%\System32\InstallDVClient.bat


Кому не нужно ставить Framework - убирают первую строку.
Установка будет производиться в режиме "для всех пользователей", на что указывает флаг ALLUSERS=1 (Prerequisites и ManagedClient всегда ставятся в этом режиме). Кому было лень создавать файлы-трансформеры, могут также указать все нужные параметры прямо в файле, но мне это кажется слишком громоздким. Логи будут складываться во вторую шарку. Для каждого компьютера свои логи для каждого пакета.

Файл Install.bat

psexec.exe @C:\DV_Remote_Install\Comps.txt -u Administrator -p password -d -c -f InstallDVClient.bat

В файле Comps.txt хранится список имён (или IP-адресов) компьютеров на которых нужно произвести установку.

Параметр -u в данном случае обязателен, поскольку иначе удалённый процесс установки запустится от имени текущего пользователя с помощью механизма имперсонации. Из соображений безопасности, запущенный в таком режиме процесс не сможет получить доступ к сетевым ресурсам. Итак, указываем пользователя, обладающего административными привилегиями на всех целевых машинах. Пароль можно явно не указывать, в таком случае его нужно будет ввести при запуске команды.

Параметр -d указывает программе не дожидаться окончания выполнения команды. Если его не указать, то установка будет производиться последовательно на каждом компьютере, что значительно увеличит время развёртывания.

Опции и -f указывают, что файл InstallDVClient.bat нужно перед выполнением предварительно скопировать на целевую машину, т.к. его там изначально нет.

Вот и всё. Можно запускать Install.bat и ждать. NET Framework будет ставиться 10-20 минут, потом установятся пакеты пакеты клиентской части (~5 минут). В случае возникновения проблем смотрим логи.

Таким же образом, в случае необходимости, пакеты можно удалить с клиентских машин. Для этого у msiexec существует ключ -x.



Читать дальше

Оставить комментарий (всего: 2)

Советы по разработке оптимальных бизнес-процессов

На партнерском форуме в 2007 году Натальей Евдокимовой был сделан доклад на тему оптимальной разработки бизнес-процессов. Данная тема периодически всплывает в запросах в службу ТП. И я решил поднять его, немного дополнив.


Как это работает.
Модуль "Управление процессами" функционально состоит из двух частей: сервиса DocsVision Workflow Service, и процесса ExecLogic.exe. Сервис осуществляет подготовку процесса к запуску и другие системные операции. ExecLogic.exe непосредственно выполняет функции. Если посмотреть загрузку процессора через Performance Monitor, то можно увидеть, что нагрузка идет пиками.




Происходит это потому, что ExecLogic обрабатывает пакеты функций не постоянно, а периодами - тиками. Последовательность действий такова.

  • Построение списка активных процессов
  • Сортировка процессов по приоритетам
  • Исполнение процессов по приоритетам
  • Проверка нормативного времени тика
Процессы могут различаться по степени их важности, и в случае если невозможно выполнить все процессы сразу и быстро часто хочется чтобы что-то выполнилось в первую очередь: именно для этого и была введена возможность приоритизации процессов. Существует 5 уровней приоритета процессов:

  • Наивысший (процесс гарантированно обрабатывается каждый тик)
  • Высокий (процесс гарантированно обрабатывается каждый третий тик)
  • Обычный (процесс гарантированно обрабатывается каждый пятый тик)
  • Низкий (процесс гарантированно обрабатывается каждый седьмой тик)
  • Самый низкий (процесс гарантированно обрабатывается каждый девятый тик)
Слово «гарантированно» не означает то, что процесс с приоритетом «Обычный» будет обрабатываться только на каждый третий тик: в случае, если не будет процессов с более высоким приоритетом он может быть обработан и раньше, хотя бы каждый тик, как процесс с наивысшим приоритетом.
С введением приоритизации связано введение возможности ограничения времени тика . Этот параметр можно указать в консоли настройки, задается в секундах. Этот параметр задает промежуток времени, при превышении которого обработка процессов прекращается и начинается ожидание следующего тика. На практике реальное время тика может быть несколько выше введенного желаемого. Это связано с тем, что некоторые могут выполняться довольно продолжительное (а самое главное совершенно непредсказуемое по длительности) время, причем прерывать их выполнение Workflow не имеет права. Также, тик может выполняться дольше чем хотелось бы в случае, если в системе присутствует большое количество процессов с наивысшим приоритетом (или приравненных к ним): тик не прерывается до тех пор пока не будут обработаны все процессы с наивысшим приоритетом. К процессам приравненным к процессам с наивысшим приоритетом относятся процессы для которых подошло время их гарантированной обработки (каждый третий тик для обычного приоритета и так далее…).

Параметрами обработки можно управлять. Назначение и подробное описание приведено в статье http://dvprofessionals.blogspot.com/2009/08/workflow.html

Немного о функциях.
Условно функции можно разделить на 3 группы:


  1. Функции, которые работают с данными в базе: мониторинг, универсальный обмен, и т.п. Таких большинство.
  2. Функции, которые работают со внешними системами: мониторинг 1С, CRM и т.д
  3. Функции, который работают только на стороне Workflow: объединение, разветвление, сценарий (в некоторых случаях)
Понятно, что основную роль в производительности может играть отклик сервера DocsVision.

Как правильно стоить схему процесса.
 Операции получения данных и преобразования переменных следует объединить в одну функцию универсального обмена данными
Неправильно:





Правильно:





К свойству нужно обращаться по имени, а не по индексу.
Не правильно:










Правильно:






Необходимо делать параллельные ветки, там где это возможно.
Не оптимально:




Оптимально:








Старайтесь не использовать историю мониторинга, а заменять её дополнительными условиями поиска. Например, есть задача обработки карточек. Создан родительский процесс, который осуществляет мониторинг, и передает найденную карточку в дочерний асинхронный подпроцесс. Нужно, чтобы переданная карточка второй раз не искалась мониторингом. В этом случае эффективнее добавить в карточку свойство типа "Да/Нет", в котором устанавливать "Да", если карточка ушла в обработку.  И на данное свойство добавить условие .






У циклических процессов, которые работают постоянно, отключайте ведение журнала. А так же удаляйте все завершенные подпроцессы. Настроить автоматическое удаление можно в свойствах процесса, на вкладке "Дополнительно", по кнопке "Завершение процесса".


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






Снижайте количество поисков. Если функция мониторинга должна вернуть набор карточек, то лучше возвращать значение в переменную - коллекцию. А затем в цикле получать каждый элемент коллекции.

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


Конец. Внимание опрос. Есть желание написать подробно, как читать сообщения в журнале Workflow. Но поскольку в версии 4.3 структура журнала поменялась, то нужно делать два описания, либо под какую-то наиболее актуальную версию. Вопрос в том, какая версия для вас актуальна: 4.3. или все, что раньше?

Читать дальше

Оставить комментарий (всего: 8)

Получение значения из справочника в XSLT преобразовании

В DocsVision существует возможность создавать XSLT преобразования для создания печатной формы - диалог "Экспорт и печать" карточки. Принцип работы таков. Печатная форма - это HTML документ, который получается следующим образом:
XML карточки + XSLT преобразование = HTML.
При этом нужно отметить, что для формирования печатной формы берется не просто XML карточки, а XML карточки + связанные карточки + связанные строки из справочников.


На рисунке показан пример xml со связанными карточки внутреннего документа. В xml есть данные карточки, данные связанной сильной ссылкой карточки "Список файлов", и данные из справочника сотрудников. Важно отметить, что из справочника сотрудников получена только одна строка, на которую ссылается карточка документа.




Итак:
1. Присоединяются только карточки на которые ссылается поле типа refcardid
 




2. Присоединяются строки из справочников, на которые ссылается поле типа refid



Рассмотрим как получить данные из справочника. Пример, необходимо вывести имя и учетную запись регистратора карточки внутреннего документа. Поскольку строка из справочника сотрудников есть в xml то нужно получить её данные по идентификатору. XPath адрес должед быть таким:


//EmployeesRow[@RowID=//CardOrd[1]/MainInfo/@RegisteredBy]/@AccountName
Т.е. получаем строку из данных справочника, у которой RowID = значению из поля RegisteredBy.

Полный текст шаблона:


<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <xsl:template match="/">
  
   
    <link href="%ServerUrl%/StorageServer/Fetch.aspx?BaseName=%BaseName%&amp;TransformID=B5344DA1-D28F-4024-8798-3FC3992C94B7" rel="stylesheet" type="text/css"></link>
    <title>&lt;xsl:value-of select="//CardOrd[1]/MainInfo/@Name"/&gt;</title>
   
   
     <xsl:value-of select="//EmployeesRow[@RowID=//CardOrd[1]/MainInfo/@RegisteredBy]/@AccountName">
     <xsl:value-of select="//EmployeesRow[@RowID=//CardOrd[1]/MainInfo/@RegisteredBy]/@LastName">
 
   
  
 </xsl:value-of>
</xsl:value-of>
</xsl:template></xsl:stylesheet>

Читать дальше

Оставить комментарий (всего: 4)

Модернизация панели "Читатели" в блоге


Совершенно неожиданно для меня, Blogger модернизировал панель "Читатели". Теперь по нажатию на иконку можно отправить сообщение, переслать ссылку, пригласить друга и опубликовать ссылку в какой-либо сети.
Пользуйтесь :) Читать дальше

Оставить комментарий (всего: 0)

Получение идентификатора пользователя, который открыл карточку

Пример скрипта, который получает идентификатор пользователя из справочника сотрудников, который открыл карточку


Function DoEvent(UserSession, CardFrame, CardData, ActivateFlags, ModeID, FolderID)

        'ID Справочника сотрудников и секции "Сотрудники"
        Const DIC_STAFF = "6710B92A-E148-4363-8A6F-1AA0EB18936C"
        Const SEC_STAFF = "DBC8AE9D-C1D2-4D5E-978B-339D22B32482"
        
        Dim Groups, oRows, FindUserID

        'Получаем пользователя, который открыл карточку
        Set RefStaff = UserSession.CardManager.DictionaryData(DIC_STAFF)
        Set oRows = RefStaff.Sections.Item(SEC_STAFF).FindRows( _
         "AccountNameSTREQ'" & _
         UserSession.Properties("AccountName") & "'")

        If oRows.Count = 0 Then
            'Не найден
            MsgBox ("ОШИБКА! Невозможно найти вашу учетную запись в справочнике")
            Exit Function
        End If
    
        'Это ID пользователя, открывшего карточку
        FindUserID = oRows.Item(0).ID
End Function



Развитие темы. Определение, входит ли пользователь в определенную группу.
Function DoEvent(UserSession, CardFrame, CardData, ActivateFlags, ModeID, FolderID)
'ID Справочника сотрудников и секции "Сотрудники"
Const DIC_STAFF = "6710B92A-E148-4363-8A6F-1AA0EB18936C"
Const SEC_STAFF = "DBC8AE9D-C1D2-4D5E-978B-339D22B32482"

Dim Groups, oRows, FindUserID

'Получаем пользователя, который открыл карточку
Set RefStaff = UserSession.CardManager.DictionaryData(DIC_STAFF)
'Поиск по справочнику сотрудников
Set oRows = RefStaff.Sections.Item(SEC_STAFF).FindRows( _
"AccountNameSTREQ'" & _
UserSession.Properties("AccountName") & "'")
If oRows.Count = 0 Then
'Не найден
MsgBox ("ОШИБКА! Невозможно найти вашу учетную запись в справочнике")
Exit Function
End If

'Это ID пользователя, открывшего карточку
FindUserID = oRows.Item(0).ID

'Поиск в группах
Dim StaffObject
Set StaffObject = CreateObject("TOHelperObjects.StaffObject")
Set StaffObject.UserSession = UserSession

Const GROUPID = "ID группы"
If StaffObject.IsEmployeeInGroup(FindUserID, GROUPID) = True Then
'Пользователь, открывающий карточку - в группе.
End If
Set StaffObject = Nothing
End Function

Читать дальше

Оставить комментарий (всего: 7)

Открытие приложенного документа Word и перенос некоторых полей в документ

Данный скрипт был создан еще для 3.6. Думаю он будет полезен и сейчас.

Пример взаимодействия с внешним приложением MS Word. Рассматриваемый скрипт карточки открывает приложенный файл *.doc, и производит вставку значений полей секции «Основная информация» в текст документа.
Вставка производится следующим образом: В тексте документа размещены названия полей в виде @Name или @Digest – т.н. теги. Скрипт производит замену этих тегов на значения из полей с таким же названием.



Function DoEvent(UserSession, CardFrame, CardData, ActivateFlags, ModeID, FolderID)
    'Открываем файл, присоединенный к карточке
    
    'Создается объект FileList
    Dim sFilesID
    sFilesID = CardDa-ta.Sections.Item(CardData.Type.Sections.GetByAlias("MainInfo").ID).FirstRow.Value("FilesID") & ""
    If sFilesID = vbNullString Then Exit Function
    Dim oFileList
    Set oFileList = CreateObject("TOFileList.FileList")
    Set oFileList.UserSession = UserSession
    
    Dim rows
    Set rows = CardDa-ta.Sections.Item(CardData.Type.Sections.GetByAlias("Properties").ID).rows
    Set oFileList.PropertyRows = rows
    
    oFileList.ID = sFilesID
    
    'Количество файлов
    Dim n: n = oFileList.FileRefs.Count
    
    'Если нет файлов, то выход
    If n = 0 Then
        Exit Function
    End If

    'Открытие файла
    Dim oFile
    Set oFile = oFileList.FileRefs.Item(1)
    oFile.OpenFile

    'Получаем объект WORD
    Dim objWord
    Set objWord = GetObject(, "Word.Application")
    
    'Меняем
    Dim arrFields, strField, oFlag
    arrFields = Array("Name", "Digest") 'Здесь перечислены все теги и поля
    Dim rngStory
    Dim oMainRow
    Set oMainRow = CardData.Sections.Item(CardData.Type.Sections.GetByAlias("MainInfo").ID).FirstRow
        
    Do
        oFlag = False
        For Each strField In arrFields
            objWord.Selection.Start = 0
            objWord.Selection.End = 0
            objWord.Selection.Find.Forward = True
            If objWord.Selection.Find.Execute("@" & strField) = True Then
                If IsNull(oMainRow.Value(strField)) Then
                    objWord.Selection.TypeText (" ")
                Else
                    objWord.Selection.TypeText (oMainRow.Value(strField))
                End If
              oFlag = True
            End If
        Next
    Loop Until oFlag = False

  
    Set oFileList = Nothing
End Function


Читать дальше

Оставить комментарий (всего: 9)

Обновление мастера сбора данных при сбоях


Выпущена новая версия мастера сбора данных при сбоях.

Скачать можно по ссылке.
Либо воспользовавшись кнопкой "Проверить наличие обновлений" Читать дальше

Оставить комментарий (всего: 0)

Права на ярлыки в DocsVision 4.3

В документе "Новое в DocsVision 4.3" есть такая строчка "Отменено назначение прав на ярлык карточки." Она означает, что ярлыки (строки в секции "Ярлыки") не имеют описателей прав. Следовательно при адаптации решения нужно убрать назначение прав на ярлыки, если оно использовалось. Права с папки наследуются непосредственно на карточки. Читать дальше

Оставить комментарий (всего: 0)

Пример. Получение пользователей, которые подписали файл.

Небольшой пример на VB. Получение пользователей, которые подписали файл.

Set m_oAccessManager = UserSession.AccessManager
Set m_oFile = UserSession.FileManager.File(FileID)

' oSignRows - DVObjectManager.InfoRowCollection
Set oSignRows = m_oAccessManager.ListCryptObjects(m_oFile.ID, 0)

For Each oSignRow In oSignRows
    ' кто подписал?
    MsgBox oSignRow.Value("AccountName")

Next oSignRow

Читать дальше

Оставить комментарий (всего: 0)

Несколько примеров бизнес-процессов, работающих со свойствами карточек

Здесь представлены примеры наиболее часто используемых БП для работы со свойствами. Загрузить шаблоны процессов можно по этой ссылке.

1. Добавление простого свойства типа строка.xml - пример создания простого свойства типа Строка, Целое, Дата/Время, сотрудник и т.п.Если свойства с таким названием нет в карточке, оно будет создано. Если есть, будет изменено его значение.

2. Создаем свойство типа карточка.xml - создание свойств других типов, на примере свойства типа Карточка.Необходимо добавить строку в секцию Свойства, затем записать в эту строку необходимые значения. Обязательными являются - Порядковый номер, Тип свойства, Название свойства, Значение свойства, Отображаемое значение.

3. Записываем значение свойства типа карточка.xml - пример изменения значения существующего свойства, на примере типа Карточка.
Необходимо получить нужную строку секции Свойства (в данном процессе это сделано с помощью атрибутивного мониторинга секции, кроме этого строку секции можно получить универсальным обменом, например, по ее индексу), далее записать новое Значение и Отображаемое значение.

4. Создаем свойство типа Перечисление.xml
Шаги по созданию свойства, записи его типа, названия аналогичны примеру 2.
Возможные значения свойства данного типа хранятся в подчиненной по отношению к секции Свойства секции Значения перечисления. Чтобы создать вариант перечисления, необходимо добавить новую строку в эту секцию и заполнить ID значения (соответствует Значению при заполнении перечисления в карточке из UI) и Название значения (соответствует Отображаемому значению). Если необходимо, чтобы в свойстве был выбран определенный вариант перечисления, необходимо заполнить Значение свойства строки секции Свойства одним из ID значения и Отображаемое значение - соответствующим Названием значения из секции Значения перечисления (В примере выбран 1-й вариант - value 1).

5. Добавляем значения в коллекционное свойство типа Подразделение.xml Отличие свойства-коллекции от обычного свойства в том, что значения свойства хранятся не в поле Значение свойства в секции Свойства, а в подчиненной секции Выбранные значения. Соответственно, чтобы добавить новое значение необходимо добавить строку в эту секцию и заполнить поля Порядок и Выбранное значение.Чтобы сформировать новое Отображаемое значение свойства, необходимо получить исходное отображаемое значение, название добавляемого подразделения и объединить их универсальной функцией Объединение строк с разделителем.

6. Получаем значения свойства коллекции типа Сотрудник.xml
Аналогично предыдущим примерам ищем свойство по названию мониторингом, далее получаем все строки секции Выбранные значения, в цикле из каждой строки секции получаем сотрудника, добавляем сотрудника в переменную-коллекцию.
Читать дальше

Оставить комментарий (всего: 0)

Отключение FileStream

Начиная с версии 4.1 появилась возможность при использовании СУБД MS SQL Server 2008 выгружать файлы на диск с использованием технологии FileStream.

В консоли настройки сейчас нет кнопки, которая отключает выгрузку FileStream, и возвращает файлы в базу. Если в этом есть необходимость, то воспользуйтесь следующими скриптами (скачать).

Последовательность выполнения

1.    CopyFileStreamToDb.sql – копируются данные файлов из FileStream-хранилища в базу данных
2.    RemoveFileStream.sql – удаляется файловая группа с Filestream Читать дальше

Оставить комментарий (всего: 0)

Генерация класса с константами по схеме карточки

В тестовом проекте библиотеки карточек есть интересный комментарий, в классе с константами.



Что это за инструмент, который генерирует код автоматически, я опишу в данной статье.


Инструментов два:
  • DVConstGenerator – по XML-описанию карточки создает cs-файл с константами (идентификаторы секций, названия полей)
  • ObjectModelGenerator – по  XML-описанию карточки создает cs-файл с объектной моделью для работы с данными. Объектная модель включает в себя также и константы, поэтому при использовании этой утилиты, предыдущая уже не требуется.
Использование утилит.

1. Запуск из командной строки.
Каждая утилита имеет мини справку по своим параметрам. Достаточно запустить с ключом "/?".
Пример запуска:
ConstGenerator.exe /i:SLA.xml /l:CS
или
ObjectModelGenerator.exe /in:SLA.xml

2. Интеграция с Visual Studio 2005/2008
Для этого нужно зарегистрировать ее библиотеку (*.dll) командой:


regasm.exe <путь к dll-файлу> /codebase

Далее нужно включить в состав проекта файл с XML-описанием (схемой) карточки. В свойствах файла, указать CustomToolName

  • DVConstGenerator – для генератора констант
  • DVAdapterGenerator – для генератора объектной модели

В поле Custom tool namespace можно отдельно специфицировать пространство имен, которое будет использоваться в сгенерированном файле.

После этого правой кнопкной мыши на XML-файле вызвать команду Run custom tool. Будет сгенерирован cs-файл.

Скачать утилиты

Известная особенность: код генерируется только для C#, для VB.net, хоть такой параметр и есть, код не создается. (кстати, если нужно перевести код, то есть хороший переводчик: http://www.developerfusion.com/tools/convert/csharp-to-vb/) Читать дальше

Оставить комментарий (всего: 1)