c# - read - Agregar cadena HTML a un documento OpenXML(*.docx)
tutorial openxml c# (2)
Estoy tratando de usar la biblioteca OpenXML 2.5 de Microsoft para crear un documento OpenXML. Todo funciona bien, hasta que intento insertar una cadena HTML en mi documento. He rastreado la red y esto es lo que he encontrado hasta ahora (en forma de la porción con la que tengo problemas):
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);
Obviamente, no he agregado el altChunk en este ejemplo, pero he intentado agregarlo en todas partes: a la ejecución, al párrafo, al cuerpo, etc. En cualquier caso, no puedo abrir el archivo docx en Word 2010.
Esto me está volviendo un poco chiflado porque parece que debería ser sencillo (admitiré que no estoy entendiendo completamente la "cosa" de AltChunk). Agradecería cualquier ayuda.
Nota al margen: una cosa que encontré que fue interesante, y no sé si en realidad es un problema o no, es esta respuesta que dice que AltChunk corrompe el archivo cuando se trabaja desde un MemoryStream. ¿Alguien puede confirmar que esto es / no es cierto?
Puedo reproducir el error "... hay un problema con el contenido" utilizando un documento HTML incompleto como contenido de la parte de importación de formato alternativo. Por ejemplo, si utiliza el siguiente fragmento de código HTML <h1>HELLO</h1>
MS Word no puede abrir el documento.
El siguiente código muestra cómo agregar un AlternativeFormatImportPart
a un documento de Word. (He probado el código con 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);
}
Según la especificación de Office OpenXML, los elementos principales válidos para el elemento w:altChunk
son body, comment, docPartBody, endnote, footnote, ftr, hdr and tc
. Por lo tanto, he añadido el w:altChunk
al elemento del cuerpo.
Para obtener más información sobre el elemento w:altChunk
, consulte este enlace de MSDN .
EDITAR
Como lo señaló @ user2945722, para asegurarse de que la biblioteca OpenXml interpreta correctamente la matriz de bytes como UTF-8, debe agregar el preámbulo UTF-8. Esto se puede hacer de esta manera:
MemoryStream ms = new MemoryStream(new UTF8Encoding(true).GetPreamble().Concat(Encoding.UTF8.GetBytes(htmlEncodedString)).ToArray()
Esto evitará que tus é se conviertan en à © ''s, tus ä''s en ä¤''s, etc.
Tenía el mismo problema aquí, pero una causa totalmente diferente. Vale la pena intentarlo si la solución aceptada no ayuda. Intenta cerrar el archivo después de guardar. En mi caso, resultó ser la diferencia entre un archivo docx corrupto y uno limpio. Curiosamente, la mayoría de las demás operaciones funcionan solo con Guardar () y salir del programa.
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();