Извлекаем текст из PDF средствами 1С:Предприятия 8.3 — от IFilter до OCR
Содержание
Встроенного парсера PDF в платформе 1С 8.3 нет: табличный документ умеет сохранять в PDF, но не открывать его. Прочитать PDF файл в 1С можно тремя путями: объектом ИзвлечениеТекста (работает через установленный в Windows фильтр PDF), вызовом внешней утилиты pdftotext с последующим чтением текстового файла или через COM-объект программы, которая понимает PDF. Для сканов без текстового слоя нужен отдельный шаг распознавания.
Типичная ситуация: поставщик присылает счета в PDF, и бухгалтер просит «чтобы 1С сама вытаскивала ИНН и сумму». Задача решается, но сначала надо понять, какой перед вами PDF и где будет выполняться код — на клиенте или на сервере.
Что внутри PDF и почему 1С не читает его напрямую
PDF — это не текстовый файл, а описание страницы для печати. Внутри лежат объекты: шрифты, картинки и потоки команд «нарисуй такие символы в такой точке листа».
Что мешает прочитать его как обычный файл:
- 🗜️ Сжатие. Потоки содержимого почти всегда упакованы алгоритмом FlateDecode. Средствами 1С распаковать такой поток напрямую нельзя:
ЧтениеZipФайлаработает с zip-архивами, а не с отдельными сжатыми потоками. - 🔤 Кодировки шрифтов. Символы часто хранятся как номера глифов. Чтобы превратить их в буквы, нужна таблица ToUnicode. Если создатель файла её не встроил, даже профессиональные утилиты выдают «кракозябры».
- 📐 Порядок текста. Строки в файле идут в том порядке, в каком их нарисовал генератор, а не в порядке чтения. Таблица может превратиться в столбик слов.
- 🖼️ Сканы. Отсканированный документ — это картинка, завёрнутая в PDF. Текста там нет вообще.
Отсюда практичный вывод: не пишите свой разбор PDF на встроенном языке. Отдайте извлечение текста готовому инструменту, а в 1С обрабатывайте уже обычную строку.
Как быстро понять тип файла: откройте его в любом просмотрщике и попробуйте выделить слово мышью. Выделяется — текстовый слой есть. Выделяется вся страница целиком как рисунок — это скан, переходите сразу к разделу про распознавание.
Способы прочитать PDF в 1С 8.3: сравнение
| Способ | Что нужно установить | Где работает | Плюсы | Минусы |
|---|---|---|---|---|
ИзвлечениеТекста | PDF IFilter (Adobe, Foxit и др.) | Windows | Две строки кода | Зависит от фильтра, порядок текста не управляется |
pdftotext (Poppler или Xpdf) | Утилита, без регистрации в системе | Windows и Linux, клиент и сервер | Бесплатно, режим -layout сохраняет колонки | Нужен временный файл и запуск процесса |
| COM Adobe Acrobat | Платный Acrobat (не Reader) | Windows | Точное извлечение | Лицензия, только клиент или сервер с GUI |
| COM Microsoft Word | Word 2013 и новее | Windows | Есть почти у всех | Медленно, ломает вёрстку таблиц |
| Внешняя компонента | Своя DLL или готовая компонента | Зависит от сборки | Работает без внешних программ | Нужна разработка на C++ |
| OCR (Tesseract) | Tesseract + pdftoppm | Windows и Linux | Читает сканы | Ошибки распознавания, нужна проверка |
Чтение PDF через объект ИзвлечениеТекста и COM-объекты
Платформенный объект ИзвлечениеТекста
В платформе есть объект ИзвлечениеТекста. Он отдаёт файл системным фильтрам Windows (IFilter) — тем же, через которые работает поиск Windows по содержимому файлов. На этом механизме построено извлечение текста для полнотекстового поиска в БСП.
&НаСервере
Функция ТекстИзPDFЧерезФильтр(ПутьКФайлу)
Извлечение = Новый ИзвлечениеТекста(ПутьКФайлу);
Возврат Извлечение.ПолучитьТекст();
КонецФункции
Код короткий, но есть условие: на компьютере, где он выполняется, должен быть установлен 64-битный или 32-битный PDF IFilter той же разрядности, что и процесс 1С. Без фильтра метод вернёт пустую строку или вызовет исключение. На сервере 1С фильтр ставят на машину с рабочими процессами, а не на компьютер пользователя.
Если код помечен &НаСервере, файл должен лежать там, где его видит сервер. Путь C:\Users\buh\Desktop\счёт.pdf с компьютера бухгалтера сервер не найдёт.
Adobe Acrobat через COM
Если в организации куплен Acrobat Pro или Standard, его COM-сервер умеет сохранить документ как простой текст. Бесплатный Acrobat Reader COM-объектов AcroExch не регистрирует — на нём этот код не заработает.
&НаКлиенте
Функция ТекстИзPDFЧерезAcrobat(ПутьКФайлу)
ИмяТекста = ПолучитьИмяВременногоФайла("txt");
Документ = Новый COMОбъект("AcroExch.PDDoc");
Если Не Документ.Open(ПутьКФайлу) Тогда
ВызватьИсключение "Acrobat не смог открыть файл " + ПутьКФайлу;
КонецЕсли;
JS = Документ.GetJSObject();
JS.saveAs(ИмяТекста, "com.adobe.acrobat.plain-text");
Документ.Close();
Текст = Новый ТекстовыйДокумент;
Текст.Прочитать(ИмяТекста);
Результат = Текст.ПолучитьТекст();
УдалитьФайлы(ИмяТекста);
Возврат Результат;
КонецФункции
Кодировку текстового файла Acrobat выбирает сам, поэтому Прочитать вызван без явной кодировки: платформа определит её по метке BOM. Если кириллица побилась — укажите кодировку явно.
Microsoft Word через COM
Word начиная с версии 2013 открывает PDF и конвертирует его в редактируемый документ. Через COM это выглядит так: создаёте Word.Application, открываете файл методом Documents.Open с параметром ConfirmConversions = False, берёте Content.Text, закрываете документ без сохранения и вызываете Quit().
Подходит для разовых задач. Для потока документов — нет: конвертация занимает секунды на страницу, Word может показать диалог и «зависнуть» в фоне, а таблицы он раскладывает непредсказуемо. На сервере 1С офисные программы через COM запускать не стоит: Microsoft не поддерживает такой сценарий для служб.
Если Новый COMОбъект выдаёт ошибку создания объекта, первым делом проверьте разрядность. 64-битный клиент 1С не создаст in-process COM-объект, у которого есть только 32-битная регистрация.
Внешние компоненты и библиотеки для разбора PDF
Под «подключением dll» в 1С обычно понимают внешнюю компоненту. Это библиотека, написанная по технологии Native API (C++) или COM, которую подключают методом ПодключитьВнешнююКомпоненту и затем создают как объект AddIn.ИмяКомпоненты.
Варианты на практике:
- 🧩 Готовая компонента. Есть коммерческие и открытые компоненты для работы с PDF. Перед покупкой проверьте, что она поддерживает нужную разрядность клиента и сервера, Linux (если сервер на нём) и именно извлечение текста, а не только создание PDF.
- 🛠️ Своя Native API компонента. Внутри — любая C++ библиотека разбора PDF, снаружи — один метод «дай текст по пути к файлу». Требует программиста на C++ и сборки под каждую нужную разрядность и ОС.
- 🔗 .NET-сборка через COM. Библиотеку на C# с открытой лицензией регистрируют как COM-видимую сборку (
regasm /codebase). В 1С её создают черезНовый COMОбъект. Работает только на Windows.
Компоненту удобно хранить в общем макете с типом «Внешняя компонента» или «Двоичные данные» и подключать по адресу во временном хранилище. Тогда её не надо раскладывать по компьютерам вручную.
Компонента оправдана, когда документов тысячи и запуск внешней программы на каждый файл заметно тормозит. Для десятков файлов в день pdftotext проще и надёжнее.
Пошаговое чтение PDF во внешней обработке через pdftotext
Самый универсальный вариант. pdftotext входит в пакеты Poppler (Linux: пакет poppler-utils) и Xpdf (есть сборки для Windows). Утилита не требует установки в систему: достаточно распаковать архив.
Шаг 1. Установите утилиту на нужную машину
- Файловая база или код
&НаКлиенте— на компьютер пользователя. - Клиент-серверная база и код
&НаСервере— на сервер 1С, где работают рабочие процессы. - Проверьте вручную в командной строке:
pdftotext -enc UTF-8 -layout счёт.pdf счёт.txt. Если файл с текстом появился — утилита работает.
Шаг 2. Создайте внешнюю обработку
В Конфигураторе: Файл → Новый → Внешняя обработка. Добавьте реквизит ПутьКФайлу (строка) и Результат (строка неограниченной длины, на форме — многострочное поле). Команда формы вызывает серверную функцию.
Шаг 3. Напишите функцию извлечения
&НаСервереБезКонтекста
Функция ПрочитатьPDF(ПутьКФайлу, ПутьКУтилите = "C:\poppler\bin\pdftotext.exe")
ИмяТекста = ПолучитьИмяВременногоФайла("txt");
Команда = СтрШаблон("""%1"" -enc UTF-8 -layout ""%2"" ""%3""",
ПутьКУтилите, ПутьКФайлу, ИмяТекста);
КодВозврата = 0;
ЗапуститьПриложение(Команда, , Истина, КодВозврата);
ФайлТекста = Новый Файл(ИмяТекста);
Если КодВозврата <> 0 Или Не ФайлТекста.Существует() Тогда
ВызватьИсключение СтрШаблон("pdftotext завершился с кодом %1",
Формат(КодВозврата, "ЧН=0; ЧГ=0"));
КонецЕсли;
Текст = Новый ТекстовыйДокумент;
Текст.Прочитать(ИмяТекста, КодировкаТекста.UTF8);
Результат = Текст.ПолучитьТекст();
УдалитьФайлы(ИмяТекста);
Возврат Результат;
КонецФункции
Ключи утилиты, которые пригодятся:
| Ключ | Что делает |
|---|---|
-enc UTF-8 | Кодировка результата. Без него кириллица может прийти в другой кодировке |
-layout | Сохраняет расположение колонок — удобно для таблиц |
-f 1 -l 1 | Читать только с первой по первую страницу |
-upw пароль | Пароль пользователя для защищённого файла |
На Linux-сервере путь к утилите обычно /usr/bin/pdftotext, кавычки вокруг путей оставьте — они спасают от пробелов в именах.
Шаг 4. Передайте файл с клиента на сервер
Если пользователь выбирает файл на своём компьютере, а утилита стоит на сервере, файл нужно переслать. На клиенте поместите его во временное хранилище (НачатьПомещениеФайлаНаСервер в современных релизах платформы), на сервере получите ДвоичныеДанные через ПолучитьИзВременногоХранилища, запишите их во временный файл методом Записать и передайте этот путь в ПрочитатьPDF.
Шаг 5. Разберите текст
Извлечённый текст — обычная строка. Делите её на строки через СтрРазделить(Текст, Символы.ПС) и ищите нужные места. Пример: вытащить ИНН, который стоит после слова «ИНН».
Функция НайтиИНН(Текст)
Позиция = СтрНайти(Текст, "ИНН");
Если Позиция = 0 Тогда
Возврат "";
КонецЕсли;
Результат = "";
Граница = Мин(Позиция + 40, СтрДлина(Текст));
Для Индекс = Позиция + 3 По Граница Цикл
Символ = Сред(Текст, Индекс, 1);
Если СтрНайти("0123456789", Символ) > 0 Тогда
Результат = Результат + Символ;
ИначеЕсли СтрДлина(Результат) > 0 Тогда
Прервать;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Для строки ИНН/КПП 7701234567/770101001 функция пропустит «/КПП », соберёт 7701234567 и остановится на косой черте. Проверяйте длину результата: 10 цифр у организации, 12 у ИП.
Не записывайте распознанные реквизиты сразу в проведённые документы. Создавайте документ без проведения или показывайте пользователю форму сверки. Одна смещённая колонка — и сумма попадёт в поле НДС.
Распознавание сканов: OCR для PDF без текстового слоя
Если pdftotext вернул пустую строку или несколько пробелов, в файле картинки. Тут нужен OCR. Бесплатная связка — Poppler и Tesseract.
- Превратите страницы в изображения:
pdftoppm -r 300 -png скан.pdf стр. Появятся файлыстр-1.png,стр-2.pngи так далее. При десяти и более страницах номера дополняются нулями, поэтому ищите их по маскеНайтиФайлы(Каталог, "стр-*.png"), а не собирайте имена вручную. - Распознайте каждую картинку:
tesseract стр-1.png стр-1 -l rus+eng. Tesseract сам добавит расширение и создастстр-1.txtв UTF-8. - Прочитайте текстовые файлы тем же
ТекстовыйДокумент.Прочитать(..., КодировкаТекста.UTF8)и склейте. - Удалите временный каталог.
Для русского языка нужен файл языковых данных rus.traineddata. В установщике для Windows его отмечают галочкой, на Linux ставят отдельным пакетом языка.
Что влияет на качество распознавания:
- 📏 Разрешение. Ниже 300 dpi мелкий шрифт в таблицах распознаётся плохо.
- 📐 Перекос. Лист, отсканированный под углом, даёт перепутанные строки.
- 🖊️ Печати и подписи поверх текста. Цифры под синей печатью — частый источник ошибок в суммах.
Альтернатива — утилита OCRmyPDF: она добавляет в скан невидимый текстовый слой, после чего файл читается обычным pdftotext. Для потоковой обработки первички есть и коммерческие сервисы распознавания, включая «1С:Распознавание первичных документов». Они понимают структуру счёта и УПД, а не только буквы, но работают по подписке.
Ошибки при чтении PDF в 1С и как их исправить
Ещё две проблемы, которые не видны сразу:
- 🔐 Файл защищён паролем.
pdftotextбез ключа-upwзавершится с ненулевым кодом. Пароль хранят в настройках обработки, а не в коде. - 🧹 Мусор во временном каталоге. Если между созданием файла и
УдалитьФайлывозникло исключение, файл останется. Оборачивайте чтение вПопытка … Исключение, а удаление вызывайте в обеих ветках.