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