Click here to Skip to main content
15,868,005 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello everyone!

I would like to start by saying thanks to everyone who takes some time to view this thread and try to help.

I have made a MS Word document, with a table. Table has 4 columns.

I would like to insert random text into columns, using C++ and pure Win32 API.

I believe this can be done via OLE and automation, but I am new to that, so If that is the only way to do it, please help me by posting some sample code example, if that is not a big deal, so I can see the logic behind using OLE and automation, I would be very grateful, since I couldn't handle the online documentation on MSDN.

That would be all, I just need help for this, in my opinion, simple task-> to fill a table in document made in MS Word with some random text.

EDIT:
---------------------------------------------------------

I have decided to use OLE and C++ for this task, following the exaple from this article:
http://support.microsoft.com/kb/216686/en-us[^]

I have managed to open the Word file, make it invisible, but I need help with selecting the existing table.

That would be enough for now, since it would enable me to try inserting text into table on my own.

Here is the code:

NOTE:
-----------------------

The handle provided in AutoWrap() is for a dialog that must be closed if error occurs, everything else is the same.

-----------------------

C++
HRESULT AutoWrap(HWND hwnd,int autoType, VARIANT *pvResult, IDispatch *pDisp, 
				 LPOLESTR ptName, int cArgs...)	
{
	// Begin variable-argument list...

	va_list marker;
	va_start(marker, cArgs);
	
	if(!pDisp)
	{
		MessageBox( NULL, L"NULL IDispatch passed to AutoWrap()", L"Error", MB_ICONERROR );
	    
		EndDialog(hwnd, IDCANCEL);
	}
	
	// Variables used...

	DISPPARAMS dp = { NULL, NULL, 0, 0 };
	DISPID dispidNamed = DISPID_PROPERTYPUT;
	DISPID dispID;
	HRESULT hr;
	wchar_t 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)) 
	{
		swprintf_s( buf, L"IDispatch::GetIDsOfNames(\"%s\") failed with error 0x%08lx", 
			szName, hr );

		MessageBox( NULL, buf, L"AutoWrap()", MB_ICONERROR );

	    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) ) 
	{
		swprintf_s(buf, L"IDispatch::Invoke(\"%s\"=%08lx) failed with error 0x%08lx", 
			szName, dispID, hr);

	    MessageBox( NULL, buf, L"AutoWrap()", MB_ICONERROR );

	    return hr;
	}

	// End variable-argument section...

	va_end(marker);
	    
	delete [] pArgs;
	    
	return hr;
}


------------------------------

When dialog button is pressed, open word and fill pre made table with some text:

-------------------------------

C++
case IDOK:
{
	// Initialize COM for this thread...

	CoInitialize(NULL);
	
	// Get CLSID for our server...

	CLSID clsid;
				
	HRESULT hr = CLSIDFromProgID(L"Word.Application", &clsid);
	
	if(FAILED(hr)) 
	{
		MessageBox( NULL, L"CLSIDFromProgID() failed", L"Error", 
						MB_ICONERROR );

		EndDialog(hwnd, IDCANCEL);
	}

	// Start server and get IDispatch...

	IDispatch *pWordApp;

	hr = CoCreateInstance( clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, 
					(void **)&pWordApp );
				
	if(FAILED(hr)) 
	{
		MessageBox( NULL, L"Word not registered properly", L"Error", 
						MB_ICONERROR );

		EndDialog(hwnd, IDCANCEL);
	}
	
	// Make it visible (i.e. app.visible = 1)

	{
		VARIANT x;
		x.vt = VT_I4;
		x.lVal = 1;	//	ako je 0 -> nevidljiva!!!
		AutoWrap( hwnd, DISPATCH_PROPERTYPUT, NULL, pWordApp, 
						L"Visible", 1, x);
	}
				
	// GetDocuments

	IDispatch *pDocuments;
	{
		VARIANT result;
		VariantInit(&result);
					
		hr = AutoWrap( hwnd, DISPATCH_PROPERTYGET, &result, pWordApp, 
						L"Documents", 0);

		pDocuments = result.pdispVal;
	}
	
	// OpenDocument

	IDispatch *pActiveDocument; 
	{
		/********* get current file path ****/

		wchar_t tmp[ _MAX_PATH ];

		memset( &tmp, '\0', sizeof(tmp) );

		if( DWORD nSize = GetModuleFileName( NULL, tmp, _MAX_PATH ) )
		{
			for (int i = nSize - 1; i >= 0; i--)
			{
				if ( tmp[i] == L'\\' || tmp[i] == L'/')
				{
					tmp[i + 1] = L'\0';
					nSize = i + 1;
					break;
				}
			}

			// concat printing folder and resource to manipulate with

			wcscat_s( tmp, _MAX_PATH, L"print\\Tabela.docx" );
		}
		else
		   {
			MessageBox( NULL, L"Грешка при учитавању ресурса за штампу!", 
								L"", MB_ICONERROR );
								
			EndDialog(hwnd, IDCANCEL);
		   }

		/************** open Word *****************/

		VARIANT result;
		VariantInit(&result);
		VARIANT x;
		x.vt = VT_BSTR;
		x.bstrVal = ::SysAllocString(tmp);

		AutoWrap( hwnd, DISPATCH_METHOD, &result, pDocuments, 
						L"Open", 1, x );

		pActiveDocument = result.pdispVal;

		SysFreeString(x.bstrVal);
	}


	MessageBox( hwnd, L"Added to give me time to see the effects", L"", MB_OK );

	// close Word

	{
		VARIANT x;
		x.vt = VT_BOOL;
		x.boolVal = false;

		AutoWrap( hwnd, DISPATCH_METHOD, NULL, pActiveDocument, L"Close", 
						1, x );

		AutoWrap( hwnd, DISPATCH_METHOD, NULL, pWordApp, L"Quit", 0);
	}	

	pActiveDocument->Release();
	pDocuments->Release();
	pWordApp->Release();

	// Uninitialize COM for this thread...

	CoUninitialize();
}

break;



Thank you.

--------------------------------------------------------------------------


I work in MS Visual Studio Express 2008, on Windows XP, in C++, using pure WIN32 API.
Posted
Updated 3-Jul-13 4:57am
v4

 
Share this answer
 
Comments
H.Brydon 28-Jun-13 13:36pm    
Good links ... be aware that the techniques for communicating with MS Word are highly dependent on the version of MS Word. Microsoft has changed the programming interface drastically, several times, over the lifetime of MS Word.

I used to do this as part of my job. Major hassle!!
Maciej Los 28-Jun-13 13:57pm    
Thank you ;)
MyOldAccount 29-Jun-13 6:45am    
Yes it is!
Thank you!
If I run into troubles I will post further questions, since I don't know C#, but with the help of community and with my hard work I think I will figure it out!

P.S.
I could still use some small code example in C++ though ;)
Maciej Los 29-Jun-13 8:06am    
You're welcome ;)
If my answer was helpful, please, mark it as "solved" (green button).
merano 29-Jun-13 18:09pm    
Solution 1 is based on CLI code - you need .NET
Nothing of this is usable for C++ and pure Win32 API.
For C++ you could start with

Office Automation Using Visual C++
http://support.microsoft.com/kb/196776/en-us

How to automate Excel from C++ without using MFC or #import
http://support.microsoft.com/kb/216686/en-us

MS Office OLE Automation Using C++
http://www.codeproject.com/Articles/34998/MS-Office-OLE-Automation-Using-C

Followin the Manual for "MS Office OLE Automation Using C++"


  • Choose a keyboard macro and assign a key for the macro
  • After the macro recording has been started, do what you want get automated
  • Stop macro
  • Go to Tools->Macro->Visual Basic Editor (F11)
  • Under "NewMacros", you can see your recorded macro at the end


You get the code:

Selection.TypeText Text:="one"
Selection.MoveRight Unit:=wdCell
Selection.TypeText Text:="two"
Selection.MoveRight Unit:=wdCell
Selection.TypeText Text:="thre"
Selection.MoveRight Unit:=wdCell
Selection.TypeText Text:="four"


Edit:

Found some more source at code.msdn.microsoft
C++ app automates Word (CppAutomateWord)
http://code.msdn.microsoft.com/office/CppAutomateWord-28938be1[^]
 
Share this answer
 
v3
Comments
Maciej Los 30-Jun-13 4:21am    
Good links!
+5
MyOldAccount 2-Jul-13 13:45pm    
Good links, I have found how to open word document, but I couldn't find how to insert text into word columns.

A code snippet, or a link would be appreciated, so I can accept your solution.

Thanks again for the links.
MyOldAccount 3-Jul-13 13:19pm    
I have updated my question with the code snippet.
I have visited some of those links in the past, but I need help with selecting a table, and inserting some text into it.

From your links I have got a vague grasp of what I need to do.

Can you please help me to finish my code that I have submitted in the question?

I am getting desperate...

Thank you kindly.
MyOldAccount 4-Jul-13 15:35pm    
I have accepted your solution, and you have got a 5 from me.

Thank you so much, that Macro advice was a thing I overlooked in that article, yet it was what helped me to solve my problem.

God bless you, and thanks again!
Thanks to the links submitted by members Maciej Los and merano, I was able to engineer a solution.

It included this link http://msdn.microsoft.com/en-us/library/Microsoft.Office.Interop.Word%28v=office.14%29.aspx[^] , combined with the article here on CodeProject : MS Office OLE Automation Using C++[^] .

The advice to use Macro in Word as assistance for a solution was what helped me in the end.

Thank you guys, both of you have my 5, and I will officially accept both your solutions.

You have earned it!
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900