asp.net open xml to download .xlsx file - asp.net

I'm trying to supply a .xlsx file from a grid, I think most of the hard work is done. I'm picking up a template file and filling it with data.
I' getting an error 'file not found' on Response.WriteFile.
by the looks of the example (linked below) this should just be the intended file name, but I imagine this needs to be a path to the file?, so do I need to save my 'myDoc' object to the server and then provide the path in the Reponse.WriteFile.
It doesn't seem like that is what is meant by the example.
the code i'm using is a modified version of : http://technet.weblineindia.com/web/export-data-to-excel-using-openxml-sdk/
due to using sharepoint to store the template file I just had to create a filestream rather than supply the URL to the file.
here is my code:
// Create cell reference array
string[] CellReferenceArray = new string[] { "A", "B", "C", "D", "E" };
//Open your saved excel file that you have created using template file.
using (SpreadsheetDocument myDoc = SpreadsheetDocument.Open(file.OpenBinaryStream(), true))
{
// Create reference of main Workbook part, which contains all reference.
WorkbookPart objworkbook = myDoc.WorkbookPart;
// Create style sheet object that will be used for applying styling.
Stylesheet objstyleSheet = objworkbook.WorkbookStylesPart.Stylesheet;
// pick up first worksheet
WorksheetPart objworksheet = objworkbook.WorksheetParts.First();
// will be used in end while creating sheet data
string objorigninalSheetId = objworkbook.GetIdOfPart(objworksheet);
WorksheetPart objreplacementPart = objworkbook.AddNewPart<WorksheetPart>();
string objreplacementPartId = objworkbook.GetIdOfPart(objreplacementPart);
// Create object reader to read from excel file.
OpenXmlReader objreader = OpenXmlReader.Create(objworksheet);
// create writer object to write in excel sheet.
OpenXmlWriter objOpenXmwriter = OpenXmlWriter.Create(objreplacementPart);
int i = 1;
Row r = new Row();
Cell c = new Cell();
Columns col1 = new Columns();
UInt32 index = 0;
while (objreader.Read())
{
if (objreader.ElementType == typeof(SheetData))
{
if (objreader.IsEndElement)
continue;
objOpenXmwriter.WriteStartElement(new SheetData());
objOpenXmwriter.WriteStartElement(r);
// Loop to insert header
foreach (DataColumn colHead in YoutdTName.Columns)
{
c = new Cell
{
DataType = CellValues.String,
CellReference = CellReferenceArray[i] + Convert.ToString(index)
};
CellValue v1 = new CellValue(colHead.ColumnName.ToString());
c.Append(v1);
objOpenXmwriter.WriteElement(c);
i += 1;
}
objOpenXmwriter.WriteEndElement();
index += 1;
//Loop to insert datatable row in excel
foreach (DataRow dr in YoutdTName.Rows)
{
objOpenXmwriter.WriteStartElement(r);
i = 1;
foreach (DataColumn col in YoutdTName.Columns)
{
c = new Cell
{
DataType = CellValues.String,
CellReference = CellReferenceArray[i] + Convert.ToString(index)
};
CellValue v1 = new CellValue(dr[col].ToString());
c.AppendChild(v1);
objOpenXmwriter.WriteElement(c);
i += 1;
}
objOpenXmwriter.WriteEndElement();
index += 1;
}
objOpenXmwriter.WriteEndElement();
}
}
//close all objects
objreader.Close();
objOpenXmwriter.Close();
Sheet sheet = objworkbook.Workbook.Descendants<Sheet>().Where(s => s.Id.Value.Equals(objorigninalSheetId)).First();
sheet.Id.Value = objreplacementPartId;
objworkbook.DeletePart(objworksheet);
}
Response.AddHeader("Content-Disposition", "inline;filename=YourExcelfileName.xlxs");
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.WriteFile("YourExcelfileName.xlxs");
Response.Flush();
Response.End();
}

Use HttpResponse.BinaryWrite instead and take the underlying stream from your SpreadsheetDocument-instance .
http://msdn.microsoft.com/en-us/library/system.web.httpresponse.binarywrite(v=vs.110).aspx

Related

Make the Title row in grey background with Blue fonts after convert json to excel

I have developed a json to csv file download function everything works fine but I'm not sure how to make the first row of the table which are "Vehicle, Date, Location, Speed" background color in lightgrey and font in blue and always expand the columns upon opening the file
Here is the fiddle http://jsfiddle.net/harvindr/v5cw94u8/1/
function JSONToCSVConvertor(JSONData, ReportTitle, ShowLabel) {
//If JSONData is not an object then JSON.parse will parse the JSON string in an Object
var arrData = typeof JSONData != 'object' ? JSON.parse(JSONData) : JSONData;
var CSV = '';
//Set Report title in first row or line
CSV += ReportTitle + '\r\n\n';
//This condition will generate the Label/Header
if (ShowLabel) {
var row = "";
//This loop will extract the label from 1st index of on array
for (var index in arrData[0]) {
//Now convert each value to string and comma-seprated
row += index + ',';
}
row = row.slice(0, -1);
//append Label row with line break
CSV += row + '\r\n';
}
//1st loop is to extract each row
for (var i = 0; i < arrData.length; i++) {
var row = "";
//2nd loop will extract each column and convert it in string comma-seprated
for (var index in arrData[i]) {
row += '"' + arrData[i][index] + '",';
}
row.slice(0, row.length - 1);
//add a line break after each row
CSV += row + '\r\n';
}
if (CSV == '') {
alert("Invalid data");
return;
}
//Generate a file name
// var fileName = "MyReport_";
//this will remove the blank-spaces from the title and replace it with an underscore
// fileName += ReportTitle.replace(/ /g,"_");
//Initialize file format you want csv or xls
var uri = 'data:text/csv;charset=utf-8,' + escape(CSV);
// Now the little tricky part.
// you can use either>> window.open(uri);
// but this will not work in some browsers
// or you will not get the correct file extension
//this trick will generate a temp <a /> tag
var link = document.createElement("a");
link.href = uri;
//set the visibility hidden so it will not effect on your web-layout
link.style = "visibility:hidden";
link.download = "PrognosData.csv";
//this part will append the anchor tag and remove it after automatic click
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}

OpenXML Excel File Parsing

I have an excel document that is supposed to be parsed using the following block of code:
var handler = new ExcelHandler(byteStream);
var currentExcelDocument = handler.CurrentDocument;
//now if the document is null
if (currentExcelDocument == null)
{
throw new Exception("Excel file handle missing");
}
var wokrbookpart = currentExcelDocument.WorkbookPart;
//get a list of all the sheets
string text = String.Empty;
var sheets = wokrbookpart.Workbook.Descendants<Sheet>().ToList();
foreach (var sh in sheets)
{
//now we have the sheets but the data must be in the first sheet
var themainsheet = sh;
if (themainsheet == null)
throw new ArgumentException("sheetName");
//now we need a reference to the worksheetpart
var worksheetpart = (WorksheetPart)wokrbookpart.GetPartById(themainsheet.Id);
SheetData data = worksheetpart.Worksheet.Elements<SheetData>().First();
//now we have a reference to the cells that contain data we start passing the data
foreach (Row r in data.Elements<Row>())
{
//we get the cells in the row
var cells = r.Elements<Cell>().ToList();
foreach (var i in cells)
{
text += i.CellValue.InnerText;
}
}
}
return text;
the excel file is uploaded via a fileupload control in asp.net and the stream is passed into the above block of code.
All is well though but then when i display the resulting text in the label, I see that the
result of reading the cell values is displayed as a sequence of numbers even though i am hindred percent sure that there are no numbers in the data
Please what could i be doing wrong??

How convert stream excel file to datatable C#?

I use Epplus to reading xlsx files from stream.
It has a bug , it cant read some columns in my workbook.How can read xlsx files from stream to datatable without epplus ?
my older code:
public static DataSet ReadExcelFile(Stream stream)
{
try
{
//2. Reading from a OpenXml Excel file (2007 format; *.xlsx)
IExcelDataReader excelReader =
ExcelReaderFactory.CreateOpenXmlReader(stream);
//...
DataSet result = excelReader.AsDataSet();
return result;
}
catch (Exception x)
{
throw x;
}
}
I didnt report it, but i tried so much combinations.If there are empty columns in worksheet ,epplus reader cant read correctly column values.
"It has a bug , it cant read some columns in my workbook"
Can you describe the bug, have you reported it or is it already known, what version are you using?
Here's a simple approach to load an excel file into a DataTable with EPPlus.
public static DataTable getDataTableFromExcel(string path)
{
using (var pck = new OfficeOpenXml.ExcelPackage())
{
using (var stream = File.OpenRead(path))
{
pck.Load(stream);
}
var ws = pck.Workbook.Worksheets.First();
DataTable tbl = new DataTable();
bool hasHeader = true; // adjust it accordingly( i've mentioned that this is a simple approach)
foreach (var firstRowCell in ws.Cells[1, 1, 1, ws.Dimension.End.Column])
{
tbl.Columns.Add(hasHeader ? firstRowCell.Text : string.Format("Column {0}", firstRowCell.Start.Column));
}
var startRow = hasHeader ? 2 : 1;
for (var rowNum = startRow; rowNum <= ws.Dimension.End.Row; rowNum++)
{
var wsRow = ws.Cells[rowNum, 1, rowNum, ws.Dimension.End.Column];
var row = tbl.NewRow();
foreach (var cell in wsRow)
{
row[cell.Start.Column - 1] = cell.Text;
}
tbl.Rows.Add(row);
}
return tbl;
}
}
This is way past, however it could still help someone.
Apparently some columns in my worksheet were merged, so for example, if columns A and B are merged it only recognizes column A as the one with the value, and so it returns column B as empty, when i call on that particular cell's value(B). To get past this, make sure you know which cells are merged and then grab only the first one and regard the rest of the merged cells as null

Replace multiple different images on one PDF template page with itext (itextsharp)

We have an ASP.NET application that users use to generate certain reports. So far we had one PDF template that had one image on it, and we would just replace that image with our programatically generated one (graph).
We have used code from this site for that:http://blog.rubypdf.com/2007/12/12/how-to-replace-images-in-a-pdf/
Problem now is that we have two different images on one PDF page, and the code from link above selects both images on one page and replaces them all at once with our generated image.
Does anyone have any idea how to replace multiple different images on one page with itext?
Thanks
Ugh. First, let me rewrite some of that source.
PdfReader pdf = new PdfReader("in.pdf");
PdfStamper stp = new PdfStamper(pdf, new FileOutputStream("c:\\out.pdf"));
PdfWriter writer = stp.getWriter();
Image img = Image.getInstance("image.png");
PdfDictionary pg = pdf.getPageN(1);
PdfDictionary res = pg.getAsDict.get(PdfName.RESOURCES);
PdfDictionary xobj = res.getAsDict(PdfName.XOBJECT);
if (xobj != null) {
for (Iterator<PdfName> it = xobj.getKeys().iterator(); it.hasNext(); ) {
PdfObject obj = xobj.get(it.next());
if (obj.isIndirect()) {
PdfDictionary tg = (PdfDictionary)PdfReader.getPdfObject(obj);
PdfName type = tg.getAsName(PdfName.SUBTYPE));
if (PdfName.IMAGE.equals(type)) {
PdfReader.killIndirect(obj);
Image maskImage = img.getImageMask();
if (maskImage != null)
writer.addDirectImageSimple(maskImage);
writer.addDirectImageSimple(img, (PRIndirectReference)obj);
break;
}
}
}
}
Whew. the getAs functions can save you quite a bit of knuckle-grease and make your code much clearer.
Now. You need to be able to differentiate between the various images. If you're willing to hard-code things, you could find out what the resource names are and go that route:
String imageResName[] = {"Img1", "Img2" ... };
Image img[] = {Image.getInstance("foo.png"), Image.getInstance("bar.png"), ... };
for (int i = 0; i < imageResName.length; ++i) {
PdfName curKey = new PdfName(imageResName[i]);
PdfIndirectReference ref = xobj.getAsIndirect(curKey);
PdfReader.killIndirect( ref );
Image maskImage = img[i].getImageMask();
if (maskImage != null) {
writer.addDirectImageSimple(maskImage);
}
writer.addDirectImageSimple(img[i], (PRIndirectReference)ref);
}
If you're not willing to go with hardcoded resource names (and no one would fault you, quite the opposite, particularly when the order they appear (and thus the number on the end) depends on their order in a hash map... [shudder]), you may be able to differentiate based on image width and height.
//keep the original for loop, stepping through resource names
if (PdfName.IMAGE.equals(type)) {
float width = tg.getAsNumber(PdfName.WIDTH).floatValue();
float height = tg.getAsNumber(PdfName.HEIGHT).floatValue();
Image img = getImageFromDimensions(width, height);
Image maskImage = img.getImageMask();
...
}
Just a note that sometimes the image will be nested in a form, so it is wise to make a function that will be called recursively.
Something like this:
public void StartHere()
{
PdfReader pdf = new PdfReader("in.pdf");
PdfStamper stp = new PdfStamper(pdf, new FileOutputStream("c:\\out.pdf"));
PdfWriter writer = stp.getWriter();
Image img = Image.getInstance("image.png");
PdfDictionary pg = pdf.getPageN(1);
replaceImage(pg, writer,img);
}
private void replaceImage(PdfDictionary pg, PdfWriter writer,Image img)
{
PdfDictionary res = pg.getAsDict.get(PdfName.RESOURCES);
PdfDictionary xobj = res.getAsDict(PdfName.XOBJECT);
if (xobj != null) {
for (Iterator<PdfName> it = xobj.getKeys().iterator(); it.hasNext(); ) {
PdfObject obj = xobj.get(it.next());
if (obj.isIndirect()) {
PdfDictionary tg = (PdfDictionary)PdfReader.getPdfObject(obj);
PdfName type = tg.getAsName(PdfName.SUBTYPE));
if (PdfName.IMAGE.equals(type))
{
PdfReader.killIndirect(obj);
Image maskImage = img.getImageMask();
if (maskImage != null)
writer.addDirectImageSimple(maskImage);
writer.addDirectImageSimple(img, (PRIndirectReference)obj);
break;
}
else if(PdfName.FORM.equals(type))
{
replaceImage(tg, writer,img);
}
}
}
}

opening an existing empty spreadsheet and writing data into it

I have a spreadsheet with multiple pages in it.When I click on a button I need to open this spreadsheet and write all the data(dataset/datatable) returned from the database into one of the pages in the spreadsheet.I saw so many articles for exporting dataset to a new excel sheet.how do i open an existing spreadsheet and write a dataset into it using asp.net/C#?
Please help..
Thanks.
UPDATE:
Basically I have the following code to export a dataset to a new excel sheet.
private void createDataInExcel(DataSet ds)
{
Application oXL;
_Workbook oWB;
_Worksheet oSheet;
Range oRng;
string strCurrentDir = Server.MapPath(".") + "\\excelreports\\";
try
{
oXL = new Application();
oXL.Visible = false;
//Get a new workbook.
oWB = (_Workbook)(oXL.Workbooks.Add(Missing.Value));
oSheet = (_Worksheet)oWB.ActiveSheet;
//System.Data.DataTable dtGridData=ds.Tables[0];
int iRow = 2;
if (ds.Tables[0].Rows.Count > 0)
{
for (int j = 0; j < ds.Tables[0].Columns.Count; j++)
{
oSheet.Cells[1, j + 1] = ds.Tables[0].Columns[j].ColumnName;
}
// For each row, print the values of each column.
for (int rowNo = 0; rowNo < ds.Tables[0].Rows.Count; rowNo++)
{
for (int colNo = 0; colNo < ds.Tables[0].Columns.Count; colNo++)
{
oSheet.Cells[iRow, colNo + 1] = ds.Tables[0].Rows[rowNo][colNo].ToString();
}
iRow++;
}
}
oRng = oSheet.get_Range("A1", "IV1");
oRng.EntireColumn.AutoFit();
oXL.Visible = false;
oXL.UserControl = false;
string strFile = "excelreport" + DateTime.Now.Ticks.ToString() + ".xls";//+
oWB.SaveAs(strCurrentDir +strFile, XlFileFormat.xlWorkbookNormal, null, null, false, false, XlSaveAsAccessMode.xlShared, false, false, null,null, null);
// Need all following code to clean up and remove all references!!!
oWB.Close(null, null, null);
oXL.Workbooks.Close();
oXL.Quit();
Marshal.ReleaseComObject(oRng);
Marshal.ReleaseComObject(oXL);
Marshal.ReleaseComObject(oSheet);
Marshal.ReleaseComObject(oWB);
}
catch (Exception theException)
{
Response.Write(theException.Message);
}
Response.Write("data exported");
}
Is it possible to improve the above code to write the dataset to an existing sheet?Also with the above code its taking about a minute to write the data into excel sheet..I do not understand why is it taking that long.
not 100% sure where you are with your code, however using the excel com object referenced in your project you can open a workbook using the Workbooks._Open method, then you can get the sheet by name using the sheets collection of the workbook and the get_Item.
if you need to add a sheet to the workbook you can use the add on the sheets collect.
Maybe if you post the code you have we can suggest where to improve it.
this line
oWB = (_Workbook)(oXL.Workbooks.Add(Missing.Value));
is creating a new workbook. use
string workbookPath = "c:/SomeWorkBook.xls";
oWB = Workbooks.Open(workbookPath,
0, false, 5, "", "", false, Excel.XlPlatform.xlWindows, "",
true, false, 0, true, false, false);
now it depends on what you want to do add a new sheet, use an existing sheet etc.
this is a codeproject link that shows more in depth here

Resources