如何将OpenXML SDK与F#和MemoryStreams一起使用

时间:2012-05-22 12:16:42

标签: f# openxml

This article表示在使用OpenXML SDK时需要使用可调整大小的MemoryStreams,示例代码工作正常。

但是,当我将样本C#代码翻译成F#时,文档保持不变:

open System.IO
open DocumentFormat.OpenXml.Packaging
open DocumentFormat.OpenXml.Wordprocessing

[<EntryPoint>]
let Main args =
    let byteArray = File.ReadAllBytes "Test.docx"

    use mem = new MemoryStream()
    mem.Write(byteArray, 0, (int)byteArray.Length)

    let para = new Paragraph()
    let run = new Run()
    let text = new Text("Newly inserted paragraph")
    run.InsertAt(text, 0) |> ignore
    para.InsertAt(run, 0) |> ignore

    use doc = WordprocessingDocument.Open(mem, true)
    doc.MainDocumentPart.Document.Body.InsertAt(para, 0) |> ignore

    // no change to the document
    use fs = new FileStream("Test2.docx", System.IO.FileMode.Create)
    mem.WriteTo(fs)

    0

使用WordprocessingDocument.Open("Test1.docx", true)时效果很好,但我想使用MemoryStream。我做错了什么?

1 个答案:

答案 0 :(得分:4)

在关闭doc之前,您对mem所做的更改不会反映在MemoryStream doc中。放置doc.Close()如下

...
doc.MainDocumentPart.Document.Body.InsertAt(para, 0) |> ignore 
doc.Close()
...

解决了问题,您会在Newly inserted paragraph的顶部找到文字Test2.docx

此外,您的代码段缺少一个必需的参考:

open DocumentFormat.OpenXml.Packaging 

来自WindowsBase.dll

编辑:正如ildjarn指出的更多F#-idiomatic将是以下重构:

open System.IO
open System.IO.Packaging
open DocumentFormat.OpenXml.Packaging 
open DocumentFormat.OpenXml.Wordprocessing 

[<EntryPoint>] 
let Main args = 
    let byteArray = File.ReadAllBytes "Test.docx" 

    use mem = new MemoryStream() 
    mem.Write(byteArray, 0, (int)byteArray.Length) 

    do
        use doc = WordprocessingDocument.Open(mem, true) 
        let para = new Paragraph() 
        let run = new Run() 
        let text = new Text("Newly inserted paragraph") 
        run.InsertAt(text, 0) |> ignore     
        para.InsertAt(run, 0) |> ignore
        doc.MainDocumentPart.Document.Body.InsertAt(para, 0) |> ignore 

    use fs = new FileStream("Test2.docx", FileMode.Create) 
    mem.WriteTo(fs) 

    0