読者です 読者をやめる 読者になる 読者になる

空談録

http://artfulplace.net/blogs/ からひっこしつつ

Wordの背景画像攻略 その2

Swayはどうした
すみません来週やります…やります…今週はごめんなさい…

というわけでWordの透かし背景画像ですが地味に面倒な仕様だったのは前に書きましたがさらに攻略を進めましょう
今回は面倒なのでアドイン公開はしません

一個細かいのと本題で

画像のアスペクト比を維持する

前回こんなコードを書いた気がしたんですけど見返したら書いてなかった

用紙サイズに合わせて画像を変更するコード書いたのがこれ

var sl = Globals.ThisAddIn.Application.Selection;

// ...

sl.ShapeRange.LockAspectRatio = Office.MsoTriState.msoFalse;
sl.ShapeRange.HeightRelative = 100.0F;
sl.ShapeRange.WidthRelative = 100.0F;

英語が多少読めればどこがまずいかは一瞬ですが、LockAspectRatioがFalseなので画像のアスペクト比は完全に無視されます
これではよろしくないのでTrueにしましょう

var sl = Globals.ThisAddIn.Application.Selection;

// ...

sl.ShapeRange.LockAspectRatio = Office.MsoTriState.msoTrue;
// sl.ShapeRange.HeightRelative = 100.0F;
// sl.ShapeRange.WidthRelative = 100.0F;

はい、HeightとWidthは消します
このとき残してしまうとLockAspectRatioを無視してHeight、Widthが指定されます

つまるところ何も指定しないと自動でHeight、Widthを指定してくれるのですが、こっちで指定してしまうとそれを無理やり適用するっぽいです
LockAspectRatioの意味とは

ちなみにこれだと画像が全域に適用できないのでその辺はMarginを調整する必要があります
めんどうなのでやりたくはないですが

背景画像を保存時のみ削除する

今日の本題はこっち

Wordで書く文書に背景画像を残すのは問題があるので
「保存前に画像を消す→保存→保存完了と同時に画像を戻す」
という動作を行うことが求められます

しかしWord選手、DocumentAfterSaveみたいなめっちゃ気の利いたEventがないです
そのため結構アクロバティックな復帰を行います

説明する気力がないのでコード貼っときます

private static bool _isPhotoRemoved = false;

private static void removeBackground()
{
    Globals.ThisAddIn.Application.ActiveDocument.Sections.First.Range.Select();
    Globals.ThisAddIn.Application.ActiveWindow.ActivePane.View.SeekView = Word.WdSeekView.wdSeekCurrentPageHeader;
    var sl = Globals.ThisAddIn.Application.Selection;
    var rms = sl.HeaderFooter.Shapes.OfType<Word.Shape>().Where(x => x.Name == "hogehoge_PictureShape");
    foreach (var rm in rms)
    {
        rm.Delete();
    }
    Globals.ThisAddIn.Application.ActiveWindow.ActivePane.View.SeekView = Word.WdSeekView.wdSeekMainDocument;
    
}

void Application_DocumentBeforeSave(Word.Document Doc, ref bool Cancel)
{
    removeBackground();
    _isPhotoRemoved = true;
}

void Application_WindowSelectionChange(Selection Sel)
{
    if (_isPhotoRemoved)
    {
        _isPhotoRemoved = false;
        setBackgroundPicture();
    }
}

あとはイベントに関連付けといてくれれば動きます

さて、背景画像のShape自体は追加したNameが分かり切ってるのでそれで抽出して削除するだけです
消すときも追加するときと同様の処理で行けます

このあとに削除したことをフィールドで持っておきます
これで復元するかどうかが指定されます

そしたら削除後の最初のSelectionChangeイベントに応じて背景画像を復元するだけです

このイベントの想定だとユーザーがカーソルを動かしたときで想定していたんですけど、実際動かしてみると保存時のEnabledの変更か何かでSelectionChangeイベントが起こるのでそこで復元されます
つまり完全自動で復元されます(タイミング的にすごい怖いですけどまあ動いてるし…)
このタイミングはファイル書き出し開始時なので本当に吐かれてないか心配にはなるレベル
(とりあえず保存はされてないですけど怪しい)

まああれだったらアドイン切って背景削除が一番安泰ですけど…


こうして、また新たな痛環境を作りだすことに成功したのであった
しかもExcelより高性能なのがまた
画像のパスをハードコーディングしちゃってるので気が向いたら直して公開するかも

なんかおとといくらいにブログの書き方とか聞いた記憶がありますがすでに内容の9割ほどを忘れています
覚えにくいブログ名です!よろしくお願いします!! PVいらないので雑に書かせてください!!

この辺で