Exception in saving word document - c#

When I execute the below code to save the word file following exception occurs.please help me to correct the issue.thanks.
Cannot get stream with FileMode.Create, FileMode.CreateNew, FileMode.Truncate, FileMode.Append when access is FileAccess.Read.
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(path, false))
{
string docText = null;
using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
{
docText = sr.ReadToEnd();
}
//Regex regexText = new Regex("<var_Date>");
docText = docText.Replace("<var_Date>", DateTime.Now.ToString("MMM dd,yyyy"));
using (StreamWriter sw = new StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
sw.Write(docText);
}

Right here:
WordprocessingDocument.Open(path, false))
The second argument is isEditable, you passed false. So you've opened it as read-only.
Ref: https://msdn.microsoft.com/en-us/library/cc562234.aspx

Related

ZIP related exception after saving WordprocessingDocument

I am trying to replace text in a docx document based on this sample, with some modifications: https://learn.microsoft.com/en-us/office/open-xml/how-to-search-and-replace-text-in-a-document-part#sample-code
However, the saved document is not valid anymore. Word is able to correct the file, but there is a Number of entries expected in End Of Central Directory does not correspond to number of entries in Central Directory. exception is thrown at System.IO.Compression.ZipArchive.ReadCentralDirectory() when trying to open the created file again with WordprocessingDocument.
My code looks like this:
using (var fs = new FileStream(fn, FileMode.Open, FileAccess.Read, FileShare.Read))
using (var ms = new MemoryStream())
{
await fs.CopyToAsync(ms);
using (var wordDoc = WordprocessingDocument.Open(ms, true))
{
string docText;
using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
{
docText = sr.ReadToEnd();
}
/*Regex regexText = new Regex("text to replace");
docText = regexText.Replace(docText, "new text");*/
using (StreamWriter sw = new StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
{
sw.Write(docText);
}
}
await File.WriteAllBytesAsync(target, ms.GetBuffer());
}
using (var wordDoc = WordprocessingDocument.Open(target, true))
{
}
The issue is not repated to the replace itself. Even reading the MainDocumentPart in any way causes this exception to be thrown.
Why the streams? I want to create and modify a document from template and save it afterwards to a stream. But I haven't found any CreateFromTemplate overload neither a Save/SaveAs overload that accepts a stream.

Download byte array from stream writer

Hi I am trying to make working this piece of code, after the copy of the word file template into a memory stream, read it and replace some text, I would convert the stream writer to byte array which will be used to download the result. Thanks in advance
public byte[] GetWordFile()
{
try
{
string sourceFile = Path.Combine("C:/[...]/somefile.docx");
using (MemoryStream inStream = new MemoryStream())
{
using (Stream fs = File.Open(sourceFile, FileMode.Open, FileAccess.Read))
{
fs.CopyTo(inStream);
}
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(inStream, true))
{
string docText = null;
using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
{
docText = sr.ReadToEnd();
}
docText = docText.Replace("numpol", "HAHAHHAHA");
using (MemoryStream outStream = new MemoryStream())
using (StreamWriter sw = new StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
{
sw.Write(docText);
sw.Flush();
sw.BaseStream.CopyTo(outStream);
outStream.Position = 0;
return outStream.ToArray();
}
}
}
}
catch (Exception ex)
{
///...
}
}

Return byte array of openxml document

I'm using the following code to generate an openxml document and save it on the server and that works fine, however now i'm trying to generate it to a byte stream to serve out straight away without saving to the server but the document gets corrupted in the process.
Working Code
public static void CreateWordDoc(List<objReplace> lstReplace, String TemplateFile, String OutputPath)
{
File.Delete(OutputPath);
File.Copy(TemplateFile, OutputPath);
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(OutputPath, true))
{
string docText = null;
using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
docText = sr.ReadToEnd();
foreach (var ro in lstReplace)
{
Regex regexText = new Regex(ro.Find);
docText = regexText.Replace(docText, ro.Replace);
}
using (StreamWriter sw = new StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
{
sw.Write(docText);
}
}
}
Code that produces currupted XML - that I want to get working
public static byte[] CreateWordDocToStream(List<objReplace> lstReplace, String TemplateFile)
{
string docText = null;
byte[] filebytes = File.ReadAllBytes(TemplateFile);
using (MemoryStream stream = new MemoryStream(filebytes))
{
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(stream, true))
{
using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
docText = sr.ReadToEnd();
foreach (var ro in lstReplace)
{
Regex regexText = new Regex(ro.Find);
docText = regexText.Replace(docText, ro.Replace);
}
}
}
return Encoding.ASCII.GetBytes(docText);
}

Append throwing an exception

I was trying to create a fixed lenght(left aligned) batch file with the below code.
when i use Append it's throwing exception "is a method but used like a type".
string batFilePath = #"c:\mockforbat.bat";
if (!File.Exists(batFilePath))
{
using (FileStream fs = File.Create(batFilePath))
{
fs.Close();
}
}
//write
using (StreamWriter sw = new File.AppendText(batFilePath))
{
string a = String.Format("{0,-24}{1,-5}{2,5}", "CostCenter", "CostObject", "ActivityType");
sw.WriteLine(#a);
}
Process process = Process.Start(batFilePath);
process.WaitForExit();
Please some one correct me what i did wrong here ?
Drop the new operator from this line
using (StreamWriter sw = new File.AppendText(batFilePath))
It should read
using (StreamWriter sw = File.AppendText(batFilePath))
string batFilePath = #"c:\mockforbat.bat";
using(var fs = new FileStream(batFilePath , FileMode.OpenOrCreate, FileAccess.Write))
{
using(var sw = new StreamWriter(fs))
{
string a = String.Format("{0,-24}{1,-5}{2,5}", "CostCenter", "CostObject", "ActivityType");
sw.WriteLine(a);
}
}

MemoryStream - Cannot access a closed Stream

Hi why using (var sw = new StreamWriter(ms)) returns Cannot access a closed Stream exception. Memory Stream is on top of this code.
using (var ms = new MemoryStream())
{
using (var sw = new StreamWriter(ms))
{
sw.WriteLine("data");
sw.WriteLine("data 2");
ms.Position = 0;
using (var sr = new StreamReader(ms))
{
Console.WriteLine(sr.ReadToEnd());
}
} //error here
}
What the best way to fix it ?
Thanks
This is because the StreamReader closes the underlying stream automatically when being disposed of. The using statement does this automatically.
However, the StreamWriter you're using is still trying to work on the stream (also, the using statement for the writer is now trying to dispose of the StreamWriter, which is then trying to close the stream).
The best way to fix this is: don't use using and don't dispose of the StreamReader and StreamWriter. See this question.
using (var ms = new MemoryStream())
{
var sw = new StreamWriter(ms);
var sr = new StreamReader(ms);
sw.WriteLine("data");
sw.WriteLine("data 2");
ms.Position = 0;
Console.WriteLine(sr.ReadToEnd());
}
If you feel bad about sw and sr being garbage-collected without being disposed of in your code (as recommended), you could do something like that:
StreamWriter sw = null;
StreamReader sr = null;
try
{
using (var ms = new MemoryStream())
{
sw = new StreamWriter(ms);
sr = new StreamReader(ms);
sw.WriteLine("data");
sw.WriteLine("data 2");
ms.Position = 0;
Console.WriteLine(sr.ReadToEnd());
}
}
finally
{
if (sw != null) sw.Dispose();
if (sr != null) sr.Dispose();
}
Since .net45 you can use the LeaveOpen constructor argument of StreamWriter and still use the using statement. Example:
using (var ms = new MemoryStream())
{
using (var sw = new StreamWriter(ms, leaveOpen:true))
{
sw.WriteLine("data");
sw.WriteLine("data 2");
}
ms.Position = 0;
using (var sr = new StreamReader(ms))
{
Console.WriteLine(sr.ReadToEnd());
}
}
When the using() for your StreamReader is ending, it's disposing the object and closing the stream, which your StreamWriter is still trying to use.
The problem is this block:
using (var sr = new StreamReader(ms))
{
Console.WriteLine(sr.ReadToEnd());
}
When the StreamReader is closed (after leaving the using), it closes it's underlying stream as well, so now the MemoryStream is closed. When the StreamWriter gets closed, it tries to flush everything to the MemoryStream, but it is closed.
You should consider not putting the StreamReader in a using block.
when it gets out from the using statement the Dispose method will be called automatically closing the stream
try the below:
using (var ms = new MemoryStream())
{
var sw = new StreamWriter(ms);
sw.WriteLine("data");
sw.WriteLine("data 2");
ms.Position = 0;
using (var sr = new StreamReader(ms))
{
Console.WriteLine(sr.ReadToEnd());
}
}
You have to leave the stream open to be able to read it.
the "StreamWriter" closes it after it is done writing
using (var ms = new MemoryStream())
{
using (var sw = new StreamWriter(ms, leaveOpen: true)))
{
sw.WriteLine("data");
sw.WriteLine("data 2");
ms.Position = 0;
using (var sr = new StreamReader(ms))
{
Console.WriteLine(sr.ReadToEnd());
}
} //error here
}
In my case (admittedly very arcane and not likely to be reproduced often), this was causing the problem (this code is related to PDF generation using iTextSharp):
PdfPTable tblDuckbilledPlatypi = new PdfPTable(3);
float[] DuckbilledPlatypiRowWidths = new float[] { 42f, 76f };
tblDuckbilledPlatypi.SetWidths(DuckbilledPlatypiRowWidths);
The declaration of a 3-celled/columned table, and then setting only two vals for the width was what caused the problem, apparently. Once I changed "PdfPTable(3)" to "PdfPTable(2)" the problem went the way of the convection oven.

Categories

Resources