Export DataTable to workbook - excel

i have exported my datatable as shown in the code below. It works fine when exporting the large data but when i try to open the xls file it prompt me this error :
"Excel found unreadable content in filename.xls. Do you want to recover the contents of this workbook? If you trust the source of this workbook, click Yes."
DataTable exportTable = Record.GetAll();
Workbook workbook = new Workbook();
Worksheet sheet = new Worksheet("Test");
for (int x = 0; x < exportTable.Columns.Count; x++)
{
sheet.Cells[0, x] = new Cell(exportTable.Columns[x].ColumnName.ToString());
}
for (int i = 0; i < exportTable.Rows.Count; i++)
{
for (int j = 0; j < exportTable.Columns.Count; j++)
{
sheet.Cells[(i + 1), j] = new Cell(exportTable.Rows[i][j].ToString());
}
}
workbook.Worksheets.Add(sheet);
workbook.Save(#"C:\temp1\Test.xls");
System.IO.FileInfo file = new System.IO.FileInfo(#"C:\temp1\Test.xls");
Response.ClearContent();
Response.AddHeader("Content-Disposition", "attachment; filename=" + file.Name);
Response.AddHeader("Content-Length", file.Length.ToString());
Response.ContentEncoding = System.Text.Encoding.UTF8;
Response.ContentType = "application/ms-excel";
Response.TransmitFile(file.FullName);
Response.End();

If you are using Excel 2010 or above ( I am not sure about 2007) the file will be saved as XLSX even if you set the extension to XLS. Change the extension to XLSX and it should be fine. Otherwise Excel will detect the difference between the extension and the file structure and will show the message above.

Related

EPPlus corrupt Excel file when having more than 65,530 rows

I'm running into an issue with EPPlus when there are more than 65,530 rows that have a column with a hyperlink. The example below is configured to create 65,530 rows. With this number it will create the Excel file correctly (not corrupt). Once you run it with anything over 65,530, the Excel file will be created but when you open it, Excel will report that is corrupt. Any ideas how to solve this issue?
try
{
int maxRowsToCreate = 65530; //-- no errors will be generated
//int maxRowsToCreate = 65531; //-- error will be generated. The Excel file will be created but will give an error when trying to open it.
string report = string.Format("D:\\temp\\hypelinkIssue-{0}.xlsx", maxRowsToCreate.ToString());
if (File.Exists(report))
{
File.Delete(report);
}
using (ExcelPackage pck = new ExcelPackage(new System.IO.FileInfo(report)))
{
//Add the Content sheet
var ws = pck.Workbook.Worksheets.Add("Catalog");
ws.View.ShowGridLines = true;
var namedStyle = pck.Workbook.Styles.CreateNamedStyle("HyperLink"); //This one is language dependent
namedStyle.Style.Font.UnderLine = true;
namedStyle.Style.Font.Color.SetColor(Color.Blue);
ws.Column(1).Width = 100;
int rowIndex = 0;
for (int i = 0; i < maxRowsToCreate; i++)
{
rowIndex += 1;
string fullFilePath = string.Format("D:\\temp\\{0}", Path.GetRandomFileName());
ws.Cells[rowIndex, 1].StyleName = "HyperLink";
ws.Cells[rowIndex, 1].Hyperlink = new Uri(string.Format(#"file:///{0}", fullFilePath));
ws.Cells[rowIndex, 1].Value = fullFilePath;
}
pck.Save();
}
System.Diagnostics.Process.Start(report);
}
catch (Exception ex)
{
throw ex;
}
The issue occurs when using ".Hyperlink". If instead I use ".Formula" and populate it with the "=HYPERLINK" Excel formula, it works fine. I was able to create 250k records with unique hyperlink using this approach. I did not try more than 250k but hopefully it will work fine.
Thanks for pointing me in the right direction.
/*
This only works with LESS than 65,530 hyperlinks
*/
ws.Cells[rowIndex, 1].StyleName = "HyperLink";
ws.Cells[rowIndex, 1].Hyperlink = new OfficeOpenXml.ExcelHyperLink(fullFilePath, ExcelHyperLink.UriSchemeFile);
ws.Cells[rowIndex, 1].Value = fullFilePath;
/*
This works with more that 65,530 hyperlinks
*/
string cellFormula = string.Format("=HYPERLINK(\"{0}\")", filePath);
ws.Cells[rowIndex, 1].Formula = cellFormula;
This is because Excel limits the amount of unique URLs in a file to 65,530. You should try to insert them as text, instead of a url.
For a possible solution, take a look at this answer.

Writing large object into excel is taking hell out of time. Any way to fix this?

I have a predefined format of an excel file and am writing my object into that excel which is taking lot of time and the application is going into stale mode.
I am using EpPlus library.
Please find the code below and let me know if I can make things better.
FileInfo fileInfo = new FileInfo(xslxpath);
using (ExcelPackage excelPackage = new ExcelPackage(fileInfo))
{
int excelRow = 2;
ExcelWorksheet worksheet1 = excelPackage.Workbook.Worksheets.First();
foreach (var rows in objDetails)
{
worksheet1.Cells[excelRow, 1].Value = rows.ID.ToString();
worksheet1.Cells[excelRow, 2].Value = rows.Name.ToString();
worksheet1.Cells[excelRow, 3].Value = rows.Days.ToString();
worksheet1.Cells[excelRow, 4].Value = rows.Amount.ToString();
worksheet1.Cells[excelRow, 5].Value = rows.Reason.ToString();
WriteToLogFile(LogFile, excelRow.ToString() + " " + rows.IPNumber.ToString());
worksheet1.Cells.AutoFitColumns();
excelRow++;
WriteToLogFile(LogFile, excelRow.ToString() + " " + rows.IPNumber.ToString());
}
excelPackage.Save();
}
worksheet1.Cells.AutoFitColumns();
You should call this once after your loop, not for each and every line.

Reading images from all excel worksheets using Apache POI

I am trying to copy all the images from all the worksheets from an existing excel file to a new excel file. For this, I read all the sheets from the existing excel file and copy the images to the new excel file. The following code accesses all the sheets and tries to copy all the images to the new sheet.
public static void modifyExcelFile(XSSFWorkbook xssfWorkbook) throws InvalidFormatException, IOException, XmlException{
String newFileName = "outputexcelfile.xlsx";
XSSFWorkbook dest = new XSSFWorkbook("test.xlsx");
int numSheets = xssfWorkbook.getNumberOfSheets();
// clone the template sheet additional number of times required
for(int i=1; i<numSheets; i++){
dest.cloneSheet(0);
}
for(int i=0; i<numSheets; i++) {
XSSFSheet destSheet = dest.getSheetAt(i);
dest.setSheetName(i, xssfWorkbook.getSheetName(i));
XSSFSheet sheet = xssfWorkbook.getSheetAt(i);
// copy images
System.out.println("Copying images ...");
copyImages(sheet, destSheet);
}
writeFile(dest, newFileName);
}
test.xlsx is the template file with only one sheet. The following copyImages function tries to copy all the images from one sheet to the other.
public static void copyImages(XSSFSheet from, XSSFSheet to) throws IOException, XmlException, InvalidFormatException{
Drawing drawingPatriarch = to.createDrawingPatriarch();
XSSFWorkbook destWorkbook = to.getWorkbook();
// Add image
for (POIXMLDocumentPart pdp : from.getRelations()) {
if (!XSSFRelation.DRAWINGS.getRelation().equals(pdp.getPackageRelationship().getRelationshipType())) continue;
PackagePart drawPP = pdp.getPackagePart();
WsDrDocument draw = WsDrDocument.Factory.parse(drawPP.getInputStream());
for (CTTwoCellAnchor twoAnc : draw.getWsDr().getTwoCellAnchorList()) {
String picId = twoAnc.getPic().getBlipFill().getBlip().getEmbed();
PackageRelationship pr = drawPP.getRelationship(picId);
PackagePart imgPP = drawPP.getRelatedPart(pr);
System.out.println(imgPP.getPartName() + ": contentType: " + imgPP.getContentType() + " size: " + imgPP.getSize()
+ ": picId: " + picId
+" - Col1: "+twoAnc.getFrom().getCol()
+" - Row1: "+twoAnc.getFrom().getRow()
+" - Col2: "+twoAnc.getTo().getCol()
+" - Row2: "+twoAnc.getTo().getRow()
);
// skip the logo
if(twoAnc.getFrom().getCol()==0 && twoAnc.getFrom().getRow()==0)
continue;
try {
InputStream is = imgPP.getInputStream();
byte[] bytes = IOUtils.toByteArray(is);
int pictureIdx = destWorkbook.addPicture(bytes, Workbook.PICTURE_TYPE_PNG);
is.close();
CreationHelper helper = destWorkbook.getCreationHelper();
//add a picture shape
ClientAnchor anchor = helper.createClientAnchor();
//set top-left corner of the picture,
anchor.setCol1(twoAnc.getFrom().getCol());
anchor.setRow1(twoAnc.getFrom().getRow());
anchor.setRow2(twoAnc.getTo().getRow());
anchor.setCol2(twoAnc.getTo().getCol());
Picture pict = drawingPatriarch.createPicture(anchor, pictureIdx);
}catch(IOException ioEx){
System.out.println("Failed to add icons. Details: " + ioEx.getMessage());
}
}
}
}
But if I run the code, it only copies images from the first sheet successfully. For all other sheets, images are not there. The code runs successfully without any errors. Any help is greatly appreciated. Thanks!
Just adding pict.resize(); function call after the Picture pict=... fixes the issue. So the modified code looks like the following:
Picture pict = drawingPatriarch.createPicture(anchor, pictureIdx);
pict.resize();
Not sure why it doesn't work without the resize() call.

how to display an excel spreadsheet on browser using jsps.?

i had a excel sheet which is coming to a jsp from the servlet. Can someone help me of how to write a jsp page to display the excel contents in the browser.
Thanks in advance.
If the excel is not changing the structure dynamically, I recommend you to build a set of objects and parse these information in the server, and then in the jsp read these objects to build an html table with this set of objects.
You can load an Excel file with the class HSSFWorkbook or XSSFWorkbook, and then loop to the rows and cells for building your objects.
Please have a look at the examples of Apache Poi here
You can do something like this...
if(sheet.getPhysicalNumberOfRows() > 0) {
lastRowNum = sheet.getLastRowNum();
for(int j = 0; j <= lastRowNum; j++) {
row = sheet.getRow(j);
lastCellNum = row.getLastCellNum();
for(int i = 0; i <= lastCellNum; i++) {
cell = row.getCell(i);
if(cell == null) {
csvLine.add("");
}
else { //set your properties here...
}
}
}
}

Get Excel SheetNames using POI jar

I need all Excel sheet Names (what r all contains the datas) using POI jar.
Like jxl jar - getSheetNames()
You don't say how you want them, so I'll guess at a list. You just need to iterate over the sheet indicies, getting the name for each. Your code would be something like:
File myFile = new File("/path/to/excel.xls");
Workbook wb = WorkbookFactory.create(myFile);
List<String> sheetNames = new ArrayList<String>();
for (int i=0; i<wb.getNumberOfSheets(); i++) {
sheetNames.add( wb.getSheetName(i) );
}
FileInputStream fis = new FileInputStream("C:\Users\Usr\Desktop\TestData.xlsx");
XSSFWorkbook wb = new XSSFWorkbook(fis);
int sheetcount = wb.getNumberOfSheets();
System.out.println("sheetcount: "+sheetcount);
for(int i=0; i<sheetcount;i++)
{
System.out.print(wb.getSheetName(i)+ " ");
}

Resources