2013-08-06 1 views
16

Я пытаюсь использовать библиотеку Microsoft OpenXML 2.5 для создания документа OpenXML. Все отлично работает, пока я не попытаюсь вставить строку HTML в свой документ. Я рыскал в Интернете, и вот что я придумал до сих пор (пропущено, чтобы только часть у меня возникли проблемы с):Добавить HTML String в OpenXML (* .docx) Документ

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

Очевидно, что я на самом деле не добавил в altChunk в этом примере, но я попробовал добавить его повсюду - в бег, абзац, тело и т. д. В любом случае я не могу открыть файл docx в Word 2010.

Это делает меня немного ореховым, потому что кажется это должно быть просто (я признаю, что я не полностью понимаю вещь AltChunk »). Поблагодарили бы за любую помощь.

Боковое примечание: Я обнаружил, что это было интересно, и я не знаю, действительно ли это проблема или нет, это this response, в котором говорится, что AltChunk повреждает файл при работе с MemoryStream. Может ли кто-нибудь подтвердить, что это/не соответствует действительности?

+0

У вас появляется сообщение об ошибке при попытке открыть сгенерированный файл docx в Word 2010? – Hans

+0

я. Я получаю «Файл [имя файла] не может быть открыт, потому что есть проблемы с содержимым». Я смотрю на содержимое инспектора, но я не вижу ничего очевидного в отношении того, что на самом деле неправильно. – JasCav

ответ

16

Я могу воспроизвести ошибку «... есть проблема с содержанием» с использованием неполный HTML документ как содержание альтернативного импорта формата части. Например, если вы используете следующий фрагмент HTML <h1>HELLO</h1> MS Word не может открыть документ.

Код, показанный ниже, показывает, как добавить AlternativeFormatImportPart в текстовый документ. (Я проверил код с 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); 
} 

Согласно спецификации офиса OpenXML действительных родительских элементов для w:altChunk элемента являются body, comment, docPartBody, endnote, footnote, ftr, hdr and tc. Итак, я добавил w:altChunk к элементу body.

Для получения дополнительной информации о элементе w:altChunk см. Это MSDN ссылка.

EDIT

Как отметил @ user2945722, чтобы убедиться, что библиотека OpenXml correctlty интерпретирует байтовый массив как UTF-8, вы должны добавить преамбулу UTF-8. Это можно сделать так:

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

Это предотвратит Ваш E от того визуализируется как © 's, ваши ых как ä-х и т.д.

+0

«... с использованием неполного HTML-документа ...» - это именно то, что было проблемой. Такая простая вещь, но очень неочевидная для меня. Спасибо за вашу помощь. – JasCav

+3

Вы должны рассмотреть возможность добавления спецификации UTF8 в массив байтов, прежде чем передавать его в память. Это помогло моему сценарию, когда файл docx не отображал правильные символы UTF8. Что-то вроде этого - 'byte [] utf8Bom = new UTF8Encoding (true) .GetPreamble();' и затем добавить это к результату GetBytes – user2945722

+0

@ user2945722 Спасибо! Это был правильный ответ на мой вопрос. Он должен быть включен в ответ. –

1

была такая же проблема здесь, но совершенно другая причина. Стоит попробовать, если принятое решение не поможет. Попробуйте закрыть файл после сохранения. В моем случае это была разница между коррумпированным и чистым файлом docx. Как ни странно, большинство других операций работают только с сохранением() и выходом программы.

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(); 
+0

Я пытался писать в MemoryStream (используя WordprocessingDocument.Create вместо WordprocessingDocument.Open) и «волшебство» document.Close() было именно тем, что мне нужно, чтобы вернуть чистый поток памяти * ЕСЛИ * Я пытался return изнутри оператора using (или не использовал оператор using). Возвращение за пределы используемого оператора не требовало этой магии. Я подозреваю, что оператор using эффективно выполняет ту же задачу, что и document.Close() при удалении объекта. –