Ajouter une chaîne HTML à OpenXML (*.docx) Document

j'essaie d'utiliser la bibliothèque OpenXML 2.5 de Microsoft pour créer un document OpenXML. Tout fonctionne très bien, jusqu'à ce que j'essaie d'insérer une chaîne HTML dans mon document. J'ai parcouru la toile et voici ce que j'ai trouvé jusqu'à présent:

Paragraph paragraph = new Paragraph();
Run run = new Run();

string altChunkId = "id1";
AlternativeFormatImportPart chunk =
       document.MainDocumentPart.AddAlternativeFormatImportPart(
           AlternativeFormatImportPartType.Html, altChunkId);
chunk.FeedData(new MemoryStream(Encoding.UTF8.GetBytes(ioi.Text)));
AltChunk altChunk = new AltChunk { Id = altChunkId };

run.AppendChild(new Break());

paragraph.AppendChild(run);
body.AppendChild(paragraph);

évidemment, je n'ai pas réellement ajouté l'altChunk dans cet exemple, mais j'ai essayé de l'ajouter partout - à la course, paragraphe, corps, etc. Dans le cas, je Je ne peux pas ouvrir le fichier docx dans Word 2010.

cela me rend un peu fou parce que cela semble comme si cela devait être simple (je dois admettre que je ne suis pas pleinement comprendre la"chose" AltChunk). Serais reconnaissant de toute aide.

Side Note: une chose que j'ai trouvé qui était intéressant, et je ne sais pas si c'est réellement un problème ou pas, est cette réponse qui dit AltChunk corrompt le fichier en travaillant à partir d'un MemoryStream. Est-ce que quelqu'un peut confirmer que c'est/n'est pas vrai?

17
demandé sur Community 2013-08-07 00:32:44

2 réponses

je peux reproduire l'erreur "... Il ya un problème avec le contenu" en utilisant un document HTML incomplet comme contenu de la partie importation en média substitut. Par exemple, si vous utilisez L'extrait HTML suivant <h1>HELLO</h1> MS Word est incapable d'ouvrir le document.

Le code ci-dessous montre comment ajouter un AlternativeFormatImportPart à un document word. (J'ai testé le code avec MS Word 2013).

using (WordprocessingDocument doc = WordprocessingDocument.Open(@"test.docx", true))
{
  string altChunkId = "myId";
  MainDocumentPart mainDocPart = doc.MainDocumentPart;

  var run = new Run(new Text("test"));
  var p = new Paragraph(new ParagraphProperties(
       new Justification() { Val = JustificationValues.Center }),
                     run);

  var body = mainDocPart.Document.Body;
  body.Append(p);        

  MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes("<html><head></head><body><h1>HELLO</h1></body></html>"));

  // Uncomment the following line to create an invalid word document.
  // MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes("<h1>HELLO</h1>"));

  // Create alternative format import part.
  AlternativeFormatImportPart formatImportPart =
     mainDocPart.AddAlternativeFormatImportPart(
        AlternativeFormatImportPartType.Html, altChunkId);
  //ms.Seek(0, SeekOrigin.Begin);

  // Feed HTML data into format import part (chunk).
  formatImportPart.FeedData(ms);
  AltChunk altChunk = new AltChunk();
  altChunk.Id = altChunkId;

  mainDocPart.Document.Body.Append(altChunk);
}

selon la spécification Office OpenXML valide les éléments parent pour w:altChunk élément body, comment, docPartBody, endnote, footnote, ftr, hdr and tc . Donc, j'ai ajouté le w:altChunk à l'élément du corps.

pour plus d'information sur l'élément w:altChunk voir ce lien MSDN .

MODIFIER

comme le souligne @user2945722, pour s'assurer que la bibliothèque OpenXml interprète correctement le tableau des octets comme UTF-8, Vous devrait ajouter le préambule UTF-8. Cela peut se faire de cette façon:

MemoryStream ms = new MemoryStream(new UTF8Encoding(true).GetPreamble().Concat(Encoding.UTF8.GetBytes(htmlEncodedString)).ToArray()

ceci empêchera que vos é's soient rendus comme és, vos ä's comme ä's, etc.

17
répondu Hans 2017-08-11 15:42:45

Avait le même problème ici, mais une cause totalement différente. Vaut la peine d'essayer si la solution retenue n'aide pas. Essayez de fermer le fichier après l'enregistrement. Dans mon cas, c'était la différence entre un fichier docx corrompu et un fichier docx propre. Curieusement, la plupart des autres opérations fonctionnent avec seulement un Save() et une sortie de programme.

String cid = "chunkid";
WordprocessingDocument document = WordprocessingDocument.Open("somefile.docx", true);
Body body = document.MainDocumentPart.Document.Body;
MemoryStream ms = new MemoryStream(System.Text.Encoding.UTF8.GetBytes("<html><head></head><body>hi</body></html>"));
AlternativeFormatImportPart formatImportPart = document.MainDocumentPart.AddAlternativeFormatImportPart(AlternativeFormatImportPartType.Html, cid);
formatImportPart.FeedData(ms);
AltChunk altChunk = new AltChunk();
altChunk.Id = cid;
document.MainDocumentPart.Document.Body.Append(altChunk);
document.MainDocumentPart.Document.Save();
// here's the magic!
document.Close();
1
répondu pragmar 2015-01-15 22:11:16