Officeドキュメントを自動化計画 #4 PPT「画像差し込み操作」

2019年6月30日

テクノロジー プログラミング

Officeドキュメントの画像を新たに差し込んだり、入れ替えたりできるするのは、非常に効率的な資料更新ができる事を意味します。 PowerPointにおいては、プレゼンテーションを行う直前に、中で使っているグラフ画像を最新版に差し替えたい時に、アプリを立ち上げて作業をするのは、非常に腰が折れる作業だったり、ちょっとした失敗により、プレゼン資料全体がオジャンになってしまうなんてケースもあるあるでしょう。 そんな時に、エンジニアであれば、コマンド操作で対応できたり、画像差し替えに特価したWEBサービスなどがあれば便利だと思いませんか? そんなサービスを作るべく、PowerPointドキュメントの技術仕様を検証してみたいと思います。

画像を挿入したpptxドキュメントを作成

sample_img.pptx.zip 検証素材として、画像を2ファイル挿入したpptxドキュメントを構築しておきました。 このpptxを解凍してみると以下のファイル群が現れます。 $ find pptx_img/ pptx_img/ pptx_img/[Content_Types].xml pptx_img/docProps pptx_img/docProps/app.xml pptx_img/docProps/thumbnail.jpeg pptx_img/docProps/core.xml pptx_img/_rels pptx_img/_rels/.rels pptx_img/ppt pptx_img/ppt/viewProps.xml pptx_img/ppt/slideLayouts pptx_img/ppt/slideLayouts/slideLayout9.xml pptx_img/ppt/slideLayouts/slideLayout8.xml pptx_img/ppt/slideLayouts/_rels pptx_img/ppt/slideLayouts/_rels/slideLayout5.xml.rels pptx_img/ppt/slideLayouts/_rels/slideLayout4.xml.rels pptx_img/ppt/slideLayouts/_rels/slideLayout2.xml.rels pptx_img/ppt/slideLayouts/_rels/slideLayout3.xml.rels pptx_img/ppt/slideLayouts/_rels/slideLayout8.xml.rels pptx_img/ppt/slideLayouts/_rels/slideLayout9.xml.rels pptx_img/ppt/slideLayouts/_rels/slideLayout11.xml.rels pptx_img/ppt/slideLayouts/_rels/slideLayout10.xml.rels pptx_img/ppt/slideLayouts/_rels/slideLayout6.xml.rels pptx_img/ppt/slideLayouts/_rels/slideLayout7.xml.rels pptx_img/ppt/slideLayouts/_rels/slideLayout1.xml.rels pptx_img/ppt/slideLayouts/slideLayout3.xml pptx_img/ppt/slideLayouts/slideLayout2.xml pptx_img/ppt/slideLayouts/slideLayout1.xml pptx_img/ppt/slideLayouts/slideLayout5.xml pptx_img/ppt/slideLayouts/slideLayout4.xml pptx_img/ppt/slideLayouts/slideLayout6.xml pptx_img/ppt/slideLayouts/slideLayout10.xml pptx_img/ppt/slideLayouts/slideLayout11.xml pptx_img/ppt/slideLayouts/slideLayout7.xml pptx_img/ppt/presentation.xml pptx_img/ppt/slideMasters pptx_img/ppt/slideMasters/slideMaster1.xml pptx_img/ppt/slideMasters/_rels pptx_img/ppt/slideMasters/_rels/slideMaster1.xml.rels pptx_img/ppt/slides pptx_img/ppt/slides/slide3.xml pptx_img/ppt/slides/slide2.xml pptx_img/ppt/slides/slide1.xml pptx_img/ppt/slides/_rels pptx_img/ppt/slides/_rels/slide2.xml.rels pptx_img/ppt/slides/_rels/slide3.xml.rels pptx_img/ppt/slides/_rels/slide1.xml.rels pptx_img/ppt/theme pptx_img/ppt/theme/theme1.xml pptx_img/ppt/_rels pptx_img/ppt/_rels/presentation.xml.rels pptx_img/ppt/presProps.xml pptx_img/ppt/tableStyles.xml pptx_img/ppt/media pptx_img/ppt/media/image1.png pptx_img/ppt/media/image2.jpg pptx_img/ppt/printerSettings pptx_img/ppt/printerSettings/printerSettings1.bin 注目するポイントは、ppt/フォルダの下に、前回までのデータでは現れなかった「media」というフォルダが作成されています。 その中に、アップロードした2ファイルが格納されているので、pptxから画像を取り出したい時は、このディレクトリから抜き出すことが可能です。 以前にブログで書いた、圧縮データからimgファイルを直接抜き出す方法で取り出せそうですね。 [PHP] zipファイル内の画像を解凍せずに表示する方法 ただし、挿入したファイル名とは違っているので、ファイル名を知りたい場合は、xmlを調査しないといけません。

データ構造調査

今回は、PowerPointドキュメントの第2スライドに2つの画像をつけたので、以下の2ファイルを確認します。
ppt/slides/slide2.xml ppt/slides/_rels/slide2.xml.rels
拡張子が"xml"が、表示データで、"rels"が、このスライドで扱うファイル一覧になるようです。 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <p:sld xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main"> <p:cSld> <p:spTree> <p:nvGrpSpPr> <p:cNvPr id="1" name=""/> <p:cNvGrpSpPr/> <p:nvPr/> </p:nvGrpSpPr> <p:grpSpPr> <a:xfrm> <a:off x="0" y="0"/> <a:ext cx="0" cy="0"/> <a:chOff x="0" y="0"/> <a:chExt cx="0" cy="0"/> </a:xfrm> </p:grpSpPr> <p:sp> <p:nvSpPr> <p:cNvPr id="2" name="Title 1"/> <p:cNvSpPr> <a:spLocks noGrp="1"/> </p:cNvSpPr> <p:nvPr> <p:ph type="title"/> </p:nvPr> </p:nvSpPr> <p:spPr/> <p:txBody> <a:bodyPr/> <a:lstStyle/> <a:p> <a:r> <a:rPr lang="en-US" dirty="0" smtClean="0"/> <a:t>{page-1:title}</a:t> </a:r> <a:endParaRPr lang="en-US" dirty="0"/> </a:p> </p:txBody> </p:sp> <p:sp> <p:nvSpPr> <p:cNvPr id="3" name="Content Placeholder 2"/> <p:cNvSpPr> <a:spLocks noGrp="1"/> </p:cNvSpPr> <p:nvPr> <p:ph idx="1"/> </p:nvPr> </p:nvSpPr> <p:spPr/> <p:txBody> <a:bodyPr/> <a:lstStyle/> <a:p> <a:pPr marL="0" indent="0"> <a:buNone/> </a:pPr> <a:r> <a:rPr lang="en-US" dirty="0" smtClean="0"/> <a:t>{page-1:txt}</a:t> </a:r> <a:endParaRPr lang="en-US" dirty="0"/> </a:p> </p:txBody> </p:sp> <p:pic> <p:nvPicPr> <p:cNvPr id="4" name="Picture 3" descr="favicon_64.png"/> <p:cNvPicPr> <a:picLocks noChangeAspect="1"/> </p:cNvPicPr> <p:nvPr/> </p:nvPicPr> <p:blipFill> <a:blip r:embed="rId2"> <a:extLst> <a:ext uri="{28A0092B-C50C-407E-A947-70E740481C1C}"> <a14:useLocalDpi xmlns:a14="http://schemas.microsoft.com/office/drawing/2010/main" val="0"/> </a:ext> </a:extLst> </a:blip> <a:stretch> <a:fillRect/> </a:stretch> </p:blipFill> <p:spPr> <a:xfrm> <a:off x="1975090" y="3022600"/> <a:ext cx="812800" cy="812800"/> </a:xfrm> <a:prstGeom prst="rect"> <a:avLst/> </a:prstGeom> </p:spPr> </p:pic> <p:pic> <p:nvPicPr> <p:cNvPr id="5" name="Picture 4" descr="website-3407280_1280.jpg"/> <p:cNvPicPr> <a:picLocks noChangeAspect="1"/> </p:cNvPicPr> <p:nvPr/> </p:nvPicPr> <p:blipFill> <a:blip r:embed="rId3"> <a:extLst> <a:ext uri="{28A0092B-C50C-407E-A947-70E740481C1C}"> <a14:useLocalDpi xmlns:a14="http://schemas.microsoft.com/office/drawing/2010/main" val="0"/> </a:ext> </a:extLst> </a:blip> <a:stretch> <a:fillRect/> </a:stretch> </p:blipFill> <p:spPr> <a:xfrm> <a:off x="3994603" y="2438546"/> <a:ext cx="4192198" cy="2793707"/> </a:xfrm> <a:prstGeom prst="rect"> <a:avLst/> </a:prstGeom> </p:spPr> </p:pic> </p:spTree> <p:extLst> <p:ext uri="{BB962C8B-B14F-4D97-AF65-F5344CB8AC3E}"> <p14:creationId xmlns:p14="http://schemas.microsoft.com/office/powerpoint/2010/main" val="1487470405"/> </p:ext> </p:extLst> </p:cSld> <p:clrMapOvr> <a:masterClrMapping/> </p:clrMapOvr> </p:sld> 内容が分かり辛いので、必要箇所だけ抜き出したのが以下の通り <p:spTree> <p:nvGrpSpPr> <p:cNvPr id="1" name=""/> <p:cNvGrpSpPr/> <p:nvPr/> </p:nvGrpSpPr> <p:grpSpPr> <a:xfrm> <a:off x="0" y="0"/> <a:ext cx="0" cy="0"/> <a:chOff x="0" y="0"/> <a:chExt cx="0" cy="0"/> </a:xfrm> </p:grpSpPr> <p:sp> <p:nvSpPr> <p:cNvPr id="2" name="Title 1"/> <p:cNvSpPr> <a:spLocks noGrp="1"/> </p:cNvSpPr> <p:nvPr> <p:ph type="title"/> </p:nvPr> </p:nvSpPr> <p:spPr/> <p:txBody> <a:bodyPr/> <a:lstStyle/> <a:p> <a:r> <a:rPr lang="en-US" dirty="0" smtClean="0"/> <a:t>{page-1:title}</a:t> </a:r> <a:endParaRPr lang="en-US" dirty="0"/> </a:p> </p:txBody> </p:sp> <p:sp> <p:nvSpPr> <p:cNvPr id="3" name="Content Placeholder 2"/> <p:cNvSpPr> <a:spLocks noGrp="1"/> </p:cNvSpPr> <p:nvPr> <p:ph idx="1"/> </p:nvPr> </p:nvSpPr> <p:spPr/> <p:txBody> <a:bodyPr/> <a:lstStyle/> <a:p> <a:pPr marL="0" indent="0"> <a:buNone/> </a:pPr> <a:r> <a:rPr lang="en-US" dirty="0" smtClean="0"/> <a:t>{page-1:txt}</a:t> </a:r> <a:endParaRPr lang="en-US" dirty="0"/> </a:p> </p:txBody> </p:sp> <p:pic> <p:nvPicPr> <p:cNvPr id="4" name="Picture 3" descr="favicon_64.png"/> <p:cNvPicPr> <a:picLocks noChangeAspect="1"/> </p:cNvPicPr> <p:nvPr/> </p:nvPicPr> <p:blipFill> <a:blip r:embed="rId2"> <a:extLst> <a:ext uri="{28A0092B-C50C-407E-A947-70E740481C1C}"> <a14:useLocalDpi xmlns:a14="http://schemas.microsoft.com/office/drawing/2010/main" val="0"/> </a:ext> </a:extLst> </a:blip> <a:stretch> <a:fillRect/> </a:stretch> </p:blipFill> <p:spPr> <a:xfrm> <a:off x="1975090" y="3022600"/> <a:ext cx="812800" cy="812800"/> </a:xfrm> <a:prstGeom prst="rect"> <a:avLst/> </a:prstGeom> </p:spPr> </p:pic> <p:pic> <p:nvPicPr> <p:cNvPr id="5" name="Picture 4" descr="website-3407280_1280.jpg"/> <p:cNvPicPr> <a:picLocks noChangeAspect="1"/> </p:cNvPicPr> <p:nvPr/> </p:nvPicPr> <p:blipFill> <a:blip r:embed="rId3"> <a:extLst> <a:ext uri="{28A0092B-C50C-407E-A947-70E740481C1C}"> <a14:useLocalDpi xmlns:a14="http://schemas.microsoft.com/office/drawing/2010/main" val="0"/> </a:ext> </a:extLst> </a:blip> <a:stretch> <a:fillRect/> </a:stretch> </p:blipFill> <p:spPr> <a:xfrm> <a:off x="3994603" y="2438546"/> <a:ext cx="4192198" cy="2793707"/> </a:xfrm> <a:prstGeom prst="rect"> <a:avLst/> </a:prstGeom> </p:spPr> </p:pic> </p:spTree> "p:spTree/p:pic"というタグ階層が画像エリアのようです。 "p:cNvPr"に画像ファイル名。 "a:blip"に、下記の設定ファイルで記されたファイルIDが書かれています。 "p:spPr"は、画像を表示する、サイズや形などの詳細が書かれています。 探してみたら、MSのこのページに、仕様の説明がされていましたね。 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"> <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout" Target="../slideLayouts/slideLayout2.xml"/> <Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="../media/image1.png"/> <Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="../media/image2.jpg"/> </Relationships> このファイルは、スライドに関するファイルの一覧が記されています。 "Relationship"タグにスライドのxmlと、画像が2つ登録されているのが見て分かります。

画像ファイルを1つ追加する実験

適当な画像ファイルを付け足してみましょう。 この画像をppt/media/にコピーして、ppt/slides/_rels/slide2.xml.relsに以下の1行を途中に追加します。 <Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="../media/binary-2372130_1280.jpg"/> ppy/slides/slide2.xmlにも、以下を追記してみます。(2つ目の画像タグのすぐ下) <p:pic> <p:nvPicPr> <p:cNvPr id="5" name="Picture 4" descr="binary-2372130_1280.jpg"/> <p:cNvPicPr> <a:picLocks noChangeAspect="1"/> </p:cNvPicPr> <p:nvPr/> </p:nvPicPr> <p:blipFill> <a:blip r:embed="rId4"> <a:extLst> <a:ext uri="{28A0092B-C50C-407E-A947-70E740481C1C}"> <a14:useLocalDpi xmlns:a14="http://schemas.microsoft.com/office/drawing/2010/main" val="0"/> </a:ext> </a:extLst> </a:blip> <a:stretch> <a:fillRect/> </a:stretch> </p:blipFill> <p:spPr> <a:xfrm> <a:off x="2994603" y="3438546"/> <a:ext cx="4192198" cy="2793707"/> </a:xfrm> <a:prstGeom prst="rect"> <a:avLst/> </a:prstGeom> </p:spPr> </p:pic> それをサーバーコマンドで圧縮処理 zip -r ../pptx_img_1.pptx ./* 見事に画像の挿入に成功しました。 ちなみに、たくさん書かれていたタグをなんとなくいらないと思って消してみたら、PPTエラーが表示されて、画像が正常に挿入できなかったので、p:pic構成は重要ということがわかりました。 x,yはスライド内の座標で、cx,cyは、サイズというのは分かりましたが、単位がいまいち不明なので、この辺はやりながら感覚を掴んでいくのがいいでしょう。 とりあえず、画像の追加、削除、修正、座標変更、サイズ変更などが分かってきたので、次は、表についての調査を行いたいと思います。

人気の投稿

このブログを検索

ごあいさつ

このWebサイトは、独自思考で我が道を行くユゲタの少し尖った思考のTechブログです。 毎日興味がどんどん切り替わるので、テーマはマルチになっています。 もしかしたらアイデアに困っている人の助けになるかもしれません。

ブログ アーカイブ