В документации https://dev.1c-bitrix.ru/api_d7/bitrix/documentgenerator/customization.php описана возможность наследования от уже существующих провайдеров. Но совсем не ясно, как потом подключить наследованный провайдер при построении документа. В моем случае, есть необходимость добавить несколько новые полей, которые можно было бы использовать в шаблонах документов для "счетов".
Добавил MyDataProvider extends Invoice
В нем переопределил getFields с нужными мне дополнительными полями
Подписался на событие onGetDataProviderList. И поля провайдера даже отображаются в админке, при просмотре всех полей.
Но как сделать так, чтобы загружались значения для этих полей, при формировании документа для счета? Ведь при формировании передается dataProviderClass = Invoice, а все остальные источники отфильтровываются. Т.е. в шаблон для счета попадают только данные из Invoice (DataProvider). Неужели ловить событие onBeforeProcessDocument? В чем секрет?
Уже готов был выкручиваться через событие onBeforeProcessDocument, но и с ним никак. Документ я из event получить могу, но вот понять к какому invoice он относится - нет, зачем-то в классе Document getValues помечен protected.
Большое спасибо, как раз то что надо! Раз уж Вы сюда заглянули, может быть подскажите, как можно в шаблон подставить содержимое из другого docx файла? Т.е. я создал свой MyDataProvider и хочу, чтобы вместо плэйсхолдера {myFormattedText} подставилось не просто одно значение, а именно отформатированный текст, который я, например, положил в какой-то docx файл (для простоты, без каких либо плейсхолдеров внутри)? Пытался подпихнуть html, но при конвертации (\Bitrix\DocumentGenerator\Body:778) все выходит криво. Подпихнуть <w:document> тоже не получается, т.к. он начинает его конвертировать как html.
Никита Мех написал: как можно в шаблон подставить содержимое из другого docx файла
Штатно - никак.
Если есть много времени - можно попробовать. Но только руками, уже после создания документа. Каким-то образом помечать нужное место, самостоятельно готовить родительские теги, вычленять теги из другого файла и всё это склеивать.
Написал свой MyInvoice с нужными мне дополнительным полями, только никак не могу разобраться почему в конченом счете они не подставляются в шаблон. Дебагом вижу, что нужные методы дергаются, значения возвращаются, но почему-то в $document->fields они помещаются с дополнительным префиксом SOURCE (\Bitrix\DocumentGenerator\Document:974) и далее, когда уже идет подстановка значений, системы ищет по ключу myField, а значение лежит по SOURCE.myField...
Нашел в чем была причина: ключи для полей в MyInvoice->getFields обязательно должны быть в заглавных буквах и с "_". У меня были MyNewField, а надо MY_NEW_FIELD
Сделал все по примерам с переопределением провайдра. Все работает, только сейчас понял, что при такой реализации очень большая вероятность конфликтов с чужими модулями. Если вдруг какой-то другой модуль тоже будет слушать onDataProviderManagerFillSubstitutionProviders и отдавать свою реализацию Invoice. Скорее всего чей-то код перестанет работать....
Получается самый "безопасный" способ все-таки подстановка в onBeforeProcessDocument, а в нем проблема с доступом к getValues... Антон, подскажите, пожалуйста, как можно подпихнуть свои данные в шаблон не рискуя нарваться на конфликт модулей?
И еще один вопрос вдогонку. Почему-то не получается подставить изображение в шаблон через DataProvider. Во все том же MyInvoice, в методе getFields добавил поле:
Никита Мех написал: Все работает, только сейчас понял, что при такой реализации очень большая вероятность конфликтов с чужими модулями. Если вдруг какой-то другой модуль тоже будет слушать onDataProviderManagerFillSubstitutionProviders и отдавать свою реализацию Invoice
Есть такое. Но по-другому никак. По крайней мере, мне не приходит в голову решения. Можно было бы отдать на откуп пользователю, какую реализацию использовать, но это слишком сложно.
Цитата
Никита Мех написал: Антон, подскажите, пожалуйста, как можно подпихнуть свои данные в шаблон не рискуя нарваться на конфликт модулей
Боюсь, что никак. Можно было бы добавить ещё одно событие, стреляющее непосредственно перед генерацией документа, но там суть та же - кто последний записал, того и тапки.
Цитата
Никита Мех написал: В шаблоне сослался на него через placeholder {QrCode}
Картинки должны вставляться в шаблон как изображения, в свойствах которых указывается код поля. Посмотрите, как сделаны печати и подписи в предустановленных шаблонах
Никита Мех написал: как можно в шаблон подставить содержимое из другого docx файла
Штатно - никак.
Если есть много времени - можно попробовать. Но только руками, уже после создания документа. Каким-то образом помечать нужное место, самостоятельно готовить родительские теги, вычленять теги из другого файла и всё это склеивать.
А есть какое-то событие, на которое можно было бы подписаться и из которого был бы доступ к сформированному docx файлу? Подпихнуть кусок другого docx файла я смогу через свою реализацию DocxXml и его метода printValue.
Но тут именно кусок document.xml получается запихнуть вместо placeholder, а как быть с _rels/document.xml и картинками из media моего внутреннего шаблона? Хочу сделать так, чтобы можно было вместо простого placeholder вставить целиком содержимое другого docx файла (без сложных слияний стилей и т.д.). Вижу решение как-то уже в готовый docx добавить картинку и перенести связь на нее, но на каком этапе можно получить доступ к файлу?
Вариант с собственной реализацией DocxXml - правильный.
Посмотрите класс Docx. Там идет обмен данными о мета-данных изображений через возвращаемые значения. Это клас-контейнер для всего docx файла, а в docxxml обрабатываются xml-файлы из архива с текстом.
В вашем случае помимо вставки готового куска xml придется - удостовериться, что он вставится корректно (если у вас там картинки, скорее всего, надо будет подняться на несколько уровней тегов вверх по иерархии, чтобы оно склеилось) - распарсить ваш кусок вставляемого xml в поисках картинок и нумерованных/ненумерованных списков. Добавить информацию о них в $this->arrayImageValues и $this->numberingIds - проверить, что всё работает.
Документации по этому делу нет, придётся смотреть исходники и дебажить. Формат обмена данными между классами там не очень прозрачный