简体   繁体   中英

Inserted a picture into Excel using C++/CLI and got 100x warning C4691

I was assigned the task of making a “small” modification to an existing C++/CLI (with Excel automation) application (target framework: .NET4.0, IDE: VS2010). The task: insert a couple of pictures (*.jpg) into an Excel worksheet. I was pleased to find here at stackoverflow a thread in which precisely this task was addressed in C#. Here is the link: please see the very end of this question

In the above thread, I followed the instructions provided in the answer from user JMK. The code compiles without errors and works! Indeed, the code successfully places a picture in the worksheet. Unfortunately, I also obtain one hundred C4691 compiler warnings.

My code:

    //attributes - used by several different methods
private:
    Excel::Application^ xlApp;
    Excel::_Workbook^ xlBook;
    Excel::Workbooks^ xlBooks;
    Excel::Sheets^ xlSheets;
    Excel::_Worksheet^ xlSheet;
    Excel::Range^ range;
    String^ templateFilename;
    String^ picFilename;

private: System::Void buttonRunExcel_Click(System::Object^  sender, System::EventArgs^  e)
{
//create the Excel Application
xlApp = gcnew Excel::Application();//55 C4691 compiler warnings for this line of code
xlBooks = xlApp->Workbooks;//no compiler warnings here

//open the Excel template - 30 C4691 compiler warnings for the next line of code
xlBook = xlApp->Workbooks->Open(templateFilename, Type::Missing, false, Type::Missing, Type::Missing, Type::Missing, Type::Missing, Type::Missing, Type::Missing, Type::Missing, Type::Missing, Type::Missing, Type::Missing, Type::Missing, Type::Missing);

xlSheets = xlBook->Worksheets;//no compiler warnings here

//set the active worksheet to sheet 3
xlSheet = (Excel::_Worksheet^)xlSheets->Item[3];//no compiler warnings here

//insert the picture - 15 C4691 compiler warnings for the next line of code
xlSheet->Shapes->AddPicture(picFilename, Core::MsoTriState::msoFalse, Core::MsoTriState::msoCTrue, 100, 200, 640, 480);

}

My references:

    using namespace System::Reflection;
using namespace System::Runtime::InteropServices;
using namespace Microsoft::Office::Core;
using namespace Microsoft::Office::Interop::Excel;

A sample compiler warning:

warning C4691: "Microsoft::Office::Core::Assistant": type referenced was expected in unreferenced assembly "office", type defined in current translation unit used instead. This diagnosis occurred while importing type 'Microsoft: Office:Interop:Excel:ApplicationClass' from Assembly "Microsoft.Office.Interop.Excel, Version = 12.0.0.0, culture = neutral, PublicKeyToken = 71e9bce111e9429c".

MSDN's description of this compiler warning was not particularly helpful (for me). I don't wish to simply ignore the warnings (foolish) nor do I want to “turn off” the warnings using pragma warning (sloppy).

How can I eliminate warning C4691? All advice, comments, even (constructive) criticism are gratefully appreciated. Thanks

    xlApp = gcnew Excel::Application();

There's a fair amount of automagic happening here, the kind that doesn't actually works so well in the C++ IDE. Unlike the VB.NET and C# IDEs, the languages normally used to write Office interop code.

Excel::Application is an interface , not a class. And of course it is never possible to create an instance of an interface, it is an abstract type. The C++/CLI compiler of course knows that this isn't possible and goes hunting for a class that implements the interface. It finds it by looking for the [CoClassAttribute] attribute on the interface type, it points to Excel::ApplicationClass, a synthetic .NET class generated by the type library importer. Notable is that the IntelliSense parser doesn't know about this trick and puts red squiggles under the statement. You'll get rid of it by making the substitution yourself:

    xlApp = gcnew Excel::ApplicationClass();

Onwards to the C4691 warnings. The Excel type library uses another type library that contains common Office type declarations. You apparently already figured this out and properly added a reference to MSO.DLL, getting types in the Microsoft::Office::Core namespace. But that's a mapped namespace name, the type library name is actually "Office", not "Microsoft.Office.Core".

So the C++/CLI compiler notices the discrepancy, ApplicationClass refers to a interface named Assistant in the Office type library so it expects an assembly named "Office" to be available. Which is the normal way a type library name is mapped to an assembly name. In other words, it doesn't know that the namespace name got mapped. Nor could it know, it didn't do that mapping. It was done by a registry key.

This is a warning and not an error because it does actually turns out correct in the end, it does properly map it to one of the available assembly reference. The one you expect to be used, Microsoft.Office.Core. That this happened correctly is a wee bit of a gamble, it would technically be possible for you to forget adding the reference to MSO.DLL and have another interop type named "Assistant". Boomshakalaka if you ignore the warning then and use the interface.

So go ahead and set your laser to stun:

    #pragma warning(disable:4691)
    using namespace Microsoft::Office;
    using namespace Microsoft::Office::Interop;

I changed the using statements, the ones you quoted were wrong and don't allow using "Excel::Application" and "Core::MsoTriState", another fruitful source of compile errors.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM