I have the below code to save the data in excel sheet as .xls
public ActionResult ExportToExcel()
{
DataTable tbl = CopyGenericToDataTable(res);
tbl.TableName = "InvalidInvoices";
using (XLWorkbook wb = new XLWorkbook())
{
wb.Worksheets.Add(tbl);
wb.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
wb.Style.Font.Bold = true;
Response.Clear();
Response.Buffer = true;
Response.Charset = "";
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment;filename= "+fileName + ".xls");
using (MemoryStream MyMemoryStream = new MemoryStream())
{
wb.SaveAs(MyMemoryStream);
MyMemoryStream.WriteTo(Response.OutputStream);
Response.Flush();
Response.End();
}
}
}
Above is code which download the xls excel sheet at client side. It works fine the data gets saved in excel sheet.
Problem is if I try to upload this same file using below code -
if (files != null)
{
HttpPostedFileBase upload = files.FirstOrDefault();
Stream stream = upload.InputStream;
DataSet result = new DataSet();
if (upload != null && upload.ContentLength > 0)
{
if (upload.FileName.EndsWith(".xls") || upload.FileName.EndsWith(".xlsx"))
{
// ExcelDataReader works with the binary Excel file, so it needs a FileStream
// to get started. This is how we avoid dependencies on ACE or Interop:
// We return the interface, so that
IExcelDataReader reader = null;
if (upload.FileName.EndsWith(".xls"))
{
reader = ExcelReaderFactory.CreateBinaryReader(stream);
}
else if (upload.FileName.EndsWith(".xlsx"))
{
reader = ExcelReaderFactory.CreateOpenXmlReader(stream);
}
reader.IsFirstRowAsColumnNames = false;
result = reader.AsDataSet();
reader.Close();
}
}
}
In above code I am getting error in ExcelReaderFactory.CreateBinaryReader(stream);
In stream it has the values in bytes too just on using createBinaryreader of excelreaderfactory reader has error message as 'Invalid file signature'.
Any help will be highly appreciated.
ClosedXML generates .xlsx files, not .xls files.
Check your code:
Response.AddHeader("content-disposition", "attachment;filename= "+fileName + ".xls");
Related
I want to convert .xlsx file to html using NPOI. Is this possible? I know , xls to html conversion is available using NPOI. But not sure if NPOI provide option to convert .xlsx file to html also. Thanks
You can use ExcelToHtmlConverter. It has method ProcessWorkbook which accepts IWorkbook as a parameter. So it can be used to convert either HSSFWorkbook (xls) or XSSFWorkbook (xlsx).
public void ConvertXlsxToHtml()
{
XSSFWorkbook xssfwb;
var fileName = #"c:\temp\test.xlsx";
using (FileStream file = new FileStream(fileName, FileMode.Open, FileAccess.Read))
{
xssfwb = new XSSFWorkbook(file);
ExcelToHtmlConverter excelToHtmlConverter = new ExcelToHtmlConverter();
//set output parameter
excelToHtmlConverter.OutputColumnHeaders = false;
excelToHtmlConverter.OutputHiddenColumns = true;
excelToHtmlConverter.OutputHiddenRows = true;
excelToHtmlConverter.OutputLeadingSpacesAsNonBreaking = false;
excelToHtmlConverter.OutputRowNumbers = false;
excelToHtmlConverter.UseDivsToSpan = true;
//process the excel file
excelToHtmlConverter.ProcessWorkbook(xssfwb);
//output the html file
excelToHtmlConverter.Document.Save(Path.ChangeExtension(fileName, "html"));
}
}
I was trying to make a rest endpoint in Spring Boot which reads from DB, generates an excel file(Using Apache POI) which is returned to the user using HttpServletResponse but when I invoke this, the excel is getting created but it's not downloading. I had some other code earlier in place which was working fine but I accidentally removed that and now I'm stuck. Any help/leads are appreciated.
#RequestMapping(path = "/save", method = RequestMethod.GET)
public ResponseEntity<String> saveToXls(#RequestParam String id, #RequestParam String appName, HttpServletResponse response) {
AppInstance appInstance = appInstanceRepo.get(id);
List<DownloadDetail> downloadDetailList = downloadDAO.searchByInstanceId(id);
//List<DownloadDetail> downloadDetailList = appInstance.getDownloads();
System.out.print("LIST SIZE:" + downloadDetailList.size());
String fileName = appName + " report";
File myFile = new File(fileName + ".xls");
FileOutputStream fileOut;
downloadDetailList.forEach(downloadDetail -> System.out.print(downloadDetail.getSid()));
try {
try (HSSFWorkbook workbook = new HSSFWorkbook()) {
HSSFSheet sheet = workbook.createSheet("lawix10");
HSSFRow rowhead = sheet.createRow((short) 0);
rowhead.createCell((short) 0).setCellValue("SID");
rowhead.createCell((short) 1).setCellValue("Download Time");
rowhead.createCell((short) 2).setCellValue("OS Version");
int i = 0;
for (DownloadDetail downloadDetail : downloadDetailList) {
System.out.print("In loop -2");
HSSFRow row = sheet.createRow((short) i);
row.createCell((short) 0).setCellValue(downloadDetail.getSid());
row.createCell((short) 1).setCellValue(downloadDetail.getDownloadTime());
row.createCell((short) 2).setCellValue(downloadDetail.getOsVersion());
i++;
}
fileOut = new FileOutputStream(myFile);
workbook.write(fileOut);
}
fileOut.close();
byte[] buffer = new byte[10240];
response.addHeader("Content-disposition", "attachment; filename=test.xls");
response.setContentType("application/vnd.ms-excel");
try (
InputStream input = new FileInputStream(myFile);
OutputStream output = response.getOutputStream();
) {
for (int length = 0; (length = input.read(buffer)) > 0;) {
output.write(buffer, 0, length);
}
}
response.flushBuffer();
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
return null;
}
EDIT:
I tried to do it another way as shown below:
try (InputStream is = new FileInputStream(myFile)) {
response.addHeader("Content-disposition", "attachment; filename=test.xls");
response.setContentType("application/vnd.ms-excel");
IOUtils.copy(is, response.getOutputStream());
}
response.flushBuffer();
This also doesn't seem to cut it.
This is a my example. Probably the issue is how you manage the OutputStream:
ServletOutputStream os = response.getOutputStream();
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment; filename=\""+fileName+".xls\"");
workbook = excelStrategyMap.get(strategy).export(idList, status, params);
workbook.write(os);
workbook.close();
os.flush();
response.flushBuffer();
Once you get the workbook file, set the file name and file type. and add the response header and content type as mentioned below.
Then write the file to the response and flush it's buffer.
XSSFWorkbook file = excelUploadService.downloadDocument();
String filename = "Export.xlsx";
String filetype = "xlsx";
response.addHeader("Content-disposition", "attachment;filename=" + filename);
response.setContentType(filetype);
// Copy the stream to the response's output stream.
file.write(response.getOutputStream());
response.flushBuffer();
In the client side, get the response from the REST API and set the content type received by the response object. Using FileSaver library save the file into your local file system.
Here is the documentation for FileSaver js -- File saver JS Library
var type = response.headers("Content-Type");
var blob = new Blob([response.data], {type: type});
saveAs(blob, 'Export Data'+ '.xlsx');
#GetMapping(value = "/", produces = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
#ResponseBody
public byte[] generateExcel() {
byte[] res = statisticsService.generateExcel();
return res;
The file you are trying is in a different format than specified by the file extension.Verify that the file is not corrupted and is from a trusted source before opening the file.Do you want to open the file now?
and this 'export to excel' dead the events on the page.
Here is my code
public void ExportToExcelitems(DataTable dt, string fileNameWithoutExt)
{
if (dt.Rows.Count > 0)
{
string filename = fileNameWithoutExt + ".xls";
System.IO.StringWriter tw = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter hw = new System.Web.UI.HtmlTextWriter(tw);
var dgGrid = new GridView();
dgGrid.DataSource = dt;
dgGrid.DataBind();
dgGrid.HeaderRow.BackColor = System.Drawing.Color.White;
dgGrid.HeaderRow.BackColor = System.Drawing.Color.White;
foreach (GridViewRow row in dgGrid.Rows)
{
row.BackColor = System.Drawing.Color.White;
foreach (TableCell cell in row.Cells)
{
if (row.RowIndex % 2 == 0)
{
cell.BackColor = dgGrid.RowStyle.BackColor;
}
else
{
cell.BackColor = System.Drawing.Color.LightGray;
}
}
}
dgGrid.AutoGenerateColumns = false;
dgGrid.RenderControl(hw);
HttpContext.Current.Response.ContentType = "application/vnd.ms-excel";
HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment; filename=" + filename + "");
this.EnableViewState = false;
HttpContext.Current.Response.Write(tw.ToString());
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.Close();
}
}
I think you should consider using OpenXML (or more specfically ClosedXML) to build a modern Excel file with the xlsx extension.
Open XML SDK: https://learn.microsoft.com/en-us/office/open-xml/open-xml-sdk
Closed XML (nuget): https://www.nuget.org/packages/ClosedXML/
Code Samples: https://github.com/ClosedXML/ClosedXML/wiki/Deliver-an-Excel-file-in-ASP.NET
I am trying to load the XLSX file using POI library that has 5 sheets. Size of the file is 5 MB. Total records in all sheets are around 30,000.
Once the file is loaded i need to delete the 1 or more sheets on the fly based on sheet neame as input.
Here is the snippet.
public void generateReportWorkBook(String[] requestedReports) throws Exception {
// Read the file
String dailyTicketReport = ReportConstants.REPORT_PATH + ReportConstants.FILE_NAME + ReportConstants.XLSX_FILE_EXTN;
FileInputStream fis = null;
XSSFWorkbook book = null;
try {
fis = new FileInputStream(dailyTicketReport);
book = new XSSFWorkbook(fis);
for (int i = book.getNumberOfSheets() - 1; i >= 0; i--) {
XSSFSheet tmpSheet = book.getSheetAt(i);
if (!ArrayUtils.contains(requestedReports, tmpSheet.getSheetName())) {
book.removeSheetAt(i);
}
}
} catch (Exception e) {
logger.error("Error occured while removing the sheets from workbook");
throw e;
} finally {
IOUtils.closeQuietly(fis);
}
}
When i execute the program. I get OutofMemory Exception.
How can i remove the sheets without memory issue.
I too faced the same issue of OOM while parsing xlsx file...after two days of struggle, I finally found out the below code that was really perfect;
This code is based on sjxlsx. It reads the xlsx and stores in a HSSF sheet.
// read the xlsx file
SimpleXLSXWorkbook = new SimpleXLSXWorkbook(new File("C:/test.xlsx"));
HSSFWorkbook hsfWorkbook = new HSSFWorkbook();
org.apache.poi.ss.usermodel.Sheet hsfSheet = hsfWorkbook.createSheet();
Sheet sheetToRead = workbook.getSheet(0, false);
SheetRowReader reader = sheetToRead.newReader();
Cell[] row;
int rowPos = 0;
while ((row = reader.readRow()) != null) {
org.apache.poi.ss.usermodel.Row hfsRow = hsfSheet.createRow(rowPos);
int cellPos = 0;
for (Cell cell : row) {
if(cell != null){
org.apache.poi.ss.usermodel.Cell hfsCell = hfsRow.createCell(cellPos);
hfsCell.setCellType(org.apache.poi.ss.usermodel.Cell.CELL_TYPE_STRING);
hfsCell.setCellValue(cell.getValue());
}
cellPos++;
}
rowPos++;
}
return hsfSheet;
I'm developing a rather simple visual WebPart for SharePoint Foundation Server 2010.
It's supposed to upload an image file to the SharePoint server and display it afterwards.
While I can successfully upload the file to a previously created document library, the file cannot be displayed (IE shows the red cross). When I upload an exact copy of the file using SharePoint frontend, it can be opened. I hope that someone can tell me what I'm missing.
Below you can find the code that successfully uploads a file to the server:
SPContext.Current.Web.AllowUnsafeUpdates = true;
string path = "";
string[] fileName = filePath.PostedFile.FileName.Split('\\');
int length = fileName.Length;
// get the name of file from path
string file = fileName[length - 1];
SPWeb web = SPContext.Current.Web;
SPFolderCollection folders = web.Folders;
SPFolder folder;
SPListCollection lists = web.Lists;
SPDocumentLibrary library;
SPList list = null;
Guid guid = Guid.Empty;
if (lists.Cast<SPList>().Any(l => string.Equals(l.Title, "SPUserAccountDetails-UserImages")))
{
list = lists["SPUserAccountDetails-UserImages"];
}
else
{
guid = lists.Add("SPUserAccountDetails-UserImages", "Enthält Mitarbeiter-Fotos", SPListTemplateType.DocumentLibrary);
list = web.Lists[guid];
}
library = (SPDocumentLibrary)list;
folder = library.RootFolder.SubFolders.Add("SPUserAccountDetails");
SPFileCollection files = folder.Files;
Stream fStream = filePath.PostedFile.InputStream;
byte[] MyData = new byte[fStream.Length];
Stream stream = new MemoryStream();
stream.Read(MyData, 0, (int)fStream.Length);
fStream.Close();
bool bolFileAdd = true;
for (int i = 0; i < files.Count; i++)
{
SPFile tempFile = files[i];
if (tempFile.Name == file)
{
folder.Files.Delete(file);
bolFileAdd = true;
break;
}
}
if (bolFileAdd)
{
SPFile f = files.Add(file, MyData);
f.Item["ContentTypeId"] = "image/jpeg";
f.Item["Title"] = file;
f.Item.SystemUpdate();
SPContext.Current.Web.AllowUnsafeUpdates = false;
imgPhoto.ImageUrl = (string)f.Item[SPBuiltInFieldId.EncodedAbsUrl];
}
Never mind. My code seems to mess with the file content. I'll post the solution later.
edit:
I'm stupid and sorry :-/
I replaced this:
Stream fStream = filePath.PostedFile.InputStream;
byte[] MyData = new byte[fStream.Length];
Stream stream = new MemoryStream();
stream.Read(MyData, 0, (int)fStream.Length);
fStream.Close();
with this:
Stream fStream = filePath.PostedFile.InputStream;
byte[] MyData = new byte[fStream.Length];
BinaryReader binaryReader = new BinaryReader(fStream);
MyData = binaryReader.ReadBytes((Int32)fStream.Length);
fStream.Close();
binaryReader.Close();
and suddenly it all worked ;-)