I am using NetOffice to edit an Excel Spreadsheet. If I call the code from an Excel user defined function it will not let me edit the invoking spreadsheet.
Excel.Application excelApplication = Excel.Application.GetActiveInstance();
Excel.Worksheet workSheet = (Excel.Worksheet) excelApplication.ActiveSheet;
Excel.Range cell = workSheet.Cells[2, 2];
object value = cell.Value; //works
cell.Value = 3; //Throws Exception
is there a workaround that will enable me to do this?
The exception is
"System.Runtime.InteropServices.COMException (0x80004005): See inner exception(s) for details. ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Runtime.InteropServices.COMException: Exception from HRESULT: 0x800A03EC
--- End of inner exception stack trace ---
at System.RuntimeType.InvokeDispMethod(String name, BindingFlags invokeAttr, Object target, Object[] args, Boolean[] byrefModifiers, Int32 culture, String[] namedParameters)
at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)
at System.Type.InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Object[] args, CultureInfo culture)
at NetOffice.Invoker.PropertySet(COMObject comObject, String name, Object[] value)
at NetOffice.Invoker.PropertySet(COMObject comObject, String name, Object[] value)
at NetOffice.ExcelApi.Range.set_Value(Object value)
at ExcelExamplesCS45.Example01.RunExample() in \psf\home\Documents\Visual Studio 2013\Projects\Excel-REPL\Excel-REPL\Example01.cs:line 29
at ClojureExcel.MainClass.Test() in \psf\home\Documents\Visual Studio 2013\Projects\Excel-REPL\Excel-REPL\MainClass.cs:line 310"
Exception from HRESULT: 0x800A03EC
I'll just describe the general trouble-shooting strategy for a problem like this, there are already many answers for this error. Perhaps too many.
An HRESULT is an error code that can help you pinpoint the underlying cause of the error. It is split into 3 parts, the severity of the error, the "facility" code and the error code. The WinError.h SDK file you have on your machine can show you exactly what bits in the code correspond with what part of the information. "Facility" is a geeky word that means "error source".
The facility code is 0x0A = 10. That means "application defined error". Or in other words, the error code is highly specific to the application that generated the error. The error code is 0x03EC = 1004. So you can put this into words: "Excel error 1004".
That's something you can Google, you'll get 356 thousand hits. Spend some time reading through the top hits to see what it is all about. Ignore the vampire site hits, the kind that promise to fix any error on your machine as long as you start by running a registry cleaner. The lay of the land is that this error is very common, it is also generated in macros and VBA code. Usually with a slightly better error message, inside Excel you can get a brief description of the error beyond the 1004 error code. You'll however have to do without it when you use Automation, that makes it harder of course.
There is another data point you can get from looking at the stack trace, you can see what NetOffice does. It uses late-binding (InvokeDispMethod) so you can't be 100% sure what specific interop method fails. An advertized feature f NetOffice, it actually makes trouble-shooting more difficult. But a very notable interop point is "Range.set_Value". That's something you can reverse-engineer to a highly specific Excel automation property, the Excel object model has a Range interface and it has a Value property. It is assigning that property that fails. Complete match with what you are trying to do, setting a value of a cell.
So you can improve your Google query to "Excel error 1004 Range.Value". That makes the hits a lot more specific, the top 4 hits are all SO questions and all the vampire site hits are filtered. Summarizing the top explanations for the error:
- you can't write to the spreadsheet because it is protected
- the value you write is incompatible with the cell format, like an invalid date
- the range you are trying to update is invalid, like a row or column number <= 0
- the code runs due to a function entered in a cell and it is trying to update another cell.
You can eliminate the 1st bullet pretty easily, just make sure the spreadsheet isn't protected and/or use Unprotect(). Same for the 2nd bullet, just write back what you read. The 3nd bullet can't be it, you can read the cell just fine. The 4th bullet is an exact match with the title of your question, "User Defined Function". In other words, the problem is
Excel.Range cell = workSheet.Cells[2, 2];
With the issue that this isn't the cell that contains the user defined function. So assigning it is illegal. I can't propose a workaround without knowing what is special about [2, 2]. Try changing it to the cell that actually contains the UDF.
What a UDF is supposed to do is return a value that then becomes the displayed cell value. This KB article documents the restrictions of a UDF. This SO question has answers that talk about implementing a UDF in .NET code, it mentions Excel-DNA.
There is a very simple workaround: simply edit the worksheet in a separate thread. Why didn't I think of it to begin with!!???