I am creating a excel file in the code as Shown Below
Microsoft.Office.Interop.Excel.Application excelFile = CreateExcelFile();
now I want to convert this excelFile to byte[] without saving to hard drive. How is it possible?
had the same problem some time ago. You have to create a temporary file, and then read it to a byte array.
Example code:
string tempPath = AppDomain.CurrentDomain.BaseDirectory + DateTime.Now.Hour + DateTime.Now.Minute + DateTime.Now.Second + DateTime.Now.Millisecond + "_temp";//date time added to be sure there are no name conflicts
workbook.SaveAs(tempPath, workbook.FileFormat);//create temporary file from the workbook
tempPath = workbook.FullName;//name of the file with path and extension
workbook.Close();
byte[] result = File.ReadAllBytes(tempPath);//change to byte[]
File.Delete(tempPath);//delete temporary file
That isn't an Excel File it is a COM object used for Excel Automation. It can be used to request Excel to save a document to disk (as a temporary file), which you could then load into a byte[] and then delete the temporary file.
The following code could be used to do this for the active workbook:
public byte[] GetActiveWorkbook(Microsoft.Office.Interop.Excel.Application app)
{
string path = Path.GetTempFileName();
try
{
app.ActiveWorkbook.SaveCopyAs(path);
return File.ReadAllBytes(path);
}
finally
{
if(File.Exists(path))
File.Delete(path);
}
}
Related
My application needs to save a byte[] to disk, the issue is that I know it is an excel file but not what the correct file extension is. Is there a way I can tell if the file is .xls or .xlsx or .xlsm from the data itself?
I ended up writing an extension method to determine the excel file type. This method is not perfect. It will only correctly detect a .xlsm file if the file has a macro.
private static string FindType(this byte[] file)
{
using(MemoryStream ms = new MemoryStream(file))
{
var zf = new ZipArchive(ms, ZipArchiveMode.Read);
if (zf.Entries.Any(e=>e.FullName.StartsWith("xl.")))
{
if (zf.Entries.Any(e=>e.FullName.Equals("xl/vbaProject.bin", StringComparison.InvariantCultureIgnoreCase)))
return ".xlsm";
else
return ".xlsx";
}
}
return string.Empty;
}
I am trying to convert a byte[] I got from an XLS file I have elsewhere, into a new XLSX file and the save it. I'm using Free Spire.XML, but can't figure out how to do it.
public byte[] ConvierteAXLSX(string cuerpo)
{
Workbook wb = new Workbook();
Worksheet sheet = wb.Worksheets[0];
byte[] array = Convert.FromBase64String(cuerpo);
sheet.InsertArray(array, 1, 1, true);
wb.SaveToFile(AppDomain.CurrentDomain.BaseDirectory + "sample.xlsx", ExcelVersion.Version2013);
byte[] fileContent = File.ReadAllBytes(AppDomain.CurrentDomain.BaseDirectory + "sample.xlsx");
//File.Delete(AppDomain.CurrentDomain.BaseDirectory + "sample.xlsx");
return fileContent;
}
This code creates the XLSX file, but just inserts the byte[] into the excel file like an array, instead of converting the data.
Edit:
My problem is slightly different from that other question. I can't just read the original file and then save it again, since the file is in another server and can't access it. The best thing I can do is send the document body and parse it into byte[].
It also works if I can convert my byte[] into a XLS file and save it, then I could use the answer to the other similar question.
Workbook workbook = new Workbook();
workbook.LoadFromFile("Input.xls");
workbook.SaveToFile("Output.xlsx", ExcelVersion.Version2013);
This is not going to war as the two file types store data completely different. The data in the xls file is stored in a proprietary binary format and the xmls file data is stored in Open XML.
I did it, saved the byte[] into a XLS file, read it and saved it again into a XLSX file.
public byte[] ConvierteAXLSX(string cuerpo)
{
File.WriteAllBytes(AppDomain.CurrentDomain.BaseDirectory + "viejo.xls", Convert.FromBase64String(cuerpo));
Workbook workbook = new Workbook();
workbook.LoadFromFile(AppDomain.CurrentDomain.BaseDirectory + "viejo.xls");
workbook.SaveToFile(AppDomain.CurrentDomain.BaseDirectory + "nuevo.xlsx", ExcelVersion.Version2013);
byte[] fileContent = File.ReadAllBytes(AppDomain.CurrentDomain.BaseDirectory + "nuevo.xlsx");
File.Delete(AppDomain.CurrentDomain.BaseDirectory + "viejo.xls");
File.Delete(AppDomain.CurrentDomain.BaseDirectory + "nuevo.xlsx");
return fileContent;
}
Thanks for your help!
I'm trying to develop some kind of FTP program in school. The service they provided me to download files from their server only downloads one file at a time and if I try to download a folder it returns a blank file. How is it possible to create some kind of system to download the whole directory (even the files inside the directory of the selected directory)?
This is what I use to get the files:
foreach (ListViewItem cadaItem in listView2.SelectedItems)
{
string type = listView2.SelectedItems[0].SubItems[2].Text;
MessageBox.Show(type);
byte[] fileBytes = new byte[666666];
byte[] hash = new byte[666666];
if (type != "")
{
servDin.GetFileMD5Async("", "", Vars.pastaLocal + #"\" + cadaItem.Text, hash, fileBytes);
using (Stream file = File.OpenWrite(Vars.pastaLocal + #"\" + Convert.ToString(cadaItem.Text)))
{
file.Write(fileBytes, 0, fileBytes.Length);
}
}
I wanted to use a datatable to get the filenames and download the files from there. is it possible?
Thank You
In this method, I saved an excel file in a directory in that path, instead of writing the whole path, is there a way to make it short so it automatically saves in the debug file?
using (var file = File.Open("C:\\Users\\john\\Documents\\Visual Studio 2015\\Projects\\EXCEl PROJECT\\webform\\" + filename + ".xlsx",FileMode.Create))
{
ms.WriteTo(file); // copy the memory stream to the file stream
}
Use this property as your base directory. You may append to it as needed.
System.AppDomain.CurrentDomain.BaseDirectory
Sample:
using (var file = File.Open(AppDomain.CurrentDomain.BaseDirectory + "\\webform\\" + filename + ".xlsx", FileMode.Create))
{
ms.WriteTo(file); // copy the memory stream to the file stream
}
I'm using EPPlus to create an excel file on the server. The problem is that I wan't the file to be saved on the clients harddrive and when I the application up on a server I believe this will save the file on the server harddrive.
Is it possible to send this file back to the client/browser some how?
public void CreateAnnuityExcelSheet(List<Calculation> cList, FormCollection form, int DTCyear)
{
List<Calculation> newList = new List<Calculation>();
newList.Add(cList.First()); //Getting the values for the first row
var StartValue = newList[0].StartValue;
var radio = form["advanceOrArrears"];
string fileName = newList[0].CalculationName;
string path = #"C:\ExcelFiles\" + fileName + ".xlsx"; //Path for the file
FileInfo info = new FileInfo(path);
info.Directory.Create(); //If C:\ExcelFiles does not exist, create it
if (!info.Exists)
{
using (ExcelPackage package = new ExcelPackage(info))
{
ExcelWorksheet ws = package.Workbook.Worksheets.Add(fileName);
//Styles for the sheet
package.Save();
}
}
}
The easiest way would be to send the bytes as File to browser. If your library for creating Excel files allows you to save to stream (like for example ClosedXML does) then you can do in your MVC action
var stream = new MemoryStream();
workbook.SaveAs(stream);
stream.Position = 0;
return File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml", "file.xlsx");
If you can't save it to memory stream then save it to server's disc and then you can just pass file path and content type to return File().
I've used a httphandler for sending the byte file object to the browser.
This link should help, Generating a file, then launching a secure download
So save the file on the server then transmit it to the user in your controller:
return new FilePathResult(myFilePath,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")