I have an excel workbook that has a button, that triggers a c# application. I need to add the returned value from the app to the excel workbook but I can't figure out how to do that while the excel workbook is already open.
I've basically been grasping at straws. Every example I've found opens a read only version of the excel workbook
Microsoft.Office.Interop.Excel._Application myExcelApp;
Microsoft.Office.Interop.Excel.Workbook myExcelWorkbook = new
Microsoft.Office.Interop.Excel.Workbook();
Microsoft.Office.Interop.Excel.Worksheet xlWorkSheet;
xlWorkSheet = myExcelWorkbook.Sheets["Sheet1"];
xlWorkSheet = myExcelWorkbook.ActiveSheet;
myExcelApp = new Microsoft.Office.Interop.Excel.Application();
myExcelApp =
(Microsoft.Office.Interop.Excel.Application)
System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application");
foreach (Microsoft.Office.Interop.Excel.Workbook item in myExcelApp.Workbooks)
{
//Select the excel target 'NAME'
if (item.Name == "DatagridviewTest.xlsm")
{
myExcelWorkbook = item;
break;
}
//Select the target workbook
xlWorkSheet = myExcelWorkbook.Sheets[1] as Microsoft.Office.Interop.Excel.Worksheet;
//Set cell value
xlWorkSheet.Cells[5, 1] = "new value";
}
I get an unhandled exception error "System runtime COM exception"
Related
I am trying to update the particular cell value, but getting an error. Below is the code which I tried.
Microsoft.Office.Interop.Excel.Application excel;
Microsoft.Office.Interop.Excel.Workbook workbook;
excel = new Microsoft.Office.Interop.Excel.Application();
workbook = excel.Workbooks.Open(#"D:\Ride\Ride Master Sheet 05 11 2020.xlsx", ReadOnly: false, Editable: true);
//Microsoft.Office.Interop.Excel.Worksheet worksheet = workbook.Worksheets.Item[1] as Microsoft.Office.Interop.Excel.Worksheet;
Microsoft.Office.Interop.Excel.Sheets sheets = excel.Worksheets;
// Select worksheets
Microsoft.Office.Interop.Excel.Worksheet ws = (Microsoft.Office.Interop.Excel.Worksheet)sheets.get_Item("Concentric Pricing");
if (ws == null)
return;
Microsoft.Office.Interop.Excel.Range range = (Microsoft.Office.Interop.Excel.Range)ws.get_Range("A7", "O7");
Microsoft.Office.Interop.Excel.Range row1 = worksheet.Rows[7].Cells[1, 1];
row1.Value = "";
excel.Application.ActiveWorkbook.Save();
excel.Application.Quit();
excel.Quit();
Getting error
Unable to cast COM object of type
'Microsoft.Office.Interop.Excel.ApplicationClass' to interface type
'Microsoft.Office.Interop.Excel._Application'.
Any help on this?
I'm trying to copy a worksheet to a different workbook into the last worksheet of the target workbook.
My workbooks and worksheets are created like this:
public Microsoft.Office.Interop.Excel.Workbook xlWorkbookMatrix;
public Microsoft.Office.Interop.Excel._Worksheet xlWorksheetMatrix;
I tried using worksheet.copy:
xlWorksheetMatrix.Copy(Type.Missing, xlWorkbookEvaluation.Sheets[xlWorkbookEvaluation.Sheets.Count]);
and worksheet.UsedRange.Copy:
xlWorksheetMatrix.UsedRange.Copy(xlWorkbookEvaluation.Sheets[xlWorkbookEvaluation.Sheets.Count]);
With both different methods I always get an error.
For worksheet.Copy:
System.Runtime.InteropServices.COMException occured in System.Dynamic.dll
The Copy-property of the worksheet object can't be assigned
For worksheet.UsedRange.Copy:
System.Runtime.InteropServices.COMException occured in System.Dynamic.dll
The Copy-property of the Range object can't be assigned
Having a template sheet you want to fill many times, Hope this helps :
public void test()
{
Excel.Application excelApp;
string fileTarget = "C:\target.xlsx";
string fileTemplate = "C:\template.xlsx";
excelApp = new Excel.Application();
Excel.Workbook wbTemp, wbTarget;
Excel.Worksheet sh;
//Create target workbook
wbTarget = excelApp.Workbooks.Open(fileTemplate);
//Fill target workbook
//Open the template sheet
sh = wbTarget.Worksheets["TEMPLATE"];
//Fill in some data
sh.Cells[1, 1] = "HELLO WORLD!";
//Rename sheet
sh.Name = "1. SHEET";
//Save file
wbTarget.SaveAs(fileTarget);
//Iterate through the rest of the files
for (int i = 1; i < 3; i++)
{
//Open template file in temporary workbook
wbTemp = excelApp.Workbooks.Open(fileTemplate);
//Fill temporary workbook
//Open the template sheet
sh = wbTemp.Worksheets["TEMPLATE"];
//Fill in some data
sh.Cells[1, 1] = "HELLO WORLD! FOR THE " + i + ".TH TIME";
//Rename sheet
sh.Name = i + ". SHEET";
//Copy sheet to target workbook
sh.Copy(wbTarget.Worksheets[1]);
//Close temporary workbook without saving
wbTemp.Close(false);
}
//Close and save target workbook
wbTarget.Close(true);
//Kill excelapp
excelApp.Quit();
}
I have an existing project that creates an excel spreadsheet using the Microsoft.Office.Interop.Excel.WorkbookClass and I am trying to convert the workbook object to the Microsoft.Office.Tools.Excel.Workbook, but I am getting an exception thrown stating:
"Unable to cast COM object of type
'Microsoft.Office.Interop.Excel.WorkbookClass' to class type
'Microsoft.Office.Tools.Excel.Workbook'. Instances of types that
represent COM components cannot be cast to types that do not represent
COM components; however they can be cast to interfaces as long as the
underlying COM component supports QueryInterface calls for the IID of
the interface."
Microsoft.Office.Interop.Excel.Application xlApp = null;
Microsoft.Office.Tools.Excel.Workbook xlWorkbook = null;
Microsoft.Office.Interop.Excel.Sheets xlSheets = null;
Microsoft.Office.Tools.Excel.Worksheet xlNewSheet = null;
xlApp = new Interop.Application();
xlApp.Visible = true;
xlWorkbook = (Microsoft.Office.Tools.Excel.Workbook)xlApp.Workbooks.Add(Interop.XlWBATemplate.xlWBATWorksheet);
xlSheets = xlWorkbook.Sheets as Interop.Sheets;
xlNewSheet = (Microsoft.Office.Tools.Excel.Worksheet)xlSheets.Add(xlSheets[1], Type.Missing, Type.Missing, Type.Missing);
xlNewSheet.Name = "SheetName1";
Is this possible if not, what other options can I take that since the excel sheet is already created using the interop class and
If possible try to avoid using the Microsoft.Office.Tools assembly which is internal to Visual Studio Tools For Office.
I've amended your code as below:
Microsoft.Office.Interop.Excel.Application xlApp = null;
Microsoft.Office.Interop.Excel.Workbook xlWorkbook = null;
Microsoft.Office.Interop.Excel.Sheets xlSheets = null;
Microsoft.Office.Interop.Excel.Worksheet xlNewSheet = null;
xlApp = new Microsoft.Office.Interop.Excel.Application();
xlApp.Visible = true;
xlWorkbook = xlApp.Workbooks.Add(Microsoft.Office.Interop.Excel.XlWBATemplate.xlWBATWorksheet);
xlSheets = xlWorkbook.Sheets as Microsoft.Office.Interop.Excel.Sheets;
xlNewSheet = xlSheets.Add(xlSheets[1], System.Type.Missing, System.Type.Missing, System.Type.Missing);
xlNewSheet.Name = "SheetName1";
It looks like to "convert" an interop workbook to a vsto workbook you just do this:
In application-level projects, you can create
Microsoft.Office.Tools.Excel.Workbook objects programmatically by
using the GetVstoObject method.
Microsoft.Office.Interop.Excel.Workbook nativeWorkbook = Globals.ThisAddIn.Application.ActiveWorkbook;
if (nativeWorkbook != null)
{
Microsoft.Office.Tools.Excel.Workbook vstoWorkbook =
Globals.Factory.GetVstoObject(nativeWorkbook);
}
in my app, I've saved a copy of a blank excel file form as a resources, I need to load this file, modify its both worksheets, save it in a new location with a new name.
user should not see that process.
I'm using C# 2010 with a SQL server, from which I'm gonna load my data and put it in the excel form.
Thank You For Your Time.
Use the Microsoft Interop Assemblies that can be found in .NET or COM (Microsoft.Office.Interop.Excel)
Then load all the required cells into a List and modify the data.
Something like this (code below):
string path = #"C:\temp\test.xls";
ApplicationClass excelApllication = null;
Workbook excelWorkBook = null;
Worksheet excelWorkSheet = null;
excelApllication = new ApplicationClass();
System.Threading.Thread.Sleep(2000);
excelWorkBook = excelApllication.Workbooks.Add();
excelWorkSheet = (Worksheet)excelWorkBook.Worksheets.get_Item(1);
// Attention: 1 indexed cells, [Row, Col]
excelWorkSheet.Cells[1, 1] = "Column A, Row 1";
excelWorkSheet.Cells[2, 5] = "Column E, Row 2";
excelWorkSheet.Cells[3, 3] = "Column C, Row 3";
excelWorkBook.SaveAs(path, XlFileFormat.xlWorkbookNormal);
excelWorkBook.Close();
excelApllication.Quit();
Marshal.FinalReleaseComObject(excelWorkSheet);
Marshal.FinalReleaseComObject(excelWorkBook);
Marshal.FinalReleaseComObject(excelApllication);
excelApllication = null;
excelWorkSheet = null;
//opens the created and saved Excel file
Process.Start(path);
That should happen inside a Thread, because you don't want a user to notice that task.
http://msdn.microsoft.com/en-us/library/aa645740%28v=vs.71%29.aspx
(Threading Tutorial)
I would try to avoid automating Excel if at all possible and use the OpenXML SDK (or a library wrapping the OpenXML SDK) for this task.
Here is an article that could help you get started.
I think you wanted to do this... at least worked for me. :)
private void btnExcel_Click(object sender, EventArgs e)
{
string newDirectoryPath = ValidateDirectory();
string newFilePath = Path.Combine(newDirectoryPath, "new.xls");
//brand new temporary file
string tempPath = System.IO.Path.GetTempFileName();
//to manage de temp file life
FileInfo tempFile = new FileInfo(tempPath);
//copy the structure and data of the template .xls
System.IO.File.WriteAllBytes(tempPath,Properties.Resources.SomeResource);
Excel.Application xlApp;
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;
object misValue = System.Reflection.Missing.Value;
xlApp = new Excel.Application();
xlWorkBook = xlApp.Workbooks.Open(tempPath, 0, true, 5, "", "", true, Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
//WorkTheExcelFile();
tempFile.Delete();
xlWorkBook.SaveAs(newFilePath);
xlWorkBook.Close(true, misValue, misValue);
xlApp.Quit();
releaseObject(xlWorkSheet);
releaseObject(xlWorkBook);
releaseObject(xlApp);
Process.Start(newFilePath + ".xlsx");
}
I am writing a program that will allow me to open excel spreadsheets and get some specific information off of them. Each sheet contains the same information that I need, but the information is not always in the same location.
I am trying to find a way to search for specific text in an Excel sheet and have the address of the cell that text is in.
For example:
If I was looking for the text "apples", the function will find the cell that contains apples and return its address (i.e., A5).
For accessing the Excel spreadsheet I am using Excel = Microsoft.Office.Interop.Excel.
I have been looking all weekend for an efficient way to to do this and have been horribly unsuccessful so far. Any help I can get would be greatly appreciated.
Edit:
This is part of a much larger project, but for this particular function, I have the ability to open and close the Excel file. I have yet to start writing the search function yet, because to be perfectly honest, I am not exactly sure on even how to go about doing this. But here is what I have at this point.
public string searchExcel(string findThis)
{
Excel.Application xlApp;
Excel.Workbook xlWorkBook;
Excel.WorkSheet xlWorkSheet;
object misvalue;
//This part will open the Excel document.
misValue = System.Reflection.Missing.Value;
xlApp = new Excel.ApplicationClass();
xlWorkBook = xlApp.Workbooks.Open("C:\\temp2\\excelDocument.xlsm",
0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows,
"\t", false, false, 0, true, 1, 0);
//Search and get address of cell
//This part will close the Excel document
xlWorkBook.Close(true, misValue, misvalue);
xlApp.Quit();
releaseObject(xlWorkSheet);
releaseObject(xlWorkBook);
releaseObject(xlApp);
xlWorkSheet = null;
xlWorkBook = null;
xlApp = null;
}
private void releaseObject(object obj)
{
try
{
System.Runtime.Interopservices.Marshal.ReleaseComObject(obj);
obj = null;
}
catch(Exception e)
{
obj = null;
MessageBox.Show("Unable to release the object " + e.ToString());
}
finally
{
GC.Collect();
}
}
I think something like this should do what you want:
var app = (Excel.Application)Marshal.GetActiveObject("Excel.Application");
var wb = app.ActiveWorkbook;
var ws = wb.Worksheets[1] as Excel.Worksheet;
var cells = ws.Cells;
var match = cells.Find("apples", LookAt:=Excel.XlLookAt.xlPart) as Excel.Range;
var matchAdd = match != null ? match.Address : null;
This will search in the first Worksheet of the current active workbook of a current Excel session.
Adjusting to fit your code:
xlWorksheet = xlWorkBook.Worksheets[1] as Excel.Worksheet;
Excel.Range cells = ws.Cells;
Excel.Range match = cells.Find("apples", LookAt:=Excel.XlLookAt.xlPart) as Excel.Range;
string matchAdd = match != null ? match.Address : null;
if (match != null) releaseObject(match);
releaseObject(cells);
One thing, is this assumes .Net 4.0 as I use missing arguments for the find call. If you are using a previous version you will need to pass in misValue for any parameter not used.