0

私は初心者です、気軽に話してください。あいまいで申し訳ありません。コードが実行され、破損したファイルが書き込まれます。エラー/異常を観察するために破損したファイルにアクセスできません。サイズは、マージされるファイルの合計のように見えます。

これ以外の鼻水をグーグルで検索しましたが、実装方法を理解できるものは何も見つかりません。

開く際の Word エラーは次のとおりです。内容に問題があるため、ファイルを開けません

Word で判読できないコンテンツが見つかりました。続行しますか?

[はい] をクリックすると、最初のエラーが再び発生し、その後、アウトになります。

ドキュメントには同じ名前のコンテンツ コントロールがありますが、重複するコンテンツ タイプが問題になるかどうかを確認するために、ドキュメントを 1 つだけ追加するように変更しました。同じ破損ファイルの結果。

ところで....私の最終的な意図は、「テンプレート」(...Aggregate Report.dotx) を上書きすることです。しかし、どこにも保存された有効なファイルを取得できないので、...... :-/

using System;   
using System.IO;
using System.ComponentModel;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Linq;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using Word = DocumentFormat.OpenXml.Wordprocessing;


namespace BobsDocMerger.VisualWebPart1
{
[ToolboxItemAttribute(false)]
public class VisualWebPart1 : WebPart
{
    // Visual Studio might automatically update this path when you change the Visual Web Part project item.
    private const string _ascxPath = @"~/_CONTROLTEMPLATES/BobsDocMerger/VisualWebPart1/VisualWebPart1UserControl.ascx";

    protected override void CreateChildControls()
    {
        System.Web.UI.Control control = this.Page.LoadControl(_ascxPath);
        Controls.Add(control);
        base.CreateChildControls();
        Button btnSubmit = new Button();
        btnSubmit.Text = "Assemble Documents";
        btnSubmit.Click += new EventHandler(btnSubmit_Click);
        Controls.Add(btnSubmit);
    }

    void btnSubmit_Click(object sender, EventArgs e)
    {
        SPFolder folder = SPContext.Current.ListItem.Folder;
        char[] splitter = { '/' };
        string[] folderName = folder.Name.Split(splitter);
        string filePrefix = @"Weekly/" + folderName[0] + "/" + folderName[0];

        SPFile template = folder.Files[filePrefix + " - Aggregate Report.dotx"];
        SPFile file;
        byte[] byteArray = template.OpenBinary();

        using (MemoryStream mem = new MemoryStream())
        {
            mem.Write(byteArray, 0, (int)byteArray.Length);

            using (WordprocessingDocument myDoc = WordprocessingDocument.Open(mem, true))
            {
                MainDocumentPart mainPart = myDoc.MainDocumentPart;
                //Loop thru content controls
                foreach (Word.SdtElement sdt in mainPart.Document.Descendants<Word.SdtElement>().ToList())
                {
                    Word.SdtAlias alias = sdt.Descendants<Word.SdtAlias>().FirstOrDefault();
                    if (alias != null)
                    {
                        //The 2 tags in the Report are AggregateHeader and AggregateBody
                        string sdtTitle = alias.Val.Value;
                        string sdtTag = sdt.GetFirstChild<SdtProperties>().GetFirstChild<Tag>().Val;
                        if (sdtTitle == "Merge")
                        {
                            for (int i = 0; i < folder.Files.Count; i++)
                            {
                                file = folder.Files[i];
                                //Do all files that are NOT the Aggregate Report
                                if (file.Name.IndexOf("Aggregate Report") == -1)
                                {
                                    if (i == folder.Files.Count-1)
                                    {
                                        AddAltChunk(mainPart, sdt, file, true);
                                    }
                                    else
                                    {
                                        AddAltChunk(mainPart, sdt, file, false);
                                    }
                                }
                            }
                        }
                    }
                }

                HttpResponse resp = HttpContext.Current.Response;
                resp.ClearContent();
                resp.ClearHeaders();
                resp.AddHeader("Content-Disposition", "attachment; filename=Assembled Document.docx");
                //resp.ContentEncoding = System.Text.Encoding.UTF8;
                resp.ContentType = "application/msword";
                resp.OutputStream.Write(mem.ToArray(), 0, (int)mem.Length);
                resp.Flush();
                resp.Close();
                HttpContext.Current.ApplicationInstance.CompleteRequest();
            }
        }
    }

    protected int id = 1;

    void AddAltChunk(MainDocumentPart mainPart, Word.SdtElement sdt, SPFile filename,bool LastPass)
    {
        string altChunkId = "AltChunkId" + id;
        id++;
        byte[] byteArray = filename.OpenBinary();

        AlternativeFormatImportPart chunk = mainPart.AddAlternativeFormatImportPart(
        AlternativeFormatImportPartType.WordprocessingML, altChunkId);

        using (MemoryStream mem = new MemoryStream())
        {
            mem.Write(byteArray, 0, (int)byteArray.Length);
            mem.Seek(0, SeekOrigin.Begin);
            chunk.FeedData(mem);
        }

        Word.AltChunk altChunk = new Word.AltChunk();
        altChunk.Id = altChunkId;
        //Replace content control with altChunk information 

        DocumentFormat.OpenXml.OpenXmlElement parent = sdt.Parent;
        parent.InsertBefore(altChunk, sdt);
        if (LastPass) { sdt.Remove(); }
    }
}
}
4

1 に答える 1

1

メインメモリストリームで適切に呼び出していないようです。.Seek()また、その単一のメモリストリームを入力と出力の両方に同時に使用しているようです。(多分それは正しいかもしれませんが、混合モードの場合は非常に混乱します)

生のファイル名とファイルシステムにアクセスできないと仮定しています:

using(Stream t = template.OpenBinaryStream())
{
    using (WordprocessingDocument myDoc = WordprocessingDocument.Open(t, true))
    {
        using (XmlWriter writer = XmlWriter.Create(resp.OutputStream))
        {
            // TODO re-add merge logic here once it works

            HttpResponse resp = HttpContext.Current.Response;
            resp.ClearContent();
            resp.ClearHeaders();
            resp.AddHeader("Content-Disposition", 
                "attachment; filename=Assembled Document.docx");
            //resp.ContentEncoding = System.Text.Encoding.UTF8;
            resp.ContentType = "application/msword";
            // resp.OutputStream.Write(mem.ToArray(), 0, (int)mem.Length);
/* new */   myDoc.MainDocumentPart.Document.WriteTo(writer);
            resp.Flush();
            resp.Close();
            HttpContext.Current.ApplicationInstance.CompleteRequest();
        }
    }
}

PS - 生のテンプレートを最初に正しく出力することをお勧めします。次に、小さな変更を 1 つ行い、その出力を確認してから、マージ ロジックを再度追加します。

于 2013-08-01T20:23:50.900 に答える