views:

1060

answers:

2

I build an assembly referencing a COM interop DLL. If I embed the COM interop types by setting Embed Interop Types to True in the Reference's properties (VS2010), at run-time an error occurs "object does not contain a definition for get_Range". If COM interop types are not embedded then no error occurs.

Does anyone know why a particular method, Worksheet.get_Range should be ommitted or how to work around this or have any other relevant insights? I should be grateful for any help.

The interop dll contains a reference to Worksheet.get_Range(object, [object]). Using reflector on my calling assembly there is no mention of get_Range under Worksheet.

The interop assembly I am embedding is generated from Excel9.olb. I am not using PIAs as the application targets multiple Excel versions.

+1  A: 

I have not tried this out myself yet, but I believe that the syntax has changed when using embedded COM Interop types under C# 4.0 to a more "C# friendly" syntax.

Therefore, instead of looking for the get_Range(object, [object]) method, you can either omit the optional parameter (instead of having to provide Type.Missing), or you can avoid calling the get accessor completely, and instead reference the property name using square brackets:

// Using C# 3.0:
Excel.Range range = worksheet.get_Range("A1", Type.Missing);

// Using C# 4.0, omitting the optional parameter:
Excel.Range range = worksheet.get_Range("A1");

// Using C# 4.0, utilizing square-bracket indexing:
Excel.Range range = worksheet.Range["A1"];

From what I understand, though, you should still be able to call it the "old way", where the new indexer syntax is really calling the required 'get' and 'set' accessor behind the scenes, so I don't really know why you are having trouble. My guess is that you need to look under Worksheet.Range instead of Worksheet.get_Range within the IntelliSense listing. If this does not work for you, then it sounds like something may be wrong with your setup or installation.

For more on this, see: Indexed Properties in C# 4.0 by Kirill Osenkov.

Hope this helps...

Mike

Mike Rosenblum
MIke, thanks for your help. The single parameter approach does not get a run-time error and is obviously a good workaround. I have submitted a bug report to Microsoft 530769.
mikemay
https://connect.microsoft.com/VisualStudio/feedback/details/530769/get-range-method-missing-with-embedded-interop-assembly?wa=wsignin1.0
mikemay
Ah, right, I posted a bad link in my previous comment, thanks for correcting that. The discussion there is very interesting, and makes sense. But, may I ask, isn't the easiest solution to now simply use the `worksheet.Range["A1"]` syntax instead of the older `worksheet.get_Range("A1", Type.Missing)` now that you are using C# 4.0? You have found a very interesting curiosity, but as for fixing it for your own code, it would seem easiest and best to just use the new syntax -- which is easier to read in any case (by design!).
Mike Rosenblum
Mike, I agree that there was an obvious workaround as soon as I tested your suggested approach and I have long since adopted a variation. The continuing discussion was strictly to help Microsoft's efforts to make the backward compatiblity as good as possible (and it is an impressive achievement).On a point of detail I can't say that I prefer the "A1" approach or even "R1C1". I don't particularly want to convert numbers into strings just to make the call (and for all I know Excel converts them straight back). Perhaps its a matter of taate. Thanks for your continuing interest.
mikemay
Ok, no, I was not suggesting to actually make use of the string "A1" to designate the cell. I was simply saying that, using C# 4.0, one can, and should, make use of the worksheet.Range[object] syntax instead of the worksheet.get_Range(object, object) syntax. That's all. It's simpler, cleaner, and works as originally intended, using the property's name ("Range") instead of exposing the get accessor ("get_Range"). But I could see where this could be a huge problem if trying to migrate a lot of code from C# 3.0 to C# 4.0. A smart Regex replace could do it -- but make sure you have unit tests!
Mike Rosenblum
We are on the same page!
mikemay
A: 

This was raised as a bug with Microsoft at beta stage https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=530769&wa=wsignin1.0 and was resolved as By Design after RTM. Mike Rosenblum's answer is approved there.

This can be summarised as Excel.Range r = sh.Range[sh.Cells[1, 1], sh.Cells[2, 2]]; where sh is a worksheet.

mikemay