Доброго дня всем!
Вопрос по вставке картинок.
Ситуация такая:
Есть форматированный документ на форме справочника. Из иерархии этого справочника собирается вордовый документ. Затем в ворде могут что-то поправить в содержимом и надо изменения загрузить обратно в 1С, каждый раздел текста в свой форматированный документ (далее ФД).
Так вот с текстовым содержимым почти все складывается хорошо, кроме там при обратном чтении появляются иногда лишние пустые абзацы между каждым абзацем. А с картинками магия, мне не понятная.
Картинку можно в ФД вставить из буфера или через ЕЩЁ>Вставить картинку. Первый способ картинки видит при разборе ФД.ПолучитьHTML(лкТекстHTML, лкВложения); В структуре лкВложения появляются картинки. А через "ЕЩЁ>Вставить картинку" там ни чего не появляется и при конвертации ФД в HTML уже просто пустое место только.
То есть проблема 1 - как обрабатывать картинки, вставленные через "ЕЩЁ>Вставить картинку"?
Ладно, вставленные через буфер картинки я в сформированном ворде получил. Теперь пробую ворд зачитать назад в 1С. Промежуточно создаются файлы HTML с найденным разделом каждым отдельно и уже это файлик вставляю в ФД и в файлике, пока он на диске, картинка из ворда есть. Потом сформированные файлы складываю в хранилище и ухожу на сервер, там уже не вижу что в них, но картинки в ФД попадают прямоугольниками с надписью, что файл был удален или перемещен.
Уже долго с этим борюсь, моих познаний не хватает. Нагуглить что-то полезное тоже не получается с уже готовым решением.
Проблема с разными вариантами хранения картинки в ворде и в ФД и как с обоими вариантами работать?
---
Ну вроде победил.
По порядку:
Собираю ворд на клиенте. Получив из собранных данных реквизит типа ХранилищеЗначений ухожу с ним на сервер и там получаю из него форматированный документ. На сервере в нем видим одинаково все картинки, как вставленные пользователем через буфер, так и через меню вставить картинку. А так же записанные программной загрузкой из ворда.
Раскладываю на сервере полученный ФД в XML-строку.

```1c
    &НаСервере
    Функция ПолучитьФД_Данные(РеквизитХранилище)

    ФД = РеквизитХранилище.Получить();
    Если НЕ ФД = Неопределено Тогда
    Попытка
    КоличествоЭлементов = ФД.Элементы.Количество();
    Если КоличествоЭлементов = 0 Тогда
    Возврат Ложь;
    КонецЕсли;
    Исключение
    Возврат Ложь;
    КонецПопытки;

    лкТекстHTML = ";
    лкВложения = Новый Структура;
    ФД.ПолучитьHTML(лкТекстHTML, лкВложения);
    Для каждого лкВложение Из лкВложения Цикл
    лкТекстHTML = СтрЗаменить(лкТекстHTML, " src="" + лкВложение.Ключ + ", " src="data:image/png;base64, " + Base64Строка(лкВложение.Значение.ПолучитьДвоичныеДанные()) + "");
    КонецЦикла;
    Возврат лкТекстHTML;
    КонецЕсли;

    Возврат Ложь;

    КонецФункции
```

Полученную строку возвращаю на клиент и на клиенте уже заново из этой строки создаю новый форматированный документ. Затем его сохраняю в HTML файл и этот файл в нужном мне месте в ворде.

```1c
    ФД = УстановитьHTMLвВременный_ФорматированныйДокумент(лкТекстHTML);
    #Если ВебКлиент Тогда
    ИмяВрФайлаХтмл = КаталогВременныхФайлов() + Строка(Новый УникальныйИдентификатор) + ".html";
    #Иначе
    ИмяВрФайлаХтмл = ПолучитьИмяВременногоФайла("html");
    #КонецЕсли

    ФД.Записать(ИмяВрФайлаХтмл, ТипФайлаФорматированногоДокумента.HTML);

    Selection.EndKey(6);
    Start = Selection.Start;
    Selection.InsertFile(ИмяВрФайлаХтмл,,, Ложь);

    &НаКлиенте
    Функция УстановитьHTMLвВременный_ФорматированныйДокумент(Знач пТекстHTML)

    Ф_Док = Новый ФорматированныйДокумент;
    лкВложения = Новый Структура;
    лкПрефикс = " src="data:image/png;base64, ";

    Пока Найти(пТекстHTML, лкПрефикс) > 0 Цикл

    лкНачалоКартинки = Найти(пТекстHTML, лкПрефикс) + СтрДлина(лкПрефикс);
    лкBase64ДанныеКартинки = Сред(пТекстHTML, лкНачалоКартинки);
    лкBase64ДанныеКартинки = Лев(лкBase64ДанныеКартинки, Найти(лкBase64ДанныеКартинки, "") - 1);

    лкКодСоответствия = "_" + СтрЗаменить(Новый УникальныйИдентификатор, "-", ");
    лкКартинка = Новый Картинка(Base64Значение(лкBase64ДанныеКартинки));
    лкВложения.Вставить(лкКодСоответствия, лкКартинка);

    пТекстHTML = СтрЗаменить(пТекстHTML, лкПрефикс + лкBase64ДанныеКартинки + ",
    " src="" + лкКодСоответствия + ");

    КонецЦикла;

    Ф_Док.УстановитьHTML(пТекстHTML, лкВложения);
    Возврат Ф_Док;

    КонецФункции
```

Код на стадии - как-то там заработало. Теперь оптимизация от бегания туда-сюда и прочие плюшки.
Всем спасибо)))
Надеюсь не зря парился, кому-то это поможет.
Вознаграждение оставляю себе :о))))
---
Как бы понимаю, что половина решения - это на скрине при чтении промежуточного файла HTML я получаю текст XML и в нем на файл ссылка только, в HTML на неё навести курсор и там путь к временному файлу появляется, но в строке XML это теряю, а должно там оказаться в виде двоичной строки.
Как получить картинку в виде двоичной строки из ФД - у меня пример есть (опять же только для картинок через буфер вставленных, а через вставить картинку уже не работает...). А из HTML файла картинку пока не понимаю - как вытащить.

А потом ещё момент часто возникает побочный. Эти картинки, которые вставлены в ФД через буфер обмена - могут пропадать просто при чтении ФД из хранилища значения программном. То есть что-то криво отработало при формировании ворда и он открывается без картинок, только прямоугольнички. И открываю соответствующий элемент справочника с исходником и там так же картинка битая уже. Хотя элемент справочника не перезаписывался, а только программно зачитывался. Бывает ворд нормально с картинками создался. Делаю копию файла и картинки на месте в копии тоже. Потом эксперименты с основным файлом, пробую его читать и картинки становятся битыми сразу и в элементе справочника и в обоих файлах ворда. То есть вообще результат ни в какие ворота...

Три закоментированные строки - это более короткий вариант переноса из HTML в ворд, но результат одинаковый. А ещё вот где-то тут все отдельно стоящие абзацы в тексте - разделяются в конечном результате ещё пустыми абзацами.
---
Вот как бы кусочек рабочий по выделению картинок из ФД в виде двоичных данных внутри строки XML и потом обратная вставка такой строки в ФД.
Но опять же, такое решение видит только картинки, которые вставлены ы ФД через буфер обмена, а через "ЕЩЁ>Вставить картинку" в строке кода - оснТребованияКСистеме.ПолучитьHTML(лкТекстHTML, лкВложения); в втором параметре "лкВложения" картинок не появляется. Если вставить две картинки разными способами, то в этом параметре видно только то, что вставили через буфер.
Что за магия и как её решить? Наверняка же уже кто-то это решал!?
---
Так, походу из заходящих на форум - нет спецов по этому вопросу...
Разбираюсь сам понемногу.
Картинку из ворда возвращать в ФорматированныйДокумент вроде научился. Но пока речь о картинках вставленных через буфер обмена в исходный ФД. Только такие получается перенести в ворд и была проблема с обратным переносом, её я вроде понял как решить. Я изначально неверно подошел к решению. Распишу, вдруг кому пригодится.
Издалека, что бы понятнее было. Формируя Общий файл в ворде, я там выделяю вставляемый текст закладками, имя закладки делаю УИДом исходного элемента справочника, что бы потом проще найти каждую область при обратном чтении куда записать в 1С.
Это предыстория.
На этом этапе из 1С в ворд переносятся картинки только вставленные через буфер обмена, другие теряются и дальше с этим разбираюсь, как перенести любые варианты.
Теперь к моей ошибке. Обратное чтение происходит на клиенте, параграфов может быть сколько угодно много. Что бы не бегать на сервер для записи полученного параграфа в ФД (реквизит типа ХрЗн) - я полученные из области закладки куски ворда сохранял в файл HTML и клал их в временное хранилище, а адрес в соответствии запоминал. Так вот тут ключевым было то, что картинка в HTML файле была лишь ссылкой на файл на диске в временной папке и при уходе на сервер уже файл становился недоступен.
Решил просто формировать текст xml сразу на клиенте и тут же получить двоичные данные прикрепления и в текст вставить. И на сервер уже готовую строку XML передавать так же в соответствии.
Так картинка появилась в форматированном документе. Но дальше она там стала вставленной не через буфер обмена, а через "ЕЩЁ>Вставить картинку". Вернулся снова к варианту переноса таких картинок из ФД в ворд...
Ну пол проблемы уже решил.

```1c
    Если НЕ ЗакладкаТребование = Неопределено Тогда
    #Если ВебКлиент Тогда
    ИмяВременногоФайлаДок = КаталогВременныхФайлов + Строка(Новый УникальныйИдентификатор) + ".DOCX";
    #Иначе
    ИмяВременногоФайлаДок = ПолучитьИмяВременногоФайла("DOCX");
    #КонецЕсли

    ДвоичныеДанные = ПолучитьМакетПроектаНаСервере();

    COMОбъект = Неопределено;
    СтруктураWord = ПолучитьМакетMSWord(ДвоичныеДанные, ИмяВременногоФайлаДок);

    СтруктураWord.COMСоединение.Application.Options.CheckSpellingAsYouType = Ложь;
    ДокументВорд = СтруктураWord.COMСоединение.ActiveDocument;
    Если Отладка Тогда
    СтруктураWord.COMСоединение.Visible = Истина;
    КонецЕсли;
    ДокументВорд.Select();
    Selection = ДокументВорд.Application.Selection;
    Selection.WholeStory();
    Selection.Delete(1, 1);

    Range = Документ.Range(ЗакладкаТребование.Range.Start,ЗакладкаТребование.Range.End);
    Range.Select();
    Область = Range.Copy();
    ДокументВорд.Activate();

    врПозицияОкончанияДокумента = ДокументВорд.Range().End;
    врОбластьВставки = ДокументВорд.Range(врПозицияОкончанияДокумента - 1, врПозицияОкончанияДокумента - 1);
    врОбластьВставки.Paste();
    #Если ВебКлиент Тогда
    ИмяВрФайлаХтмл = КаталогВременныхФайлов() + Строка(Новый УникальныйИдентификатор) + ".html";
    #Иначе
    ИмяВрФайлаХтмл = ПолучитьИмяВременногоФайла("html");
    #КонецЕсли

    ДокументВорд.SaveAs(ИмяВрФайлаХтмл,8);
    ДокументВорд.Close();
    Если (СтруктураWord.COMСоединение.Documents.Count = 0) Тогда
    СтруктураWord.COMСоединение.Quit();
    КонецЕсли;
    ЧтениеHTML = Новый ЧтениеHTML;
    ЧтениеHTML.ОткрытьФайл(ИмяВрФайлаХтмл);
    ПостроительDOM = Новый ПостроительDOM;
    ДокументHTML = ПостроительDOM.Прочитать(ЧтениеHTML);
    ЧтениеHTML.Закрыть();
    АдресHTML = ПолучитьТекстHTMLнаКлиенте(ДокументHTML);
    АдресHTML = СтрЗаменить(АдресHTML,"o:p","p");
    Картинки = ДокументHTML.Картинки;
    Для каждого лкВложение Из Картинки Цикл
    БинДанные = Новый ДвоичныеДанные(КаталогВременныхФайлов()+ лкВложение.Источник);
    АдресHTML = СтрЗаменить(АдресHTML, " src="" + лкВложение.Источник + ", " src="data:image/png;base64, " + Base64Строка(БинДанные) + "");
    КонецЦикла;
    Попытка
    УдалитьФайлы(ИмяВрФайлаХтмл);
    УдалитьФайлы(СтруктураWord.ИмяФайла);
    Исключение
    Сообщить(ОписаниеОшибки());
    КонецПопытки;
    Элемент = СоответствиеЭлементов.Получить(Строка.Процесс);
    Если НЕ Элемент = Неопределено Тогда
    Элемент.Вставить("Т_",АдресHTML);
    Иначе
    Структура = Новый Структура("Т_",АдресHTML);
    СоответствиеЭлементов.Вставить(Строка.Процесс,Структура);
    КонецЕсли;
    КонецЕсли;
```

 и далее обработка на сервере

```1c
    &НаСервере
    Процедура ЗагрузитьHTML(СоответствиеЭлементов)
    Для Каждого ЭлементСоответствия ИЗ СоответствиеЭлементов Цикл
    Для Каждого Элемент ИЗ ЭлементСоответствия.Значение Цикл
    АдресHTML = Элемент.Значение;
    Процесс = ЭлементСоответствия.Ключ;
    ФорматированныйДокумент = УстановитьHTMLвФорматированныйДокумент(АдресHTML);
    ПроцессОбъект = Процесс.ПолучитьОбъект();
    Если Элемент.Ключ = "Т_" Тогда
    ПроцессОбъект.оснХранилищеТребованияКСистеме = Новый ХранилищеЗначения(ФорматированныйДокумент);
    ИначеЕсли Элемент.Ключ = "О_" Тогда
    ПроцессОбъект.ХранилищеОписания = Новый ХранилищеЗначения(ФорматированныйДокумент);
    КонецЕсли;
    Попытка
    ПроцессОбъект.Записать();
    Исключение
    КонецПопытки;
    КонецЦикла;
    КонецЦикла;
    КонецПроцедуры

    &НаКлиенте
    Функция ПолучитьТекстHTMLнаКлиенте(ДокументHTML)

    ЗапиcьHTML = Новый ЗаписьHTML;
    ЗапиcьHTML.УстановитьСтроку();
    ЗаписьDOM = Новый ЗаписьDOM;
    ЗаписьDOM.Записать(ДокументHTML, ЗапиcьHTML);
    Возврат ЗапиcьHTML.Закрыть();

    КонецФункции

    &НаСервере
    Функция УстановитьHTMLвФорматированныйДокумент(Знач пТекстHTML)

    ФорматированныйДокумент = Новый ФорматированныйДокумент;

    лкВложения = Новый Структура;
    лкПрефикс = " src="data:image/png;base64, ";

    Пока Найти(пТекстHTML, лкПрефикс) > 0 Цикл

    лкНачалоКартинки = Найти(пТекстHTML, лкПрефикс) + СтрДлина(лкПрефикс);
    лкBase64ДанныеКартинки = Сред(пТекстHTML, лкНачалоКартинки);
    лкBase64ДанныеКартинки = Лев(лкBase64ДанныеКартинки, Найти(лкBase64ДанныеКартинки, "") - 1); // "'"

    лкКодСоответствия = "_" + СтрЗаменить(Новый УникальныйИдентификатор, "-", ");
    лкКартинка = Новый Картинка(Base64Значение(лкBase64ДанныеКартинки));
    лкВложения.Вставить(лкКодСоответствия, лкКартинка);

    пТекстHTML = СтрЗаменить(пТекстHTML, лкПрефикс + лкBase64ДанныеКартинки + ",
    " src="" + лкКодСоответствия + ");

    КонецЦикла;

    ФорматированныйДокумент.УстановитьHTML(пТекстHTML, лкВложения);
    Возврат ФорматированныйДокумент;

    КонецФункции
```
---
Продолжение.
строка - ФД.Записать(ИмяВрФайлаХтмл, ТипФайлаФорматированногоДокумента.HTML);
На Клиенте записывает картинки из ФД только те, которые вставлены через буфер обмена. Записанные же картинки кодом выше или вставленные через "ЕЩЁ>Вставить картинку" - теряются. Эти картинки так же не получаются в переменной лкВложения из следующего кода.

```1c
    лкТекстHTML = ";
    лкВложения = Новый Структура;
    ФД.ПолучитьHTML(лкТекстHTML, лкВложения);
```

Если уйти на сервер и там обработать этот же код - то всеми способами вставленные картинки там получим в переменной лкВложения.
Разжовываю, может кому поможет.

```1c
    лкТекстHTML = ";
    лкВложения = Новый Структура;
    ФД.ПолучитьHTML(лкТекстHTML, лкВложения);
    Для каждого лкВложение Из лкВложения Цикл

    лкТекстHTML = СтрЗаменить(лкТекстHTML, " src="" + лкВложение.Ключ + ", " src="data:image/png;base64, " + Base64Строка(лкВложение.Значение.ПолучитьДвоичныеДанные()) + "");

    КонецЦикла;
```

Уйдя на сервер и обработав там мой форматированный документ в XML-строку, я получаю полную строку для формирования HTML файла для вставки в ворде. Картинки в строке вбиты двоичными данными. Возвращаюсь на клиент, сохраняю строку, как файл HTML. Все картинки отлично отображаются. Но вставляю полученный файл в ворд и картинок снова нет.
Теперь надо как-то обработать включенные в HTML картинки, для переваривания вордом. Там если они ссылками на файлики в временной папке, то вставляется, но у меня сейчас внутри тела двоичными данными.
Продолжаю беседу)))))
---
Ну вроде победил.
По порядку:
Собираю ворд на клиенте. Получив из собранных данных реквизит типа ХранилищеЗначений ухожу с ним на сервер и там получаю из него форматированный документ. На сервере в нем видим одинаково все картинки, как вставленные пользователем через буфер, так и через меню вставить картинку. А так же записанные программной загрузкой из ворда.
Раскладываю на сервере полученный ФД в XML-строку.

```1c
    &НаСервере
    Функция ПолучитьФД_Данные(РеквизитХранилище)

    ФД = РеквизитХранилище.Получить();
    Если НЕ ФД = Неопределено Тогда
    Попытка
    КоличествоЭлементов = ФД.Элементы.Количество();
    Если КоличествоЭлементов = 0 Тогда
    Возврат Ложь;
    КонецЕсли;
    Исключение
    Возврат Ложь;
    КонецПопытки;

    лкТекстHTML = ";
    лкВложения = Новый Структура;
    ФД.ПолучитьHTML(лкТекстHTML, лкВложения);
    Для каждого лкВложение Из лкВложения Цикл
    лкТекстHTML = СтрЗаменить(лкТекстHTML, " src="" + лкВложение.Ключ + ", " src="data:image/png;base64, " + Base64Строка(лкВложение.Значение.ПолучитьДвоичныеДанные()) + "");
    КонецЦикла;
    Возврат лкТекстHTML;
    КонецЕсли;

    Возврат Ложь;

    КонецФункции
```

Полученную строку возвращаю на клиент и на клиенте уже заново из этой строки создаю новый форматированный документ. Затем его сохраняю в HTML файл и этот файл в нужном мне месте в ворде.

```1c
    ФД = УстановитьHTMLвВременный_ФорматированныйДокумент(лкТекстHTML);
    #Если ВебКлиент Тогда
    ИмяВрФайлаХтмл = КаталогВременныхФайлов() + Строка(Новый УникальныйИдентификатор) + ".html";
    #Иначе
    ИмяВрФайлаХтмл = ПолучитьИмяВременногоФайла("html");
    #КонецЕсли

    ФД.Записать(ИмяВрФайлаХтмл, ТипФайлаФорматированногоДокумента.HTML);

    Selection.EndKey(6);
    Start = Selection.Start;
    Selection.InsertFile(ИмяВрФайлаХтмл,,, Ложь);

    &НаКлиенте
    Функция УстановитьHTMLвВременный_ФорматированныйДокумент(Знач пТекстHTML)

    Ф_Док = Новый ФорматированныйДокумент;
    лкВложения = Новый Структура;
    лкПрефикс = " src="data:image/png;base64, ";

    Пока Найти(пТекстHTML, лкПрефикс) > 0 Цикл

    лкНачалоКартинки = Найти(пТекстHTML, лкПрефикс) + СтрДлина(лкПрефикс);
    лкBase64ДанныеКартинки = Сред(пТекстHTML, лкНачалоКартинки);
    лкBase64ДанныеКартинки = Лев(лкBase64ДанныеКартинки, Найти(лкBase64ДанныеКартинки, "") - 1);

    лкКодСоответствия = "_" + СтрЗаменить(Новый УникальныйИдентификатор, "-", ");
    лкКартинка = Новый Картинка(Base64Значение(лкBase64ДанныеКартинки));
    лкВложения.Вставить(лкКодСоответствия, лкКартинка);

    пТекстHTML = СтрЗаменить(пТекстHTML, лкПрефикс + лкBase64ДанныеКартинки + ",
    " src="" + лкКодСоответствия + ");

    КонецЦикла;

    Ф_Док.УстановитьHTML(пТекстHTML, лкВложения);
    Возврат Ф_Док;

    КонецФункции
```

Код на стадии - как-то там заработало. Теперь оптимизация от бегания туда-сюда и прочие плюшки.
Всем спасибо)))
Надеюсь не зря парился, кому-то это поможет.
Вознаграждение оставляю себе :о))))