I'm currently working on some Excel import/export using c#,
her is my export function:
private void myButton11_Click(object sender, EventArgs e)
{
Microsoft.Office.Interop.Excel.Application excel;
Microsoft.Office.Interop.Excel.Workbook excelworkbook;
Microsoft.Office.Interop.Excel.Worksheet excelsheet;
Microsoft.Office.Interop.Excel.Range excelCellFormat;
excel = new Microsoft.Office.Interop.Excel.Application();
excel.Visible = false;
excel.DisplayAlerts = false;
excelworkbook = excel.Workbooks.Add(Type.Missing);
excelsheet = (Microsoft.Office.Interop.Excel.Worksheet)excelworkbook.ActiveSheet;
excelsheet.Name = "dataToExcel";
// fill in data
excelsheet.Cells[1, 1] = "test";
// left it pretty much empty so you have a nice exemple
excelCellFormat = excelsheet.Range[excelsheet.Cells[1, 1], excelsheet.Cells[max+1, 13]];
excelCellFormat.EntireColumn.AutoFit();
Microsoft.Office.Interop.Excel.Borders border = excelCellFormat.Borders;
border.LineStyle = Microsoft.Office.Interop.Excel.XlLineStyle.xlContinuous;
border.Weight = 2d;
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "Excel (*.xlsx)|*.xlsx";
sfd.Title = "Sauvegarde";
sfd.ShowDialog();
if(sfd.FileName != "")
{
System.IO.FileStream fs = (System.IO.FileStream)sfd.OpenFile();
// save excel
excelworkbook.SaveAs(fs,
System.Reflection.Missing.Value,
System.Reflection.Missing.Value,
System.Reflection.Missing.Value,
System.Reflection.Missing.Value,
System.Reflection.Missing.Value,
Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange,
System.Reflection.Missing.Value,
System.Reflection.Missing.Value,
System.Reflection.Missing.Value,
System.Reflection.Missing.Value,
System.Reflection.Missing.Value);
fs.Close();
}
excel.Quit();
// for a pdf version
//excelworkbook.ExportAsFixedFormat(Microsoft.Office.Interop.Excel.XlFixedFormatType.xlTypePDF,
// Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "//dataAsPDF.pdf",
// Microsoft.Office.Interop.Excel.XlFixedFormatQuality.xlQualityStandard,
// true, true, 1, 10, false);
}
my problem is, when saving using the external window, It saves properly... but as an empty file, like totally empty (opening it with notepad shows an empty file)
any idea what my problem could be?
thanks!
Here is a generic code sample which creates a new file, renames a sheet, adds a sheet then sets text of the first sheet cell A1 to Hello Excel.
Excel class
using System;
using System.Diagnostics;
using System.Linq;
using System.IO;
using System.Runtime.InteropServices;
using Excel = Microsoft.Office.Interop.Excel;
namespace ExcelInteropApp.Classes
{
public class ExcelOperations
{
public delegate void OnAction(string sender);
public static event OnAction ActionHandler;
/// <summary>
/// create an excel file, rename sheet1 (default sheet),
/// create another worksheet, rename it and re-order to end.
/// </summary>
/// <param name="fileName">path and file name for excel file</param>
/// <param name="firstWorkSheetName">name for default sheet</param>
/// <param name="secondWorkSheetName">name for newly added sheet</param>
public static (bool success, Exception exception) CreateExcelFile(string fileName, string firstWorkSheetName, string secondWorkSheetName, bool open)
{
try
{
if (File.Exists(fileName))
{
File.Delete(fileName);
}
Excel.Application xlApp;
Excel.Workbooks xlWorkBooks;
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;
Excel.Sheets xlWorkSheets;
xlApp = new Excel.Application { DisplayAlerts = false };
xlWorkBooks = xlApp.Workbooks;
xlWorkBook = xlWorkBooks.Add();
xlWorkSheets = xlWorkBook.Sheets;
xlWorkSheet = (Excel.Worksheet)xlWorkSheets[1];
xlWorkSheet.Name = firstWorkSheetName;
ActionHandler?.Invoke("renamed first sheet");
Excel.Worksheet xlNewSheet = (Excel.Worksheet)xlWorkSheets
.Add(xlWorkSheets[1],
Type.Missing,
Type.Missing,
Type.Missing);
xlNewSheet.Move(System.Reflection.Missing.Value, xlWorkSheets[xlWorkSheets.Count]);
xlNewSheet.Name = secondWorkSheetName;
Excel.Range xlRange1 = null;
xlRange1 = xlWorkSheet.Range["A1"];
xlRange1.Value = "Hello Excel";
Marshal.FinalReleaseComObject(xlRange1);
xlRange1 = null;
ActionHandler?.Invoke("Done with add sheet");
Marshal.FinalReleaseComObject(xlNewSheet);
xlNewSheet = null;
xlWorkBook.SaveAs(fileName);
ActionHandler?.Invoke("Saved file");
xlWorkBook.Close();
xlApp.UserControl = true;
xlApp.Quit();
Marshal.FinalReleaseComObject(xlWorkSheets);
xlWorkSheets = null;
Marshal.FinalReleaseComObject(xlWorkSheet);
xlWorkSheet = null;
Marshal.FinalReleaseComObject(xlWorkBook);
xlWorkBook = null;
Marshal.FinalReleaseComObject(xlWorkBooks);
xlWorkBooks = null;
Marshal.FinalReleaseComObject(xlApp);
xlApp = null;
ActionHandler?.Invoke($"Clean-up: {(Process.GetProcesses().Any((p) => p.ProcessName.Contains("EXCEL")) ? "Released" : "Not released")}");
if (open)
{
ActionHandler?.Invoke("Opening");
Process.Start(fileName);
}
else
{
ActionHandler?.Invoke("Not opening");
}
return (true, null);
}
catch (Exception exception)
{
return (false, exception);
}
}
}
}
Form code, one button and a list box
using System;
using System.IO;
using System.Windows.Forms;
using ExcelInteropApp.Classes;
namespace ExcelInteropApp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void CreateExcelButton1_Click(object sender, EventArgs e)
{
listBox1.Items.Clear();
ExcelOperations.ActionHandler += ExcelOperationsOnActionHandler;
string fileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Demo.xlsx");
string firstSheet = "Karen";
string secondSheet = "Karen 1";
var (success, exception) = ExcelOperations.CreateExcelFile(fileName,firstSheet, secondSheet, openWhenDoneCheckBox.Checked);
if (success == false)
{
Console.WriteLine(exception.Message);
}
ExcelOperations.ActionHandler -= ExcelOperationsOnActionHandler;
}
private void ExcelOperationsOnActionHandler(string sender)
{
listBox1.Items.Add(sender);
}
}
}
Related
Say a new Excel file is opened and data is entered into it. Could an external C# application hook onto the Excel process and get the data from it? Also, the Excel file is never saved into a file.
Would this be difficult to do and also could you point me in the right direction on how to achieve this.
Just add this code in the code behind of a windows form application that has a button named "button1" added on it. This sample code will iterate through cells of the Excel file and display the content of each cell in a Message Box. Of course a project reference to "Microsoft.Office.Interop.Excel" is required.
And don't forget to actually create the excel file, in this example I used this path "C:\ExcelData\DataToImp.xlsx".
using Excel = Microsoft.Office.Interop.Excel;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Excel.Application xlApp;
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;
Excel.Range range;
string str;
int rCnt = 0;
int cCnt = 0;
xlApp = new Excel.Application();
xlWorkBook = xlApp.Workbooks.Open("C:\\ExcelData\\DataToImp.xlsx", 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
range = xlWorkSheet.UsedRange;
for (int rowIndex = 1; rowIndex <= range.Rows.Count; rowIndex++)
{
for (int columnIndex = 1; columnIndex <= range.Columns.Count; columnIndex++)
{
Excel.Range rangeTest = range.Cells[rowIndex, columnIndex] as Excel.Range;
if (rangeTest.MergeCells)// && rangeTest.Value2 == null)
{
//continue;
int columns = rangeTest.Columns.Count;
columnIndex += columns;
}
MessageBox.Show("m " + (string)rangeTest.Value2);
}
}
xlWorkBook.Close(true, null, null);
xlApp.Quit();
releaseObject(xlWorkSheet);
releaseObject(xlWorkBook);
releaseObject(xlApp);
}
private void releaseObject(object obj)
{
try
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
obj = null;
}
catch (Exception ex)
{
obj = null;
MessageBox.Show("Unable to release the Object " + ex.ToString());
}
finally
{
GC.Collect();
}
}
I have a c# application with the following features:
read a password from a config file.
export an Excel file.
when I read the password at fist: it's ok. but once I export the Excel file, I can't no more read the password from config file. the following instruction fail.
xmlDoc.Load("Cfg.xml");
this issue appear only on Windows XP. on windows 7 it's ok.
the code for reading password from config file:
private void OK_Click(object sender, EventArgs e)
{
try
{
// Check password
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("Cfg.xml");
XmlNode node = xmlDoc.SelectSingleNode("Config/ManagerPW");
if (node != null)
{
string MangerPW = node.Attributes[0].Value;
PCCrypto PWCrypto = new PCCrypto();
if (PWCrypto.verifyMd5(this.Password.Text, MangerPW) == true)
{
isCorrectPassWord = true;
this.Dispose();
}
else
{
MessageBox.Show("Incorrect Password!", "PW Authentication", MessageBoxButtons.OK,
MessageBoxIcon.Error);
this.Password.Text = "";
}
}
else
{
MessageBox.Show("You tried to perform an unauthorized operation!", "PW Authentication", MessageBoxButtons.OK,
MessageBoxIcon.Error);
this.Password.Text = "";
}
}
catch
{
MessageBox.Show("Error in loading configuration file", "Configuration Error", MessageBoxButtons.OK,
MessageBoxIcon.Error);
this.Dispose();
}
}
the code of exporting Excel file
public bool exportToExcel(string path)
{
bool bRet = true;
int columnsNum = resultList.Columns.Count - 1;
int rowsNum = resultList.Items.Count;
object[,] array = new object[rowsNum + 1, columnsNum];
//Change Current System Time to US
System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.CreateSpecificCulture("en-US");
Excel.Application xlApp = new Excel.ApplicationClass();
Excel.Workbooks xlWorkBooks = xlApp.Workbooks;
Excel.Workbook xlWorkBook = xlWorkBooks.Add(Type.Missing);
Excel.Sheets xlWorkSheets = xlWorkBook.Sheets;
Excel.Worksheet xlWorkSheet = (Excel.Worksheet)xlWorkSheets[1];
//disable alerts
xlApp.DisplayAlerts = false;
//Add Header to array
for (int i = 0; i < columnsNum; i++)
{
array[0, i] = resultList.Columns[i + 1].Text;
}
//Add Listview data to array
for (int r = 0; r < rowsNum; r++)
{
for (int c = 0; c < columnsNum; c++)
{
this.Invoke(new MethodInvoker(delegate
{
array[r + 1, c] = resultList.Items[r].SubItems[c+1].Text;
}));
}
}
//Save array data into excel
Excel.Range c1 = (Excel.Range)xlWorkSheet.Cells[1, 1];
Excel.Range c2 = (Excel.Range)xlWorkSheet.Cells[rowsNum + 1, columnsNum];
Excel.Range xlRange = xlWorkSheet.get_Range(c1, c2);
xlRange.Borders.LineStyle = Excel.XlLineStyle.xlContinuous;
xlRange.EntireColumn.NumberFormat = "#";
xlRange.Value2 = array;
xlRange.EntireColumn.AutoFit();
//Add Header color
xlWorkSheet.get_Range("A1", "I1").Interior.Color = ColorTranslator.ToOle(Color.Aquamarine);
//Save Excel file
try
{
xlWorkBook.SaveAs(#path, Excel.XlFileFormat.xlWorkbookNormal, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Excel.XlSaveAsAccessMode.xlExclusive, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
xlWorkBook.Close(true, Type.Missing, Type.Missing);
}
catch
{
bRet = false;
}
xlWorkBooks.Close();
xlApp.Application.Quit();
xlApp.Quit();
releaseObject(c1);
releaseObject(c2);
releaseObject(xlRange);
releaseObject(xlWorkSheet);
releaseObject(xlWorkSheets);
releaseObject(xlWorkBook);
releaseObject(xlWorkBooks);
releaseObject(xlApp);
return bRet;
}
Try specifying the full path in
xmlDoc.Load("Cfg.xml");
e.g.
xmlDoc.Load(#"C:\myfolder\Cfg.xml");
The current folder is being changed when you export the excel.
I have the following code which write a value to the activecell in the excel. It works fine 50% of the time but not the last 50% it does not.
Why??
void ValueToExcel(string value)
{
Excel.Application oXL=null;
Excel.Workbook oWB=null;
Excel.Worksheet oSheet=null;
Excel.Range rng =null;
try
{
oXL = (Excel.Application)Marshal.GetActiveObject("Excel.Application");
oXL.Visible = true;
oWB = (Excel.Workbook)oXL.ActiveWorkbook;
oSheet = oWB.ActiveSheet;
rng = oSheet.Application.ActiveCell;
rng.Value = value;
rng.Application.ActiveCell.Offset[1, 0].Select();
}
catch (Exception EX)
{
MessageBox.Show(EX.Message);
}
}
I tried to change the code but it still not works. It seems that the value is written to some other Excel application.
void ValueToExcel(string value)
{
//Gets Excel and gets Activeworkbook and worksheet
Excel.Application oXL=null;
Excel.Workbook oWB=null;
Excel.Worksheet oSheet=null;
Excel.Range rng =null;
try
{
while (oXL==null)
oXL = (Excel.Application)Marshal.GetActiveObject("Excel.Application");
oXL.Visible = true;
while (oWB == null)
oWB = (Excel.Workbook)oXL.ActiveWorkbook;
while (oSheet == null)
oSheet = oWB.ActiveSheet;
while (rng == null)
rng = oSheet.Application.ActiveCell;
while(rng.Value=="")
rng.Value = value;
MessageBox.Show(value);
Console.Beep();
rng.Application.ActiveCell.Offset[1, 0].Select();
}
catch (Exception EX)
{
MessageBox.Show(EX.Message);
}
}
somebody have some help?
I'm looking for how to export a datagrid (or dataSet) (not datagridview) to Excel using dialog box which saves data in specific place, I am working on VS 2003 Winform not Webform.
This is my code:
I just need too open a dialog box to let the user choose where he wants to put his file:
private void button2_Click(object sender, System.EventArgs e)
{
#region
string data = null;
int i = 0;
int j = 0;
Excel.Application xlApp ;
Excel.Workbook xlWorkBook ;
Excel.Worksheet xlWorkSheet ;
object misValue = System.Reflection.Missing.Value;
xlApp = new Excel.ApplicationClass();
xlWorkBook = xlApp.Workbooks.Add(misValue);
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
for (i = 0; i <= dsSelectionListeDiffere.Tables[0].Rows.Count - 1; i++)
{
for (j = 0; j <= dsSelectionListeDiffere.Tables[0].Columns.Count - 1; j++)
{
data = dsSelectionListeDiffere.Tables[0].Rows[i].ItemArray[j].ToString();
xlWorkSheet.Cells[i + 1, j + 1] = data;
}
}
xlWorkBook.SaveAs("csharp.net-informations.xls", Excel.XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, Excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue);
xlWorkBook.Close(true, misValue, misValue);
xlApp.Quit();
releaseObject(xlWorkSheet);
releaseObject(xlWorkBook);
releaseObject(xlApp);
MessageBox.Show("Excel file created , you can find the file c:\\csharp.net-informations.xls");
#endregion
}
and i have another code it works too :
#region
//// lblMessage.Visible = true;
//// lblMessage.Text = "";
// // Export all the details
// try
// {
// // Get the datatable to export
// DataTable dt = dsSelectionListeDiffere.Tables[0].Copy();
// dsSelectionListeDiffere = FrmFonctionPrincipale.getListeDifferesParClient(1);
// // Export all the details to Excel
//
//
// RKLib.ExportData.Export objExport = new RKLib.ExportData.Export("Win");
// objExport.ExportDetails(dt, Export.ExportFormat.Excel, "C:\\EmployeesInfo.xls");
// MessageBox.Show("Exporté Avec Succès dans C:\\EmployeesInfo.xls");
// }
// catch(Exception Ex)
// {
// MessageBox.Show(Ex.Message);
//// lblMessage.Text = Ex.Message;
// }
#endregion
If you don't need to change the filename, but only the folder where this file is saved, then you can use the FolderBrowserDialog to ask just the folder where the file will be saved
private void button2_Click(object sender, System.EventArgs e)
{
FolderBrowserDialog fbd = new FolderBrowserDialog();
fbd.Description = "Select the destination folder";
fbd.ShowNewFolderButton = true;
fbd.RootFolder = Environment.SpecialFolder.Personal;
if( fbd.ShowDialog() == DialogResult.OK )
{
string folderName = fbd.SelectedPath;
.... the rest of your excel export code .....
// Pass the full path to the SaveAs method
string fullPathName = Path.Combine(folderName, "csharp.net-informations.xls");
xlWorkBook.SaveAs(fullPathName, .....);
.....
MessageBox.Show("Excel file created , you can find the file in: " + fullPathName);
}
If you need to change also the file name, then you need to use a SaveFileDialog instance.
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "Excel files (*.xls)|*.xls|All files (*.*)|*.*" ;
sfd.FilterIndex = 1 ;
sfd.RestoreDirectory = true ;
sfd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
if(sfd.ShowDialog() == DialogResult.OK)
{
if(sfd.FileName.Length > 0)
{
... the rest of your excel code here ....
// sfd.FileName already contains the full path so
xlWorkBook.SaveAs(sfd.FileName, .....);
}
}
else
{
if(MessageBox.Show("Are you sure you want to quit without saving?", "Quitting",
MessageBoxButtons.YesNo) == DialogResult.No)
{
// This important to stop the Form to close if this button is the Cancel/AcceptButton
// or its property DialogResult is not DialogResult.None
this.DialogResult = DialogResult.None;
}
}
I am trying to export data to an Excel template. I have multiple tabs in the workbook. The worksheet tab I want to export to is called "Feasibility". Question is: how can I export to this specific worksheet name?
using Excel = Microsoft.Office.Interop.Excel;
//excel output variables
private string excelFileName = SqlDB.GetFolderTemplates() + SqlDB.GetFileEngOrd();
private static Excel.Application xlsApp;
private static Excel.Workbooks workbooks;
private static Excel.Workbook workbook;
private Excel.Worksheet worksheet;
private void btnFeasibility_Click(object sender, EventArgs e)
{
xlsApp = new Excel.ApplicationClass();
if (xlsApp == null)
{
MessageBox.Show(Constants.EXCEL_INSTALL);
return;
}
try
{
xlsApp.Visible = true;
workbooks = xlsApp.Workbooks;
workbook = xlsApp.Workbooks.Open(excelFileName);
//PROBLEM IS HERE -- HOW CAN I GO TO THE WORKSHEET NAMED "FEASIBILITY"
worksheet = (Excel.Worksheet)workbook.Sheets[1];
worksheet.Select();
worksheet.Cells[3, 4] = newEngOrd.CustName;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
//release excel
System.Runtime.InteropServices.Marshal.ReleaseComObject(worksheet);
worksheet = null;
System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook);
workbook = null;
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlsApp);
xlsApp = null;
GC.GetTotalMemory(false);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.GetTotalMemory(true);
MessageBox.Show("Export Complete");
}
}
Run a for look through all the sheets, and see if the name match.
int foundNr=-1;
InteropExcel.Sheets sheets = workbook.Sheets;
InteropExcel.Sheet tempSheet = null;
for (int sheetIndex = 1; sheetIndex <= sheets.Count; sheetIndex++)
{
tempSheet = (InteropExcel.Worksheet)sheets[sheetIndex];
if (tempSheet.Name == "Feasibility")
{
foundNr = sheetIndex;
Marshal.FinalReleaseComObject(tempSheet);
tempSheet = null;
break
}
Marshal.FinalReleaseComObject(tempSheet);
tempSheet = null;
}
if (foundNr != -1)
{
sheet = (InteropExcel.Worksheet)sheets[foundNr];
}
The way I do release is to assign null to your COM variables. Then you call FinalReleaseComObject if it is not null in the finally statement. That way it gets released even if there is an exception in the method.
Excel process not closing
InteropExcel.Sheets sheets = null
try
{
sheets = ....;
}
finally
{
if (sheets != null)
{
Marshal.FinalReleaseComObject(sheets);
sheets = null;
}
}
did you tried the Name property?
check this Worksheet documentation: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.worksheet_members.aspx