この記事の目次
chevron_right
関連リンク
PHPWordを使って、既存のdocxファイルを開き、パスワード
をバズワード
に置換するコードです。
ついでに、編集履歴もつけちゃいます。
編集履歴をつけれるPHPWordのバージョンは、2018/03/09現在ではまだマスターリリースされていないので、
developのブランチを使います
composer require phpoffice/phpword:dev-develop
composer update
<?php
// 必要モジュールの読み込み
require_once 'vendor/autoload.php';
use PhpOfficePhpWordElementTrackChange; // 編集履歴系のクラス
$search_word = 'パスワード';
$replace_word = 'バズワード';
// 読み込むファイルのパス
$source = __DIR__ . '/base.docx';
// DOCXファイルの読み込み
$phpWord = PhpOfficePhpWordIOFactory::load($source, 'Word2007');
// コピー先のdocx作成
$phpWord_copy = new PhpOfficePhpWordPhpWord();
// 編集履歴系のクラスをインスタンス化
$trackChangesView = new PhpOfficePhpWordComplexTypeTrackChangesView();
// 編集履歴記録開始
$phpWord->getSettings()->setTrackRevisions(true);
// セクションの取得
$sections = $phpWord->getSections();
// セクションの分だけ、ぶん回せ
foreach ($sections as $key => $value) {
// コピー先にセクションを追加
$section_copy = $phpWord_copy->addSection();
// セクションの要素を全部取得
$sectionElement = $value->getElements();
// 要素の分だけくーるくる
foreach ($sectionElement as $elementKey => $elementValue) {
// getTextメソッドを持っているか確認 → 持っていたら、それはテキスト情報なので置換対象
if (method_exists($elementValue, 'getText') === true) {
// 置換したりとか
makeTextData($elementValue, $section_copy, $search_word, $replace_word);
} else {
// テキストではない場合は、クラスによって処理を変える(無理やり感半端ない)
$class = get_class($elementValue);
switch ($class) {
// 改行の場合
case 'PhpOfficePhpWordElementTextBreak':
// 改行を追加
$section_copy->addTextBreak();
break;
// リッチテキストの場合
case 'PhpOfficePhpWordElementTextRun':
// リッチテキストの中の要素全取得
getTextRunsTexts($elementValue, $section_copy, $search_word, $replace_word);
break;
}
}
}
}
// DOCXファイルに書き出し
$objWriter = PhpOfficePhpWordIOFactory::createWriter($phpWord_copy, 'Word2007');
$objWriter->save('php_output.docx');
/**
* リッチテキストデータの中に含まれるテキストを抽出してセクションとして追加する
*
* @param $elementValue
* @param $section_copy
* @param $search_word
* @param $replace_word
*/
function getTextRunsTexts(&$elementValue, &$section_copy, $search_word, $replace_word)
{
// リッチテキストの中の要素全取得
$sectionElement = $elementValue->getElements();
// 回す
foreach ($sectionElement as $sectionElementKey => $sectionElementValue) {
// 純粋なテキストエリアの場合
if (method_exists($sectionElementValue, 'getText') === true) {
// 置換したりとか
makeTextData($sectionElementValue, $section_copy, $search_word, $replace_word);
}
}
}
/**
* テキストデータを作成して新しいdocxデータに追加していく
*
* @param $elementValue
* @param $section_copy
* @param $search_word
* @param $replace_word
*/
function makeTextData(&$elementValue, &$section_copy, $search_word, $replace_word)
{
// テキスト取得
$text = htmlspecialchars($elementValue->getText());
// テキストがスペースだけなら無視する(変に改行されるため)
if ($text === ' ') {
return;
}
// フォントスタイルの取得
$font_style = $elementValue->getFontStyle();
// パラグラフスタイル(多分色とかそういうのやと思う)を取得
$paragraph_style = $elementValue->getParagraphStyle();
// インデントがあるかの取得
$indent = $paragraph_style->getIndentation();
// インデントがあれば、デザインがめっさ崩れるので
if ( method_exists($indent, 'getLeft') === true && $indent->getLeft() > 0 ){
// 幅を小さくしてあげる
$indent->setLeft($indent->getLeft()/1000);
}
// 取得したテキストをコピー先に作成
$text_elem = $section_copy->addText($text, $font_style, $paragraph_style);
// 特定ワードで置換してみる
if (preg_match('/' . $search_word . '/', $text) === 1) {
// 置換
$text = str_replace($search_word, $replace_word, $text);
// デリートの変更履歴を設定
$text_elem->setChangeInfo(TrackChange::DELETED, 'Nな人');
// 変更後のテキストを設定
$new_text = $section_copy->addText($text, $font_style, $paragraph_style);
// インサートの変更履歴を設定
$new_text->setChangeInfo(TrackChange::INSERTED, 'Nな人');
}
}
関連リンク
https://www.bricoleur.co.jp/blog/archives/3643
この記事を書いた人
Nな人(えぬなひと)。
Nは本名から取っています。
Laravelが大好きなPHPerで、WEBを作るときはLaravelを技術スタックに絶対推すマン。
PHP、Pythonと、昔はperlを書いていたP言語エンジニア。
最近はNimを書いたりしています。
Nは本名から取っています。
Laravelが大好きなPHPerで、WEBを作るときはLaravelを技術スタックに絶対推すマン。
PHP、Pythonと、昔はperlを書いていたP言語エンジニア。
最近はNimを書いたりしています。