Кастомизируем экспорт в ABBYY FlexiCapture 9.0+ с помощью COM-компоненты

16 сентября 2010 г.

Сегодня поговорить хотелось бы о кастомизированном экспорте в Abyy FlexiCapture 9.0+.
Кратко пробежимся по основным моментам:

Как гласит сайт ABBYY — «ABBYY FlexiCapture 9.0 — это новое мощное решение для потокового ввода данных и обработки документов, позволяющее автоматически извлекать информацию из бумажных документов и форм и сохранять ее в различные информационные системы предприятия.». В принципе очень понятное определение основных фич продукта.
От себя могу добавить, что по сути мы имеем распределенную систему, которая на вход принимает кучу отсканированных документов, а на выходе дает необходимые распознанные данные, детализированные до документа. Стоит заметить, что у системы есть куча плюсов, таких как возможность верификации распознанных данных, экспорта в файл, БД, а так же неплохую производительность. Серьезных минусов же не так много и думаю в будущих релизах они будут замечены и исправлены.

В одном из последних проектов пришлось очень плотно поработать с данным продуктом, в следствие чего появился некоторый опыт, коим и хотелось бы поделиться, ибо такой информации реально мало и я её черпал исключительно методом проб и ошибок.
В данной статье я хотел бы написать о кастомном экспорте распознанных данных, а именно использовании внешней COM-компоненты.
Подробно останавливаться на создании COM я думаю не стоит и будет полезней осветить основные моменты. В качестве языка и платформы я использовал .NET C# просто потому что это самый удобный способ на мой взгляд.

Итак, приступим:
Что бы направить процесс экспорта на COM достаточно выполнить следующие действия:
Открыть Станцию настройки проектов — Проект — Определения документов — выбрать интересующее определение — определение документа — настройки экспорта — добавить пользовательский экспорт:
Выбираем язык (Jscript или VBscript) и цепляем COM. В моему случае это делается такими строчками:

1
2
var autoExport = new ActiveXObject("CustomExport.Export");
autoExport.ExportDocument( this, ExportTools );

где CustomExport — имя COM-dll, Export — класс, обрабатывающий экспорт, а ExportDocuments() — метод, принимающий распознанный документ и служебный объект ExportTools.

Вообще выбор COM-компоненты обусловлен необходимостью отправлять распознанные данные в систему документооборота IBM FileNet посредством web-сервиса. Далее представлен код простейшего класса, который просто принимает распознанные данные, заполняет внутренние объекты и отсылает в FileNet:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
[Guid("32B10C3B-EEA3-4194-B0A0-E358C31025A")]
using System;
using System.Runtime.InteropServices;
using System.IO;
using FlexiCapturescriptingObjects;
 
namespace ExportLibrary1
{
// Интерфейс компоненты экспорта, с которым можно работать из скрипта
// При создании новой компоненты следует сгенеровать новый GUID
 
[Guid("32B10C3B-EEA3-4194-B0A0-E358C310225A")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)
public interface _cExport
{
[DispId(1)]
void ExportDocument(ref IExportDocument DocRef, ref IExportTools Tools);
}
 
// Класс с реализацией функциональности компоненты экспорта
// При создании новой компоненты следует сгенерировать новый GUID и
// задать свой ProgId
[Guid("3BA19BD7-C6DC-4f63-BC08-0D95254DADC3")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("ExportLibrary1.Export")]
[ComVisible(true)]
public class Export : _cExport
{
private List fields;
 
public Export()
{
}
 
// Функция осуществляет экспорт документа - создает папку
// экспорта, сохраняет в нее файлы изображений страниц и
// текстовый файл с полями документа и информацией о документе
public void ExportDocument( ref IExportDocument docRef, ref IExportTools exportTools )
{
try
{
// экспорт информации о документе
ParameterMap parameters = new ParameterMap();
parameters.parameters = exportDocInfo( docRef );
// экспорт полей
fields = new List();
exportFields( docRef.Children );
}
catch( Exception e )
{
docRef.Action.Succeeded = false;
docRef.Action.ErrorMessage = e.ToString();
}
}
 
// Экспортирует информацию о документе
private Parameter[] exportDocInfo( IExportDocument docRef)
{
List list = new List();
 
Parameter batchIdEntry = new Parameter();
batchIdEntry.key = Constants.ParameterNames.batchId;
batchIdEntry.value = getBatchId(docRef.Id);
list.Add(batchIdEntry);
 
Parameter totalSymbolsCountEntry = new Parameter();
totalSymbolsCountEntry.key = Constants.ParameterNames.totalSymbolsCount;
totalSymbolsCountEntry.value = docRef.TotalSymbolsCount;
list.Add(totalSymbolsCountEntry);
 
Parameter recognizedSymbolsCountEntry = new Parameter();
recognizedSymbolsCountEntry.key = Constants.ParameterNames.recognizedSymbolsCount;
recognizedSymbolsCountEntry.value = docRef.RecognizedSymbolsCount;
list.Add(recognizedSymbolsCountEntry);
 
Parameter uncertainSymbolsCountEntry = new Parameter();
uncertainSymbolsCountEntry.key = Constants.ParameterNames.uncertainSymbolsCount;
uncertainSymbolsCountEntry.value = docRef.UncertainSymbolsCount;
list.Add(uncertainSymbolsCountEntry);
 
Parameter docTemplate = new Parameter();
docTemplate.key = Constants.ParameterNames.docTemplate;
docTemplate.value = docRef.TemplateName;
list.Add(docTemplate);
 
Parameter docId = new Parameter();
docId.key = Constants.ParameterNames.docId;
Int32 docIdTemp = 0;
Int32.TryParse(docRef.Id, out docIdTemp);
docId.value = docIdTemp;
list.Add(docId);
 
return list.ToArray();
}
 
// Экспортирует коллекцию полей
private void exportFields( IExportFields fields, StreamWriter sw, string indent )
{
foreach( IExportField curField in fields )
{
exportField( curField, sw, indent );
}
}
 
// Экспортирует указанное поле
private void exportField( IExportField field)
{
 
Field newField = new Field();
newField.fieldName = field.Name;
 
newField.fieldValue = field.Value.ToString();
newField.recognitionStats = field.SuspiciousSymbols;
 
fields.Add(newField);
 
if( field.Children != null )
{
// экспорт дочерних полей
exportFields( field.Children, sw, indent + " " );
}
else if( field.Items != null )
{
// экспорт экземпляров поля
exportFields( field.Items, sw, indent + " " );
}
}
}
}

Вот такой незамысловатый класс.
Это самая простая реализация кастомного экспорта, нюансов у которого просто куча.

Теги:
рубрика C#