2010-09-28 6 views
2

J'apprends OpenXML. J'ai cherché pendant des heures à trouver comment faire une tâche simple: insérer du texte dans un contrôle de contenu en C#.OpenXML insérer du texte dans le contrôle du contenu Word 2007

J'ai un document modèle avec deux contrôles "Nom" et "Âge". Je peux les trouver assez bien, mais je ne peux pas y ajouter de texte. J'ai essayé un certain nombre de choses, mais en vain.

 byte[] templateBytes = System.IO.File.ReadAllBytes(fileName); 
     using (MemoryStream templateStream = new MemoryStream()) 
     { 
      templateStream.Write(templateBytes, 0, (int)templateBytes.Length); 

      using (WordprocessingDocument outDoc = WordprocessingDocument.Open(templateStream, true)) 
      { 
       MainDocumentPart mainPart = outDoc.MainDocumentPart; 

       foreach (SdtElement sdt in mainPart.Document.Descendants<SdtElement>().ToList()) 
       { 
        SdtAlias alias = sdt.Descendants<SdtAlias>().FirstOrDefault(); 

        if (alias != null) 
        { 
         string sdtTitle = alias.Val.Value; 

         switch (sdtTitle) 
         { 
          case "Name": 
           // ¿Qué? 
           break; 
          case "Age": 
           // ¿Qué? 
           break; 
         } 
        } 
       } 

       outDoc.ChangeDocumentType(DocumentFormat.OpenXml.WordprocessingDocumentType.Document); 
      } 

      using (FileStream fileStream = new FileStream(savePath, System.IO.FileMode.CreateNew)) 
      { 
       templateStream.WriteTo(fileStream); 
      } 
     } 

Tout aide grandement apprécié.

Cheers,

Tim.

EDITER -

Merci pour la réponse. Prenant votre conseil, j'ai essayé de lancer et de forer avec l'outil de productivité pour trouver les éléments enfants à mettre à jour. Pourriez-vous me dire si vous pouvez voir pourquoi ce code n'écrit rien au document?

 foreach (SdtElement sdt in mainPart.Document.Descendants<SdtElement>().ToList()) 
       { 
        SdtAlias alias = sdt.Descendants<SdtAlias>().FirstOrDefault(); 

        if (alias != null) 
        { 
         SdtRun xRun = (SdtRun)sdt; 
         SdtContentRun xContentRun = xRun.Descendants<SdtContentRun>().FirstOrDefault(); 
         Run xRun = xContentRun.Descendants<Run>().FirstOrDefault(); 
         Text xText = xRun.Descendants<Text>().FirstOrDefault(); 

         string sdtTitle = alias.Val.Value; 

         switch (sdtTitle) 
         { 
          case "Name": 
           xText.Text = "Whatever";     
           break; 
          case "Age":      
           xText.Text = "69"; 
           break; 
         } 
        }  
       } 
+0

Salut, vous avez xRun déclaré deux fois, donc Visual Studio ne compile pas. Voici le changement: [code] Exécutez xRun2 = xContentRun.Descendants () .FirstOrDefault(); [/ code] –

Répondre

5

Vous avez besoin de transformer votre SdtElement en quoi que ce soit, afin d'obtenir son contenu enfant.

Par exemple, si c'est un SdtBlock:

((SdtBlock)sdt).SdtContentBlock 

Ensuite, vous pouvez ajouter des choses (par exemple ajouter des enfants) à cela.

From MSDN, la hiérarchie d'héritage:

DocumentFormat.OpenXml.Wordprocessing.SdtElement 
    DocumentFormat.OpenXml.Wordprocessing.SdtBlock 
    DocumentFormat.OpenXml.Wordprocessing.SdtCell 
    DocumentFormat.OpenXml.Wordprocessing.SdtRow 
    DocumentFormat.OpenXml.Wordprocessing.SdtRun 
    DocumentFormat.OpenXml.Wordprocessing.SdtRunRuby 
+0

Merci, mon pote. Voir la modification ci-dessus ... À votre santé. – Hanshan

1

Après de nombreuses heures de douleur, je l'ai résolu.

Deux choses étaient le problème: 1) J'avais besoin d'un mainPart.Document.Save(); commande là-bas. 2) J'avais ajouté un customXmlPart avec le Content Control Toolkit. Donc, je suppose que cette partie customxml remplaçait le texte que j'ajoutais avec le code, parce que quand je suis retourné dans la boîte à outils de contrôle de contenu et que j'ai supprimé la partie xml, cela a fonctionné.

Merci encore plutext pour m'avoir mis sur la solution!

+0

Exemple de code complet serait apprécié :-) –

0

Soit dit en passant, en ajoutant la ligne suivante de code avant le foreach nettoiera automatiquement toute xml personnalisée existante:

mainPart.DeleteParts<CustomXmlPart>(mainPart.CustomXmlParts); 
1

Tous ceux qui veulent le code en format VB pour faire une trouvaille droite/remplacer une clé/valeur de tableau dictionnaire ...

  Using document As WordprocessingDocument = WordprocessingDocument.Open(cls_sNewFilename, True) 
       Dim mainPart As MainDocumentPart = document.MainDocumentPart 
       Dim body As Body = mainPart.Document.Body 

       'if custom xml content exists, delete it first 
       mainPart.DeleteParts(Of CustomXmlPart)(mainPart.CustomXmlParts) 

       For Each sdt As SdtElement In body.Descendants(Of SdtElement)().ToList() 
        Dim [alias] As SdtAlias = sdt.Descendants(Of SdtAlias)().FirstOrDefault() 

        If [alias] IsNot Nothing Then 

         If sdt.ToString() = "DocumentFormat.OpenXml.Wordprocessing.SdtRun" Then 
          Dim xStdRun As SdtRun = DirectCast(sdt, SdtRun) 
          Dim xStdContentRun As SdtContentRun = xStdRun.Descendants(Of SdtContentRun)().FirstOrDefault() 
          Dim xRun As Run = xStdContentRun.Descendants(Of Run)().FirstOrDefault() 
          Dim xText As Text = xRun.Descendants(Of Text)().FirstOrDefault() 
          Dim sdtTitle As String = [alias].Val.Value 

          xText.Text = dictReplacements.Item(sdtTitle) 

         ElseIf sdt.ToString() = "DocumentFormat.OpenXml.Wordprocessing.SdtBlock" Then 
          Dim xStdBlock As SdtBlock = DirectCast(sdt, SdtBlock) 
          Dim xStdContentBlock As SdtContentBlock = xStdBlock.Descendants(Of SdtContentBlock)().FirstOrDefault() 
          Dim xRun As Run = xStdContentBlock.Descendants(Of Run)().FirstOrDefault() 
          Dim xText As Text = xStdContentBlock.Descendants(Of Text)().FirstOrDefault() 
          Dim sdtTitle As String = [alias].Val.Value 

          xText.Text = dictReplacements.Item(sdtTitle) 
         End If 
        End If 
       Next 

       mainPart.Document.Save() 
       document.Close() 
      End Using 

pour une raison quelconque la dernière partie semble être sdtBlock au lieu de sdtRun où le ElseIf ..!

Questions connexes