3

私は Open-XML の世界には不慣れですが、Open-XML を使用してすでにいくつかのトラブルや問題に遭遇しています。それらのほとんどは簡単に解決できましたが、これを回避することはできません:

public class ReportDocument : IDisposable
{
    private MemoryStream stream;
    private WordprocessingDocument document;
    private MainDocumentPart mainPart;

    public byte[] DocumentData
    {
        get 
        {
            this.document.ChangeDocumentType(WordprocessingDocumentType.MacroEnabledDocument);
            byte[] documentData = this.stream.ToArray();
            return documentData;
        }
    }

    public ReportDocument()
    {
        byte[] template = DocumentTemplates.SingleReportTemplate;
        this.stream = new MemoryStream();
        stream.Write(template, 0, template.Length);
        this.document = WordprocessingDocument.Open(stream, true);
        this.mainPart = document.MainDocumentPart;
    }

    public void SetReport(Report report)
    {
        Body body = mainPart.Document.Body;
        var placeholder = body.Descendants<SdtBlock>();
        this.SetPlaceholderTextValue(placeholder, "Company", WebApplication.Service.Properties.Settings.Default.CompanyName);
        this.SetPlaceholderTextValue(placeholder, "Title", String.Format("Status Report for {0} to {1}", report.StartDate.ToShortDateString(),
            report.ReportingInterval.EndDate.ToShortDateString()));
        //this.SetPlaceholderTextValue(placeholder, "Subtitle", String.Format("for {0}", report.ReportingInterval.Project.Name));
        this.SetPlaceholderTextValue(placeholder, "Author", report.TeamMember.User.Username);
        this.SetPlaceholderTextValue(placeholder, "Date", String.Format("for {0}", DateTime.Today.ToShortDateString()));
    }

    private void SetPlaceholderTextValue(IEnumerable<SdtBlock> sdts, string alias, string value)
    {
        SdtContentBlock contentBlock = this.GetContentBlock(sdts, alias);
        Text text = contentBlock.Descendants<Text>().First();
        text.Text = value;
    }

    private SdtContentBlock GetContentBlock(IEnumerable<SdtBlock> sdts, string alias)
    {
        return sdts.First(sdt => sdt.Descendants<SdtAlias>().First().Val.Value == alias).SdtContentBlock;
    }

    public void Dispose()
    {
        this.document.Close();
    }
}

そのため、メモリ ストリームを介して取得したテンプレートに基づいて新しいドキュメントを作成し、変更が加えられたときにそれをメモリ ストリームに書き戻したいと考えています。

大きな問題は、結果のバイト配列を保存すると、データ docx ファイルが破損することです。

.\word の document.xml は document2.xml と呼ばれます。.\word_rels の document.xml.rels は document2.xml.rels と呼ばれ、含まれています。

MFG SakeSushiBig

4

1 に答える 1

7

DocumentData プロパティをこれに変更すると、うまくいくと思います。重要なことは、メモリストリームを読み取る前にドキュメントを閉じることです。

public byte[] DocumentData
    {
        get 
        {
            this.document.ChangeDocumentType(WordprocessingDocumentType.MacroEnabledDocument);
            this.document.MainDocumentPart.Document.Save();
            this.document.Close();            
            byte[] documentData = this.stream.ToArray();
            return documentData;
        }
    }
于 2012-10-02T11:01:11.357 に答える