2017-02-06 2 views
1

J'essaie de créer un fichier .docx à partir d'un modèle de mot (. dotx), en utilisant la bibliothèque OpenXML 2.5. Plus exactement, j'essaie de suivre this, mais je veux ouvrir le document en utilisant un MemoryStream et non le chemin vers le fichier. Par conséquent, dans le lien ci-dessus, l'approche est la suivante: Copiez le fichier de modèle dans un nouveau fichier sur le disque. Ouvrez le nouveau fichier en tant que WordProcessingDocument, changez son type en document et ajoutez une référence au modèle (je ne suis pas sûr de savoir pourquoi est-ce nécessaire ...)Open XML SDK - Créer docx à partir du modèle (dotx) en utilisant MemoryStream comme détenteur docx

Ce dont j'ai besoin est. Obtenez mon modèle de la base de données en tant que tableau d'octets. Copiez le tableau dans un flux et ouvrez-le en tant que WordProcessingDocument. Ensuite, faites la même chose que ci-dessus. Je ne veux pas utiliser les fichiers temporaires sur le disque et ainsi de suite. Ce que je ne comprends pas, c'est pourquoi devrais-je référencer le fichier gabarit dans le nouveau document (En fait, inspecter les fichiers xml dans l'archive docx, il ajoute juste un nœud xml contenant le nom du template ... pourquoi?)

Maintenant, mon problème est que si j'utilise un MemoryStream et non un chemin physique vers le fichier, le résultat docx est corrompu. Je reçois "Microsoft Office ne peut pas ouvrir ce fichier car certaines pièces sont manquantes ou invalides". Si j'utilise des fichiers disque temporaires, cela fonctionne. Pourquoi cela se produit-il?

simplifié, mon code ressemble à ceci:

byte[] result = null; 
byte[] templateBytes = System.IO.File.ReadAllBytes("template.dotx"); 
using (MemoryStream templateStream = new MemoryStream()) 

{ 
    templateStream.Write(templateBytes, 0, (int)templateBytes.Length); 

    using (WordprocessingDocument doc = WordprocessingDocument.Open(templateStream, true)) 
      { 
       doc.ChangeDocumentType(WordprocessingDocumentType.Document); 
       var mainPart = doc.MainDocumentPart; 

       //Here I should create an AttachedTemplate object and assign a relationship id to it, which also implies 
       //setting a "reference" to the template ? I'm not using files so there's nothing to "reference" anyway 
       // If it's doing more than just putting a visual reference to the template file, then why limit the way of referencing the template 
       // only by using the Uri to the file? Please take a look at the above link to see what I'm referring to. 

       //Write some text in the file .... 
       mainPart.Document.Save(); 

       File.WriteAllBytes("Result.docx", templateStream.ToArray()); 
      } 
    } 

Cela me obtient un fichier docx corrompu. Si je passe de MemoryStream à l'ouverture du nouveau fichier docx à partir du disque (en utilisant l'autre constructeur de la classe WordProcessingDocument), cela fonctionne. Je ne fais pas quelque chose de mal (comme essayer d'écrire le résultat dans le fichier après avoir disposé le flux de mémoire), donc ça devrait me donner le même résultat.

Quel est le problème avec mon code?

Merci

Répondre

1

Si vous prenez la dernière ligne de votre File.WriteAllBytes de code hors du bloc à l'aide intérieure, il devrait fonctionner correctement. Mettez juste cette ligne juste avant l'attelle de fermeture du bloc d'utilisation externe.

+0

Merci pour la réponse, Michael. Il était tard et je ne le vois pas. Vous avez raison, en quittant le bloc using du document, Open XML enregistre les changements et ferme/dispose également les ressources non managées. J'ai donc essentiellement essayé d'ouvrir quelque chose qui n'était pas complètement sauvegardé. – darkdante