Договора из Шаблона MS Word 2007+ без OLE

Обработка показывает, как можно создать шаблон в MS Word 2007+ и заполнить его данными из 1с, не используя технологию OLE

Обработка показывает как можно создать шаблон в MS Word 2007+ и заполнить его данными из 1с  не используя технологию OLE. Многие пользуются методом закладок, не считаю его удобным, поэтому хочу предложить идею которая использовалась мной давно в Delphi

Идея проста, сделать в тексте шаблона определённый текст который не будет повторяться и потом заменой заменить поля на нужные данные, поскольку файлы Word 2007+ это уже просто архивы ХМL, просто распаковываем делаем замену упаковываем обратно. На словах может немного сумбурно поэтому публикую сам код и пример в обработке.

поля могут быть отформатированы как нужно пользователю, т.е. можно использовать весь арсенал Word.

скорость работы высока,шаблон на 110 страниц который выложен в примере обрабатывается мение секунды.

 

Процедура кПолучитьДоговорНажатие(Элемент)
Режим = РежимДиалогаВыбораФайла.Открытие;
ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(Режим);
ДиалогОткрытияФайла.ПолноеИмяФайла = "";
Фильтр = "Word (*.docx)|*.docx";
ДиалогОткрытияФайла.Фильтр = Фильтр;
ДиалогОткрытияФайла.МножественныйВыбор = Ложь;
ДиалогОткрытияФайла.Заголовок = "Выберите файл";

Если ДиалогОткрытияФайла.Выбрать() Тогда
ВыбФайл = Новый Файл(ДиалогОткрытияФайла.ПолноеИмяФайла);
ПутьИмяШаблона = ВыбФайл.ПолноеИмя;
ПутьИмяФайла = ПутьИмяШаблона + "_результат.docx";
Иначе
Текст = "ru = ""Файл(ы) не выбран!""; en = ""File(s) not selected!""";
Предупреждение(НСтр(Текст));
Возврат;
КонецЕсли;

СписокПараметров = Новый Структура;
СписокПараметров.Вставить("ААФИОАА","ИВАНОВ");
СписокПараметров.Вставить("ААНОМЕРАА","№456-АВ-789");
СписокПараметров.Вставить("ААДАТААА","16.01.2012");
Сообщить(ТекущаяДата());
псоПолучитьДоговор(ПутьИмяШаблона,ПутьИмяФайла,СписокПараметров);
Сообщить(ТекущаяДата());
КонецПроцедуры
//получает готовый договор с файла шаблона
//ПутьИмяШаблона - путь и имя файла шаблона docx
//ПутьИмяФайла - путь и имя файла куда сохранять готовый договор
//СписокПараметров - параметры и их значения для замены в договоре тип структура (Ключ,Значение)

Процедура псоПолучитьДоговор(ПутьИИмяШаблона,ПутьИИмяФайла,СписокПараметров);
Сейчас = ТекущаяДата();
ПутьИИмя = ПолучитьИмяВременногоФайла();
Путь = "";
Имя = "";
ПозСлэш = Найти(ПутьИИмя,"");
Пока ПозСлэш > 0 Цикл
Путь = Путь+Сред(ПутьИИмя,1,ПозСлэш);
ПутьИИмя = Сред(ПутьИИмя,ПозСлэш+1);
ПозСлэш = Найти(ПутьИИмя,"");
КонецЦикла;
Имя = ПутьИИмя;
Имя = Сред(Имя,1,СтрДлина(Имя)-4);
ВременнаяПапка = КаталогВременныхФайлов() + "1c" + Формат(Год("20031120"),"ЧГ=0") + Месяц(Сейчас) + День(Сейчас) + Час(Сейчас) + Минута(Сейчас) + Секунда(Сейчас) + Имя;

ЧтениеZIP = Новый ЧтениеZipФайла(ПутьИИмяШаблона);
ЧтениеZIP.ИзвлечьВсе(ВременнаяПапка, РежимВосстановленияПутейФайловZIP.Восстанавливать);
ЧтениеZIP.Закрыть();

Текст = Новый ЧтениеТекста(ВременнаяПапка + "worddocument.xml", КодировкаТекста.UTF8);
РезТекст = Новый ЗаписьТекста(ВременнаяПапка + "worddocument1.xml", КодировкаТекста.UTF8);

Стр = Текст.Прочитать();
Пока Стр <> Неопределено Цикл
Для каждого Элемент Из СписокПараметров Цикл
Стр = СтрЗаменить(Стр,Элемент.Ключ,Элемент.Значение);
КонецЦикла;
РезТекст.Записать(Стр);
Стр = Текст.Прочитать();
КонецЦикла;
Текст.Закрыть();
РезТекст.Закрыть();

Попытка
УдалитьФайлы(ВременнаяПапка + "worddocument.xml");
ПереместитьФайл(ВременнаяПапка + "worddocument1.xml",ВременнаяПапка + "worddocument.xml");
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;

ЗаписьZIP = Новый ЗаписьZipФайла(ПутьИИмяФайла);
ЗаписьZIP.Добавить(ВременнаяПапка + "*.*", РежимСохраненияПутейZIP.СохранятьОтносительныеПути, РежимОбработкиПодкаталоговZIP.ОбрабатыватьРекурсивно);
ЗаписьZIP.Записать();
Попытка
УдалитьФайлы(ВременнаяПапка);
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;

КонецПроцедуры

16 Comments

  1. sytkosa

    (0) Да для фиксированного шаблона самая быстрая реализация. я бы добавил ещё код который упрощенно копи-пастом добавляет новую строку в простой таблице (Таблица без объединенных ячеек по вертикали)

    Reply
  2. RayCon

    Файл не найден или был удален 🙁

    Reply
  3. wbazil

    странно, в понедельник перезайлью т.к. файлы на работе

    Reply
  4. wbazil

    перезалил архив

    Reply
  5. rasswet

    (1) поддерживаю.

    (0)Можете добавить? раз уж вы в этой теме.

    Reply
  6. Cyberhawk

    (1) или (6) — код по добавлению строк есть?

    Reply
  7. wbazil

    (7) я добавление строк не делал, но в общем думаю надо брать простую таблицу выгружать в ХМЛ и смотреть как добавлять новую строку, если сами сделаете поделитесь в ЛС или прямо тут

    Reply
  8. Cyberhawk

    К сожалению, пришлось отказаться от работы с Вордом без СОМ-модели, т.к. для замены текста (классическая задача по заполнению параметров печатных форм — договоров, например) через ковыряние в docx выяснилось, что текст иногда произвольным обрзом разделяется тегами w:r (параграфы, «run»); также положение курсора, начало-конец проверки орфографии и пунктуации и теги форматирования «вклиниваются» в куски текста внутри document.xml и делают замену текста делом практически нереальным.

    Простой пример: пишу в Ворде текст (который должен заменяться потом программно в 1С) «[Договор.Номер]», в document.xml это превращается в

    <w:t>Договор</w:t>
    </w:r>
    <w:r w:rsidR=»00BD0530″>
    <w:rPr>
    <w:rFonts w:ascii=»Calibri» w:hAnsi=»Calibri» w:cs=»Calibri»/>
    <w:sz w:val=»22″/>
    <w:szCs w:val=»22″/>
    </w:rPr>
    <w:t>.</w:t>
    </w:r>
    <w:r w:rsidR=»007F59CC»>
    <w:rPr>
    <w:rFonts w:ascii=»Calibri» w:hAnsi=»Calibri» w:cs=»Calibri»/>
    <w:sz w:val=»22″/>
    <w:szCs w:val=»22″/>
    </w:rPr>
    <w:t>НомерДоговора</w:t>)

    Показать

    Найденный способ обхода — вставлять текст-параметр в документ Ворд путем копирования цельного куска текста из внешнего редактора (из блокнота, например), для пользователя не под силу.

    Reply
  9. wbazil

    тоже встречался с этой проблемой, 100% ловиться когда при написании названия параметра переключать шрифт нажимать бекспейс

    от решения не отказывался т.к. шаблоны делаются намного реже чем печатаются, да и пользователю сразу видно какой параметр ошибочно написан, имхо лучше поискать ошибочно написанный параметр чем воевать с зависшими вордами в терминале

    ЗЫ. поэтому параметры в примере и обрамляются через АА…АА а не через {} или <>

    Reply
  10. NoRazum

    сама идея великолепная.

    сделал на ней выгрузку. Все отлично немного со заменой помучился, но стоит этого.

    Даже колонтитулы можно менять

    ПЛЮС.

    Reply
  11. XelOla

    С Эксель сработает?

    Reply
  12. wbazil

    нет с Эксель из примера не сработает, но подобный подход можно применить и там, т.к. файл Эекселя 2007+ это такой же контейнер с xml файлами, как и файл Ворд, хотя там на каждый лист свой xml файл.

    Reply
  13. bogdan_sukonnov

    (9) мне кажется, самое гуманное решение проблемы вставки лишних тэгов внутрь наших «переменных» — макрос, обрабатывающий шаблон после того, как его подготовил пользователь, но до того, как его начали использовать в 1С. Пусть зло побеждает само себя!

    Reply
  14. artms

    Давно написал парсер (увы не все предусмотрено, но легко создать рабочий шаблон, в WORD):

    https://infostart.ru/public/675307/

    Увы строки замены могут разбиты тегами, определяющий шрифт, иногда пробел. Это частично решено этим парсером.

    Reply
  15. wbazil

    (15) в (9) (10) уже обсуждали данную проблему

    Reply
  16. artms

    (16) Эта проблема решена этим парсером https://infostart.ru/public/675307/ . Поэтому этот не совсем то что обсуждали.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *