【Swift】WKWebViewを使ってパワーポイントをPDFに変換する
以前開発したPDF Margin Adjusterについて、パワーポイントのファイルを直接読み込めるようにしてほしいという要望を頂きました。
なんとかそれらしいものを実装できましたが、意外と手こずったのでハマった部分などをまとめました。
前回の記事:PDFの余白を調整するだけのアプリを作りました - のどあめ
apps.apple.comソースコード
今回はパワーポイントからPDFに変換する部分だけを切り出したコードを公開しています。
ハマり1:パワーポイントファイルのUniform Type Identifier(UTI)がわからない
iOSアプリはファイルの読み込み・他アプリから連携できるファイルをUTIで指定します。
今回はパワーポイントファイルの読み込みを対応させるので、対応するUTIをInfo.plistに記載する必要がありました。
UTIの公式は System-Declared Uniform Type Identifiers のようなのですが、サードパーティで定義されたUTIは網羅されていないようです。
調べると com.microsoft.powerpoint.ppt
org.openxmlformats.presentationml.presentation
あたりはすぐ見つかるのですが、
これだけでは開けないファイルも少なからずあります。
GitHubでUTI名で検索して周辺の類似したものを取得するという方法で、
以下のものを追加しました。
これで手元にあったパワーポイントファイルは開けるようになりましたが、すべてを網羅できているかは不明です。。
com.microsoft.powerpoint.ppt com.microsoft.powerpoint.pot com.microsoft.powerpoint.pps com.microsoft.powerpoint.openxml.presentation com.microsoft.powerpoint.openxml.slideshow com.microsoft.powerpoint.openxml.template org.openxmlformats.presentationml.presentation org.openxmlformats.presentationml.slideshow org.openxmlformats.presentationml.template
ハマり2:WKWebViewからPDF変換のあれこれ
PDF変換方法
UIViewからPDFに変換する方法はいくつかあるようですが、 一部の方法ではページの後半が描画されなかったりして苦戦しました。
結論としては UIPrintPageRenderer
を使ってPDFデータを取得する方法でうまくいきました。
実装は このあたり です
WKWebViewで開いているパワーポイントのスライドサイズを取得する
UIPrintPageRenderer
は印刷用のレンダラーなので用紙サイズ(=1スライドのサイズ)を指定する必要があります。
以下のブログを参考に、描画後の innerHTMLからスライドサイズが入っている要素をevaluateJavascriptで取得します。
実装は このあたり です
WKWebViewのマージン削除
WKWebViewでパワーポイントファイルを開くと、top・left・ページ間にマージンが発生します(下図)
UIPrintPageRenderer
を使ってPDFファイルに変換すると、このマージンも正確に描画されてしまうため、実際のスライドサイズとずれてしまいます。
そこでWKWebViewConfiguration
を使ってファイル読み込み後にCSSを適用し、このマージンを削除します。
実装は このあたり です
WKWebViewのロード後1秒待つ
WKWebViewがパワーポイントファイルを描画するときに、先に一部が描画されて少し時間が経ってから全体が描画されることがあります
全体が描画されたかどうかを判定する術はなさそう(例えばisLoadingは一部が描画された時点で false
になる)ですが、一部だけ描画されたタイミングでPDF変換をすると、その一部だけが描画されたPDFになってしまいます。
今回はファイルをロードしてから1秒待つという残念ロジックでこれを回避しました。
(GitHubに載せたコードでは省略しています)
用紙サイズをスライドサイズの0.8倍にする(おまじない)
先程取得したスライドサイズを UIPrintPageRenderer
のpaperRect
printableRect
に指定するのですが、これをそのまま指定すると何故か用紙サイズがちょっと大きくなります。
色々試しましたが、paperRect
やprintableRect
に用紙サイズ * 0.8を入れることで安定してPDFファイルに変換することができました。
理由は不明で完全におまじない状態です。。
実装は このあたり です
まとめと感想
WKWebViewからPDFに変換する方法と、そのハマりポイントをまとめました。
PDF変換周りは挙動が怪しいところがあるので、もう二度とやりたくないです。。
謎のおまじないを残してしまったのは残念ですが、これ以上時間をかけても意味がないので放置しました。
どなたかわかる方がいらっしゃいましたらご指摘いただけると助かります。
SwiftUIを初めて触ってみましたが、結構良さげな雰囲気がありますね。
iOSだけだったらReactNative+Expoなどを使わずとも簡単にアプリ作れそうです。