F#でWordのドキュメントを作成する


F#でWordのドキュメントを作成してみました。
C#でもよかったのですが、Rユーザー(dplyr)だったのでF#の方がしっくりくるためです。
ライブラリとしてMicrosoft.Office.Interop.Wordを使えば、Wordを編集することが可能になります。

環境

Visual studio 2017
Visual F#

プロジェクトの作成、参照設定

[ファイル]→[新規作成]→[プロジェクト]
[Visual F#]→[コンソールアプリケーション]→プロジェクトの作成

[ソリューションエクスプローラー]→[参照設定]右クリック→[参照の追加]→Microsoft.Office.Interop.WordとOfficeを選択

Program.fsを書いていきます。
let mutable app = new Applicatioくらいまで書くとインテリセンスが聞いて勝手にライブラリが上の方に追加されます。できるだけ楽をしましょう。
出ない場合はCtrl+Spaceを押すとインテリセンスが出ます。

C#の様に書くと、最終的に以下のようなコードになります。

Propram.fs
open Microsoft.Office.Interop.Word

// F# の詳細については、http://fsharp.org を参照してください
// 詳細については、'F# チュートリアル' プロジェクトを参照してください。

[<EntryPoint>]
let main argv = 
    let mutable app = new ApplicationClass()//Wordを開く
    app.Visible <- false//Wordが画面に表示されないようにする

    let mutable doc = app.Documents.Add()//Wordの中に文書を開く
    doc.Range().Text <- "Hello, World!\n"//文書の内容を書き換え

    let mutable endOfLines = (doc.Range().End - 1) :> obj //文末を取りだしてobj型にアップキャスト
    doc.Range(ref endOfLines).Text <- "Hello, Word!\n"//obj型を参照型にして範囲を指定後、文章を追加

    let filename = (System.IO.Directory.GetCurrentDirectory() + @"\HelloWord.docx") :> obj
    doc.SaveAs2000(ref filename) //保存

    doc.Close() //文書を閉じる
    app.Quit() //Wordを閉じる

    0 // 整数の終了コードを返します

書いてからCtrl+F5を押すとアプリがスタートします。
終わったら プロジェクト名\bin\debugフォルダにHelloWord.docxが生成されています。

おまけ:代入演算子を憎むあなたへ

今回、C#のコードを参考にしたのですが、コードを見てみると、代入(バインド)しすぎじゃね?と思いました。イライラします。
筆者は代入演算子を憎んでいるRユーザーなので、F#なのですがもう一度心の赴くままにパイプライン演算子で書き直しました。

Program.fs
open Microsoft.Office.Interop.Word

// F# の詳細については、http://fsharp.org を参照してください
// 詳細については、'F# チュートリアル' プロジェクトを参照してください。

[<EntryPoint>]
let main argv = 
    let mutable app = new ApplicationClass() //Word開く
    app.Visible <- false //画面に表示させない

    let mutable doc = app.Documents.Add() //文書開く

    "Hello, World!\n" 
    |> fun x -> doc.Range().Text <- x //文書内容書き換え

    "Hello, Word!\n" //文末に書き加える(内容と書込場所の2変数必要)
    |> fun x -> doc.Range().End //ネストして1変数関数にカリー化
                |> fun y -> y - 1 //0スタートのため
                |> fun y -> ref (y :> obj) //参照渡し用にアップキャスト
                |> fun y -> doc.Range(y).Text <- x //代入

    "HelloWord.docx"
    |> fun x -> System.IO.Directory.GetCurrentDirectory() + @"\" + x //実行場所の情報を加える
    |> fun x -> ref (x :> obj) //参照渡し用にアップキャスト
    |> fun x -> doc.SaveAs2000(x) //保存

    doc.Close()
    app.Quit()
    0 // 整数の終了コードを返します

スッキリ!
これでインプットが何か分かりやすくなりました。

それとQiitaのシンタックスハイライトでは出ていませんが、Visual Studioの場合はMutableな変数が黄色くなっているので、どこで参照が書き換わりうるか分かりやすいです。この辺F#良いわぁ…。

参考