Hi I am having a list container which contains the list of values. I wish to export the list values directly to Excel. Is there any way to do it directly?
OK, here is a step-by-step guide if you want to use COM.
You have to have Excel installed.
Add a reference to your project to the excel interop dll. To do this
on the .NET tab select
Microsoft.Office.Interop.Excel.
There could be multiple assemblies
with this name. Select the
appropriate for your Visual Studio
AND Excel version.
Here is a code sample to create a new Workbook and fill a column with
the items from your list.
using NsExcel = Microsoft.Office.Interop.Excel;
public void ListToExcel(List<string> list)
{
//start excel
NsExcel.ApplicationClass excapp = new Microsoft.Office.Interop.Excel.ApplicationClass();
//if you want to make excel visible
excapp.Visible = true;
//create a blank workbook
var workbook = excapp.Workbooks.Add(NsExcel.XlWBATemplate.xlWBATWorksheet);
//or open one - this is no pleasant, but yue're probably interested in the first parameter
string workbookPath = "C:\test.xls";
var workbook = excapp.Workbooks.Open(workbookPath,
0, false, 5, "", "", false, Excel.XlPlatform.xlWindows, "",
true, false, 0, true, false, false);
//Not done yet. You have to work on a specific sheet - note the cast
//You may not have any sheets at all. Then you have to add one with NsExcel.Worksheet.Add()
var sheet = (NsExcel.Worksheet)workbook.Sheets[1]; //indexing starts from 1
//do something usefull: you select now an individual cell
var range = sheet.get_Range("A1", "A1");
range.Value2 = "test"; //Value2 is not a typo
//now the list
string cellName;
int counter = 1;
foreach (var item in list)
{
cellName = "A" + counter.ToString();
var range = sheet.get_Range(cellName, cellName);
range.Value2 = item.ToString();
++counter;
}
//you've probably got the point by now, so a detailed explanation about workbook.SaveAs and workbook.Close is not necessary
//important: if you did not make excel visible terminating your application will terminate excel as well - I tested it
//but if you did it - to be honest - I don't know how to close the main excel window - maybee somewhere around excapp.Windows or excapp.ActiveWindow
}
Using ClosedXML edit library( there is no need to install MS Excel
I just write a simple example to show you how you can name the file, the worksheet and select cells:
var workbook = new XLWorkbook();
workbook.AddWorksheet("sheetName");
var ws = workbook.Worksheet("sheetName");
int row = 1;
foreach (object item in itemList)
{
ws.Cell("A" + row.ToString()).Value = item.ToString();
row++;
}
workbook.SaveAs("yourExcel.xlsx");
If you prefer you can create a System.Data.DataSet or a System.Data.DataTable with all data and then just add it as a workseet with workbook.AddWorksheet(yourDataset) or workbook.AddWorksheet(yourDataTable);
Using the CSV idea, if it's just a list of Strings. Assuming l is your list:
using System.IO;
using(StreamWriter sw = File.CreateText("list.csv"))
{
for(int i = 0; i < l.Count; i++)
{
sw.WriteLine(l[i]);
}
}
Fast way - ArrayToExcel (github)
byte[] excel = myList.ToExcel();
File.WriteAllBytes("result.xlsx", excel);
The simplest way using ClosedXml.
Imports ClosedXML.Excel
var dataList = new List<string>() { "a", "b", "c" };
var workbook = new XLWorkbook(); //creates the workbook
var wsDetailedData = workbook.AddWorksheet("data"); //creates the worksheet with sheetname 'data'
wsDetailedData.Cell(1, 1).InsertTable(dataList); //inserts the data to cell A1 including default column name
workbook.SaveAs(#"C:\data.xlsx"); //saves the workbook
For more info, you can also check wiki of ClosedXml.
https://github.com/closedxml/closedxml/wiki
Exporting values List to Excel
Install in nuget next reference
Install-Package Syncfusion.XlsIO.Net.Core -Version 17.2.0.35
Install-Package ClosedXML -Version 0.94.2
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ClosedXML;
using ClosedXML.Excel;
using Syncfusion.XlsIO;
namespace ExporteExcel
{
class Program
{
public class Auto
{
public string Marca { get; set; }
public string Modelo { get; set; }
public int Ano { get; set; }
public string Color { get; set; }
public int Peronsas { get; set; }
public int Cilindros { get; set; }
}
static void Main(string[] args)
{
//Lista Estatica
List<Auto> Auto = new List<Program.Auto>()
{
new Auto{Marca = "Chevrolet", Modelo = "Sport", Ano = 2019, Color= "Azul", Cilindros=6, Peronsas= 4 },
new Auto{Marca = "Chevrolet", Modelo = "Sport", Ano = 2018, Color= "Azul", Cilindros=6, Peronsas= 4 },
new Auto{Marca = "Chevrolet", Modelo = "Sport", Ano = 2017, Color= "Azul", Cilindros=6, Peronsas= 4 }
};
//Inizializar Librerias
var workbook = new XLWorkbook();
workbook.AddWorksheet("sheetName");
var ws = workbook.Worksheet("sheetName");
//Recorrer el objecto
int row = 1;
foreach (var c in Auto)
{
//Escribrie en Excel en cada celda
ws.Cell("A" + row.ToString()).Value = c.Marca;
ws.Cell("B" + row.ToString()).Value = c.Modelo;
ws.Cell("C" + row.ToString()).Value = c.Ano;
ws.Cell("D" + row.ToString()).Value = c.Color;
ws.Cell("E" + row.ToString()).Value = c.Cilindros;
ws.Cell("F" + row.ToString()).Value = c.Peronsas;
row++;
}
//Guardar Excel
//Ruta = Nombre_Proyecto\bin\Debug
workbook.SaveAs("Coches.xlsx");
}
}
}
You could output them to a .csv file and open the file in excel. Is that direct enough?
The most straightforward way (in my opinion) would be to simply put together a CSV file. If you want to get into formatting and actually writing to a *.xlsx file, there are more complicated solutions (and APIs) to do that for you.
the one easy way to do it is to open Excel create sheet containing test data you want to export then say to excel save as xml open the xml see the xml format excel is expecting and generate it by head replacing the test data with export data
SpreadsheetML Markup Spec
#lan this is xml fo a simle execel file with one column value i genereted with office 2003 this format is for office 2003 and above
<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="http://www.w3.org/TR/REC-html40">
<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
<Author>Dancho</Author>
<LastAuthor>Dancho</LastAuthor>
<Created>2010-02-05T10:15:54Z</Created>
<Company>cc</Company>
<Version>11.9999</Version>
</DocumentProperties>
<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
<WindowHeight>13800</WindowHeight>
<WindowWidth>24795</WindowWidth>
<WindowTopX>480</WindowTopX>
<WindowTopY>105</WindowTopY>
<ProtectStructure>False</ProtectStructure>
<ProtectWindows>False</ProtectWindows>
</ExcelWorkbook>
<Styles>
<Style ss:ID="Default" ss:Name="Normal">
<Alignment ss:Vertical="Bottom"/>
<Borders/>
<Font/>
<Interior/>
<NumberFormat/>
<Protection/>
</Style>
</Styles>
<Worksheet ss:Name="Sheet1">
<Table ss:ExpandedColumnCount="1" ss:ExpandedRowCount="6" x:FullColumns="1"
x:FullRows="1">
<Row>
<Cell><Data ss:Type="String">Value1</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="String">Value2</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="String">Value3</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="String">Value4</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="String">Value5</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="String">Value6</Data></Cell>
</Row>
</Table>
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<Selected/>
<Panes>
<Pane>
<Number>3</Number>
<ActiveRow>5</ActiveRow>
</Pane>
</Panes>
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
</WorksheetOptions>
</Worksheet>
<Worksheet ss:Name="Sheet2">
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
</WorksheetOptions>
</Worksheet>
<Worksheet ss:Name="Sheet3">
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
</WorksheetOptions>
</Worksheet>
</Workbook>
Depending on the environment you're wanting to do this in, it is possible by using the Excel Interop. It's quite a mess dealing with COM however and ensuring you clear up resources else Excel instances stay hanging around on your machine.
Checkout this MSDN Example if you want to learn more.
Depending on your format you could produce CSV or SpreadsheetML yourself, thats not too hard. Other alternatives are to use 3rd party libraries to do it. Obviously they cost money though.
List<"classname"> getreport = cs.getcompletionreport();
var getreported = getreport.Select(c => new { demographic = c.rName);
where cs.getcompletionreport() reference class file is Business Layer for App
I hope this helps.
I know, I am late to this party, however I think it could be helpful for others.
Already posted answers are for csv and other one is by Interop dll where you need to install excel over the server, every approach has its own pros and cons.
Here is an option which will give you
Perfect excel output [not csv]
With perfect excel and your data type match
Without excel installation
Pass list and get Excel output :)
you can achieve this by using NPOI DLL, available for both .net as well as for .net core
Steps :
Import NPOI DLL
Add Section 1 and 2 code provided below
Good to go
Section 1
This code performs below task :
Creating New Excel object - _workbook = new XSSFWorkbook();
Creating New Excel Sheet object - _sheet =_workbook.CreateSheet(_sheetName);
Invokes WriteData() - explained later Finally, creating and
returning MemoryStream object
=============================================================================
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
namespace GenericExcelExport.ExcelExport
{
public interface IAbstractDataExport
{
HttpResponseMessage Export(List exportData, string fileName, string sheetName);
}
public abstract class AbstractDataExport : IAbstractDataExport
{
protected string _sheetName;
protected string _fileName;
protected List _headers;
protected List _type;
protected IWorkbook _workbook;
protected ISheet _sheet;
private const string DefaultSheetName = "Sheet1";
public HttpResponseMessage Export
(List exportData, string fileName, string sheetName = DefaultSheetName)
{
_fileName = fileName;
_sheetName = sheetName;
_workbook = new XSSFWorkbook(); //Creating New Excel object
_sheet = _workbook.CreateSheet(_sheetName); //Creating New Excel Sheet object
var headerStyle = _workbook.CreateCellStyle(); //Formatting
var headerFont = _workbook.CreateFont();
headerFont.IsBold = true;
headerStyle.SetFont(headerFont);
WriteData(exportData); //your list object to NPOI excel conversion happens here
//Header
var header = _sheet.CreateRow(0);
for (var i = 0; i < _headers.Count; i++)
{
var cell = header.CreateCell(i);
cell.SetCellValue(_headers[i]);
cell.CellStyle = headerStyle;
}
for (var i = 0; i < _headers.Count; i++)
{
_sheet.AutoSizeColumn(i);
}
using (var memoryStream = new MemoryStream()) //creating memoryStream
{
_workbook.Write(memoryStream);
var response = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ByteArrayContent(memoryStream.ToArray())
};
response.Content.Headers.ContentType = new MediaTypeHeaderValue
("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.Content.Headers.ContentDisposition =
new ContentDispositionHeaderValue("attachment")
{
FileName = $"{_fileName}_{DateTime.Now.ToString("yyyyMMddHHmmss")}.xlsx"
};
return response;
}
}
//Generic Definition to handle all types of List
public abstract void WriteData(List exportData);
}
}
=============================================================================
Section 2
In section 2, we will be performing below steps :
Converts List to DataTable Reflection to read property name, your
Column header will be coming from here
Loop through DataTable to Create excel Rows
=============================================================================
using NPOI.SS.UserModel;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Text.RegularExpressions;
namespace GenericExcelExport.ExcelExport
{
public class AbstractDataExportBridge : AbstractDataExport
{
public AbstractDataExportBridge()
{
_headers = new List<string>();
_type = new List<string>();
}
public override void WriteData<T>(List<T> exportData)
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
foreach (PropertyDescriptor prop in properties)
{
var type = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType;
_type.Add(type.Name);
table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ??
prop.PropertyType);
string name = Regex.Replace(prop.Name, "([A-Z])", " $1").Trim(); //space separated
//name by caps for header
_headers.Add(name);
}
foreach (T item in exportData)
{
DataRow row = table.NewRow();
foreach (PropertyDescriptor prop in properties)
row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
table.Rows.Add(row);
}
IRow sheetRow = null;
for (int i = 0; i < table.Rows.Count; i++)
{
sheetRow = _sheet.CreateRow(i + 1);
for (int j = 0; j < table.Columns.Count; j++)
{
ICell Row1 = sheetRow.CreateCell(j);
string type = _type[j].ToLower();
var currentCellValue = table.Rows[i][j];
if (currentCellValue != null &&
!string.IsNullOrEmpty(Convert.ToString(currentCellValue)))
{
if (type == "string")
{
Row1.SetCellValue(Convert.ToString(currentCellValue));
}
else if (type == "int32")
{
Row1.SetCellValue(Convert.ToInt32(currentCellValue));
}
else if (type == "double")
{
Row1.SetCellValue(Convert.ToDouble(currentCellValue));
}
}
else
{
Row1.SetCellValue(string.Empty);
}
}
}
}
}
}
=============================================================================
Now you just need to call
WriteData() function by passing your list, and it will provide you your excel.
I have tested it in WEB API and WEB API Core, works like a charm.
Pass List to "Write" Method, which will convert the list to buffer and return buffer, a file will be downloaded
byte[] buffer = Write(ListData, true, "AttendenceSummary"); return File(buffer, "application/excel", reportTitle + ".xlsx");
public static byte[] Write<T>(IEnumerable<T> list, bool xlsxExtension, string sheetName = "ExportData")
{
if (list == null)
{
throw new ArgumentNullException("list");
}
XSSFWorkbook hssfworkbook = new XSSFWorkbook();
int Rowspersheet = 15000;
int TotalRows = list.Count();
int TotalSheets = TotalRows / Rowspersheet;
for (int i = 0; i <= TotalSheets; i++)
{
ISheet sheet1 = hssfworkbook.CreateSheet(sheetName + "_" + i);
IRow row = sheet1.CreateRow(0);
int index = 0;
foreach (PropertyInfo property in typeof(T).GetProperties())
{
ICellStyle cellStyle = hssfworkbook.CreateCellStyle();
IFont cellFont = hssfworkbook.CreateFont();
cellFont.Boldweight = (short)NPOI.SS.UserModel.FontBoldWeight.Bold;
cellStyle.SetFont(cellFont);
ICell cell = row.CreateCell(index++);
cell.CellStyle = cellStyle;
cell.SetCellValue(property.Name);
}
int rowIndex = 1;
// int rowIndex2 = 1;
foreach (T obj in list.Skip(Rowspersheet * i).Take(Rowspersheet))
{
row = sheet1.CreateRow(rowIndex++);
index = 0;
foreach (PropertyInfo property in typeof(T).GetProperties())
{
ICell cell = row.CreateCell(index++);
cell.SetCellValue(Convert.ToString(property.GetValue(obj)));
}
}
}
MemoryStream file = new MemoryStream();
hssfworkbook.Write(file);
return file.ToArray();
}
Related
I have a method which create an excel file (.xlsx) from a list of strings using DocumentFormat.OpenXml. The created file needs to be repaired when I try to open it with Excel 2016. When I click "Yes" Excel shows my file correctly.
Does anyone have any suggestions? Thanks in advance.
Here's my code:
private byte[] ExportDataXlsx(System.Data.Common.DbDataReader reader, string[] fields, string[] headers, string Culture) {
System.IO.MemoryStream sw = new System.IO.MemoryStream();
using (var workbook = Packaging.SpreadsheetDocument.Create(sw, SpreadsheetDocumentType.Workbook)) {
var sheetData = CreateSheet(workbook);
while (reader.Read()) {
Spreadsheet.Row newRow = new Spreadsheet.Row();
foreach (string column in fields) {
Spreadsheet.Cell cell = new Spreadsheet.Cell();
cell.DataType = Spreadsheet.CellValues.String;
object value = null;
try {
int index = reader.GetOrdinal(column);
cell.DataType = DbKymosDomainService.ToXlsType(reader.GetFieldType(index));
value = DbKymosDomainService.ToStringFromCulture(reader.GetValue(index), reader.GetFieldType(index), Culture);
if (cell.DataType == Spreadsheet.CellValues.Number){
value = value == null ? "" : value.ToString().Replace(",", ".");
}
}
catch { }
cell.CellValue = new Spreadsheet.CellValue(value == null ? null : value.ToString()); //
newRow.AppendChild(cell);
try { var x = newRow.InnerXml; } catch { newRow.RemoveChild(cell); }
}
sheetData.AppendChild(newRow);
}
workbook.Close();
}
byte[] data = sw.ToArray();
sw.Close();
sw.Dispose();
return data;
}
Function which create sheet:
private Spreadsheet.SheetData CreateSheet(Packaging.SpreadsheetDocument workbook)
{
var workbookPart = workbook.AddWorkbookPart();
workbook.WorkbookPart.Workbook = new Spreadsheet.Workbook();
workbook.WorkbookPart.Workbook.Sheets = new Spreadsheet.Sheets();
var sheetPart = workbook.WorkbookPart.AddNewPart<Packaging.WorksheetPart>();
var sheetData = new Spreadsheet.SheetData();
sheetPart.Worksheet = new Spreadsheet.Worksheet(sheetData);
Spreadsheet.Sheets sheets = workbook.WorkbookPart.Workbook.GetFirstChild<Spreadsheet.Sheets>();
string relationshipId = workbook.WorkbookPart.GetIdOfPart(sheetPart);
uint sheetId = 1;
if (sheets.Elements<Spreadsheet.Sheet>().Count() > 0) {
sheetId =
sheets.Elements<Spreadsheet.Sheet>().Select(s => s.SheetId.Value).Max() + 1;
}
Spreadsheet.Sheet sheet = new Spreadsheet.Sheet() { Id = relationshipId, SheetId = sheetId, Name = "Export" };
sheets.Append(sheet);
return sheetData;
}
In my experience when a file needs to be repaired after creating it using OpenXML it means that it is missing a crucial element or the crucial element is in the wrong place. I'm having difficulty following your code so that in itself points to something being in the wrong place. Code should be sequential and self-explanatory. A few pointers however to help with getting to the root cause of your issue.
I would suggest first using ClosedXML as it takes so much strain out of the coding.https://github.com/closedxml/closedxml
Debug your code and step through each step to see what's going on.
Open the created file in OpenXML Productivity Tool https://github.com/OfficeDev/Open-XML-SDK/releases/tag/v2.5 and have a look around.
Another tool that I couldn't be without is OpenXML FileViewer: https://github.com/davecra/OpenXmlFileViewer
Lastly I always run this sub routine to validate documents I create using OpenXML:
public static List<string> ValidateWordDocument(FileInfo filepath, ref Int32 maxerrors = 100)
{
try
{
using (WordprocessingDocument wDoc = WordprocessingDocument.Open(filepath.FullName, false))
{
OpenXmlValidator validator = new OpenXmlValidator();
int count = 0;
List<string> er = new List<string>()
{
string.Format($"Assessment of {filepath.Name} on {DateTime.Now} yielded the following result: {Constants.vbCrLf}")
};
// set at zero so that we can determine the total quantity of errors
validator.MaxNumberOfErrors = 0;
// String.Format("<strong> Warning : </strong>")
foreach (ValidationErrorInfo error in validator.Validate(wDoc))
{
count += 1;
if (count > maxerrors)
break;
er.Add($"Error {count}{Constants.vbCrLf}" + $"Description {error.Description}{Constants.vbCrLf}" + $"ErrorType: {error.ErrorType}{Constants.vbCrLf}" + $"Node {error.Node}{Constants.vbCrLf}" + $"Name {error.Node.LocalName}{Constants.vbCrLf}" + $"Path {error.Path.XPath}{Constants.vbCrLf}" + $"Part: {error.Part.Uri}{Constants.vbCrLf}" + $"-------------------------------------------{Constants.vbCrLf}" + $"Outer XML: {error.Node.OuterXml}" + $"-------------------------------------------{Constants.vbCrLf}");
}
int validatorcount = validator.Validate(wDoc).Count;
switch (validatorcount)
{
case object _ when validatorcount > maxerrors:
{
er.Add($"Returned {count - 1} as this is the Maximum Number set by the system. The actual number of errors in {filepath.Name} is {validatorcount}");
er.Add("A summary list of all error types encountered is given below");
List<string> expectedErrors = validator.Validate(wDoc).Select(_e => _e.Description).Distinct().ToList();
er.AddRange(expectedErrors);
break;
}
case object _ when 1 <= validatorcount && validatorcount <= maxerrors:
{
er.Add($"Returned all {validator} errors in {filepath.Name}");
break;
}
case object _ when validatorcount == 0:
{
er.Add($"No Errors found in document {filepath.Name}");
break;
}
}
return er;
wDoc.Close();
}
}
catch (Exception ex)
{
Information.Err.MessageElevate();
return null;
}
}
It helps greatly with problem solving any potential issues.
Using .net core & c# here.
I have a UI from which user can upload the Excel or CSV files. Once they upload this goes to my web api which handles the reading of the data from these files and returns json.
My Api code as:
[HttpPost("upload")]
public async Task<IActionResult> FileUpload(IFormFile file)
{
JArray data = new JArray();
using (ExcelPackage package = new ExcelPackage(file.OpenReadStream()))
{
ExcelWorksheet worksheet = package.Workbook.Worksheets[1];
//Process, read from excel here and populate jarray
}
return Ok(data );
}
In my above code I am using EPPlus for reading the excel file. For excel file it works all fine but it cannot read csv file which is the limitation of EPPlus.
I searched and found another library CSVHelper: https://joshclose.github.io/CsvHelper/ The issue with this is it does vice versa and can read from CSV but not from Excel.
Is there any library available which supports reading from both.
Or would it be possible use EPPlus only but convert uploaded CSV to excel on the fly and then read. (please note I am not storing the excel file anywhere so cant use save as to save it as excel)
Any inputs please?
--Updated - Added code for reading data from excel---
int rowCount = worksheet.Dimension.End.Row;
int colCount = worksheet.Dimension.End.Column;
for (int row = 1; row <= rowCount; row++)
{
for (int col = 1; col <= colCount; col++)
{
var rowValue = worksheet.Cells[row, col].Value;
}
}
//With the code suggested in the answer rowcount is always 1
You can use EPPLus and a MemoryStream for opening csv files into an ExcelPackage without writing to a file. Below is an example. You may have to change some of the the parameters based on your CSV file specs.
[HttpPost("upload")]
public async Task<IActionResult> FileUpload(IFormFile file)
{
var result = string.Empty;
string worksheetsName = "data";
bool firstRowIsHeader = false;
var format = new ExcelTextFormat();
format.Delimiter = ',';
format.TextQualifier = '"';
using (var reader = new System.IO.StreamReader(file.OpenReadStream()))
using (ExcelPackage package = new ExcelPackage())
{
result = reader.ReadToEnd();
ExcelWorksheet worksheet =
package.Workbook.Worksheets.Add(worksheetsName);
worksheet.Cells["A1"].LoadFromText(result, format, OfficeOpenXml.Table.TableStyles.Medium27, firstRowIsHeader);
}
}
Here's using Aspose, which is unfortunately not free, but wow it works great. My API is using the streaming capability with Content-Type: multipart/form-data rather than the IFormFile implementation:
[HttpPut]
[DisableFormValueModelBinding]
public async Task<IActionResult> UploadSpreadsheet()
{
if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
{
return BadRequest($"Expected a multipart request, but got {Request.ContentType}");
}
var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(Request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit);
var reader = new MultipartReader(boundary, HttpContext.Request.Body);
var section = (await reader.ReadNextSectionAsync()).AsFileSection();
//If you're doing CSV, you add this line:
LoadOptions loadOptions = new LoadOptions(LoadFormat.CSV);
var workbook = new Workbook(section.FileStream, loadOptions);
Cells cells = workbook.Worksheets[0].Cells;
var rows = cells.Rows.Cast<Row>().Where(x => !x.IsBlank);
//Do whatever else you want here
Please try with below code
private string uploadCSV(FileUpload fl)
{
string fileName = "";
serverLocation = Request.PhysicalApplicationPath + "ExcelFiles\\";
fileName = fl.PostedFile.FileName;
int FileSize = fl.PostedFile.ContentLength;
string contentType = fl.PostedFile.ContentType;
fl.PostedFile.SaveAs(serverLocation + fileName);
string rpath = string.Empty, dir = string.Empty;
HttpContext context = HttpContext.Current;
string baseUrl = context.Request.Url.Scheme + "://" + context.Request.Url.Authority + context.Request.ApplicationPath.TrimEnd('/') + '/';
try
{
rpath = serverLocation + fileName;//Server.MapPath(dir + fileName);
using (Stream InputStream = fl.PostedFile.InputStream)
{
Object o = new object();
lock (o)
{
byte[] buffer = new byte[InputStream.Length];
InputStream.Read(buffer, 0, (int)InputStream.Length);
lock (o)
{
File.WriteAllBytes(rpath, buffer);
buffer = null;
}
InputStream.Close();
}
}
}
catch (Exception ex)
{
lblSOTargetVal.Text = ex.Message.ToString();
}
return rpath;
}
Use the Open XML SDK package and add insert working solution for it.
I'm developing an app which can generate a excel file using html table. Up to now I developed html table download as excel file part. (This happens in client side with javascript). Now I need to send email with that attachment (The excel file) to particular person's email address. So I'm confuse how to do this, because up to now I generate excel in client side and need to send that file via email. In this case is it needed to copy client side excel to the server? If so how to do this?
Please give me a direction.
Update 1 (Adding codes)
This is the javascript, that I used to download html table as excel to client side.
var tablesToExcel = (function () {
var uri = 'data:application/vnd.ms-excel;base64,'
, tmplWorkbookXML = '<?xml version="1.0"?><?mso-application progid="Excel.Sheet"?><Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">'
+ '<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office"><Author>Axel Richter</Author><Created>{created}</Created></DocumentProperties>'
+ '<Styles>'
+ '<Style ss:ID="Currency"><NumberFormat ss:Format="Currency"></NumberFormat></Style>'
+ '<Style ss:ID="Date"><NumberFormat ss:Format="Medium Date"></NumberFormat></Style>'
+ '</Styles>'
+ '{worksheets}</Workbook>'
, tmplWorksheetXML = '<Worksheet ss:Name="{nameWS}"><Table>{rows}</Table></Worksheet>'
, tmplCellXML = '<Cell{attributeStyleID}{attributeFormula}><Data ss:Type="{nameType}">{data}</Data></Cell>'
, base64 = function (s) { return window.btoa(unescape(encodeURIComponent(s))) }
, format = function (s, c) { return s.replace(/{(\w+)}/g, function (m, p) { return c[p]; }) }
return function (tables, wsnames, wbname, appname) {
var ctx = "";
var workbookXML = "";
var worksheetsXML = "";
var rowsXML = "";
for (var i = 0; i < tables.length; i++) {
if (!tables[i].nodeType) tables[i] = document.getElementById(tables[i]);
for (var j = 0; j < tables[i].rows.length; j++) {
rowsXML += '<Row>'
for (var k = 0; k < tables[i].rows[j].cells.length; k++) {
var dataType = tables[i].rows[j].cells[k].getAttribute("data-type");
var dataStyle = tables[i].rows[j].cells[k].getAttribute("data-style");
var dataValue = tables[i].rows[j].cells[k].getAttribute("data-value");
dataValue = (dataValue) ? dataValue : tables[i].rows[j].cells[k].innerHTML;
var dataFormula = tables[i].rows[j].cells[k].getAttribute("data-formula");
dataFormula = (dataFormula) ? dataFormula : (appname == 'Calc' && dataType == 'DateTime') ? dataValue : null;
ctx = {
attributeStyleID: (dataStyle == 'Currency' || dataStyle == 'Date') ? ' ss:StyleID="' + dataStyle + '"' : ''
, nameType: (dataType == 'Number' || dataType == 'DateTime' || dataType == 'Boolean' || dataType == 'Error') ? dataType : 'String'
, data: (dataFormula) ? '' : dataValue
, attributeFormula: (dataFormula) ? ' ss:Formula="' + dataFormula + '"' : ''
};
rowsXML += format(tmplCellXML, ctx);
}
rowsXML += '</Row>'
}
ctx = { rows: rowsXML, nameWS: wsnames[i] || 'Sheet' + i };
worksheetsXML += format(tmplWorksheetXML, ctx);
rowsXML = "";
}
ctx = { created: (new Date()).getTime(), worksheets: worksheetsXML };
workbookXML = format(tmplWorkbookXML, ctx);
var link = document.createElement("A");
link.href = uri + base64(workbookXML);
link.download = wbname || 'Workbook.xls';
link.target = '_blank';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
})();
Still I do not have idea to save generated excel to server and send it as email.
AS per our discussion:
1. you need to send data from client to server
you can use this code to do this sending headers and values to server using ajax and you can also filter columns as you want
function SaveToServer() {
var gov = GetHeaders('tbl');
$.ajax({
url: '#Url.Content("~/Home/ReciveData")',
data: { headers: JSON.stringify(gov.heasers), data: JSON.stringify(gov.data) },
success: function (data) {
// Success
},
error: function (xhr) {
}
});
}
function GetHeaders(tableName) {
table = document.getElementById(tableName);
var tbl_Hdata = [];
var tbl_Data = [];
for (var i = 0, row; row = table.rows[i]; i++) {
var rowData = [];
for (var j = 0, col; col = row.cells[j]; j++) {
// add column filter
if (i == 0) {
tbl_Hdata.push(col.innerHTML);
}
else {
rowData.push(col.innerHTML);
}
}
if (i > 0) {
tbl_Data.push(rowData);
}
}
return { heasers: tbl_Hdata, data: tbl_Data };
}
now we want to recive this data and convert it to datatable to save it to excel in server side
using NPOI
public void ReciveData(string headers, string data)
{
#region Read Data
List<string> tbl_Headers = new List<string>();
List<List<string>> tbl_Data = new List<List<string>>();
tbl_Headers = Newtonsoft.Json.JsonConvert.DeserializeObject<List<string>>(headers);
tbl_Data = Newtonsoft.Json.JsonConvert.DeserializeObject<List<List<string>>>(data);
#endregion
#region Create Data Table
DataTable dataTable = new DataTable("Data");
foreach (var prop in tbl_Headers)
{
dataTable.Columns.Add(prop);
}
DataRow row;
foreach (var rw in tbl_Data)
{
row = dataTable.NewRow();
for (int i = 0; i < rw.Count; i++)
{
row[tbl_Headers[i]] = rw[i];
}
dataTable.Rows.Add(row);
}
#endregion
#region Save To excel
string path = #"D:\";
string fileName = "";
GenerateExcelSheetWithoutDownload(dataTable, path, out fileName);
#endregion
}
public bool GenerateExcelSheetWithoutDownload(DataTable dataTable, string exportingSheetPath, out string exportingFileName)
{
#region Validate the parameters and Generate the excel sheet
bool returnValue = false;
exportingFileName = Guid.NewGuid().ToString() + ".xls";
if (dataTable != null && dataTable.Rows.Count > new int())
{
string excelSheetPath = string.Empty;
#region Check If The directory is exist
if (!Directory.Exists(exportingSheetPath))
{
Directory.CreateDirectory(exportingSheetPath);
}
excelSheetPath = exportingSheetPath + exportingFileName;
FileInfo fileInfo = new FileInfo(excelSheetPath);
#endregion
#region Write stream to the file
MemoryStream ms = DataToExcel(dataTable);
byte[] blob = ms.ToArray();
if (blob != null)
{
using (MemoryStream inStream = new MemoryStream(blob))
{
FileStream fs = new FileStream(excelSheetPath, FileMode.Create);
inStream.WriteTo(fs);
fs.Close();
}
}
ms.Close();
returnValue = true;
#endregion
}
return returnValue;
#endregion
}
private static MemoryStream DataToExcel(DataTable dt)
{
MemoryStream ms = new MemoryStream();
using (dt)
{
#region Create File
HSSFWorkbook workbook = new HSSFWorkbook();//Create an excel Workbook
ISheet sheet = workbook.CreateSheet("data");//Create a work table in the table
int RowHeaderIndex = new int();
#endregion
#region Table Headers
IRow headerTableRow = sheet.CreateRow(RowHeaderIndex);
if (dt != null)
{
foreach (DataColumn column in dt.Columns)
{
headerTableRow.CreateCell(column.Ordinal).SetCellValue(column.Caption);
}
RowHeaderIndex++;
}
#endregion
#region Data
foreach (DataRow row in dt.Rows)
{
IRow dataRow = sheet.CreateRow(RowHeaderIndex);
foreach (DataColumn column in dt.Columns)
{
dataRow.CreateCell(column.Ordinal).SetCellValue(row[column].ToString());
}
RowHeaderIndex++;
}
#endregion
workbook.Write(ms);
ms.Flush();
//ms.Position = 0;
}
return ms;
}
Now you can send this file as attachment in mail
You can't create Excel files with HTML tables. This is a hack that's used to fake actual Excel files. Excel isn't fooled, it recognizes the HTML file and tries to import the data using defaults. This will easily break for any number of reasons, eg different locale settings for decimals and dates.
Excel files are just zipped XML files. You can create them using XML manipulation, the Open XML SDK or a library like EPPlus.
Creating an Excel file with EPPlus is as easy as calling the LoadFromCollection or LoadFromDatatable method. The sheet can be saved to any stream, including FileStream or MemoryStream. A MemoryStream can be used to send the data to a web browser as shown in this answer:
public ActionResult ExportData()
{
//Somehow, load data to a DataTable
using (ExcelPackage package = new ExcelPackage())
{
var ws = package.Workbook.Worksheets.Add("My Sheet");
//true generates headers
ws.Cells["A1"].LoadFromDataTable(dataTable, true);
var stream = new MemoryStream();
package.SaveAs(stream);
string fileName = "myfilename.xlsx";
string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
stream.Position = 0;
return File(stream, contentType, fileName);
}
}
Mail attachments can also be created from a MemoryStream. The Attachment(Stream, string,string) constructor accepts any stream as input. The example above could be modified to create an attachment instead of sending the data to the browser:
public void SendData(string server, string recipientList)
{
//Same as before
using (ExcelPackage package = new ExcelPackage())
{
var ws = package.Workbook.Worksheets.Add("My Sheet");
ws.Cells["A1"].LoadFromDataTable(dataTable, true);
var stream = new MemoryStream();
package.SaveAs(stream);
string fileName = "myfilename.xlsx";
string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
stream.Position = 0;
SendExcel(server,recipientList);
}
}
void SendExcel(string server, string recipientList)
{
//Send the file
var message = new MailMessage("logMailer#contoso.com", recipientList);
message.Subject = "Some Data";
Attachment data = new Attachment(stream, name, contentType);
// Add the attachment to the message.
message.Attachments.Add(data);
// Send the message.
// Include credentials if the server requires them.
var client = new SmtpClient(server);
client.Credentials = CredentialCache.DefaultNetworkCredentials;
client.Send(message);
}
}
UPDATE
Generating an XSLX table on the client side becomes a lot easier if you use a library like js-xlsx. There's even a sample that generates an XLSX file from an HTML table
file path is #"E:\BCFNA-orig-1.xsl"
excel file consists of 9 columns and 500 rows i want to get data from each row into an array int[] NumberOfInputs = {7,4,4,4,2,4,5,5,0}; " the values inside array are supposed to get from excel file , use it in my program and than get data from next row.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.OleDb;
using System.IO;
namespace ConsoleApplication3
{
class Program
{
static void Main()
{
}
public class SomethingSometingExcelClass
{
public void DoSomethingWithExcel(string filePath)
{
List<DataTable> worksheets = ImportExcel(filePath);
foreach(var item in worksheets){
foreach (DataRow row in item.Rows)
{
//add to array
}
}
}
/// <summary>
/// Imports Data from Microsoft Excel File.
/// </summary>
/// <param name="FileName">Filename from which data need to import data
/// <returns>List of DataTables, based on the number of sheets</returns>
private List<DataTable> ImportExcel(string FileName)
{
List<DataTable> _dataTables = new List<DataTable>();
string _ConnectionString = string.Empty;
string _Extension = Path.GetExtension(FileName);
//Checking for the extentions, if XLS connect using Jet OleDB
_ConnectionString =
"Provider=Microsoft.Jet.OLEDB.4.0; Data Source=E:\\BCFNA-
orig-1.xls;Extended
Properties=Excel 8.0";
DataTable dataTable = null;
using (OleDbConnection oleDbConnection =
new OleDbConnection(string.Format(_ConnectionString, FileName)))
{
oleDbConnection.Open();
//Getting the meta data information.
//This DataTable will return the details of Sheets in the Excel
File.DataTable dbSchema =
oleDbConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables_Info, null);
foreach (DataRow item in dbSchema.Rows)
{
//reading data from excel to Data Table
using (OleDbCommand oleDbCommand = new OleDbCommand())
{
oleDbCommand.Connection = oleDbConnection;
oleDbCommand.CommandText = string.Format("SELECT * FROM
[B1415:J2113]", item["TABLE_NAME"].ToString());
using (OleDbDataAdapter oleDbDataAdapter = new
OleDbDataAdapter())
{
oleDbDataAdapter.SelectCommand = oleDbCommand;
dataTable = new
DataTable(item["TABLE_NAME"].ToString());
oleDbDataAdapter.Fill(dataTable);
_dataTables.Add(dataTable);
}
}
}
}
return _dataTables;
}
}
}
}
//////////////////////////////////////
above is the code which i am using to get data from excel but
///////////////////////////////////////////////////////
below is the nested loop in which i want to use data
/////////////////////////////////////////////////
for (ChromosomeID = 0; ChromosomeID < PopulationSize; ChromosomeID++)
{
Fitness = 0;
Altemp = (int[])AlPopulation[ChromosomeID];
for (int z = 0; z < 500; z++)
{
int[] NumberOfInputs = new int[9];
//// this is the array where in which data need to be added
InputBinary.AddRange(DecBin.Conversion2(NumberOfInputs));
for (i = 0; i < Altemp.Length; i++)
{
AlGenotype[i] = (int)Altemp[i];
}
Class1 ClsMn = new Class1();
AlActiveGenes = ClsMn.ListofActiveNodes(AlGenotype);
ClsNetworkProcess ClsNWProcess = new
ClsNetworkProcess();
AlOutputs = ClsNWProcess.NetWorkProcess(InputBinary,
AlGenotype, AlActiveGenes);
int value = 0;
for (i = 0; i < AlOutputs.Count; ++i)
{
value ^= (int)AlOutputs[i]; // xor the
output of the system
}
temp = Desired_Output[0];
if (value == temp) // compare system Output with
DesiredOutput bit by bit
Fitness++;
else
Fitness = Fitness;
}
AlFitness.Add(Fitness);
}
}
Zahra, no one on here that is answering questions is paid to answer them. We answer because others have helped us so we want to give back. Your attitude of "want a complete code with all reference assemblies used" seems rather demanding.
Having said that. xlsx is a proprietary format. You will need a tool like ExcelLibrary to be able to do this. Even though this answer is more related to writing to xlsx it should still give you some more options: https://stackoverflow.com/a/2603625/550975
I would suggest to use my tool Npoi.Mapper, which is based on popular library NPOI. You can import and export with POCO types directly with convention based mapping, or explicit mapping.
Get objects from Excel (XLS or XLSX)
var mapper = new Mapper("Book1.xlsx");
var objs1 = mapper.Take<SampleClass>("sheet2");
// You can take objects from the same sheet with different type.
var objs2 = mapper.Take<AnotherClass>("sheet2");
Export objects
//var objects = ...
var mapper = new Mapper();
mapper.Save("test.xlsx", objects, "newSheet", overwrite: false);
I have a cell that contains the placeholder "$$value" in the Excel sheet, the thing is that I need to replace the placeholder's actual value using Open XML and save it as separate workbook.
Here is the code that I tried...it is not replacing the actual value and also I'm unable to save the workbook. I need to sort out this issue.
WorksheetPart worksheetPart = (WorksheetPart)myWorkbook.WorkbookPart.GetPartById(sheet.Id);
DocumentFormat.OpenXml.Spreadsheet.Worksheet worksheet = worksheetPart.Worksheet;
string _txt1 = "$$value";
if (_txt1.Contains("$$"))
{
worksheet.InnerText.Replace(_txt1, "test");
}
by default Excel stores strings in the global (1 per workbook) SharedStringTablePart. So, this is the one you need to target. However, the OpenXML format also allows inline text inside the WorksheetParts. hence, a complete solution needs to look there as well.
Here's a sample app (with some inline comments):
using DocumentFormat.OpenXml.Packaging;
using x = DocumentFormat.OpenXml.Spreadsheet;
class Program
{
private static readonly string placeHolder = "$$value";
static void Main()
{
var templatePath = #"C:\Temp\template.xlsx";
var resultPath = #"C:\Temp\result.xlsx";
string replacementText = "test";
using (Stream xlsxStream = new MemoryStream())
{
// Read template from disk
using (var fileStream = File.OpenRead(templatePath))
fileStream.CopyTo(xlsxStream);
// Do replacements
ProcessTemplate(xlsxStream, replacementText);
// Reset stream to beginning
xlsxStream.Seek(0L, SeekOrigin.Begin);
// Write results back to disk
using (var resultFile = File.Create(resultPath))
xlsxStream.CopyTo(resultFile);
}
}
private static void ProcessTemplate(Stream template, string replacementText)
{
using (var workbook = SpreadsheetDocument.Open(template, true, new OpenSettings { AutoSave = true }))
{
// Replace shared strings
SharedStringTablePart sharedStringsPart = workbook.WorkbookPart.SharedStringTablePart;
IEnumerable<x.Text> sharedStringTextElements = sharedStringsPart.SharedStringTable.Descendants<x.Text>();
DoReplace(sharedStringTextElements, replacementText);
// Replace inline strings
IEnumerable<WorksheetPart> worksheetParts = workbook.GetPartsOfType<WorksheetPart>();
foreach (var worksheet in worksheetParts)
{
var allTextElements = worksheet.Worksheet.Descendants<x.Text>();
DoReplace(allTextElements, replacementText);
}
} // AutoSave enabled
}
private static void DoReplace(IEnumerable<x.Text> textElements, string replacementText)
{
foreach (var text in textElements)
{
if (text.Text.Contains(placeHolder))
text.Text = text.Text.Replace(placeHolder, replacementText);
}
}
Solution:
private static void ProcessTemplate(Stream template, Dictionary<string,string> toReplace)
{
using (var workbook = SpreadsheetDocument.Open(template, true, new OpenSettings { AutoSave = true }))
{
workbook.WorkbookPart.Workbook.CalculationProperties.ForceFullCalculation = true;
workbook.WorkbookPart.Workbook.CalculationProperties.FullCalculationOnLoad = true;
//Replace SheetNames
foreach (Sheet sheet in workbook.WorkbookPart.Workbook.Sheets)
foreach (var key in toReplace.Keys)
sheet.Name.Value = sheet.Name.Value.Replace(key, toReplace[key]);
foreach (WorksheetPart wsheetpart in workbook.WorkbookPart.WorksheetParts)
foreach (SheetData sheetd in wsheetpart.Worksheet.Descendants<x.SheetData>())
foreach (Row r in wsheetpart.Worksheet.Descendants<x.Row>())
foreach (Cell c in r.Descendants<x.Cell>())
if (c.CellFormula != null)
{
foreach (var key in toReplace.Keys)
c.CellFormula.Text = c.CellFormula.Text.Replace(key, toReplace[key]);
}
// Replace shared strings
SharedStringTablePart sharedStringsPart = workbook.WorkbookPart.SharedStringTablePart;
IEnumerable<x.Text> sharedStringTextElements = sharedStringsPart.SharedStringTable.Descendants<x.Text>();
for(int i =0;i<toReplace.Keys.Count; i++)
DoReplace(sharedStringTextElements, toReplace);
IEnumerable<x.Formula> sharedStringTextElementsF = sharedStringsPart.SharedStringTable.Descendants<x.Formula>();
for (int i = 0; i < toReplace.Keys.Count; i++)
DoReplaceFormula(sharedStringTextElementsF, toReplace);
// Replace inline strings
IEnumerable<WorksheetPart> worksheetParts = workbook.GetPartsOfType<WorksheetPart>();
foreach (var worksheet in worksheetParts)
{
var allTextElements = worksheet.Worksheet.Descendants<x.Text>();
DoReplace(allTextElements, toReplace);
var allTextElements2 = worksheet.Worksheet.Descendants<x.Formula>();
DoReplaceFormula(allTextElements2, toReplace);
}
} // AutoSave enabled
}