I am basically creating a xlsx file but I am getting an error while using that file like below.
System.IO.FileFormatException: Archive file cannot be size 0.
The way I tried.
string file = "c:\\DoneDone61.xlsx";
using(File.Create(file))
{
}
Also I cannot open excel file manually because it says the file is corrupted.
Thanks for answers in advance.
An Excel file which you consider to be "blank" is not just a file with no data in it (which is what you are creating). You can see this yourself by creating a document manually in Excel and then opening it in notepad. You'll notice that it actually has data inside of it. That data is used to store information regarding the three empty sheets named "Sheet1", "Sheet2" and "Sheet3". Also, there is some header information so that any program looking at the file knows that it is actually a compressed file (as per the Excel file format). So, as you can see, even a pretty empty excel file still contains SOME data.
If you want to create a blank excel document using C#, you have two good options:
Use a library that allows you to actually work with creating Excel documents that takes care of creating the file correctly. Check out something like the Microsoft OpenXML SDK or ExcelPackage.
Create an empty Excel document, store it somewhere, and when you want to "create" a new empty Excel document, just make a copy of this file.
This one ...
using(File.Create(filePath))
{
}
... creates an empty file. Read: really empty (=> 0 bytes) not an empty XLSX with an XLSX skeleton: ZIP container, file header, style definitions, ....
What exactly did you expect?
EDIT:
If you want to create an empty XLSX file (like "Right Click on Mouse > New > New Microsoft Excel"), you have to use such an template, ... and write it onto the disk.
To achieve that, you have to deploy this template file with your application, and then do a File.Copy(source, dest), or integrate it as a resource and write the resource content to the disk.
What you need to use is Interop.Excel namespace. Here's a guide from msdn
please use this...Its a bit hacky but couldn't get a better way to do this using InterOp
public static void CreateEmptyXLSXFile(string FilePath)
{
FileStream MyStream = new FileStream(FilePath, FileMode.CreateNew, FileAccess.ReadWrite);
MyStream.Write(ExcelDocumentsInterOps.GetEmptyXSLXFileBytes(), 0, ExcelDocumentsInterOps.GetEmptyXSLXFileBytes().Length);
MyStream.Flush();
MyStream.Close();
MyStream.Dispose();
MyStream = null;
}
/// <summary>
/// Returns the bytes for an empty xslx file
/// </summary>
/// <returns></returns>
public static byte[] GetEmptyXSLXFileBytes()
{
string TheSting = "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";
return Convert.FromBase64String(TheSting);
}
When dealing with spreadsheet related tasks in .NET, you can use this open source library called SpreadsheetLight to write an excel file (especially, if you want to write content at some point).
If you prefer adding it as package via Nuget, you can say:
Install-Package SpreadsheetLight
After that, going by GenerateReport() exmaple:
// this one creates an empty workbook
using (SLDocument sl = new SLDocument())
{
// sl.SetCellValue("B3", "I love ASP.NET MVC");
sl.SaveAs("c:\\DoneDone61.xlsx");
}
Also see their tutorial for more interesting stuff.
Related
I want a method to write the datatable data to .xls,.xlsx or.csv based on the input provided along with the delimiter as input
public class DataTableExtensions
{
/*Input Params : Datatable input
fileFormat(.xls,.csv,.xlsx)
delimeter('\t' (tabSpace) or ,(comma) or | (pipe Symbol)
filepath - Any local folder*/
public void WriteToCsvFile(DataTable dataTable,string fileFormat,string delimeter, string filePath)
{
//Code to convert file based on the input
//Code to create file
System.IO.File.WriteAllText(filePath, fileContent.ToString());
}
}
You said it is only 1000 rows every 2 hours in the comments. That is a acceptable amount of data for a C# programm. I would say the big question left is wich output format you use.
.CSV is the simplest one. This format can be done with a File.WriteLine() and some string concaction. There is no build in CSV parser or writer code I am aware off in C#, but there is plenty of 3rd party code.
.XLS requires the (t)rusty Office COM Interop. That requires office to be installed and does not work from a non-interactive session (like a Windows Service). On top of all the normal issues for using COM interop.
There is the odd "export to XLS" function on existing classses, but those are rare, far inbetween and about everything you get. Unfortunately as we always had COM Interop as fallback, we never quite developed a standalone library for working with .XLS. Ironically working with this old format is harder from C#/.NET then it would be from Java.
.XLSX however is easier. It can be written using the OpenXML SDK. Or the XML writer and ZipArchive class: At their core all the ???x formats are a bunch of .XML files in a renamed .ZIP container. There should even be 3rd party code out there to make using the SDK easier.
.CSV is the lowest common denominator and propably the easiest to create. However if a user is supposed to open this document, the lack for formating might become an issue.
.XSLX would be my choice if you need a user to open it.
.XSL I would avoid like a swarm of angry bees.
I have written this Program to convert Xls,XLSx using console application with
Datatable as input and for text file I have written a simple stream writer logic.This works good. Initially I have installed package manage console and below code
using expertXLs package.I am not sure wheather I can share the key of that
or not.Please search the key and give in config before running it
Package Manage Console - Install-Package ExpertXls.ExcelLibrary -Version 5.0.0
Code :
--------
private static void GenerateTxtFileFromDataTable(DataTable sampleDataTable,string delimiter)
{
var _expertxlsLK = ConfigurationManager.AppSettings["ExpertxlsLK"];
//GetKey Value from config
// Create the workbook in which the data from the DataTable will be loaded 0 for 2003 Excel(xls),1 for 2007 Excel(xlsx)
ExcelWorkbookFormat workbookFormat = ExcelWorkbookFormat.0;
// create the workbook in the desired format with a single worksheet
ExcelWorkbook workbook = new ExcelWorkbook(workbookFormat);
workbook.EnableFormulaCalculations();
workbook.LicenseKey = _expertxlsLK;
// get the first worksheet in the workbook
ExcelWorksheet worksheet = workbook.Worksheets[0];
// set the default worksheet name
worksheet.Name = "ClaimInformation";
// load data from DataTable into the worksheet
worksheet.LoadDataTable(sampleDataTable, 1, 1, true);
worksheet.Workbook.EnableFormulaCalculations();
workbook.Save(#"M:\Rupesh\test.xlsx");
workbook.Close();
}
I am using DotNetZip 1.9.6 in my application which uses a file structure similar to e.g. *.docx: Zip file containing XML files.
Now every module of the application can store such XML files to my custom file management and on "save" they are serialized to streams which are then saved to the Zip file via DotNetZip.
To update the entries I use ZipFile.UpdateEntry(path, stream).
This works fine and the first time I save my file via calling ZipFile.Save() everything works.
But If I do this a second time (first some UpdateEntrycalls then Save) on the same instance the Zip file is corrupted: The file structure and meta-data (e.g. uncompressed size of each file) is still there, but all files are 0 byte in compressed size.
If I create a new instance from the just saved file after saving everything works fine, but shouldn't it be possible to avoid that and "reuse" the same instance?
The following example (also see https://dotnetfiddle.net/mHxEIy) can be used to reproduce the problem:
using System.IO;
using System.Text;
public class Program
{
public static void Main()
{
var zipFile = new Ionic.Zip.ZipFile();
var content1 = new MemoryStream(Encoding.Default.GetBytes("Content 1"));
zipFile.UpdateEntry("test.txt", content1);
zipFile.Save("test.zip"); // here the Zip file is correct
//zipFile = new Ionic.Zip.ZipFile("test.zip"); // uncomment and it works too
var content2 = new MemoryStream(Encoding.Default.GetBytes("Content 2"));
zipFile.UpdateEntry("test.txt", content2);
zipFile.Save(); // after that it is corrupt
}
}
To run this you need to add the "DotNetZip 1.9.6" NuGet package.
After the first save, this is what you get:
and after the second save:
This looks like it's a bug in the library, around removing an entry. If you just remove an entry and then save again, it correctly removes the file.
However, if you remove an entry and then add another one with the same name - which is what UpdateEntry is documented to do if the entry already exists - the old entry appears to be used instead.
The reason you're ending up with an empty file the second time is that the original MemoryStream is being read again - but by now, it's positioned at the end of the data, so there's no data to read. If you reset the position to the start of the stream (content1.Position = 0;) it will rewrite the original data. If you modify the data within content1, you end up with invalid compressed data.
The only workaround I can immediately think of is to keep your own map from filename to MemoryStream, and replace the contents of each MemoryStream when you want to update it... or just load the file each time, as per your existing workaround.
It's definitely worth filing a bug around this though, as it should work as far as I can tell.
As already suspected this was a bug in DotNetZip up to version 1.9.6.
I think I was able to fix this with THIS change which was just released as version 1.9.7 on NuGet. At least for me the problem does not happen anymore.
Some background what happend as far as I found out:
When you call Save the library sets an internal flag which remembers that the ZIP file was just save and on the second Save call instead of "recompressing" all entries in the ZIP file it copies them from the just saved file.
This works fine for adding/removing entries, but breaks when one of the entries was changed as then it "mixes" the old and the new entry and produces the inconsisten ZIP file.
My fix basically disables that "copy from old file" logic if an entry was changed.
How can I read content of a text file inside a zip archive?
For example I have an archive qwe.zip, and insite it there's a file asd.txt, so how can I read contents of that file?
Is it possible to do without extracting the whole archive? Because it need to be done quick, when user clicks a item in a list, to show description of the archive (it needed for plugin system for another program). So extracting a whole archive isn't the best solution... because it might be few Mb, which will take at least few seconds or even more to extract... while only that single file need to be read.
You could use a library such as SharpZipLib or DotNetZip to unzip the file and fetch the contents of individual files contained inside. This operation could be performed in-memory and you don't need to store the files into a temporary folder.
Unzip to a temp-folder take the file and delete the temp-data
public static void Decompress(string outputDirectory, string zipFile)
{
try
{
if (!File.Exists(zipFile))
throw new FileNotFoundException("Zip file not found.", zipFile);
Package zipPackage = ZipPackage.Open(zipFile, FileMode.Open, FileAccess.Read);
foreach (PackagePart part in zipPackage.GetParts())
{
string targetFile = outputDirectory + "\\" + part.Uri.ToString().TrimStart('/');
using (Stream streamSource = part.GetStream(FileMode.Open, FileAccess.Read))
{
using (Stream streamDestination = File.OpenWrite(targetFile))
{
Byte[] arrBuffer = new byte[10000];
int iRead = streamSource.Read(arrBuffer, 0, arrBuffer.Length);
while (iRead > 0)
{
streamDestination.Write(arrBuffer, 0, iRead);
iRead = streamSource.Read(arrBuffer, 0, arrBuffer.Length);
}
}
}
}
}
catch (Exception)
{
throw;
}
}
Although late in the game and the question is already answered, in hope that this still might be useful for others who find this thread, I would like to add another solution.
Just today I encountered a similar problem when I wanted to check the contents of a ZIP file with C#. Other than NewProger I cannot use a third party library and need to stay within the out-of-the-box .NET classes.
You can use the System.IO.Packaging namespace and use the ZipPackage class. If it is not already included in the assembly, you need to add a reference to WindowsBase.dll.
It seems, however, that this class does not always work with every Zip file. Calling GetParts() may return an empty list although in the QuickWatch window you can find a property called _zipArchive that contains the correct contents.
If this is the case for you, you can use Reflection to get the contents of it.
On geissingert.com you can find a blog article ("Getting a list of files from a ZipPackage") that gives a coding example for this.
SharpZipLib or DotNetZip may still need to get/read the whole .zip file to unzip a file. Actually, there is still method could make you just extract special file from the .zip file without reading the entire .zip file but just reading small segment.
I needed to have insights into Excel files, I did it like so:
using (var zip = ZipFile.Open("ExcelWorkbookWithMacros.xlsm", ZipArchiveMode.Update))
{
var entry = zip.GetEntry("xl/_rels/workbook.xml.rels");
if (entry != null)
{
var tempFile = Path.GetTempFileName();
entry.ExtractToFile(tempFile, true);
var content = File.ReadAllText(tempFile);
[...]
}
}
I start my application from withint Visual Studio 2010.
I add then some files into my application and each file type`s icon like icon from doc,docx,xls,pdf etc are added as String/Bitmap key/value pair to my IconImages.Resx file via
private void DumpTempResourceToRealResourceFile(IDictionary<String, Bitmap> tempResource)
{
using (ResXResourceWriter writer = new ResXResourceWriter("IconImages.Resx"))
{
foreach (KeyValuePair<String,Bitmap> item in tempResource)
{
writer.AddResource(item.Key, item.Value);
}
writer.Generate();
}
}
When the icons are added to the resource I close the application.
Then I start my application again with VS 2010 and add some files within my document application. The file types are written again to my IconImages.Resx.
Then I close my application and check the IconImages.Resx file under the \bin\ folder and the previous saved images are gone and I have new/different ones now.
Why can I not say OPEN a .resx file and append stuff to it? Everytime I create a ResourceWriter object with the same name "IconImages.Resx" I overwrite the previous added stuff and thats stupid.
How can my IconImages.Resx file stay alive over an application session without being overwritten by other stuff I add?
I haven't used ResXResourceWriter, but usually *Writer classes simply write a data file from scratch.
If you want to "append" new data you would typically have to use a *Reader class to deserialise the existing data into memory, then merge/add in any new data you wish to, and use a *Writer object to then write the resulting data back out. Take a look at ResXResourceReader to see if it supports what you need to do this.
I am having now a lookup table "FiletypeImage" with the filetype ".docx" and the raw binary data aka blob. This table gets retrieved in my documentService and cached in a static variable. with a Get and Add method which are called by my DocumentListViewModel. Its very fast thx to sqlite :)
I've produced a MVC app that when you access /App/export it zips up all the files in a particular folder and then returns the zip file. The code looks something like:
public ActionResult Export() {
exporter = new Project.Exporter("/mypath/")
return File(exporter.filePath, "application/zip", exporter.fileName);
}
What I would like to do is return the file to the user and then delete it. Is there any way to set a timeout to delete the file? or hold onto the file handle so the file isn't deleted till after the request is finished?
Sorry, I do not have the code right now...
But the idea here is: just avoid creating a temporary file! You may write the zipped data directly to the response, using a MemoryStream for that.
EDIT Something on that line (it's not using MemoryStream but the idea is the same, avoiding creating a temp file, here using the DotNetZip library):
DotNetZip now can save directly to ASP.NET Response.OutputStream.
I know this thread is too old , but here is a solution if someone still faces this.
create temp file normally.
Read file into bytes array in memory by System.IO.File.ReadAllBytes().
Delete file from desk.
Return the file bytes by File(byte[] ,"application/zip" ,"SomeNAme.zip") , this is from your controller.
Code Sample here:
//Load ZipFile
var toDownload = System.IO.File.ReadAllBytes(zipFile);
//Clean Files
Directory.Delete(tmpFolder, true);
System.IO.File.Delete(zipFile);
//Return result for download
return File(toDownload,"application/zip",$"Certificates_{rs}.zip");
You could create a Stream implementation similar to FileStream, but which deletes the file when it is disposed.
There's some good code in this SO post.