簡體   English   中英

Powerpoint OpenXML空白正在消失

[英]Powerpoint OpenXML whitespace is disappearing

我遇到一個問題,一旦我引用幻燈片,就會在powerpoint文檔中刪除空格。 以下代碼示例說明了我的意思 -

//Open the document.
using(PresentationDocument presentationDocument = PresentationDocument.Open(pptxFileName, true))
{
 //Just making this reference modifies the whitespace in the slide.
 Slide slide = presentationDocument.PresentationPart.SlideParts.First().Slide;
}

要重現此問題,請使用單個幻燈片創建演示文稿,其中包含單個文本框,其中包含文本“[]”(無引號)。 現在,將方括號之間的空格字體設置為與文本其余部分不同的顏色。 這將導致Run僅包含空格字符。 一旦上面的代碼針對此演示文稿運行,引用幻燈片的行將導致運行中的空白消失,最終使我們的視覺更改演示文稿比我們最初開始時,即使我們從未明確更改任何內容 - 在powerpoint應用程序中打開時,文本現在將為“[]”。

在Word中,可以將xml:space屬性設置為“保留”文本元素以保留空格,但似乎沒有Powerpoint的等效項。

在將空白用作幻燈片設計的關鍵組件的情況下,這是一個關鍵問題。 有沒有人找到解決這個問題的方法?

是的,您在SDK中發現了一個錯誤。

@Chris,首先,根據Open XML SDK的語義,該代碼是修改文件的。 當您訪問部件的內容,然后超出using語句的范圍時,部件的內容將寫回到包中。 這是因為為讀/寫(調用Open方法的第二個參數)打開了演示文稿。

問題是當從包中讀取部件的內容時,空間被剝離。

        //Open the document. 
    using (PresentationDocument presentationDocument = PresentationDocument.Open("test.pptx", true))
    {
        //Just making this reference modifies the whitespace in the slide. 
        Slide slide = presentationDocument.PresentationPart.SlideParts.First().Slide;
        var sh = slide.CommonSlideData.ShapeTree.Elements<DocumentFormat.OpenXml.Presentation.Shape>().First();
        Run r = sh.TextBody.Elements<Paragraph>().First().Elements<Run>().Skip(1).FirstOrDefault();
        Console.WriteLine(">{0}<", r.Text.Text);
        //r.Text.Text = " ";
    } 

如果在演示文稿上運行上述代碼,則可以看到,當您訪問該文本元素時,文本元素的文本已經不正確。

如果取消注釋設置文本的行,有趣的是,幻燈片確實包含空格。

這顯然是一個錯誤。 我已向負責Open XML SDK的Microsoft程序經理報告。

由於這種情況對您很重要,我建議您使用LINQ to XML代碼。 以下代碼工作正常:

    using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Presentation;
using DocumentFormat.OpenXml.Drawing;

public static class PtOpenXmlExtensions
{
    public static XDocument GetXDocument(this OpenXmlPart part)
    {

        XDocument partXDocument = part.Annotation<XDocument>();
        if (partXDocument != null)
            return partXDocument;
        using (Stream partStream = part.GetStream())
        using (XmlReader partXmlReader = XmlReader.Create(partStream))
            partXDocument = XDocument.Load(partXmlReader);
        part.AddAnnotation(partXDocument);
        return partXDocument;
    }

    public static void PutXDocument(this OpenXmlPart part)
    {
        XDocument partXDocument = part.GetXDocument();
        if (partXDocument != null)
        {
            using (Stream partStream = part.GetStream(FileMode.Create, FileAccess.Write))
            using (XmlWriter partXmlWriter = XmlWriter.Create(partStream))
                partXDocument.Save(partXmlWriter);
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        using (PresentationDocument presentationDocument = PresentationDocument.Open("test.pptx", true))
        {
            XDocument slideXDoc = presentationDocument.PresentationPart.SlideParts.First().GetXDocument();
            XNamespace p = "http://schemas.openxmlformats.org/presentationml/2006/main";
            XNamespace a = "http://schemas.openxmlformats.org/drawingml/2006/main";
            XElement sh = slideXDoc.Root.Element(p + "cSld").Element(p + "spTree").Elements(p + "sp").First();
            XElement r = sh.Element(p + "txBody").Elements(a + "p").Elements(a + "r").Skip(1).FirstOrDefault();
            Console.WriteLine(">{0}<", r.Element(a + "t").Value);
        } 
    }
}

理論上,您可以編寫一些通用代碼來挖掘LINQ to XML樹,查找僅包含重要空白區域的所有元素,然后遍歷Open XML SDK元素樹,並設置這些元素的文本。 這有點亂,但一旦完成,您可以使用Open XML SDK 2.0的強類型OM。 這些元素的值將是正確的。

使用Open XML更容易使用LINQ to XML的一種技術是對XName對象進行preatomization。 http://blogs.msdn.com/b/ericwhite/archive/2008/12/15/a-more-robust-approach-for-handling-xname-objects-in-linq-to-xml.aspx

-Eric

Open XML SDK 2.5已更正此問題

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM