I'm trying to create an excel file and make that available as download. But i have some trouble with the download part.
I'm using EPPlus to create an xml file. I've got that working. But just local. I'm not sure how to force the download of the file.
This is my code:
public Stream GetXlsxDocument(IQueryable data)
{
const string sheetName = "Sheet1";
var localFile = new FileInfo(#"C:\test2.xlsx");
var file = new FileInfo("test2.xlsx");
// Used for local creation
//ExcelPackage p = new ExcelPackage();
MemoryStream stream = new MemoryStream();
using (ExcelPackage p = new ExcelPackage(stream))
{
p.Workbook.Worksheets.Add("Sheet1");
ExcelWorksheet ws = p.Workbook.Worksheets[1];
ws.Name = sheetName;
ws.Cells.Style.Font.Size = 11;
ws.Cells.Style.Font.Name = "Calibri";
ws.SetValue(1, 1, "aaa"); // Test data
// Used for local creation
//p.SaveAs(localFile);
p.SaveAs(stream);
}
return stream;
}
Like i said before. Creating the xlsx file locally on my C:\ disk works. But how can i force the download of the created xlsx file?
Right now its giving me an xlsx file of 0 bytes. I'd need to return a stream which isn't empty. Anyone any idea how i can do this..??
rewind it:
stream.Position = 0;
return stream;
Related
public static byte[] AddDataToPredifinedFormat(string path, string sheetName = "")
{
byte[] fileBytes = null;
var employee = new List<Employee>
{
new Employee{Name = "XYZ", Number = "12345"},
new Employee{Name = "ABC", Number = "12345"}
};
try
{
using (MemoryStream ms = new MemoryStream())
{
using (SpreadsheetDocument document = SpreadsheetDocument.Open(ms, false))
{
WorkbookPart wbPart = document.WorkbookPart;
IEnumerable<Sheet> sheets = wbPart.Workbook.GetFirstChild<Sheets>().Elements<Sheet>();
string sheetId = sheetName != "" ? sheets.Where(q => q.Name == sheetName).First().Id.Value : sheets.First().Id.Value;
WorksheetPart wsPart = (WorksheetPart)wbPart.GetPartById(sheetId);
SheetData sheetData = wsPart.Worksheet.GetFirstChild<SheetData>();
foreach (var x in employee)
{
Row newRow = new Row();
Cell cell = new Cell();
cell.CellValue = new CellValue(x.Name.ToString());
cell.StyleIndex = 0;
newRow.AppendChild(cell);
sheetData.AppendChild(newRow);
}
wbPart.Workbook.Save(ms);
fileBytes = ms.ToArray();
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return fileBytes;
}
Reading the existing file and appending rows but on downloading the file, Excel app shows it's corrupted.
Using OpenXML read the existing file and append some rows with data, then return it as bytes so as to download the form
I think in order to return the sheet you need to need to refactor code a little. Instead of expecting the memory stream to write directly to array and download file wont help,
What i did is in my code:
Write data to stream and read that back. So you need to return the updated stream
Write the stream data to ExcelPackage
Something like this
using OfficeOpenXml;
Stream stream = new MemoryStream(<process and return your steam>);
using (ExcelPackage package = new ExcelPackage(stream))
{
//write any more extra data to sheet
return package.GetAsByteArray();
}
Important bit to notice is : package.GetAsByteArray();
Can you try moving fileBytes = ms.ToArray(); to outside of the inner using block?
I have very similar code to this for modifying WordprocessingDocuments with OpenXML but I don't use MemoryStream. I File.Copy the original to a temporary file, modify, save and then load the byte[] from the temporary file for streaming.
I am trying to download a zip file from SFTP and unzip in the memory to process the file
I am using SSH.Net to download the file.
private static void processfilesfromftp(List<TSOracleMicrosDownLoadSetUp> list)
{
SftpClient sftp = HelperFunctions.GetClientConnection();
if(sftp.IsConnected)
{
var files = sftp.ListDirectory("/");
ZipFile zips = new ZipFile();
string path = string.Empty;
foreach(var file in files)
{
Stream unzippedEntryStream = new MemoryStream();
path = string.Format("/{0}", file.Name);
//byte[] arr = sftp.ReadAllBytes(file.FullName);
var stream = new BufferedStream(sftp.OpenRead(file.FullName));
//System.IO.TextReader textReader = new System.IO.StreamReader(stream);
//System.IO.MemoryStream mStream = new MemoryStream();
using (ZipFile zip = ZipFile.Read(stream))
{
ZipEntry e = zip[0];
e.Extract(unzippedEntryStream);
System.IO.TextReader textReader = new System.IO.StreamReader(unzippedEntryStream);
string data = textReader.ReadToEnd();
}
}
}
}
memorystream throw error System.InvalidOperationException exception at
var stream = new BufferedStream(sftp.OpenRead(file.FullName));
Update
It is not throwing any error, but the final output of the unzip file is empty.
Using Framework 4.5.2 and Visual studio 2017
This is more a SSH.Net question and not specific Acumatica.
It seems the problem is related to the SSH connection.
To change the timeout you can use SshClient.ConnectionInfo.Timeout. But you need to catch the exception and handle it gracefully.
Here is a post with a similar issue.
BTW, you could use the included Acumatica library to read the zip file.
I think you are not writing the file from FTP to the memory stream so it's empty.
Try using the DownloadFile method from SSH.Net to write file content in the stream.
Reference:
https://stackoverflow.com/a/46907346/7376238
SftpClient _sftpClient;
_sftpClient = new SftpClient("sftp.server.domain", "MyLoginHere", "MyPasswordHere");
Stream fileBody = new MemoryStream();
_sftpClient.DownloadFile(ftpFile.FullName, fileBody);
fileBody.Position = 0;
I am creating excel and filling values into it. i am using EPPlus.
I can save it using filestream and open it.
but i want to open it without saving.
I thought we can use memorystream in some way to generate the excel directly.
Please guide.
try
{
MemoryStream newFile = new MemoryStream();
using (ExcelPackage package = new ExcelPackage(newFile))
{
// Add Data Collection worksheet
ExcelWorksheet dataWorksheet = package.Workbook.Worksheets.Add("Sheet1");
dataWorksheet.Cells[1, 1].Value = " My Text";
dataWorksheet.Cells[1, 1].Style.Font.Size = 14;
dataWorksheet.Cells[3, 1].Value = BALGlobalVariables.cocName;
dataWorksheet.Cells[5, 1].Value = "IR From Date :";
dataWorksheet.Cells[6, 1].Value = "IR To Date : ";
dataWorksheet.Cells[5, 6].Value = "From Date :";
dataWorksheet.Cells[6, 6].Value = "To Date : ";
dataWorksheet.Cells[5, 2].Value = fromDate;
dataWorksheet.Cells[6, 2].Value = toDate;
dataWorksheet.Cells[5, 7].Value = invFromDate;
dataWorksheet.Cells[6, 7].Value = invFromDate;
// Template specific excel generation goes in here
FillPurchaseExcelData(ref dataWorksheet, masterTable, subTable);
// save package
package.Save();
}
byte[] fileContent = newFile.ToArray();
#if DEBUG
string tempName = "MTemp.xlsx";
string tempFileName = System.IO.Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]) + #"\" + tempName;
//Write the stream data of workbook to the root directory
using (FileStream file = new FileStream(tempFileName, FileMode.Create))
{
file.Write(fileContent, 0, fileContent.Length);
}
System.Diagnostics.Process.Start(tempFileName);
You can generate excel file and choose not to save it, but Excel can't open files that are not saved on disk (it becomes a 'file' when it's on disk), so in short - you have to save document in order to open it in Excel.
If you're concerned about storing data on hard drive, as an alternative you could create a data source on a medium you trust, and then create an xslx that would instruct Excel to consume that data source when opening worksheet (instead of creating a file pre-filled with data). But this is a whole other story...
So I'm using the fancy EPPlus library to write an Excel file and output it to the user to download. For the following method I'm just using some test data to minimize on the code, then I'll add the code I'm using to connect to database later. Now I can download a file all fine, but when I go to open the file, Excel complains that it's not a valid file and might be corrupted. When I go to look at the file, it says it's 0KB big. So my question is, where am I going wrong? I'm assuming it's with the MemoryStream. Haven't done much work with streams before so I'm not exactly sure what to use here. Any help would be appreciated!
[Authorize]
public ActionResult Download_PERS936AB()
{
ExcelPackage pck = new ExcelPackage();
var ws = pck.Workbook.Worksheets.Add("Sample1");
ws.Cells["A1"].Value = "Sample 1";
ws.Cells["A1"].Style.Font.Bold = true;
var shape = ws.Drawings.AddShape("Shape1", eShapeStyle.Rect);
shape.SetPosition(50, 200);
shape.SetSize(200, 100);
shape.Text = "Sample 1 text text text";
var memorystream = new MemoryStream();
pck.SaveAs(memorystream);
return new FileStreamResult(memorystream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") { FileDownloadName = "PERS936AB.xlsx" };
}
Here's what I'm using - I've been using this for several months now and haven't had an issue:
public ActionResult ChargeSummaryData(ChargeSummaryRptParams rptParams)
{
var fileDownloadName = "sample.xlsx";
var contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
var package = CreatePivotTable(rptParams);
var fileStream = new MemoryStream();
package.SaveAs(fileStream);
fileStream.Position = 0;
var fsr = new FileStreamResult(fileStream, contentType);
fsr.FileDownloadName = fileDownloadName;
return fsr;
}
One thing I noticed right off the bat is that you don't reset your file stream position back to 0.
I am new to this Open Office XML and I was wondering what file extension the XLPackage takes.
For example I assumed I just needed to input the file location of a CSV file I am using, but it does not work, do I have to convert the file to .xlsx or is there something other then the XLPackage that I should use?
The problem is that once it gets to the using a new OpenDialog is initiated and I cant find my file. I am probably just missing something obvious. File Contains Corrupt data, FileFormatException, I assume I need to convert the file before use?
I appreciate any feedback.
Some code:
FileInfo existingFile = new FileInfo(eFilePath);
using (ExcelPackage xlPackage = new ExcelPackage(existingFile)) // I think the issue is here.
{
ExcelWorksheet exeedSheet = xlPackage.Workbook.Worksheets[1];
//Total rows
for (int row = 1; row > 0; )
If you are working with a CSV the ExcelPackage is overkill for what you are doing.
CSV:
using (var Sr = new StreamReader("\\SomeCoolFile.CSV"))
{
var text = Sr.ReadToEnd();
Sr.Close();
text = text.Replace("\n", string.Empty);
var lines = text.Split('\r');
var info = lines.Select(line => line.Split(',')).ToList();
......
}
ExcelPackage:
using (var fs = new FileStream("\\SomeCoolFile.xlsx", FileMode.Open))
{
using (var package = new ExcelPackage(fs))
{
var workBook = package.Workbook;
.....
}
}