2016-03-31 23 views
0

Ich habe eine .docx, die ein MailMerge enthält, muss ich seine Quelle über Code (C#) ändern. Als Bibliothek verwende ich OpenXml. Durch Öffnen des docx als Zip-Datei und Suchen nach den Pfaden habe ich festgestellt, dass der Link der Datenquelle an zwei verschiedenen Stellen gespeichert ist: in der word/settings.xml und in der word/_rels/settings.xml.rels.MailMerge über OpenXml bearbeiten

die fisrt ersetzen:

var template = new MemoryStream(myDocxInByteArray); 

using (var doc = DocumentFormat.OpenXml.Packaging.WordprocessingDocument.Open(template, true)) 
{ 
    var s = doc.MainDocumentPart.DocumentSettingsPart.Settings; 
    foreach (var els in s.ChildElements) 
    { 
     if (els is DocumentFormat.OpenXml.Wordprocessing.MailMerge) 
     { 
      var mm = (DocumentFormat.OpenXml.Wordprocessing.MailMerge)els; 

      mm.Query.Val = "SELECT * FROM " + myNewPath; 

      break; 
     } 
    } 
} 

Dies funktioniert gut, aber wenn die Datei fragt geöffnet wird Word die Datei aus dem neuen Pfad zu laden, sondern auch von dem alten, da es in den word/_rels/settings.xml.rels definiert ist .

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"> 
    <Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/mailMergeSource" Target="oldPath" TargetMode="External"/> 
</Relationships> 

Wie kann ich dieses Objekt finden (Relation) in der WordprocessingDocument? Kann es nicht finden ... Oder gibt es einen anderen Weg, es zu ändern?

EDIT:

habe ich zwei verschiedene leere Dateien mit einer anderen Quelle und dann mit dem OpenXml Produktivitätswerkzeug zu vergleichen, um sie geöffnet. Wie ich bereits gesehen habe sind die Unterschiede in der word/settings.xml und in der word/_rels/settings.xml.rels.

+0

Try Öffnen des Dokuments in Word, Ändern der Datenquelle und Speichern unter einem anderen Namen. Verwenden Sie die Funktion "Vergleichen" im Open XML SDK Productivity Tool, um den Code zu sehen, der generiert wird, um das eine Dokument in das andere zu ändern. FWIW, Sie müssen wahrscheinlich eine neue Beziehungs-ID erstellen (die in der rels-Datei gespeichert wird) und sie ersetzen/löschen Sie die rId1 damit. So funktioniert das normalerweise mit dem Open XML SDK. –

+0

Ok, aber wie lösche ich die alte Beziehung? Ich kann es nicht finden, es mit OpenXml öffnend ... – Emaborsa

Antwort

0

Am Ende ich mit folgenden Lösung kam:

using (WordprocessingDocument doc = WordprocessingDocument.Open(docInByteArray, isEditable: true)) 
{ 
    Settings settings = doc.MainDocumentPart.DocumentSettingsPart.Settings; 
    OpenXmlElement openXmlElement = null; 
    foreach (OpenXmlElement element in settings.ChildElements) 
    { 
     if (element is MailMerge mailMerge) 
     { 
      mailMerge.Query.Val = "SELECT * FROM " + csvPath; 
      mailMerge.DataSourceObject.Remove(); 
     } 
     else if (element is AttachedTemplate) 
     { 
      openXmlElement = element; 
     } 
    } 
    if (openXmlElement != null) 
    { 
     openXmlElement.Remove(); 
    } 
    doc.Save(); 
} 
0

Ich glaube, dass Sie es auf diese Weise tun können, wenn Sie bereits die entsprechende rID (Beziehungs-ID) im relevanten Teil des XML-Parameters für die Einstellungen haben. Der Ansatz, den ich gebe, beruht auf Linq.

Beachten Sie jedoch, dass Word zwei Datenquellendateinamen in Settings.xml speichern kann, mit 2 entsprechenden Beziehungen in settings.xml.rels. Außerdem haben beide die gleiche Beziehungszeichenfolge. AIUI Word verwendet den Datendateiname nicht tatsächlich im ODSO-Teil ("Office-Datenquellenobjekt") der MailMerge-Einstellungen, aber Sie sollten dies überprüfen.

Ein Weg, um das alte Verhältnis zu bekommen, ist wie folgt (diese Linq erfordert, wie es steht):

// Get the Settings part 
var settingsPart = wordDocument.MainDocumentPart.DocumentSettingsPart; 

// Create a MailMerge object and populate it with the existing data 
// (You do not have to do this - you could get the individual 
// elements/attributes from the part's XML) 

var mailMerge = 
    new MailMerge(settingsPart.Settings.ChildElements.First<MailMerge>().OuterXml); 

// Get the relationship 

ReferenceRelationship oldRel 
    = settingsPart.ExternalRelationships.Where(
     Rel => Rel.Id == mailMerge.DataSourceReference.Id 
    ).First(); 

/* 
// to get the ODSO relationship, use the following, and to replace it, follow the pattern I give below for oldRel and newRel 
ReferenceRelationship oldOdsoRel = 
    settingsPart.ExternalRelationships.Where(
    Rel => Rel.Id == mailMerge.DataSourceObject.SourceReference.Id 
).First(); 
*/ 

// Delete the old Relationship (but notice that the oldRel object remains) 

settingsPart.DeleteExternalRelationship(oldRel.Id); 
var newRel = 
    settingsPart.AddExternalRelationship(
    oldRel.RelationshipType, 
    new Uri("your file path/name",UriKind.RelativeOrAbsolute), 
    oldRel.Id); 
+0

Ich habe bereits versucht, den Eintrag aus den externen Beziehungen zu löschen, aber 'settingsPart.ExternalRelationships' ist null. – Emaborsa

+0

Wenn es Ihnen erlaubt ist, bearbeiten Sie Ihre ursprüngliche Frage so, dass sie den Code enthält, mit dem Sie die Beziehungen abgerufen und gelöscht haben. Ich schlage auch vor, dass Sie versuchen, ein neues Dokument mit einer ähnlichen Datenquelle (in Word) zu erstellen und Ihren Code dagegen zu testen. –