2009-07-17 12 views
6

Używam Word i OPENXML dostarczenie poczty funkcjonalność łączą się w aplikacji sieci web C# ASP.NET:dokument powielania Słowo użyciu OpenXML i C#

1) dokument został przesłany z wielu predefiniowanych ciągów do zastąpienia .

2) Przy użyciu OpenXML SDK 2.0 Otwieram dokument Word, pobierz mainDocumentPart jako ciąg i dokonuję podstawienia przy użyciu Regex.

3) Następnie utworzę nowy dokument za pomocą OpenXML, dodam nowy mainDocumentPart i wstawię łańcuch wynikający z podstawienia do tego mainDocumentPart.

Jednak wszystkie formatowanie/style itp. Są tracone w nowym dokumencie.

Zgaduję, że mogę skopiować i dodać styl, definicje, części komentarza itp. Indywidualnie, aby naśladować oryginalny dokument.

Czy istnieje jednak metoda wykorzystująca Open XML do powielenia dokumentu pozwalającego na dokonanie zmian w nowej kopii?

Dzięki.

Odpowiedz

-1

Gdy patrzysz na dokument openxml, zmieniając rozszerzenie na zip i otwierając go, zobaczysz, że podfolder tego słowa zawiera folder _rels, w którym wymienione są wszystkie relacje. Te relacje wskazują na części, o których wspomniałeś (styl ...). Właściwie potrzebujesz tych części, ponieważ zawierają one definicję formatowania. Dlatego ich skopiowanie nie spowoduje, że nowy dokument będzie korzystał z formatowania zdefiniowanego w pliku normal.dot, a nie z dokumentu zdefiniowanego w oryginalnym dokumencie. Więc myślę, że musisz je skopiować.

+0

Naprawdę nie odpowiada na pytanie. przeczytaj, jak to zrobić, zanim odpowiesz. –

2

Zrobiłem kilka bardzo podobnych rzeczy, ale zamiast używać łańcuchów zastępujących tekst, używam formantów treści Word. Udokumentowałem niektóre szczegóły w następującym poście na blogu: SharePoint and Open Xml. Ta technika jest specyficzna dla SharePoint. Możesz ponownie użyć wzorca w czystej ASP.NET lub innych aplikacjach.

Ponadto, SILNIE zachęcam do przejrzenia Eric White's Blog po wskazówki, porady i techniki dotyczące Open Xml. W szczególności sprawdź posty in-memory manipulation of Open Xml post i Word content controls. Myślę, że na dłuższą metę okaże się, że są one o wiele bardziej pomocne.

Mam nadzieję, że to pomoże.

4

Po drugie używam rekomendacji Content Controls. Używanie ich do zaznaczania obszarów dokumentu, w których chcesz dokonać zamiany, jest zdecydowanie najłatwiejszym sposobem.

chodzi o powielenie dokumentu (i zachowując całą zawartość dokumentu, style i wszystkie) jest stosunkowo proste:

string documentURL = "full URL to your document"; 
byte[] docAsArray = File.ReadAllBytes(documentURL); 

using (MemoryStream stream = new MemoryStream) 
{ 
    stream.Write(docAsArray, 0, docAsArray.Length); // THIS performs doc copy 
    using (WordprocessingDocument doc = WordprocessingDocument.Open(stream, true)) 
    { 
     // perform content control substitution here, making sure to call .Save() 
     // on any documents Part's changed. 
    } 
    File.WriteAllBytes("full URL of your new doc to save, including .docx", stream.ToArray()); 
} 

Właściwie znalezienie elementów sterujących zawartość jest bułka z masłem przy użyciu LINQ. Następujący przykład wyszukuje wszystkie proste sterowanie treści tekstu (które są wpisane jako SdtRun):

using (WordprocessingDocument doc = WordprocessingDocument.Open(stream, true)) 
{      
    var mainDocument = doc.MainDocumentPart.Document; 
    var contentControls = from sdt in mainDocument.Descendants<SdtRun>() select sdt; 

    foreach (var cc in contentControls) 
    { 
     // drill down through the containment hierarchy to get to 
     // the contained <Text> object 
     cc.SdtContentRun.GetFirstChild<Run>().GetFirstChild<Text>().Text = "my replacement string"; 
    } 
} 

W <Run> i <Text> elementy nie mogą już istnieją, ale ich tworzenie jest proste jak:

cc.SdtContentRun.Append(new Run(new Text("my replacement string"))); 

Nadzieja to pomaga komuś.: D

2

Jako dodatek do powyższego; być może bardziej przydatnym jest znalezienie elementów sterujących treści, które zostały oznaczone (przy użyciu GUI słowa). Ostatnio napisałem oprogramowanie, które zawierało szablony dokumentów, które zawierały kontrolę treści z dołączonymi znacznikami. Aby je znaleźć, jest to tylko rozszerzenie powyższego zapytania LINQ:

var mainDocument = doc.MainDocumentPart.Document; 
var taggedContentControls = from sdt in mainDocument.Descendants<SdtElement>() 
          let sdtPr = sdt.GetFirstChild<SdtProperties>() 
          let tag = (sdtPr == null ? null : sdtPr.GetFirstChild<Tag>()) 
          where (tag != null) 
          select new 
          { 
           SdtElem = sdt, 
           TagName = tag.GetAttribute("val", W).Value 
          }; 

Dostałem ten kod z innego miejsca, ale nie pamiętam, gdzie w tej chwili; pełny kredyt trafia do nich.

Kwerenda właśnie tworzy IEnumerable anonimowy typ, który zawiera kontrolę treści i związany z nim znacznik jako właściwości. Poręczny!

10

Ten fragment kodu powinien skopiować wszystkie części z istniejącego dokumentu na nowy.

using (var mainDoc = WordprocessingDocument.Open(@"c:\sourcedoc.docx", false)) 
using (var resultDoc = WordprocessingDocument.Create(@"c:\newdoc.docx", 
    WordprocessingDocumentType.Document)) 
{ 
    // copy parts from source document to new document 
    foreach (var part in mainDoc.Parts) 
    resultDoc.AddPart(part.OpenXmlPart, part.RelationshipId); 
    // perform replacements in resultDoc.MainDocumentPart 
    // ... 
} 
+1

Waliłem głową w ścianę przez wiele godzin, bawiąc się tym biznesem MemoryStream ... To działa świetnie i jest znacznie bardziej zwięzłe. Wielkie dzięki! – lukiffer

+0

Czy istnieje sposób na robienie podobnej rzeczy, a jedyną różnicą jest to, że zawartość "mainDoc" musi być dołączona na końcu istniejącego dokumentu? –

+0

Tak, choć znacznie trudniejsze, ponieważ wiele danych z części obu dokumentów musi zostać połączonych. Na szczęście [Eric White] (http://ericwhite.com/blog/) zbudował zestaw [PowerTools dla OpenXML] (http://ericwhite.com/blog/category/open-xml/powertools/), który obsługuje to dla ciebie zniechęcające zadanie. W szczególności spójrz na [DocumentBuilder] (http://openxmldeveloper.org/wiki/w/wiki/documentbuilder.aspx), którego użyłem do dołączania jednego dokumentu do drugiego w przeszłości. Pracował jak urok! – bernhof

Powiązane problemy