Export to specific Excel worksheet name - c#

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

Related

c# data to excel export gives empty file

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);
}
}
}

Is it possible to import data from Excel through memory?

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();
}
}

xml load after exporting excel file failed

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.

Writing to the activecell in 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?

Just another Excel COM issue

I have an app that imports data from an excel file. It creates an excel COM object and reads data from it. After that i release all object and release all excel objects.
It does all this on a windows server, using excel installed on this machine. The import files are stored on user's machines.
If i try to import data from an file that is also open in Excel on the user's machine, then the app can't release the Excel COM objects.
Any ideea how can i fix this (close that instance anyway) ?
Thanks!
I've added my code :
public DataTable DoImportToDataTable(BackgroundWorker worker, string strPath, int columnCount, bool bIgnoreFirstLine = true)
{
bool importOk = false;
DataTable datatable = new System.Data.DataTable("ExcelContent");
Excel.Application excelApp = null; // the excel application instance
Excel.Workbook importFile = null; // the export workbook
Excel.Worksheet sheet = null; // the worksheet
Excel.Range range = null;
Excel.Sheets sheets = null;
try
{
excelApp = new Excel.Application();
excelApp.DisplayAlerts = false;
// try to open the file
importFile = excelApp.Workbooks.Open(strPath, Type.Missing, true, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
sheets = importFile.Worksheets;
sheet = (Excel.Worksheet)sheets.get_Item(1);
range = sheet.UsedRange;
int usedColumnsCount = range.Cells.Columns.Count;
int usedRowsCount = range.Cells.Rows.Count;
if (usedColumnsCount < columnCount)
{
throw new ImportException("Wrong file structure! Please check and correct the import file to match the requirements.");
}
Object[,] values = (Object[,])range.Value2;
data.Clear();
int row = 1;
// read data from used range
while (row <= usedRowsCount)
{
if (row == 1 && bIgnoreFirstLine)
{
row++;
continue;
}
if (worker.CancellationPending)
{
throw new Exception("Operation cancelled");
}
ArrayList line = new ArrayList();
bool bIsLineEmpty = true;
for (int i = 0; i < columnCount; i++)
{
if (values[row, i + 1] == null)
line.Add("");
else
{
line.Add((String)values[row, i + 1].ToString());
bIsLineEmpty = false;
}
}
if (bIsLineEmpty)
// return after first empty line in range
break;
datatable.Rows.Add(line.ToArray());
data.Add(line);
row++;
}
// cleanup
excelApp.DisplayAlerts = false;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
if (range != null) {
Marshal.FinalReleaseComObject(range);
range = null;
}
if (sheet != null) {
Marshal.FinalReleaseComObject(sheet);
sheet = null;
}
if (sheets != null)
{
Marshal.FinalReleaseComObject(sheets);
sheets = null;
}
if (importFile != null)
{
importFile.Close(Type.Missing, Type.Missing, Type.Missing);
Marshal.FinalReleaseComObject(importFile);
importFile = null;
}
if (excelApp != null)
{
excelApp.Quit();
Marshal.FinalReleaseComObject(excelApp);
excelApp = null;
}
importOk = true;
}
catch (COMException e)
{
message = e.Message;
}
catch (ImportException e)
{
message = e.ImportMessage;
}
catch (Exception e)
{
message = e.Message;
}
finally
{
if (!importOk)
{
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
if (range != null)
{
Marshal.FinalReleaseComObject(range);
range = null;
}
if (sheet != null)
{
Marshal.FinalReleaseComObject(sheet);
sheet = null;
}
if (sheets != null)
{
Marshal.FinalReleaseComObject(sheets);
sheets = null;
}
if (importFile != null)
{
importFile.Close(Type.Missing, Type.Missing, Type.Missing);
Marshal.FinalReleaseComObject(importFile);
importFile = null;
}
if (excelApp != null)
{
excelApp.Quit();
Marshal.FinalReleaseComObject(excelApp);
excelApp = null;
}
}
}
return datatable;
}
I've just tried what you described, like this:
_Application app = new Application();
Workbook wb = app.Workbooks.Open(#"C:\Users\josip.INCENDO\Desktop\Payment (uplate) - primjer.xls");
wb.Close();
wb = null;
app.Quit();
app = null;
And it works perfectly fine, even if the user has opened document. Can you post the code maybe?
Have a look here: Excel 2007 Hangs When Closing via .NET
Always assign your excel objects to local variables, never going 'two dots down', like this:
//fail
Workbook wkBook = xlApp.Workbooks.Open(#"C:\mybook.xls");
//win
Worksheets sheets = xlApp.Worksheets;
Worksheet sheet = sheets.Open(#"C:\mybook.xls");
...
Marshal.ReleaseComObject(sheets);
Marshal.ReleaseComObject(sheet);
.NET creates a wrapper for the COM object that is invisible to you and is not released until the GC weaves its magic.

Categories