Working with C# and Excel Interop - c#

I have this code:
Microsoft.Office.Interop.Excel.Application xla = new Microsoft.Office.Interop.Excel.Application();
xla.Visible = false;
Workbook wb = xla.Workbooks.Add(XlSheetType.xlWorksheet);
Worksheet ws = (Worksheet)xla.ActiveSheet;
ws.Name = "Serial";
int i = 1;
foreach (DataRow comp in dsView.Tables[0].Rows)
{
ws.Cells[i, 1] = "'" + comp[0].ToString();
ws.Cells[i, 2] = "'" + comp[1].ToString();
ws.Cells[i, 3] = "'" + comp[2].ToString();
i++;
}
if (File.Exists(#"d:\DDD.xlsx"))
File.Delete(#"d:\DDD.xlsx");
xla.Save(#"d:\DDD.xlsx"); ---->>>> on this line i get the error
The error:
Exception from HRESULT: 0x800A03EC
I am working on C# winforms with Office 2012

Your problem is that the variable xla is your excel application and not a workbook. You want to save the workbook.
so
xla.Save(#"d:\DDD.xlsx"); ---->>>> on this line i get the error
should be
wb.SaveAs(#"d:\DDD.xlsx", 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);

When I run Excel.Application.Save() with Visual Studio 2010 and Excel 2010 interop (Office 14) targeting .NET 4, it displays a dialog to select a location to save the file. Clicking Cancel on that dialog results in a COM exception. But clicking Save has odd results: When I supply a valid file path and name as a parameter like Excel.Application.Save(#"C:\blah.xlsx"), I end up with two files saved. The first is named Sheet1.xlsx and contains what I'd expect, even though I didn't choose that name in the dialog. The other is named blah.xlsx (as per my file name parameter) and won't open correctly in Excel. If I call Excel.Application.Save() without a file name as a parameter, a valid file is saved with the name and path I selected in the dialog, but I also get a "RESUME.XLW" file as well. So it seems that the Application.Save method may not be a good choice to use. Instead, you can do something like this, which works as you'd expect:
using System;
using Excel = Microsoft.Office.Interop.Excel;
namespace WindowsFormsApplication2
{
static class Program
{
static void Main()
{
Excel.Application xlApp = new Excel.Application();
Excel.Workbook book = xlApp.Workbooks.Add(Excel.XlSheetType.xlWorksheet);
Excel.Worksheet sheet = book.ActiveSheet;
sheet.Name = "Booya";
Excel.Range range = sheet.Cells[1, 1];
range.Value = "This is some text";
book.SaveAs(#"C:\blah.xlsx");
}
}
}

Related

C# code that remove all macros from Excel file

I have a Windows form app project (C#).
I am trying unsuccessfully to write code so that when I click a button I created, it will load an excel file that actually has macros in it and delete them all.
I know you can delete macros manually in the excel file itself but I need a way to do it programmatically (I just delete them all for the user).
I know that the macros in Excel files are written in VBA language, so I try to use the related libraries in c# but I get an error when I try to use VBProject, VBComponent.
This what I tried so far:
using Microsoft.Office.Interop.Excel;
namespace MacroRemover
{
public partial class Main : Form
{
private void Btn_Click(object sender, EventArgs e)
{
string filePath = "path\\to\\file.xlsm";
Application excel = new Application();
Workbook workbook = excel.Workbooks.Open(filePath);
VBProject vbProject = workbook.VBProject;
foreach (VBComponent component in vbProject.VBComponents)
{
vbProject.VBComponents.Remove(component);
}
workbook.Save();
workbook.Close();
excel.Quit();
}
}
}
Any way that works will help me, I would appreciate the help
Thanks in advance guys!!!
If you don't need to save xlsm format of the file, you can save this file to xlsx format and all scripts will be removed.
using Aspose.Cells;
var workbook = new Workbook("input.xlsm");
workbook.Save("Output.xlsx");
Thanks for all the replies, #tttony's response helped me to understand more deeply and #Bushuev's response here is definitely a possible and simple solution for deleting the macros.
I finally managed to delete all the macros like this:
string filePath = Path_TxtBox.Text;
Microsoft.Office.Interop.Excel.Application excel = new Microsoft.Office.Interop.Excel.Application();
Workbook workbook = excel.Workbooks.Open(filePath);
VBProject project = workbook.VBProject;
for (int i = project.VBComponents.Count; i >= 1; i--)
{
VBComponent component = project.VBComponents.Item(i);
try
{
project.VBComponents.Remove(component);
}
catch (ArgumentException)
{
continue;
}
}
for (int i = project.VBComponents.Count; i >= 1; i--)
{
VBComponent component = project.VBComponents.Item(i);
component.CodeModule.DeleteLines(1, component.CodeModule.CountOfLines);
}
workbook.Save();
workbook.Close();
excel.Quit();
MessageBox.Show("Macros Removed");
It should only be noted that I encountered an error: 'Programmatic access to Visual Basic Project is not trusted'
It was solved after I realized that I had to change the option to access the VBA Project object model in the Trust Center settings.

Method in Service that uses excel isn't saving and doesn't appear to produce an exception

I have a problem with some code in a service I have. The method just creates a datatable of the report that needs to be created and then writes it to an existing excel file. The problem is that it fails at the save of the file. Somewhat more oddly, it doesn't appear to be catching errors, and I don't know why. I've included the code below. Of note:
excel.Visible=true; doesn't seem to make the excel sheet visible each time so I can't really watch what's going on in the excel itself. I assume it's not becoming visible because it's a service, but I don't really know.
I know that the datatable is producing output as I've had the log (Which is just a text file where I can write events and errors) writes both the cells value and it's location and it has never stopped in the Foreach loop or the for loop within it
I know that it's failing at the wb.Save(); because the Log.WriteLine("WriteTIByEmp 4"); successfully writes to the text file, but the Log.WriteLine("WriteTIByEmp 5"); does not.
The catch (Exception ex) also doesn't seem to be working, as it doesn't write anything about the exception but doesn't even write the Log.WriteLine("Catching Exception");, so I'm a bit lost.
Edit: Just to note, this is all using Interops in the excel portion. It's just that the "using Microsoft.Office.Interop.Excel" is declared at the top of the class to save time and typing as almost all the methods in this particular class are using excel. The excel file is always opening in this process, I can see it in the task manager, and I have had other methods successfully write to excel files in this process. Only this particular method has had issues.
public void WriteTIByEmp(CI.WriteReport Log)
{
try
{
System.Data.DataTable Emps = Pinpoint.TICardsByEmpStatsDaily.GetTICardsByEmployer();
Log.WriteLine("WriteTIByEmp 1");
Application excel = new Application();
excel.Visible = true;
Workbook wb = excel.Workbooks.Open(TIEMPPath);
Worksheet ws = wb.Worksheets[1];
ws.Range["A:G"].Clear();
Log.WriteLine("WriteTIByEmp 2");
int RowNum = 0;
int ColCount = Emps.Columns.Count;
Log.WriteLine("WriteTIByEmp 3");
foreach (DataRow dr in Emps.Rows)
{
RowNum++;
for (int i = 0; i < ColCount; i++)
{
ws.Cells[RowNum, i + 1] = dr[i].ToString();
Log.WriteLine("Cell Val:" + dr[i].ToString() + ". Cell Location: " + RowNum + "," + i);
}
}
Log.WriteLine("WriteTIByEmp 4");
wb.Save();
Log.WriteLine("WriteTIByEmp 5");
wb.Close();
Log.WriteLine("WriteTIByEmp 6");
excel = null;
Log.WriteLine("WriteTIByEmp 7");
}
catch (Exception ex)
{
Log.WriteLine("Catching Exception");
var st = new StackTrace(ex, true);
var frame = st.GetFrame(0);
var line = frame.GetFileLineNumber();
string msg = "Component Causing Error:" + ex.Source + System.Environment.NewLine + "Error Message: " + ex.Message + System.Environment.NewLine + "Line Number: " + line + System.Environment.NewLine + System.Environment.NewLine;
Log.WriteLine(msg, true);
}
}
Meaby try to use Interops
i don't understand how Your code can start Excel application
by this line :
Application excel = new Application();
try this
Microsoft.Office.Interop.Excel.Application xlexcel;
xlexcel = new Microsoft.Office.Interop.Excel.Application();
xlexcel.Visible = true;
I have been in similar situation.
Note: While using Interop Excel is a dependency as well as other processes accessing the file could cause issues. Therefore, I recommend using EPPlus Nuget Package as it works wonders.
https://www.nuget.org/packages/EPPlus/
Please refer to the below sample code.
FileInfo fi = new FileInfo(ExcelFilesPath + "myExcelFile.xlsx");
using (ExcelPackage pck = new ExcelPackage())
{
// Using Existing WorkSheet 1.
ExcelWorksheet ws = pck.Workbook.Worksheets[1];
// Loading Data From DataTable Called dt.
ws.Cells["A1"].LoadFromDataTable(dt, true);
// If you want to enable auto filter
ws.Cells[ws.Dimension.Address].AutoFilter = true;
// Some Formatting
Color colFromHex = System.Drawing.ColorTranslator.FromHtml("#00B388");
ws.Cells[ws.Dimension.Address].Style.Fill.PatternType = ExcelFillStyle.Solid;
ws.Cells[ws.Dimension.Address].Style.Fill.BackgroundColor.SetColor(colFromHex);
ws.Cells[ws.Dimension.Address].Style.Font.Color.SetColor(Color.White);
ws.Cells[ws.Dimension.Address].Style.Font.Bold = true;
ws.Cells["D:K"].Style.Numberformat.Format = "0";
ws.Cells["M:N"].Style.Numberformat.Format = "mm-dd-yyyy hh:mm:ss";
ws.Cells[ws.Dimension.Address].AutoFitColumns();
pck.SaveAs(fi);
}
You can refer to the above code from my project. I am loading the DataTable data into my excel file by providing the Range or Starting Cell.
I had found the issue. The Excel file was open on someone else's computer which resulted in it not being able to save the file, but it couldn't display the excel popup because excel wouldn't become visible (I still don't know why but Probably something to do with it being a service). So it just couldn't save but it wasn't a code error so it didn't show up in the log and couldn't continue so the code was just stuck. I'll make a copy for the purposes of updating in the future.

C# Run Excel Macro Through IIS Server

I have a C# (using Razor) Web Application that runs through my company's intranet.
I have been using ClosedXML to manage all of my Excel needs and it works great, however, now I need to run Macros inside Excel Files and apparently ClosedXML cannot do this, so I must use Excel Interop.
My code below gives the dreaded:
Microsoft Excel cannot access the file ... There are several possible
reasons: • The file name or path does not exist. • The file is being
used by another program. • The workbook you are trying to save has the
same name as a currently open workbook.
The file name and path DOES exist
I made sure that Excel is not even running on the server
The workbook is not open (see above).
Things I've tried.
I've tried to create security provisions for the C:\Windows\System32\config\systemprofile and SysWOW64\config\systemprofile.
(Side Note: I could not find IIS_USRS when I tried to add the security provisions - this may be the problem.)
I've also tried editing the Excel Application properties via dcomcnfg and I still get the same error.
here's what I'm trying to do:
//C# with Razor Syntax
#using MSExcel = Microsoft.Office.Interop.Excel
#using System.Runtime.InteropServices
#using System.Web
#using System.IO
string worksheetName = "Sheet1";
string[] macros = new string[] { "Module1.Reset_List()", "Module1.Run_Setup()"};
string workbookPath = HttpContext.Current.Server.MapPath(#"~/uploads/test.xlsm");
FileInfo xlsFile = new FileInfo(workbookPath);
string msg = (File.Exists(xlsFile.FullName)) ? "Found It!" : "Can't Find It...";
<p>#msg</p>; // <-- This always returns "Found It!"
//Create the Excel Object
MSExcel.Application xlsApp = new MSExcel.Application();
xlsApp.Visible = true;
try
{
//Identify the workbook (open the file)
// *** the error occurs on the line below *** //
MSExcel.Workbook xlsBook = xlsApp.Workbooks.Open(xlsFile.FullName);
xlsBook.Activate();
//Identify the worksheet
MSExcel.Worksheet xlsSheet = (MSExcel.Worksheet)xlsBook.Sheets[worksheetName];
xlsSheet.Activate();
foreach (string macro in macros)
{
xlsApp.Run(macro);
}
xlsBook.Save();
xlsBook.Close(false, "", false);
xlsApp.Quit();
}
catch (Exception e)
{
<p>#e.Message</p>
Marshal.ReleaseComObject(xlsApp);
xlsApp = null;
}
if (xlsApp != null)
{
Marshal.ReleaseComObject(xlsApp);
xlsApp = null;
}

System.Runtime.InteropServices error when exporting dataGridView to Excel workbook

I have an application that displays certain database data, and includes a function to save that data to an excel workbook on request using the Microsoft.Office.Interop.Excel assembly. One of my users reports the following error when trying to save to an excel workbook:
System.Runtime.InteropServices.COMException (0x8002000B): Invalid index. (Exception from HRESULT: 0x8002000B (DISP_E_BADINDEX))
at Microsoft.Office.Interop.Excel.Sheets.get__Default(Object Index)
at WorkCalendar.Form1.saveBtn_Click(Object sender, EventArgs e)
We've verified that he does have Excel 2013 installed and all of the necessary assemblies came through ok according to the full exception details, so I hope one of you can shed some light on what's going on here.
Here's the saveBtn_Click event method mentioned in the error above (edited for conciseness)
private void saveBtn_Click(object sender, EventArgs e)
{
// creating Excel Application
_Application app = new Microsoft.Office.Interop.Excel.Application();
_Workbook workbook;
_Worksheet worksheet;
string fetchString = fetch.ToString("HH.mm.ss");
try
{
// Check for existing workbook and add new page
}
catch
{
// If no workbook found, create a brand new one
workbook = app.Workbooks.Add(Type.Missing);
worksheet = null;
worksheet = workbook.Sheets["Sheet1"];
}
try
{
// do not show the excel sheet being created
app.Visible = false;
worksheet = workbook.ActiveSheet;
worksheet.Name = fetchString;
// Get dataGridView data, insert it into the excel worksheet and format it
}
catch { }
finally
{
// save the application
// Exit from the application
app.Quit();
}
}
As I said, the application works fine on my and other computers on which it's been tested. Any ideas?
EDIT: Altered code example slightly to show the method looking for an existing workbook, and creating one if no workbook found.

Iterating through and Populating Named Ranges in Excel

I have a WinForms app written in C# and I want to programmatically export some data into the some named ranges in an Excel Template. I've looked on these forums and elsewhere and the closest code I can find to what I want is as follows -
private Excel.Workbook m_workbook;
object missing = Type.Missing;
public void testNamedRangeFind()
{
m_workbook = Globals.ThisAddIn.Application.ActiveWorkbook;
int i = m_workbook.Names.Count;
string address = "";
string sheetName = "";
if (i != 0)
{
foreach (Excel.Name name in m_workbook.Names)
{
string value = name.Value;
//Sheet and Cell e.g. =Sheet1!$A$1 or =#REF!#REF! if refers to nothing
string linkName = name.Name;
//gives the name of the link e.g. sales
if (value != "=#REF!#REF!")
{
address = name.RefersToRange.Cells.get_Address(true, true, Excel.XlReferenceStyle.xlA1, missing, missing);
sheetName = name.RefersToRange.Cells.Worksheet.Name;
}
Debug.WriteLine("" + value + ", " + linkName + " ," + address + ", " + sheetName);
}
}
}
However I get an error saying 'The name Globals does not exist in the current context'.
Can someone please explain what it is I am not understanding about this code, or alternatively point me at some other code that will enable me to post values from my Database into the Excel Template named ranges.
This code runs on VSTO (Visual Studio Tools for Office) and uses the Microsoft.Office.Interop.Excel.
So you should create an Office Excel Workbook solution in Visual Studio:
File -> New -> Visual C# -> Office -> [ Select your Office version ] -> Excel Workbook

Categories