Excel automation in C++

Pages: 12
Last two interfaces...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
interface IShellNameSpace : IShellFavoritesNameSpace
{
 virtual HRESULT __stdcall GetEnumOptions(LONG* pgrfEnumFlags)=0;
 virtual HRESULT __stdcall SetEnumOptions(LONG pgrfEnumFlags)=0;
 virtual HRESULT __stdcall GetSelectedItem(IDispatch** pItem)=0;
 virtual HRESULT __stdcall SetSelectedItem(IDispatch* pItem)=0;
 virtual HRESULT __stdcall GetRoot(VARIANT* pvar)=0;
 virtual HRESULT __stdcall SetRoot(VARIANT pvar)=0;
 virtual HRESULT __stdcall GetDepth(int* piDepth)=0;
 virtual HRESULT __stdcall SetDepth(int piDepth)=0;
 virtual HRESULT __stdcall GetMode(unsigned int* puMode)=0;
 virtual HRESULT __stdcall SetMode(unsigned int puMode)=0;
 virtual HRESULT __stdcall GetFlags(unsigned int* pdwFlags)=0;
 virtual HRESULT __stdcall SetFlags(unsigned int pdwFlags)=0;
 virtual HRESULT __stdcall SetTVFlags(unsigned int dwFlags)=0;
 virtual HRESULT __stdcall GetTVFlags(unsigned int* dwFlags)=0;
 virtual HRESULT __stdcall GetColumns(BSTR* bstrColumns)=0;
 virtual HRESULT __stdcall SetColumns(BSTR bstrColumns)=0;
 virtual HRESULT __stdcall GetCountViewTypes(int* piTypes)=0;
 virtual HRESULT __stdcall SetViewType(int iType)=0;
 virtual HRESULT __stdcall SelectedItems(IDispatch** ppid)=0;
 virtual HRESULT __stdcall Expand(VARIANT var, int iDepth)=0;
 virtual HRESULT __stdcall UnselectAll(void)=0;
};


interface IScriptErrorList : IDispatch
{
 virtual HRESULT __stdcall advanceError(void)=0;
 virtual HRESULT __stdcall retreatError(void)=0;
 virtual HRESULT __stdcall canAdvanceError(LONG* pfCanAdvance)=0;
 virtual HRESULT __stdcall canRetreatError(LONG* pfCanRetreat)=0;
 virtual HRESULT __stdcall getErrorLine(LONG* plLine)=0;
 virtual HRESULT __stdcall getErrorChar(LONG* plChar)=0;
 virtual HRESULT __stdcall getErrorCode(LONG* plCode)=0;
 virtual HRESULT __stdcall getErrorMsg(BSTR* pstr)=0;
 virtual HRESULT __stdcall getErrorUrl(BSTR* pstr)=0;
 virtual HRESULT __stdcall getAlwaysShowLockState(LONG* pfAlwaysShowLocked)=0;
 virtual HRESULT __stdcall getDetailsPaneOpen(LONG* pfDetailsPaneOpen)=0;
 virtual HRESULT __stdcall setDetailsPaneOpen(LONG fDetailsPaneOpen)=0;
 virtual HRESULT __stdcall getPerErrorDisplay(LONG* pfPerErrorDisplay)=0;
 virtual HRESULT __stdcall setPerErrorDisplay(LONG fPerErrorDisplay)=0;
};


#endif // SHDocVw_h

You need Atl90.dll for an ActiveX Control Container.  See my StartOleProcess in Main.cpp.  Actually, I believe any version of Atl.dll should work.  And now that I think of it, I'm not sure I need the function pointers.  Nope, just thought about it.  I think I need them for MinGW.  I don't have a usable *.lib file to link with, and I want it to work with GNU.
Once you get it working, to use it you need to type some url (such as www.cplusplus.com) into the text box at top and then hit the 'Navigate' button.
I know its complicated as h*** but I haven't gotten around to commenting anything yet. Its all hot off the press. But in a few words what's going on is I'm using some global ATL functions to create an ActiveX Control Container for the internet control. It helps to give it a child window control to act as a parent and that is what the "static" hContainer is in fnWndProc_OnCreate). I eventually end up with an IWebBrowser* with which I can call the IWebBrowser interface methods.

Actually, I need to make some minor changes to my Type Lib generator program, because what it generated wasn't exactly like what I posted above. Some of the enums were mixed up with the interfaces, but I can pretty easily fix that. The two TypeLibs I was continually testing me code against were the Ado typelib and the MSFlexGrid TypeLibs. I didn't notice the problem with the enums until I tested this one.

I'm thinking I might test yet with the Windows Media Player before posting the code.
Hello all!
Can we please get back to initial topic. So where I am now is how to read the value from any cell I want? (What I do have is a pointer to ActiveSheet):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include <ole2.h> // OLE2 Definitions
#include <stdio.h>

// AutoWrap() - Automation helper function...
HRESULT AutoWrap(int autoType, VARIANT *pvResult, IDispatch *pDisp, LPOLESTR ptName, int cArgs...) {
    // Begin variable-argument list...
    HRESULT hr;
    va_list marker;
    va_start(marker, cArgs);
    if(!pDisp) {
		 hr = E_UNEXPECTED;
       return hr;
    }

    // Variables used...
    DISPPARAMS dp = { NULL, NULL, 0, 0 };
    DISPID dispidNamed = DISPID_PROPERTYPUT;
    DISPID dispID;
    char buf[200];
    char szName[200];
    
    // Convert down to ANSI
    WideCharToMultiByte(CP_ACP, 0, ptName, -1, szName, 256, NULL, NULL);
    
    // Get DISPID for name passed...
    hr = pDisp->GetIDsOfNames(IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT, &dispID);
    if(FAILED(hr)) {
        sprintf(buf, "IDispatch::GetIDsOfNames(\"%s\") failed w/err 0x%08lx", szName, hr);
        return hr;
    }
    
    // Allocate memory for arguments...
    VARIANT *pArgs = new VARIANT[cArgs+1];
    // Extract arguments...
    for(int i=0; i<cArgs; i++) {
        pArgs[i] = va_arg(marker, VARIANT);
    }
    
    // Build DISPPARAMS
    dp.cArgs = cArgs;
    dp.rgvarg = pArgs;
    
    // Handle special-case for property-puts!
    if(autoType & DISPATCH_PROPERTYPUT) {
        dp.cNamedArgs = 1;
        dp.rgdispidNamedArgs = &dispidNamed;
    }
    
    // Make the call!
    hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, autoType, &dp, pvResult, NULL, NULL);
    if(FAILED(hr)) {
        sprintf(buf, "IDispatch::Invoke(\"%s\"=%08lx) failed w/err 0x%08lx", szName, dispID, hr);
        return hr;
    }

    // End variable-argument section...
    va_end(marker);
    delete [] pArgs;
    return hr;
}

// main algorithm
HRESULT DoJob()
{
   // Get CLSID for our server...
   CLSID clsid;
   HRESULT hr = CLSIDFromProgID(L"Excel.Application", &clsid);
   if(FAILED(hr)) {
      return hr;
   }

	// Connect to Currently Running Excel 
	IUnknown *pUnk = NULL;
	hr = GetActiveObject(clsid, NULL, (IUnknown**)&pUnk);
	if(FAILED(hr)) {
		return hr;
	}
	IDispatch *pXlApp = NULL;
	hr = pUnk->QueryInterface(IID_IDispatch, (void **)&pXlApp);
	if(FAILED(hr)) {
		return hr;
	}

   // Get Active Sheet object
   IDispatch *pXlSheet;
   {
      VARIANT result;
      VariantInit(&result);
      AutoWrap(DISPATCH_PROPERTYGET, &result, pXlApp, L"ActiveSheet", 0);
      pXlSheet = result.pdispVal;
		if(pXlSheet == NULL)
		{
			hr = E_UNEXPECTED;
         return hr;		
		}
   }

	// *** Here I need to read a cell
	
   // Release references...
   pXlSheet->Release();
   pXlApp->Release();
	return hr;
}

int main(void)
{
   // Initialize COM for this thread...
   CoInitialize(NULL);

	// main algorithm
	HRESULT hr;
	hr = DoJob();

   // Uninitialize COM for this thread...
   CoUninitialize();
}


Initial example put some values into cells but I need the opposite action, to read something. I am now trying to "invert" example to do what I need but if someone feels easy to provide a code snippet as an example I would appreciate greatly.
Last edited on
But the whole reason I'm doing this is that I like to be able to do the same things in C++ that I can so easily do in PowerBASIC. In this latter language they provide a GUI utility that allows you to double click on a type library listed in a Tree View Grid Control, and then it auto-generates the declares, enums, etc., necessary to use the COM object. That tool lists the GUIDs like you mentioned. Here is a little of that for "Shell.Explorer"...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
'ShellExplorer.inc

 Generated by: PowerBASIC COM Browser v.2.00.0086
 Date & Time : 12/27/2011 at 11:46 AM
 Options:
 Always use an Interface Prefix : Off
 Interface Prefix               : IE
 Prefix ProgIDs, ClassIDs...    : Off
 Use ANSI Strings               : Off
 Use Singular Enumerations      : Off
 Generate Dispatch Interfaces   : Off
 Include Parameter Names        : On
 Use Property Get/Set statements: On
 ------------------------------------------------
 Library Name: SHDocVw
 Library File: C:\WINDOWS\system32\ieframe.dll
 Description : Microsoft Internet Controls
 GUID : {EAB22AC0-30C1-11CF-A7EB-0000C05BAE0B}
 LCID : 0
 Version : 1.1

' Version Dependent ProgIDs
$PROGID_WebBrowser_V11 = "Shell.Explorer.1"
$PROGID_WebBrowser2 = "Shell.Explorer.2"
$PROGID_InternetExplorer1 = "InternetExplorer.Application.1"
$PROGID_ShellUIHelper1 = "Shell.UIHelper.1"
$PROGID_ShellNameSpace1 = "ShellNameSpace.ShellNameSpace.1"
$PROGID_ShellShellNameSpace1 = "ShellNameSpace.ShellNameSpace.1"

' Version Independent ProgIDs
$PROGID_WebBrowser_V1 = "Shell.Explorer"
$PROGID_WebBrowser = "Shell.Explorer"
$PROGID_InternetExplorer = "InternetExplorer.Application"
$PROGID_ShellNameSpace = "ShellNameSpace.ShellNameSpace"
$PROGID_ShellShellNameSpace = "ShellNameSpace.ShellNameSpace"

' Class Identifiers
$CLSID_WebBrowser_V1 = GUID$("{EAB22AC3-30C1-11CF-A7EB-0000C05BAE0B}")
$CLSID_Event_DWebBrowserEvents2 = GUID$("{E0C3265B-A665-41F4-BA17-AC5D9B05728E}")
$CLSID_Event_DWebBrowserEvents = GUID$("{741720AB-1094-49C2-B6B1-503F74BC8125}")
$CLSID_WebBrowser = GUID$("{8856F961-340A-11D0-A96B-00C04FD705A2}")
$CLSID_InternetExplorer = GUID$("{0002DF01-0000-0000-C000-000000000046}")
$CLSID_InternetExplorerMedium = GUID$("{D5E8041D-920F-45E9-B8FB-B1DEB82C6E5E}")
$CLSID_ShellBrowserWindow = GUID$("{C08AFD90-F2A1-11D1-8455-00A0C91F3880}")
$CLSID_ShellWindows = GUID$("{9BA05972-F6A8-11CF-A442-00A0C90A8F39}")
$CLSID_Event_DShellWindowsEvents = GUID$("{B12F86FB-3C13-407B-872A-51FA6915C1B6}")
$CLSID_ShellUIHelper = GUID$("{64AB4BB7-111E-11D1-8F79-00C04FC2FBE1}")
$CLSID_ShellNameSpace = GUID$("{55136805-B2DE-11D1-B9F2-00A0C98BC547}")
$CLSID_Event_DShellNameSpaceEvents = GUID$("{1353051D-B4E5-4242-A9CE-3A68F975C429}")
$CLSID_ShellShellNameSpace = GUID$("{2F2F1F96-2BC1-4B1C-BE28-EA3774F4676A}")
$CLSID_CScriptErrorList = GUID$("{EFD01300-160F-11D2-BB2E-00805FF7EFCA}")

' Interface Identifiers
$IID_IWebBrowser = GUID$("{EAB22AC1-30C1-11CF-A7EB-0000C05BAE0B}")
$IID_DWebBrowserEvents = GUID$("{EAB22AC2-30C1-11CF-A7EB-0000C05BAE0B}")
$IID_IWebBrowserApp = GUID$("{0002DF05-0000-0000-C000-000000000046}")
$IID_IWebBrowser2 = GUID$("{D30C1661-CDAF-11D0-8A3E-00C04FC9E26E}")
$IID_DWebBrowserEvents2 = GUID$("{34A715A0-6587-11D0-924A-0020AFC7AC4D}")
$IID_DShellWindowsEvents = GUID$("{FE4106E0-399A-11D0-A48C-00A0C90A8F39}")
$IID_IShellWindows = GUID$("{85CB6900-4D95-11CF-960C-0080C7F4EE85}")
$IID_IShellUIHelper = GUID$("{729FE2F8-1EA8-11D1-8F85-00C04FC2FBE1}")
$IID_IShellUIHelper2 = GUID$("{A7FE6EDA-1932-4281-B881-87B31B8BC52C}")
$IID_IShellUIHelper3 = GUID$("{528DF2EC-D419-40BC-9B6D-DCDBF9C1B25D}")
$IID_DShellNameSpaceEvents = GUID$("{55136806-B2DE-11D1-B9F2-00A0C98BC547}")
$IID_IShellFavoritesNameSpace = GUID$("{55136804-B2DE-11D1-B9F2-00A0C98BC547}")
$IID_IShellNameSpace = GUID$("{E572D3C9-37BE-4AE2-825D-D521763E3108}")
$IID_IScriptErrorList = GUID$("{F3470F24-15FD-11D2-BB2E-00805FF7EFCA}")

Enum CommandStateChangeConstants
    CSC_UPDATECOMMANDS = -1
    CSC_NAVIGATEFORWARD = 1
    CSC_NAVIGATEBACK = 2
End Enum

Enum OLECMDID
    OLECMDID_OPEN = 1
    OLECMDID_NEW = 2
    OLECMDID_SAVE = 3
    OLECMDID_SAVEAS = 4
    OLECMDID_SAVECOPYAS = 5
    OLECMDID_PRINT = 6
    OLECMDID_PRINTPREVIEW = 7
    OLECMDID_PAGESETUP = 8
    OLECMDID_SPELL = 9
    OLECMDID_PROPERTIES = 10
    OLECMDID_CUT = 11
    OLECMDID_COPY = 12
    OLECMDID_PASTE = 13
    OLECMDID_PASTESPECIAL = 14
    OLECMDID_UNDO = 15
    OLECMDID_REDO = 16
    OLECMDID_SELECTALL = 17
    OLECMDID_CLEARSELECTION = 18
    OLECMDID_ZOOM = 19
    OLECMDID_GETZOOMRANGE = 20
    OLECMDID_UPDATECOMMANDS = 21
    OLECMDID_REFRESH = 22
    OLECMDID_STOP = 23
    OLECMDID_HIDETOOLBARS = 24
    OLECMDID_SETPROGRESSMAX = 25
    OLECMDID_SETPROGRESSPOS = 26
    OLECMDID_SETPROGRESSTEXT = 27
    OLECMDID_SETTITLE = 28
    OLECMDID_SETDOWNLOADSTATE = 29
    OLECMDID_STOPDOWNLOAD = 30
    OLECMDID_ONTOOLBARACTIVATED = 31
    OLECMDID_FIND = 32
    OLECMDID_DELETE = 33
    OLECMDID_HTTPEQUIV = 34
    OLECMDID_HTTPEQUIV_DONE = 35
    OLECMDID_ENABLE_INTERACTION = 36
    OLECMDID_ONUNLOAD = 37
    OLECMDID_PROPERTYBAG2 = 38
    OLECMDID_PREREFRESH = 39
    OLECMDID_SHOWSCRIPTERROR = 40
    OLECMDID_SHOWMESSAGE = 41
    OLECMDID_SHOWFIND = 42
    OLECMDID_SHOWPAGESETUP = 43
    OLECMDID_SHOWPRINT = 44
    OLECMDID_CLOSE = 45
    OLECMDID_ALLOWUILESSSAVEAS = 46
    OLECMDID_DONTDOWNLOADCSS = 47
    OLECMDID_UPDATEPAGESTATUS = 48
    OLECMDID_PRINT2 = 49
    OLECMDID_PRINTPREVIEW2 = 50
    OLECMDID_SETPRINTTEMPLATE = 51
    OLECMDID_GETPRINTTEMPLATE = 52
    OLECMDID_PAGEACTIONBLOCKED = 55
    OLECMDID_PAGEACTIONUIQUERY = 56
    OLECMDID_FOCUSVIEWCONTROLS = 57
    OLECMDID_FOCUSVIEWCONTROLSQUERY = 58
    OLECMDID_SHOWPAGEACTIONMENU = 59
    OLECMDID_ADDTRAVELENTRY = 60
    OLECMDID_UPDATETRAVELENTRY = 61
    OLECMDID_UPDATEBACKFORWARDSTATE = 62
    OLECMDID_OPTICAL_ZOOM = 63
    OLECMDID_OPTICAL_GETZOOMRANGE = 64
    OLECMDID_WINDOWSTATECHANGED = 65
    OLECMDID_ACTIVEXINSTALLSCOPE = 66
    OLECMDID_UPDATETRAVELENTRY_DATARECOVERY = 67
End Enum

...
...

' Interface Name  : IWebBrowser
' Description     : Web Browser interface
' Class Name      : WebBrowser
' ClassID         : $CLSID_WebBrowser
' ProgID          : $PROGID_WebBrowser
' Version ProgID  : $PROGID_WebBrowser2
Interface IWebBrowser $IID_IWebBrowser : Inherit IDispatch
  Method GoBack <100> ()
  Method GoForward <101> ()
  Method GoHome <102> ()
  Method GoSearch <103> ()
  Method Navigate <104> (Byval URL As WString, Opt ByRef In Flags As Variant, Opt ByRef In TargetFrameName As Variant, Opt ByRef In PostData As Variant, Opt ByRef In Headers As Variant)
  Method Refresh <-550> ()
  Method Refresh2 <105> (Opt ByRef In Level As Variant)
  Method Stop <106> ()
  Property Get Application <200> () As IDispatch
  Property Get Parent <201> () As IDispatch
  Property Get Container <202> () As IDispatch
  Property Get Document <203> () As IDispatch
  Property Get TopLevelContainer <204> () As Integer
  Property Get Type <205> () As WString
  Property Get Left <206> () As Long
  Property Set Left <206> (ByVal pl As Long)
  Property Get Top <207> () As Long
  Property Set Top <207> (ByVal pl As Long)
  Property Get Width <208> () As Long
  Property Set Width <208> (ByVal pl As Long)
  Property Get Height <209> () As Long
  Property Set Height <209> (ByVal pl As Long)
  Property Get LocationName <210> () As WString
  Property Get LocationURL <211> () As WString
  Property Get Busy <212> () As Integer
End Interface        
 


So you see, C++ isn't the only 'hot' language out there!
Oh, by the way, the outgoing 'event' interfaces weren't included in the above code. My Type Lib dumper generates them too, but puts them in a seperate file. Just in case you're curious, this is what the fnWndProc_OnCreate() code looks like for the exact same thing in PowerBASIC. However, this code does connect an events interface using proprietary PowerBASIC techniques (however, it can be done using connection points too)...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Function fnWndProc_OnCreate(wea As WndEventArgs) As Long
  Local lpCreateStruct As CREATESTRUCT Ptr
  Local pStream,ppUnkContainer As IUnknown
  Local hContainer,hCtrl As Dword
  Local szCtrl As ZStr*32
  Local hr As Long

  lpCreateStruct=Wea.lParam
  Wea.hInst=@lpCreateStruct.hInstance
  Call AtlAxWinInit()
  hContainer=CreateWindowEx(0,"static","",%WS_CHILD OR %WS_VISIBLE,0,0,975,750,Wea.hWnd,%ID_CONTAINER,Wea.hInst,Byval %NULL)
  szCtrl="Shell.Explorer" 'Program ID
  hr=AtlAxCreateControl(szCtrl,hContainer,pStream,ppUnkContainer)
  If SUCCEEDED(hr) Then
     pEvents=Class "Class_DWebBrowserEvents"
     pWebBrowser=AtlAxGetDispatch(hContainer)
     If IsObject(pWebBrowser) Then
        Events From pWebBrowser Call pEvents
     End If
     hCtrl=CreateWindowEx(0,"button","Navigate",%WS_CHILD OR %WS_VISIBLE,20,760,150,30,Wea.hWnd,%ID_NAVIGATE,Wea.hInst,Byval %NULL)
     hCtrl=CreateWindowEx(%WS_EX_CLIENTEDGE,"edit","",%WS_CHILD OR %WS_VISIBLE,200,760,400,30,Wea.hWnd,%ID_URL,Wea.hInst,Byval %NULL)
     hCtrl=CreateWindowEx(0,"button","Close",%WS_CHILD OR %WS_VISIBLE,700,760,80,30,Wea.hWnd,%ID_CLOSE,Wea.hInst,Byval %NULL)
  End If
  Print #fp, "Leaving fnWndProc_OnCreate()"

  fnWndProc_OnCreate=0
End Function     
Hello all!
Can we please get back to initial topic. So where I am now is how to read the value from any cell I want? (What I do have is a pointer to ActiveSheet):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include <ole2.h> // OLE2 Definitions
#include <stdio.h>

// AutoWrap() - Automation helper function...
HRESULT AutoWrap(int autoType, VARIANT *pvResult, IDispatch *pDisp, LPOLESTR ptName, int cArgs...) {
    // Begin variable-argument list...
    HRESULT hr;
    va_list marker;
    va_start(marker, cArgs);
    if(!pDisp) {
		 hr = E_UNEXPECTED;
       return hr;
    }

    // Variables used...
    DISPPARAMS dp = { NULL, NULL, 0, 0 };
    DISPID dispidNamed = DISPID_PROPERTYPUT;
    DISPID dispID;
    char buf[200];
    char szName[200];
    
    // Convert down to ANSI
    WideCharToMultiByte(CP_ACP, 0, ptName, -1, szName, 256, NULL, NULL);
    
    // Get DISPID for name passed...
    hr = pDisp->GetIDsOfNames(IID_NULL, &ptName, 1, LOCALE_USER_DEFAULT, &dispID);
    if(FAILED(hr)) {
        sprintf(buf, "IDispatch::GetIDsOfNames(\"%s\") failed w/err 0x%08lx", szName, hr);
        return hr;
    }
    
    // Allocate memory for arguments...
    VARIANT *pArgs = new VARIANT[cArgs+1];
    // Extract arguments...
    for(int i=0; i<cArgs; i++) {
        pArgs[i] = va_arg(marker, VARIANT);
    }
    
    // Build DISPPARAMS
    dp.cArgs = cArgs;
    dp.rgvarg = pArgs;
    
    // Handle special-case for property-puts!
    if(autoType & DISPATCH_PROPERTYPUT) {
        dp.cNamedArgs = 1;
        dp.rgdispidNamedArgs = &dispidNamed;
    }
    
    // Make the call!
    hr = pDisp->Invoke(dispID, IID_NULL, LOCALE_SYSTEM_DEFAULT, autoType, &dp, pvResult, NULL, NULL);
    if(FAILED(hr)) {
        sprintf(buf, "IDispatch::Invoke(\"%s\"=%08lx) failed w/err 0x%08lx", szName, dispID, hr);
        return hr;
    }

    // End variable-argument section...
    va_end(marker);
    delete [] pArgs;
    return hr;
}

// main algorithm
HRESULT DoJob()
{
   // Get CLSID for our server...
   CLSID clsid;
   HRESULT hr = CLSIDFromProgID(L"Excel.Application", &clsid);
   if(FAILED(hr)) {
      return hr;
   }

	// Connect to Currently Running Excel 
	IUnknown *pUnk = NULL;
	hr = GetActiveObject(clsid, NULL, (IUnknown**)&pUnk);
	if(FAILED(hr)) {
		return hr;
	}
	IDispatch *pXlApp = NULL;
	hr = pUnk->QueryInterface(IID_IDispatch, (void **)&pXlApp);
	if(FAILED(hr)) {
		return hr;
	}

   // Get Active Sheet object
   IDispatch *pXlSheet;
   {
      VARIANT result;
      VariantInit(&result);
      AutoWrap(DISPATCH_PROPERTYGET, &result, pXlApp, L"ActiveSheet", 0);
      pXlSheet = result.pdispVal;
		if(pXlSheet == NULL)
		{
			hr = E_UNEXPECTED;
         return hr;		
		}
   }

	// *** Here I need to read a cell
	
   // Release references...
   pXlSheet->Release();
   pXlApp->Release();
	return hr;
}

int main(void)
{
   // Initialize COM for this thread...
   CoInitialize(NULL);

	// main algorithm
	HRESULT hr;
	hr = DoJob();

   // Uninitialize COM for this thread...
   CoUninitialize();
}


Initial example put some values into cells but I need the opposite action, to read something. I am now trying to "invert" example to do what I need but if someone feels easy to provide a code snippet as an example I would appreciate greatly.
There is a PropertyGet member of the WorkSheet objject named "Range". The inputs to that is the cell you want retrieved such as "AK12".
I've never done it in C++, but in PowerBASIC it looks like this to retrieve a cell...

1
2
3
4
5
6
7
Local pXLSheet As ExcelWorkSheet
Local vVariant As Variant
Local vRange As Variant

vRange="AK43"
Object Get pXLSheet.Range(vRange) To vVariant


And then the Variant vVariant would contain the value from the cell.
By the way (and this is a bit off topic), if you only need to read data for what you are working on, its possible to use ODBC to read Excel spreadsheets. The code isn't as ugly as this COM code (I know that's not your fault). A year or two ago I provided C++ code in this forum showing how to do that.

In any case, you need to have something in the cell to be able to read it back out? Or else you'll just get an empty string.
Topic archived. No new replies allowed.
Pages: 12