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

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

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

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

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

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

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

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

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

[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#