Откройте XML заменить текст из файла Word и вернуть поток памяти с помощью MVC - PullRequest
2 голосов
/ 15 апреля 2011

У меня есть файл слов, который содержит текст указанного шаблона {pattern}, и я хочу заменить этот шаблон новой строкой, прочитанной из базы данных. Поэтому я использовал открытый поток чтения xml из моего файла шаблона docx, заменив строку моего шаблона, а затем вернулся к потоку, который поддерживает загрузку файла без создания временного файла. Но когда я открыл, это вызвало у меня ошибку в файле docx. Ниже приведен пример кода

public ActionResult SearchAndReplace(string FilePath)
{
    MemoryStream mem = new MemoryStream(System.IO.File.ReadAllBytes(FilePath));
    using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(mem, true))
    {
        string docText = null;
        using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
        {
            docText = sr.ReadToEnd();
        }

        Regex regexText = new Regex("Hello world!");
        docText = regexText.Replace(docText, "Hi Everyone!");

//Instead using this code below to write text back the original file. I write new string back to memory stream and return to a stream download file
        //using (StreamWriter sw = new //StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
        //{
        //    sw.Write(docText);
        //}

        using (StreamWriter sw = new StreamWriter(mem))
                    {
                        sw.Write(docText);
                    }
    }
    mem.Seek(0, SeekOrigin.Begin); 

    return File(mem, "application/octet-stream","download.docx"); //Return to download file
}

Пожалуйста, предложите мне любые решения, вместо этого прочитайте текст из файла слова и замените этот ожидаемый текстовый шаблон, а затем запишите данные обратно в исходный файл. Есть ли какие-либо решения заменить текст с библиотекой WordprocessingDocument? Как я могу вернуться в поток памяти с проверкой формата файла docx?

Ответы [ 3 ]

2 голосов
/ 16 мая 2011

Ваш подход не верен.Если случайно шаблон, который вы ищете, соответствует какой-то разметке Open XML, вы испортите документ.Если искомый текст разбит на несколько прогонов, ваш код поиска / замены не найдет текст и будет работать неправильно.Если вы хотите искать и заменять текст в документе WordprocessingML, вы можете использовать довольно простой алгоритм:

  • Разбить все серии на отдельные символы.Это включает в себя прогоны, которые имеют специальные символы, такие как разрыв строки, возврат каретки или жесткая табуляция.
  • Тогда довольно легко найти набор прогонов, которые соответствуют символам в строке поиска.
  • Как только вы определили набор прогонов, которые соответствуют, вы можете заменить этот набор прогонов на вновь созданный прогон (в котором есть свойства прогона, содержащие первый символ, соответствующий строке поиска).
  • После замены односимвольных прогонов на вновь созданный прогон вы можете затем объединить смежные прогоны с идентичным форматированием.

Я написал сообщение в блоге и записал скриншот, проходящий черезэтот алгоритм.

Сообщение в блоге: http://openxmldeveloper.org/archive/2011/05/12/148357.aspx
Снимок экрана: http://www.youtube.com/watch?v=w128hJUu3GM

-Eric

2 голосов
/ 05 мая 2012
string sourcepath = HttpContext.Server.MapPath("~/File/Form/s.docx");            
string targetPath = HttpContext.Server.MapPath("~/File/ExportTempFile/" + DateTime.Now.ToOADate() + ".docx");
System.IO.File.Copy(sourcepath, targetPath, true);
using (WordprocessingDocument wordDocument = WordprocessingDocument.Open(targetPath, true))
{
    string docText = null;
    using (StreamReader sr = new StreamReader(wordDocument.MainDocumentPart.GetStream()))
    {
        docText = sr.ReadToEnd();
    }
    Regex regexText = new Regex("Hello world!");
    docText = regexText.Replace(docText, "Hi Everyone!");
    byte[] byteArray = Encoding.UTF8.GetBytes(docText); 
    MemoryStream stream = new MemoryStream(byteArray);
    wordDocument.MainDocumentPart.FeedData(stream);
}
MemoryStream mem = new MemoryStream(System.IO.File.ReadAllBytes(targetPath));
return File(mem, "application/octet-stream", "download.docx");
1 голос
/ 10 мая 2011

Запись непосредственно в поток документов word действительно повредит его. Вместо этого вы должны записать в поток MainDocumentPart, но вы должны сначала его обрезать. Похоже, что метод MainDocumentPart.FeedData(Stream sourceStream) сделает именно это.

Я не проверял, но это должно работать.

public ActionResult SearchAndReplace(string FilePath)
{
    MemoryStream mem = new MemoryStream(System.IO.File.ReadAllBytes(FilePath));
    using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(mem, true))
    {
        string docText = null;
        using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
        {
            docText = sr.ReadToEnd();
        }

        Regex regexText = new Regex("Hello world!");
        docText = regexText.Replace(docText, "Hi Everyone!");

        using (MemoryStream ms = new MemoryStream())
        {
            using (StreamWriter sw = new StreamWriter(ms))
            {
                sw.Write(docText);
            }
            ms.Seek(0, SeekOrigin.Begin);
            wordDoc.MainDocumentPart.FeedData(ms);
        }
    }
    mem.Seek(0, SeekOrigin.Begin); 

    return File(mem, "application/octet-stream","download.docx"); //Return to download file
}
...