Чтение данных из файла docx средствами 1С

Задача: спарсить данные из таблицы, которая находится в файле формата docx средствами 1С

Решение: по сути своей файл формата docx является zip архивом, в котором находятся файлы формата xml и внешние ресурсы, типа картинок, стилей и т.п. Текстовое же содержимое находится непосредственно в файле document.xml. Его нужно лишь прочитать, найти в нём таблицу и распарсить данные.

Для начала загрузим файл на сервер, переименуем его в zip, и откроем его при помощи метода 1С «ЧтениеZipФайла», а найденный в архиве файл document.xml извлекем для дальнейшей обработки:

&НаКлиенте
Процедура ВыбратьФайлыИСделатьХорошо(Команда)
	Режим = РежимДиалогаВыбораФайла.Открытие;
    ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(Режим);
    ДиалогОткрытияФайла.ПолноеИмяФайла = "";
    Фильтр = НСтр("ru = 'Текст'; en = 'Text'")+ "(*.docx)|*.docx";
    ДиалогОткрытияФайла.Фильтр = Фильтр;
    ДиалогОткрытияФайла.МножественныйВыбор = ложь;
    ДиалогОткрытияФайла.Заголовок = "Выберите файлы";
    Если ДиалогОткрытияФайла.Выбрать() Тогда
        МассивФайлов = ДиалогОткрытияФайла.ВыбранныеФайлы;
		ФайлСМС="";
		Для Каждого ИмяФайла Из МассивФайлов Цикл
			ФайлСМС=ИмяФайла;
		конеццикла;
		если ФайлСМС<>"" тогда 			
					АдресХранилищаФайла = "";			
					Состояние("Перемещаю файл на сервер");
		            ПоместитьФайл(АдресХранилищаФайла, ФайлСМС, , Ложь, ЭтаФорма.УникальныйИдентификатор);   					
					Состояние("Обрабатывается файл "+ФайлСМС);							
					таблицы=ПреобразоватьФайлDocXВМассивТаблиц(АдресХранилищаФайла);					
		иначе
			сообщить("Файл не выбран");
		конецесли;	
	конецесли;	        
КонецПроцедуры

&НаСервере
Функция ПреобразоватьФайлDocXВМассивТаблиц(АдресХранилищаФайла)	
	ТЗ=Новый ТаблицаЗначений();	
	ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресХранилищаФайла);
	ИмяВременногоФайлаСпр = ПолучитьИмяВременногоФайла("zip");
	ДвоичныеДанные.Записать(ИмяВременногоФайлаСпр);     

	Архив = Новый ЧтениеZipФайла(ИмяВременногоФайлаСпр);
	ИмяВременногоФайлаXML = ПолучитьИмяВременногоФайла("xml");
	Для Каждого Элемент Из Архив.Элементы Цикл	
		если  Элемент.Имя="document.xml" тогда			
			Архив.Извлечь(Элемент, КаталогВременныхФайлов(), РежимВосстановленияПутейФайловZIP.НеВосстанавливать);			
		конецесли;
	Конеццикла;	
	Архив.Закрыть();
....

Далее файл documnet.xml необходимо загрузить как XML и распарсить в структуру при помощи построителя DOM. После чего останется только найти таблицу по имени узла w:tbl и поместить содержимое в таблицу значений:

ФайлXML = Новый ЧтениеXML;
    ФайлXML.ОткрытьФайл(КаталогВременныхФайлов()+"document.xml");
		ПостроительDOMXML=Новый ПостроительDOM;
		ДокументДом=ПостроительDOMXML.Прочитать(ФайлXML);
		ПрочитаноСтрок=0;		
		для каждого document из ДокументДом.ДочерниеУзлы цикл
			для каждого body из document.ДочерниеУзлы цикл
				для каждого el из body.ДочерниеУзлы цикл
					если el.ИмяУзла="w:tbl" тогда
							для каждого tab_el из el.ДочерниеУзлы цикл							
								если tab_el.ИмяУзла="w:tr" тогда
									если ПрочитаноСтрок=0 тогда
										ТЗ.Колонки.Добавить(УбратьНеОбрабатываемыеСимволы(tab_el.ДочерниеУзлы[1].ТекстовоеСодержимое));
										ТЗ.Колонки.Добавить(УбратьНеОбрабатываемыеСимволы(tab_el.ДочерниеУзлы[2].ТекстовоеСодержимое));
										ТЗ.Колонки.Добавить(УбратьНеОбрабатываемыеСимволы(tab_el.ДочерниеУзлы[3].ТекстовоеСодержимое));
										ТЗ.Колонки.Добавить(УбратьНеОбрабатываемыеСимволы(tab_el.ДочерниеУзлы[4].ТекстовоеСодержимое));
										ТЗ.Колонки.Добавить(УбратьНеОбрабатываемыеСимволы(tab_el.ДочерниеУзлы[5].ТекстовоеСодержимое));
										ТЗ.Колонки.Добавить(УбратьНеОбрабатываемыеСимволы(tab_el.ДочерниеУзлы[6].ТекстовоеСодержимое));
										ТЗ.Колонки.Добавить(УбратьНеОбрабатываемыеСимволы(tab_el.ДочерниеУзлы[7].ТекстовоеСодержимое));
										ТЗ.Колонки.Добавить(УбратьНеОбрабатываемыеСимволы(tab_el.ДочерниеУзлы[8].ТекстовоеСодержимое));
									иначе	                 
										если tab_el.ДочерниеУзлы[1].ТекстовоеСодержимое="Всего:" тогда 
											прервать;
										КонецЕсли;           
										если tab_el.ДочерниеУзлы[1].ТекстовоеСодержимое<>"1" тогда
											если tab_el.ДочерниеУзлы[6].ТекстовоеСодержимое<>"" тогда
												нс=ТЗ.Добавить();
												нс[0]=tab_el.ДочерниеУзлы[1].ТекстовоеСодержимое;
												нс[1]=tab_el.ДочерниеУзлы[2].ТекстовоеСодержимое;
												нс[2]=tab_el.ДочерниеУзлы[3].ТекстовоеСодержимое;
												нс[3]=tab_el.ДочерниеУзлы[4].ТекстовоеСодержимое;
												нс[4]=tab_el.ДочерниеУзлы[5].ТекстовоеСодержимое;
													нс[4]=СтрЗаменить(нс[4],",",".");
													нс[4]=СтрЗаменить(нс[4]," ","");
													если нс[4]="" тогда нс[4]="0";конецесли;
													нс[4]=Число(Формат(нс[4],"ЧГ=0"));												
												нс[5]=tab_el.ДочерниеУзлы[6].ТекстовоеСодержимое;
												нс[6]=tab_el.ДочерниеУзлы[7].ТекстовоеСодержимое;
												нс[7]=tab_el.ДочерниеУзлы[8].ТекстовоеСодержимое;
													нс[7]=СтрЗаменить(нс[7],",",".");
													нс[7]=СтрЗаменить(нс[7]," ","");
													если нс[7]="" тогда нс[7]="0";конецесли;
													нс[7]=Число(Формат(нс[7],"ЧГ=0"));												
												
											конецесли;
										конецесли;
									конецесли;	
									ПрочитаноСтрок=ПрочитаноСтрок+1;
								конецесли;
							конеццикла;
							если ПрочитаноСтрок>0 тогда прервать;конецесли;
						конецесли;
						если ПрочитаноСтрок>0 тогда прервать;конецесли;
					конеццикла;
					если ПрочитаноСтрок>0 тогда прервать;конецесли;
				конеццикла;
				если ПрочитаноСтрок>0 тогда прервать;конецесли;
		конеццикла;	
	ФайлXML.Закрыть();
	Возврат ТЗ;