PHPWord — чтение MSWord документов средствами PHP

PHPWord — чтение MSWord документов средствами PHP

От автора: не так давно на нашем сайте был опубликован урок по созданию документов MS Word средствами языка PHP, и с использованием специальной библиотеки PHPWord. Но в комментариях к данному видео – прозвучал вопрос, как при помощи данной библиотеки читать готовые документы, что собственно и подтолкнуло меня к записи данного урока, в котором мы с Вами научимся, используя выше указанную библиотеку, читать ранее созданные документы MSWord.

скачать исходникискачать урок

В данном уроке мы продолжаем изучать возможности PHPWord, а именно рассмотрим инструменты по чтению готовых документов MS Word. Хотел бы отметить, что сегодня мы будем работать с уже установленной библиотекой, потому как это уже второй урок по данной теме, а значит, на основах подробно останавливаться не будем. Поэтому рекомендую, перед просмотром данного видео ознакомиться с первой часть урока – PHPWord — создание MS Word документов средствами PHP.

Итак, заготовка, тестового скрипта состоит из одного единственного файла index.php, в коде которого выполнена установка библиотеки.

Итак, заготовка, тестового скрипта состоит из одного единственного файла index.php, в коде которого выполнена установка библиотеки.

require 'vendor/autoload.php';

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

$source = __DIR__."/docs/text.docx"; 

Далее, вспомним, что в начале работы с библиотекой необходимо создать объект главного класса PHPWord, но это в том случае если создается новый документ. Если же осуществляется чтение готового файла MS Word – объект указанного класса необходимо создать для интересующего документа, но перед этим его нужно прочитать.

Для чтения готовых документов в PHPWord предусмотрена группа классов, отвечающих за чтение документов различных форматов. А значит, первым делом создадим объект специального “класса-риддера“.

$objReader = \PhpOffice\PhpWord\IOFactory::createReader('Word2007');

Далее, используя данный объект – выполним чтение документа формата MS Word.

$phpWord = $objReader->load($source); 

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

По официальной документации любая информация документа MS Word, согласно библиотеке PHPWord, располагается в отдельных секциях. При этом каждая секция содержит определенный набор элементов – текст, таблица, изображение, ссылка и т.д. Элементы – же в свою очередь, так же могут быть сложными и включать в себя некий набор вложенных элементов, к примеру таблицы.

Поэтому, вызывая на исполнение метод getSections(), мы получаем доступ к секциям документа, при этом в качестве результата будет возвращен массив, а значит мы его можем обойти циклом foreach().

foreach($phpWord->getSections() as $section) {
$arrays = $section->getElements();
	
}

При этом в коде цикла, для каждой секции, получим массив входящих элементов, вызывая на исполнение метод getElements(). Так как возвращаемое значение – это массив, значит, используя выше указанный цикл, мы можем получить доступ к каждой его ячейке.

foreach($arrays as $e) {
	
} 

При этом в переменной $e на каждой итерации цикла, содержится объект одного из элементов массива секций. Казалось бы, мы сразу можем получить текстовые данные MS Word, но для начала нужно проверить, что содержится в переменной $e.

if(get_class($e) === 'PhpOffice\PhpWord\Element\TextRun') { 

Если в данной переменной содержится объект класса ‘PhpOffice\PhpWord\Element\TextRun’, значит мы работаем с сложной текстовой областью, в которой располагается несколько более простых элементов. Поэтому повторно вызываем метод getElements() и по результату проходимся в цикле foreach().

<?php

require 'vendor/autoload.php';

$source = __DIR__."/docs/text.docx";

$objReader = \PhpOffice\PhpWord\IOFactory::createReader('Word2007');

$phpWord = $objReader->load($source);


$body = '';
foreach($phpWord->getSections() as $section) {
	$arrays = $section->getElements();
	
	foreach($arrays as $e) {
		if(get_class($e) === 'PhpOffice\PhpWord\Element\TextRun') {
			foreach($e->getElements() as $text) {
				
				$font = $text->getFontStyle();
				
				$size = $font->getSize()/10;
				$bold = $font->isBold() ? 'font-weight:700;' :'';
				$color = $font->getColor();
				$fontFamily = $font->getName();
				
				$body .= '<span style="font-size:' . $size . 'em;font-family:' . $fontFamily . '; '.$bold.'; color:#'.$color.'">';
				$body .= $text->getText().'</span>';

			}
		}
		
	}
}

include 'templ.php';

Таким образом, для текущего документа, в переменную $text, попадает объект элемента Text, то есть элемент простейшего текст, для получения которого достаточно вызвать на исполнение метод getText(). Для получения информации о форматировании текущего элемента, необходимо обратиться к методу getFontStyle(), который вернет объект в закрытых свойствах которого содержится указанная информация. Соответственно для доступа к значениям этих свойств необходимо использовать специальные методы:

getSize() – размер шрифта;

isBold() — возвращает истину, если используется полужирный шрифт;

getColor() – цвет текста;

getName() – имя шрифта.

Все содержимое документа, записывается в переменную $body, значение которой будет отображено на экране, используя шаблон. Пустые строки документа представляют собой объект элемента TextBreak, который можно обработать следующим образом:

else if(get_class($e) === 'PhpOffice\PhpWord\Element\TextBreak') {
			$body .= '<br />';
		}

Для обработки таблиц, придется добавить достаточно много строк кода, потому как таблица – это сложный элемент Table, который состоит из отдельных строк, а те в свою очередь из отдельных ячеек. И более того, каждая ячейка, может содержать еще вложенные элементы, потому как, к примеру в одной ячейке так же можно сформировать таблицу. Ниже приведу весь код, вместе с кодом обработки таблиц.

<?php

require 'vendor/autoload.php';

$source = __DIR__."/docs/text.docx";

$objReader = \PhpOffice\PhpWord\IOFactory::createReader('Word2007');

$phpWord = $objReader->load($source);

$body = '';
foreach($phpWord->getSections() as $section) {
	$arrays = $section->getElements();
	
	foreach($arrays as $e) {
		if(get_class($e) === 'PhpOffice\PhpWord\Element\TextRun') {
			foreach($e->getElements() as $text) {
				
				$font = $text->getFontStyle();
				
				$size = $font->getSize()/10;
				$bold = $font->isBold() ? 'font-weight:700;' :'';
				$color = $font->getColor();
				$fontFamily = $font->getName();
				
				$body .= '<span style="font-size:' . $size . 'em;font-family:' . $fontFamily . '; '.$bold.'; color:#'.$color.'">';
				$body .= $text->getText().'</span>';
			}
		}
		
		else if(get_class($e) === 'PhpOffice\PhpWord\Element\TextBreak') {
			$body .= '<br />';
		}
		
		else if(get_class($e) === 'PhpOffice\PhpWord\Element\Table') {
			$body .= '<table border="2px">';
			
			$rows = $e->getRows();
			
			foreach($rows as $row) {
				$body .= '<tr>';
				
				$cells = $row->getCells();
				foreach($cells as $cell) {
					$body .= '<td style="width:'.$cell->getWidth().'">';
					$celements = $cell->getElements();
					foreach($celements as $celem) {
						if(get_class($celem) === 'PhpOffice\PhpWord\Element\Text') {
							$body .= $celem->getText();
						}
						
						else if(get_class($celem) === 'PhpOffice\PhpWord\Element\TextRun') {
							foreach($celem->getElements() as $text) {
								$body .= $text->getText();
							}
						}
					}	
					$body .= '</td>';
				}
				
				$body .= '</tr>';
			}
			
			$body .= '</table>';
		}
		else {
			$body .= $e->getText();
		}
	}
	
	break;
}

include 'templ.php';

Для получения строк, необходимо вызвать метод getRows(), при этом в качестве результата будет возвращен массив объектов с информацией по каждой строке (элемент Row). Используя foreach(), обходим данный массив и для каждой строки получаем ячейки, при помощи метода getCells(). При этом опять же возвращается массив, который все так же мы обходим циклом. А далее для каждой ячейки вызываем на исполнение метод getElements(), для получения ее элементов. И так далее по принципу описанным выше.

Далее, осталось только отобразить значение переменной $body, любым удобным для Вас способом.

На этом данный урок я буду завершать. Как Вы видите, PHPWord предоставляет достаточно мощные инструменты по работе с документами MS Word, но и в тоже время сложные в плане получения данных из объектов.

Всего Вам доброго и удачного кодирования!!!

Курс по программированию на языке PHP

Изучите PHP с нуля до результата!

Смотреть курс

Метки:

Комментарии Вконтакте:

Комментарии Facebook:

Комментарии (5)

  1. Alexey

    Здравствуйте!!!
    Можете ли вы записать видео о том как сделать функцию «Кто сейчас на сайте»?

  2. Елена

    Здравствуйте, а можно ли с помощью этой библиотеки поменять форматирование загруженного пользователем документа?

  3. Alexander

    я правильно понимаю, что чтобы прочесть не *.docx-файл, а, например, *.doc-файл, требуется писать не
    $objReader = \PhpOffice\PhpWord\IOFactory::createReader('Word2007')
    a
    $objReader = \PhpOffice\PhpWord\IOFactory::createReader('MsDoc')

    ?

    • Alexander

      я просто в Кодигнайтере это пытаюсь задействовать и выдаёт ошибку: Message: Undefined property: PhpOffice\PhpWord\Shared\OLERead::$documentSummaryInformation

      Filename: Reader/MsDoc.php

      Line Number: 144

  4. Татьяна

    Добрый день. Я загружаю документ с картинкой, затем сохраняю его в другой файл, и картинка исчезает. Картинки не загружаются или я что-то делаю не так? Спасибо

Добавить комментарий

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

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree