Кастомизируем экспорт в ABBYY FlexiCapture 9.0+ с помощью COM-компоненты
Сегодня поговорить хотелось бы о кастомизированном экспорте в 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 + " " ); } } } }
Вот такой незамысловатый класс.
Это самая простая реализация кастомного экспорта, нюансов у которого просто куча.