cara mengotomatisasi Microsoft Word dengan Microsoft Visual C++ untuk mengambil kembali dan manipulasi properti dokumen

Untuk membangun aplikasi konsol Visual C++ 6.0 sederhana yang mengotomatisasi Microsoft Word menggunakan Visual C++, ikuti langkah-langkah berikut:
  1. Mulai Visual C++ 6.0, dan membuat aplikasi konsol Win32 baru yang bernama AutoWord. Pilih aplikasi "Halo, dunia!" dasar, dan kemudian klik selesai.
  2. Buka berkas AutoWord.cpp dihasilkan, dan kemudian ganti isinya dengan kode berikut:
    #include "stdafx.h"
    #include <ole2.h>
    
    // 
    // AutoWrap() - Automation helper function...
    // 
    HRESULT AutoWrap(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, "NULL IDispatch passed to AutoWrap()", 
                           "Error", 0x10010);
                _exit(0);
          }
    
          // Variables used...
          DISPPARAMS dp = { NULL, NULL, 0, 0 };
          DISPID dispidNamed = DISPID_PROPERTYPUT;
          DISPID dispID;
          HRESULT hr;
          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/err0x%08lx",
                        szName, hr);
                MessageBox(NULL, buf, "AutoWrap()", 0x10010);
                _exit(0);
                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);
                MessageBox(NULL, buf, "AutoWrap()", 0x10010);
                _exit(0);
                return hr;
          }
          // End variable-argument section...
          va_end(marker);
       
          delete [] pArgs;
       
          return hr;
    
    }
    
    int main(int argc, char* argv[])
    {
          // Initialize COM for this thread...
          CoInitialize(NULL);
    
          // Get CLSID for Word.Application...
          CLSID clsid;
          HRESULT hr = CLSIDFromProgID(L"Word.Application", &clsid);
          if(FAILED(hr)) {
                ::MessageBox(NULL, "CLSIDFromProgID() failed", "Error", 
                             0x10010);
                return -1;
          }
    
          // Start Word and get IDispatch...
          IDispatch *pWordApp;
          hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, 
                                IID_IDispatch, (void **)&pWordApp);
          if(FAILED(hr)) {
                ::MessageBox(NULL, "Word not registered properly", 
                             "Error", 0x10010);
                return -2;
          }
    
          // Make Word visible
          {
                VARIANT x;
                x.vt = VT_I4;
                x.lVal = 1;
                AutoWrap(DISPATCH_PROPERTYPUT, NULL, pWordApp, L"Visible", 1, 
                         x);
          }
    
          // Get Documents collection
          IDispatch *pDocs;
          {
                VARIANT result;
                VariantInit(&result);
                AutoWrap(DISPATCH_PROPERTYGET, &result, pWordApp, L"Documents", 
                         0);
    
                pDocs = result.pdispVal;
          }
    
          // Call Documents.Open() to open C:\Doc1.doc
          IDispatch *pDoc;
          {
                VARIANT result;
                VariantInit(&result);
                VARIANT x;
                x.vt = VT_BSTR;
                x.bstrVal = ::SysAllocString(L"C:\\Doc1.doc");
    
                AutoWrap(DISPATCH_METHOD, &result, pDocs, L"Open", 1, x);
                pDoc = result.pdispVal;
                SysFreeString(x.bstrVal);
          }
    
          // Get BuiltinDocumentProperties collection
          IDispatch *pProps;
          {
                VARIANT result;
                VariantInit(&result);
                AutoWrap(DISPATCH_PROPERTYGET, &result, pDoc, 
                         L"BuiltinDocumentProperties", 0);
                pProps = result.pdispVal;
          }
    
          // Get "Subject" from BuiltInDocumentProperties.Item("Subject")
          IDispatch *pPropSubject;
          {
                VARIANT result;
                VariantInit(&result);
                VARIANT x;
                x.vt = VT_BSTR;
                x.bstrVal = ::SysAllocString(L"Subject");
                AutoWrap(DISPATCH_PROPERTYGET, &result, pProps, L"Item", 1, x);
                pPropSubject = result.pdispVal;
                SysFreeString(x.bstrVal);
          }
    
          // Get the Value of the Subject property and display it
          {
                VARIANT result;
                VariantInit(&result);
                AutoWrap(DISPATCH_PROPERTYGET, &result, pPropSubject, L"Value",
                         0);
                char buf[512];
                wcstombs(buf, result.bstrVal, 512);
                ::MessageBox(NULL, buf, "Subject", 0x10000);
    		 
          }
    
          // Set the Value of the Subject DocumentProperty
          {
                VARIANT x;
                x.vt = VT_BSTR;
                x.bstrVal = ::SysAllocString(L"This is my subject");
                AutoWrap(DISPATCH_PROPERTYPUT, NULL, pPropSubject, L"Value", 1, 
                         x);
                ::MessageBox(NULL, 
                             "Subject property changed, examine document.",
                             "Subject", 0x10000);
                SysFreeString(x.bstrVal);
          }
    
          // Get CustomDocumentProperties collection
          IDispatch *pCustomProps;
          {
                VARIANT result;
                VariantInit(&result);
                AutoWrap(DISPATCH_PROPERTYGET, &result, pDoc, 
                         L"CustomDocumentProperties", 0);
                pCustomProps = result.pdispVal;
          }
    
          // Add a new property named "CurrentYear"
          {	  	
                VARIANT parm1, parm2, parm3, parm4;
                parm1.vt = VT_BSTR;
                parm1.bstrVal = SysAllocString(L"CurrentYear");
                parm2.vt = VT_BOOL;
                parm2.boolVal = false;
                parm3.vt = VT_I4;
                parm3.lVal = 1; //msoPropertyTypeNumber = 1
                parm4.vt = VT_I4;
                parm4.lVal = 1999;
    
                AutoWrap(DISPATCH_METHOD, NULL, pCustomProps, L"Add", 4, parm4,
                         parm3, parm2, parm1);
                ::MessageBox(NULL, "Custom property added, examine document.",
                             "Custom Property", 0x10000);
                SysFreeString(parm1.bstrVal);
          }
    
          // Get the custom property "CurrentYear" and delete it
          IDispatch *pCustomProp;
          {
                VARIANT result;
                VariantInit(&result);
                VARIANT x;
                x.vt = VT_BSTR;
                x.bstrVal = ::SysAllocString(L"CurrentYear");
                AutoWrap(DISPATCH_PROPERTYGET, &result, pCustomProps, L"Item",
                         1, x);
                pCustomProp = result.pdispVal;
                SysFreeString(x.bstrVal);
                AutoWrap(DISPATCH_METHOD, NULL, pCustomProp, L"Delete", 0);
                ::MessageBox(NULL,
                             "Custom property removed, examine document.",
                             "Custom Property", 0x10000);
          }
    	  
          // Close the document without saving changes and quit Word
          {
                VARIANT x;
                x.vt = VT_BOOL;
                x.boolVal = false;
                AutoWrap(DISPATCH_METHOD, NULL, pDoc, L"Close", 1, x);
                AutoWrap(DISPATCH_METHOD, NULL, pWordApp, L"Quit", 0);
          }
    
          // Cleanup
          pCustomProp->Release();
          pCustomProps->Release();
          pPropSubject->Release();
          pProps->Release();
          pDoc->Release();
          pDocs->Release();
          pWordApp->Release();
    
    
          // Uninitialize COM for this thread...
          CoUninitialize();
    
          return 0;
    }
    					
  3. Menggunakan Microsoft Word untuk membuat dokumen baru, dan menyimpan dokumen baru sebagai C:\Doc1.doc.Jika tidak, galat 0x800A1436 (-2146823114) akan ditampilkan. Galat ini menunjukkan bahwa "file yang tidak ada" ketika mencoba kode untuk membukanya.
  4. Kompilasi dan jalankan.
Kode menunjukkan membaca dan menulis properti dokumen internal dan properti kustom dokumen. Ketika menjalankan, kode menampilkan nilai properti subjek internal, perubahan nilai ini adalah subjek saya, dan membuat properti kustom dokumen baru yang bernama CurrentYearSaat Anda diminta untuk Memeriksa dokumen dengan kode, beralih ke Microsoft Word, dan kemudian klik properti pada File menu. Ketika selesai, membaca komentar kode untuk mempelajari cara kerjanya.

Catatan Tujuan fungsi AutoWrap dalam contoh ini adalah untuk membungkus panggilan GetIDsOfNames dan Invoke untuk memfasilitasi otomatisasi dengan lurus C++. Ketika Anda membuat struktur DISPPARAMS untuk panggilan ke Invoke, unsur-unsur sebenarnya disampaikan dalam urutan terbalik dari apa mengharapkan fungsi yang terlibat. Oleh karena itu, ketika Anda menggunakan panggilan AutoWrap untuk memanggil fungsi dengan lebih dari satu argumen, Anda harus melewati mereka dalam urutan terbalik seperti digambarkan dalam contoh dengan panggilan untuk memanggil DocumentProperties::Add:

      AutoWrap(DISPATCH_METHOD, NULL, pCustomProps, L"Add", 4, parm4,
               parm3, parm2, parm1);

No comments:

Post a Comment