I have this code that export an excel file using c# from 1 listview. My problem now is if I have 2 listviews that will be generated in 1 excel file, my plan is listview1 is for sheet1 and listview2 is for sheet2.
this is my code generates listview1 to excel into sheet1:
string[] st = new string[listView1.Columns.Count];
DirectoryInfo di = new DirectoryInfo(Environment.ExpandEnvironmentVariables("%USERPROFILE%") + #"\Desktop\");
if (di.Exists == false)
di.Create();
fileName f = new fileName();
if (f.ShowDialog() == DialogResult.OK)
{
StreamWriter sw = new StreamWriter(Environment.ExpandEnvironmentVariables("%USERPROFILE%") + #"\Desktop\" + f.Filenam + ".xls", false);
sw.AutoFlush = true;
string header = "";
for (int col = 0; col < listView1.Columns.Count; col++)
{
header += listView1.Columns[col].Text.ToString() + "\t";
}
sw.Write(header);
int rowIndex = 1;
int row = 0;
string st1 = "";
for (row = 0; row < listView1.Items.Count; row++)
{
if (rowIndex <= listView1.Items.Count)
rowIndex++;
st1 = "\n";
for (int col = 0; col < listView1.Columns.Count; col++)
{
st1 = st1 + listView1.Items[row].SubItems[col].Text.ToString() + "\t";
}
sw.Write(st1);
}
sw.Close();
FileInfo fil = new FileInfo(Environment.ExpandEnvironmentVariables("%USERPROFILE%") + #"\Desktop\" + f.Filenam + ".xls");
if (fil.Exists == true)
MessageBox.Show("Process Completed", "Export to Excel", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
I have used EPPlus, its free, give performance benefits, and provides many Excel functions. Other option you can look for is Microsoft InterOp for Excel export, but it has performance problems.
As Irfan already mentioned, you could do that with Microsoft.Office.Interop
Excel.Application xlsApp = new Excel.Application();
Excel.Workbook workbook;
workbook = xlsApp.Workbooks.Open(configuration.XLSExportedFile, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
foreach (Excel.Worksheet sheet in workbook.Sheets)
{
workbook.Activate();
sheet.Activate();
}
That would help you to step through all your sheets in your Excel file.
Now in case you want to expand it with multiple sheets, you can read C# how to add Excel Worksheet programmatically Office XP / 2003 in order to find how to add additional sheets.
What you could do now, is put your text into a variable for example HTML or any kind of information from your listbox.
string html = Clipboard.GetText(TextDataFormat.Html);
Now you can play around with the Clipboard(alternative solution, but to avoid).
Clipboard.SetText(html);
It actually enters information into your Clipboard, what you could do is pass all your listbox values into the Clipboard.
And now the final step would be to paste it at the position that you want.
sheet.Range(cellmapp).PasteSpecial();
Where cellmap is supposed to be for example A1. In case your text that you have in your listbox is too long you can adapt your rows/columns.
//Auto fits all columns and rows
//https://stackoverflow.com/questions/14748322/c-sharp-autofit-method-for-excel-sheet
sheet.Columns.AutoFit();
sheet.Rows.AutoFit();
Don't forget, if you work with COM processes, close every object and file.
workbook.SaveAs(configuration.XLSExportedFile);
workbook.Close();
xlsApp.Quit();
xlsApp.Dispose();
I don't say that would be the best solution to do, but you could look up for OpenXML also.
I've used ClosedXML before, the syntax is really clean and simple and you can get this sort of task done in just a few lines
This block shows how to add a list to a new sheet and save it
List<string> list = new List<string>();
var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add("Sample Sheet");
worksheet.Cell(1, 1).Value = list;
workbook.SaveAs("HelloWorld.xlsx");
Related
I have a UWP app that I am developing in Visual Studio. It successfully makes api calls and returns data. So far I have only bound this data to grid views for displaying. Now however I would like to add a "save" function that will export this data to an excel document.
Any thoughts on how I could go about this ?
Any help is greatly appreciated.
I would advise you NOT to use excel directly, but use a different approach; try to get a nuget package to do the work for you (handling excel etc). Excel itself (as interop library) is a pain in the proverbial but cheeks.
A good one : https://www.nuget.org/packages/EPPlus/
You can still use the same data you get for your grid, but export it to excel. There are numerous examples to be found for above mentioned EPPLus.
try this
private void button_SAVE(object sender, EventArgs e)
{
// creating Excel Application
Microsoft.Office.Interop.Excel._Application app = new Microsoft.Office.Interop.Excel.Application();
// creating new WorkBook within Excel application
Microsoft.Office.Interop.Excel._Workbook workbook = app.Workbooks.Add(Type.Missing);
// creating new Excelsheet in workbook
Microsoft.Office.Interop.Excel._Worksheet worksheet = null;
// see the excel sheet behind the program
app.Visible = true;
// get the reference of first sheet. By default its name is Sheet1.
// store its reference to worksheet
worksheet = workbook.Sheets["Sheet1"];
worksheet = workbook.ActiveSheet;
// changing the name of active sheet
worksheet.Name = "Exported from gridview";
// storing header part in Excel
for (int i = 1; i < dataGridView1.Columns.Count + 1; i++)
{
worksheet.Cells[1, i] = dataGridView1.Columns[i - 1].HeaderText;
}
// storing Each row and column value to excel sheet
for (int i = 0; i < dataGridView1.Rows.Count - 1; i++) {
for (int j = 0; j < dataGridView1.Columns.Count; j++) {
worksheet.Cells[i + 2, j + 1] = dataGridView1.Rows[i].Cells[j].Value.ToString();
}
}
// save the application
workbook.SaveAs("c:\\output.xls", Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlExclusive, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
// Exit from the application
app.Quit();
See Sunteen's reply in this post. There are exist libraries which can do this.(Example doc)
If you want to create csv yourself, there is a blog about parsing CSV.
I am reading an Excel sheet programmatically using Microsoft.Office.Interop.Excel in C#.
I am able to read it row by row and converting each row to a string arrray. Then, I am adding these rows to a DataTable.
Every thing works fine except the one of the column in the Excel contains Date values, and when I fetch it from the Excel Range object and cast it to string array, the date values gets converted to some sort of decimal numbers.
For e.g.-
If the date value is '6/4/2016 8:14:39 PM', I get the value as '42522.5224305556'
If the date value is '5/27/2016 1:10:12 PM', I get the value as '42517.54875'
Below is my code-
private System.Data.DataTable GetTicketsFromExcel(string excelFilePath)
{
System.Data.DataTable dtblTickets = new System.Data.DataTable();
Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
Worksheet ws = new Worksheet();
Workbook wb = null;
try
{
wb = excelApp.Workbooks.Open(excelFilePath, Type.Missing, Type.Missing,
Type.Missing, Type.Missing,
Type.Missing, Type.Missing,
Type.Missing, Type.Missing,
Type.Missing, Type.Missing,
Type.Missing, Type.Missing,
Type.Missing, Type.Missing);
ws = (Microsoft.Office.Interop.Excel.Worksheet)wb.Sheets.get_Item(1);
Range usedRange = ws.UsedRange;
Range rowRange;
string[] lsRow = null;
for (int i = 1; i <= usedRange.Columns.Count; i++)
{
dtblTickets.Columns.Add(usedRange.Cells[5, i].Value.ToString());
}
string sortColumn = "Reported On";
string sortDirection = "DESC";
dtblTickets.Columns[sortColumn].DataType = typeof(DateTime);
for (int row = 6; row <= usedRange.Rows.Count; row++)
{
//dtblTickets.Columns.Add()
rowRange = usedRange.Rows[row];
object[,] cellValues = (object[,])rowRange.Value2;
lsRow = cellValues.Cast<object>().Select(o => Convert.ToString(o)).ToArray<string>();
dtblTickets.Rows.Add(lsRow.ToArray());
}
dtblTickets.DefaultView.Sort = sortColumn + " " + sortDirection;
dtblTickets = dtblTickets.DefaultView.ToTable();
}
catch (Exception ex)
{
}
finally
{
wb.Close();
excelApp.Quit();
Marshal.ReleaseComObject(ws);
Marshal.ReleaseComObject(wb);
Marshal.ReleaseComObject(excelApp);
ws = null;
wb = null;
excelApp = null;
}
return dtblTickets;
}
Please note-
I don't want to use OLEDB to read and export this
I want to able to read the Excel row by row (without extracting each cell value and converting them)
I don't want to convert/format the original Excel document data
Can someone please help me with this?
Not quite sure, if you want to solve the problem this way, but one way is to change the property of the Cells (or the whole row or column) in Excel.
Right click on a Cell
Format Cells
Under "Number" select Category "Text" for the Cells.
I've tested it and it worked.
I like to delete rows from multiple worksheet in Excel. Currently my code only delete rows from active worksheet. I am looking for a specific value on the cell then when I find this value then I am deleting all the rows up to that value that stored on that row.
Code
private void button2_Click(object sender, EventArgs e)
{
Microsoft.Office.Interop.Excel.Application Excel = new Microsoft.Office.Interop.Excel.Application();
Workbook workBook = Excel.Workbooks.Open(FilePath);
Worksheet ws = (Worksheet)Excel.ActiveSheet;
for (int j = 1; j <= 10; j++)
{
for (int i = 1; i <= 20; i++)
{
if (Convert.ToString(((Microsoft.Office.Interop.Excel.Range)ws.Cells[j, i]).Value2) == "Matter")
{
for (int r = 1; r <= j; r++)
{
((Range)ws.Rows[r]).Delete(XlDeleteShiftDirection.xlShiftUp);
MessageBox.Show(Convert.ToString(r));
workBook.SaveAs(#"C:\Users\Separate\New.xlsx", Microsoft.Office.Interop.Excel.XlFileFormat.xlWorkbookDefault, Type.Missing, Type.Missing,
false, false, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange,
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
}
}
}
}
workBook.Close(Type.Missing, Type.Missing, Type.Missing);
Excel.Quit();
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(Excel);
Excel = null;
}
I would highly suggest trying to use ClosedXML as it makes working with Excel so much easier. Specifically with ClosedXML you can have a line like this:
ws.Row(5).Delete();
where ws is your initialized worksheet, and it handles the heavy lifting for deleting that row.
Getting or setting cell data is just as simple:
ws.Cell(2, 2).Value = "Initial Value";
or alternatively
ws.Cell("B2").Value = "Value;
They also have type specific value assignment like this:
ws.Cell("B2").SetValue<T>(object);
The documentation is very thorough, and you can get the package through nuget (note it requires the DocumentFormat.OpenXML package installed as well)
EDIT:
I missed the part about multiple worksheets so here it is. The XLWorkbook type has a property Worksheets, which is an enumerable of all the worksheets in the workbook. Use this to get the worksheets you want to delete rows on
I am using below code to export excel using Microsoft.Office.Interop.Excel. [Ms office 2003].
I need to export around 150000 rows can have maximum 300 columns.
but getting error on Get_Range. [ Working fine for 50000 rows and 40 columns]
public static void ExportToExcel(DataTable dt, string outputPath)
{
try
{
// Create the Excel Application object
ApplicationClass excelApp = new ApplicationClass();
// Create a new Excel Workbook
Workbook excelWorkbook = excelApp.Workbooks.Add(Type.Missing);
int sheetIndex = 0;
// Copy each DataTable
// Copy the DataTable to an object array
object[,] rawData = new object[dt.Rows.Count + 1, dt.Columns.Count];
// Copy the column names to the first row of the object array
for (int col = 0; col < dt.Columns.Count; col++)
{
rawData[0, col] = dt.Columns[col].ColumnName;
}
// Copy the values to the object array
for (int col = 0; col < dt.Columns.Count; col++)
{
for (int row = 0; row < dt.Rows.Count; row++)
{
rawData[row + 1, col] = dt.Rows[row].ItemArray[col];
}
}
// Calculate the final column letter
string finalColLetter = string.Empty;
string colCharset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int colCharsetLen = colCharset.Length;
if (dt.Columns.Count > colCharsetLen)
{
finalColLetter = colCharset.Substring(
(dt.Columns.Count - 1) / colCharsetLen - 1, 1);
}
finalColLetter += colCharset.Substring(
(dt.Columns.Count - 1) % colCharsetLen, 1);
// Create a new Sheet
Worksheet excelSheet = (Worksheet)excelWorkbook.Sheets.Add(
excelWorkbook.Sheets.get_Item(++sheetIndex),
Type.Missing, 1, XlSheetType.xlWorksheet);
excelSheet.Name = "data";
// Fast data export to Excel
string excelRange = string.Format("A1:{0}{1}",
finalColLetter, dt.Rows.Count + 1);
//excelSheet.get_Range(
excelSheet.get_Range(excelRange, Type.Missing).Value2 = rawData;
// Mark the first row as BOLD
((Range)excelSheet.Rows[1, Type.Missing]).Font.Bold = true;
// Save and Close the Workbook
excelWorkbook.SaveAs("C:\\Dashsrv\\data.Xls", XlFileFormat.xlWorkbookNormal, Type.Missing,
Type.Missing, Type.Missing, Type.Missing, XlSaveAsAccessMode.xlExclusive,
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
excelWorkbook.Close(true, Type.Missing, Type.Missing);
excelWorkbook = null;
// Release the Application object
excelApp.Quit();
excelApp = null;
// Collect the unreferenced objects
GC.Collect();
GC.WaitForPendingFinalizers();
MessageBox.Show("File created at");
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Getting error on below line of code
[{"Exception from HRESULT: 0x800A03EC"}]
excelSheet.get_Range(excelRange, Type.Missing).Value2 = rawData;
IS Get_Range() has some limitation for rows/Columns?
As I know for MS Office 2003 column's limit is 256, not sure about rows limt.
Thanks
Excel 2003 can have a maximum of 65536 rows in a single worksheet (specification)
Excel 2007 and newer can have 1048576 rows (specification: Excel 2007, Excel 2010 and Excel 2013)
Excel 2003 row limit is 65,536 - http://support.microsoft.com/kb/120596
I have a list of array List<float[]> and I want to create excel file so i can email the arrays for testing. I need it in excel and not XML - serialization will not do here.
I want to have each array in its own worksheet(tab) - here CSV goes out of the window :(
Can someone guide me what is the best approach for achieving it? using Microsoft.Office.Interop.Excel seems like overkill for my needs but if this is the best way i would appreciate a sample on how to do it.
Thanks.
Hello you can follow theses steps
1 Add Reference to Microsoft.Office.Interop.Excel;
2 Add using Microsoft.Office.Interop.Excel in your class
3 try this code
Reading
var applicationClass = new Application();
var workbook = applicationClass.Workbooks.Open(workbookPath, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing
, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
var worksheet = workbook.GetWorksheet(sheet);
var usedRange = worksheet.UsedRange;
for (int i = beginIndexRow; i < usedRange.Rows.Count; i++)
{
var input = (Range)usedRange.Cells[i, 1]; //I read the first column
}
workbook.Close(false, workbookPath, null);
applicationClass.Quit();
while (Marshal.ReleaseComObject(usedRange) > 0)
{ }
while (Marshal.ReleaseComObject(worksheet) > 0)
{ }
while (Marshal.ReleaseComObject(workbook) > 0)
{ }
while (Marshal.ReleaseComObject(applicationClass) > 0)
{ }
Writing
usedRange.Cells[i, 1].Value2 = .....; //I write the first column
Using Interop is probably the simplest thing to do.
If l is your list:
Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.ApplicationClass();
xlApp.Visible = true;
xlApp.Workbooks.Add(misValue);
int nWS = xlApp.ActiveWorkbook.Worksheets.Count;
for (int i = nWS; i < l.Count; i++)
xlApp.ActiveWorkbook.Worksheets.Add(misValue, misValue, misValue, misValue);
int iWS = 1;
foreach (float[] ff in l)
{
Microsoft.Office.Interop.Excel.Worksheet ws = (Microsoft.Office.Interop.Excel.Worksheet)xlApp.ActiveWorkbook.Worksheets[iWS++];
int idxRow = 1;
foreach (float aFloat in ff)
ws.Cells[idxRow++, 1] = aFloat;
}
I found the ClosedXML api pretty easy to work with and way faster because it generate Excel XML instead.
Here's how to do it in ClosedXML:
var list = new List<float[]>() { new float[] { 1, 2 }, new float[] { 3, 4 } };
var wb = new XLWorkbook();
int i = 1;
foreach (var l in list)
wb.AddWorksheet("Sheet" + i++).FirstCell().Value = l;
wb.SaveAs("Arrays.xlsx");
You could take a look at Matt Hidinger's open source project - DoddleReport - "Out of the box it can render reports to Excel, PDF, HTML, and CSV – fully pluggable of course".
It can generate tabular reports from any IEnumerable datasource