2016-03-31 19 views
0

私は.docxにMailMergeが含まれているので、コード(C#)でソースを変更する必要があります。ライブラリとして私はOpenXmlを使用しています。 docxをzipファイルとして開き、パスを検索すると、データソースのリンクがword/settings.xmlword/_rels/settings.xml.relsという2つの異なる場所に格納されていることがわかりました。OpenMmlでMailMergeを編集する

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; 
     } 
    } 
} 

これは正常に動作し、ファイルが開かれたときしかし言葉は、それがword/_rels/settings.xml.relsで定義されているので、新しいパスからだけでなく、古いものからファイルをロードするように求められます:・ファーストを置き換えるために

<?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> 

どのように私はWordprocessingDocumentでこのオブジェクト(Relation)を見つけることができますか?それを見つけることができません... またはそれを変更する別の方法はありますか?

EDIT:

私は別のソースを持つ2つの異なる空のファイルを作成し、それらを比較するために、生産性向上ツールのOpenXmlで開かれました。私がすでに見たように、違いはword/settings.xmlword/_rels/settings.xml.relsです。

+0

てみてください古い関係を取得する

一つの方法は、以下のように(そのままで、これは、LINQのを必要とする)でありますWordで文書を開き、データソースを変更して別の名前で保存します。 Open XML SDK生産性ツールの「比較」機能を使用して、1つのドキュメントを別のドキュメントに変更するために生成するコードを確認します。 FWIWの場合は、新しいRelation ID(Relsファイルに格納される)を作成し、それを使ってrId1を置き換えて削除する必要があります。これは、通常、この種のことがOpen XML SDKでどのように機能するかです。 –

+0

しかし、古い関係を削除するにはどうすればよいですか? OpenXmlで開くことができません。 – Emaborsa

答えて

0

私は、次の解決策を考え出した:

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

設定パーツXMLの関連部分に適切なrID(関係ID)が既にある場合は、この方法で対応できると思います。私が与えるアプローチはLinqに依存しています。

ただし、の2つのデータソースファイル名はSettings.xmlに格納でき、settings.xml.relsには2つの対応関係があることに注意してください。しかも、どちらも同じRelationshipタイプの文字列を持っています。 AIUI Wordは、MailMerge設定のODSO(Officeデータソースオブジェクト)の部分で実際にデータファイル名を使用しませんが、チェックする必要があります。終わり

// 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

すでに外部関係からエントリを削除しようとしましたが、 'settingsPart.ExternalRelationships'はnullです。 – Emaborsa

+0

可能な場合は、オリジナルの質問を編集して、関係の取得と削除に使用したコードを含めてください。また、同様のデータソースを持つ新しい文書を(Wordで)作成し、それに対してコードをテストすることをお勧めします。 –

関連する問題