Epplus Csharp | How to manipulate already opened(in use) Excel File - epplus

Epplus Csharp | How to manipulate already opened(in use) Excel File. it works only when Excel file is closed. I can do like closing before code execution and reopen again, but do not think it's a way to go as my file contains more than 50000 rows (file size is big). Please advise, how to figure it out.
Thanks in advance

Rather than using a FileInfo to open the ExcelPackage workbook, use a stream:
FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
ExcelPackage pkg = new ExcelPackage(fs);
path is the path to the file that you would otherwise use for FileInfo
FileMode says you want to open it
FileAccess says you want to read it
FileShare says that other programs can read/write.
With the workbook specified by path open in excel, you will be able to read lines from the file, but will get an exception if you try to call ExcelPackage.Save().

It is only possible, if the file is opened for reading by a third-party, but not for writing.
If the third-party opened the file for writing, your attempt to open the same file even just for reading will result in System.IO.IOException. In fact, it's all about FileStream and not specific to EpPlus and ExcelPackage. Example in terms of .NET:
var fileStream1 = new FileStream(#"File.ext", FileMode.Open, FileAccess.Read);
var fileStream2 = new FileStream(#"File.ext", FileMode.Open, FileAccess.Read);
will work just fine. But the second line of the following fragment:
var fileStream1 = new FileStream(#"File.ext", FileMode.Open, FileAccess.Write);
var fileStream2 = new FileStream(#"File.ext", FileMode.Open, FileAccess.Read);
will result in a System.IO.IOException.

Related

Writing PDF in C:\ folder

I'm using .NET 4 on Windows 10.
I have a winform application written in vb.net which converts TIFF into PDF using PDFSharp api.
When I try to save the PDF into the C:\ folder there is no exception raised but nothing is written.
When I check if I have write access permission on folder C:\ , VB.NET tells me I do.
I'm using this chunk of code:
Private Function HasFolderWriteAccess(path As String) As Boolean
Try
Using inputstreamreader As New StreamReader(path)
inputstreamreader.Close()
End Using
Using inputStream As FileStream = File.Open(path, FileMode.Open, FileAccess.Write, FileShare.None)
inputStream.Close()
Return True
End Using
Catch ex As Exception
Return False
End Try
End Function
When I try to write a file using a StreamWriter, I face the same behavior:
Dim FILE_NAME As String = "C:\test2.txt"
Dim objWriter As New System.IO.StreamWriter(FILE_NAME)
objWriter.Write("Some text....")
objWriter.Close()
MessageBox.Show("Text written to file")
Is there some kind of magic happening in the Windows 10 C:\ folder that I don't know ?
Thanks for your replies.
Chris Dunaway's answer (in the comments) is right:
...look in this folder instead: C:\Users\User_name\‌​AppData\Local\Virtual‌​Store and see if your file is there. Windows doesn't allow writing of files to certain folders and silently redirects them to the virtual store...

Add a table to a PDF template using iTextSharp and VB.net

I've been stuck on this far longer than I care to admit. I'm trying to use iTextSharp to build a table that I can then insert into a PDF template (which is really just a PDF with a header and an acrofield that needs to be populated). I've currently got code that follows the same outline below:
Dim doc As New Document
Dim reader As PdfReader
Dim stamper As PdfStamper
Dim filestream As FileStream
Dim tempfile As String = My.Computer.FileSystem.GetTempFileName
filestream = New FileStream(tempfile, FileMode.Create)
PdfWriter.GetInstance(doc, filestream)
doc.Open()
generateTableForPdf(listOfData, numColumns, doc)
doc.Close()
reader = New PdfReader(pdfTemplatePath)
stamper = New PdfStamper(reader, filestream)
stamper.AcroFields.SetField("topmostSubform[0].Page1[0].headerField", "some text to go in the field")
The pdfTemplatePath is a private const that has the template's file path that I am trying to use and generateTableForPdf simply creates a dynamically sized table and puts it in doc (doc is passed by ref). I know the table is created because it displays when the page loads, however, the header in the template doesn't appear. I've looked around and found a couple of examples that use byte streams or memory streams, but my attempts at implementing those methods have failed more dramatically. Any help or guidance in better understanding how to go about this is greatly appreciated.

How do you delete a file generated via webapi after returning the file as response?

I'm creating a file on the fly on a WebAPI call, and sending that file back to the client.
I think I'm misunderstanding flush/close on a FileStream:
Dim path As String = tempFolder & "\" & fileName
Dim result As New HttpResponseMessage(HttpStatusCode.OK)
Dim stream As New FileStream(path, FileMode.Open)
With result
.Content = New StreamContent(stream)
.Content.Headers.ContentDisposition = New Headers.ContentDispositionHeaderValue("attachment")
.Content.Headers.ContentDisposition.FileName = fileName
.Content.Headers.ContentType = New Headers.MediaTypeHeaderValue("application/octet-stream")
.Content.Headers.ContentLength = stream.Length
End With
'stream.Flush()
'stream.Close()
'Directory.Delete(tempFolder, True)
Return result
You can see where I've commented things out above.
Questions:
Does the stream flush/close itself?
How can I delete the tempFolder after returning the result?
On top of all this, it would be great to know how to generate the file and send it to the user without writing it to the file system first. I'm confident this is possible, but I'm not sure how. I'd love to be able to understand how to do this, and solve my current problem.
Update:
I went ahead with accepted answer, and found it to be quite simple:
Dim ReturnStream As MemoryStream = New MemoryStream()
Dim WriteStream As StreamWriter = New StreamWriter(ReturnStream)
With WriteStream
.WriteLine("...")
End With
WriteStream.Flush()
WriteStream.Close()
Dim byteArray As Byte() = ReturnStream.ToArray()
ReturnStream.Flush()
ReturnStream.Close()
Then I was able to stream the content as bytearraycontent:
With result
.Content = New ByteArrayContent(byteArray)
...
End With
On top of all this, it would be great to know how to generate the file and send it to the user without writing it to the file system first. I'm confident this is possible, but I'm not sure how. I'd love to be able to understand how to do this, and solve my current problem.
To do the same thing without writing a file to disk, you might look into the MemoryStream class. As you'd guess, it streams data from memory like the FileStream does from a file. The two main steps would be:
Take your object in memory and instead of writing it to a file, you'd serialize it into a MemoryStream using a BinaryFormatter or other method (see that topic on another StackOverflow Q here: How to convert an object to a byte array in C#).
Pass the MemoryStream to the StreamContent method, exactly the same way you're passing the FileStream now.

Modifying pdf metadata using VB.NET

Below is the code I am using to modify pdf metadata. The code works fine but I have one issue - instead of modifying the source file, it creates a new file in a different directory. My question is - is there a way to modify source document instead of creating a new document with necessary changes?
If File.Exists(strSource) Then
Dim pdfFileReader As New PdfReader(strSource)
psStamp = New PdfStamper(pdfFileReader, New FileStream(strDest, FileMode.Create))
Dim inf As New SortedDictionary(Of String, String)(StringComparer.Ordinal)
inf.Add("Title", "Modifying metadata")
inf.Add("Company", "My Company")
inf.Add("Author", "myself")
psStamp.MoreInfo = inf
psStamp.Close()
End If
I have tried modifying the line below:
psStamp = New PdfStamper(pdfFileReader, New FileStream(strDest, FileMode.Create))
to point to the source file but then I get an error because file is in use.
Can anyone help?
I'd like to modify the current document without creating a new one. One way to do that would be create a new doc in a different directory, then delete the source doc and then save the newly created doc with the old doc's name but I wanted to see if there is a more elegant solution. Would appreciate any help

Open a file from a remote network share

I am trying to open a file from a server
I currently have
Dim attachedFilePath As String = "\\myserver\myshare\test.txt"
File.Open(attachedFilePath, FileMode.Open, FileAccess.Read, FileShare.Read)
This does not open a file.
However, if I change the path to be local then there is no issue.
Dim attachedFilePath As String = "c:\...\test.txt"
So, is there a way to open a file from remote storage?
File.Open is for reading the contents of a file. Use Process.Start to launch the default application for that file type
Dim Path = "\\myserver\myshare\test.txt"
System.Diagnostics.Process.Start(Path)