Verfasst: 29.04.2006 16:17
				
				bin seit einiger Zeit dran so etwas umzusetzen.
Das Grundgerüst steht schon. Man kann damit ohne
Interfaces zu importieren oder CLSIDs zu kennen
auf Excel Word und Co. zugreifen
Hier ein Beispiel mit Excel in PB 3.94
ist nicht so komfortabel wie das von http://disphelper.sourceforge.net/
aber dafür deutlich schneller.
Es wäre zu überlegen die Objekte in einer LinkedList mit String-Namen
und Zeiger zu sammeln. Wenn man eins weitere Male benötigt,
kann das dann aus der Liste gesucht werden.
Wie man PB-Typen (long, Word, String etc.) automatisiert und komfortabel
in Variants umwandelt, oder umgekehrt, dazu habe ich noch keine Idee.
Müsste sich aber auch realisieren lassen.
_____
schic
			Das Grundgerüst steht schon. Man kann damit ohne
Interfaces zu importieren oder CLSIDs zu kennen
auf Excel Word und Co. zugreifen
Hier ein Beispiel mit Excel in PB 3.94
Code: Alles auswählen
; http://support.microsoft.com/kb/216686/EN-US/
; How To Automate Excel From C++ Without Using MFC or #import
; transfered and extend from VC++ to PureBasic from schic
Enumeration   ; VARENUM
  #VT_EMPTY = 0
  #VT_NULL = 1
  #VT_I2 = 2
  #VT_I4 = 3
  #VT_R4 = 4
  #VT_R8 = 5
  #VT_CY = 6
  #VT_DATE = 7
  #VT_BSTR = 8
  #VT_DISPATCH = 9
  #VT_ERROR = 10
  #VT_BOOL = 11
  #VT_VARIANT = 12
  #VT_UNKNOWN = 13
  #VT_DECIMAL = 14
  #VT_I1 = 16
  #VT_UI1 = 17
  #VT_UI2 = 18
  #VT_UI4 = 19
  #VT_I8 = 20
  #VT_UI8 = 21
  #VT_INT = 22
  #VT_UINT = 23
  #VT_VOID = 24
  #VT_HRESULT = 25
  #VT_PTR = 26
  #VT_SAFEARRAY = 27
  #VT_CARRAY = 28
  #VT_USERDEFINED = 29
  #VT_LPSTR = 30
  #VT_LPWSTR = 31
  #VT_RECORD = 36
  #VT_INT_PTR = 37
  #VT_UINT_PTR = 38
  #VT_FILETIME = 64
  #VT_BLOB = 65
  #VT_STREAM = 66
  #VT_STORAGE = 67
  #VT_STREAMED_OBJECT = 68
  #VT_STORED_OBJECT = 69
  #VT_BLOB_OBJECT = 70
  #VT_CF = 71
  #VT_CLSID = 72
  #VT_VERSIONED_STREAM = 73
  #VT_BSTR_BLOB = $FFF
  #VT_VECTOR = $1000
  #VT_ARRAY = $2000
  #VT_BYREF = $4000
  #VT_RESERVED = $8000
  #VT_ILLEGAL = $FFFF
  #VT_ILLEGALMASKED = $FFF
  #VT_TYPEMASK = $FFF
EndEnumeration 
;{-Constants
#CLSCTX_INPROC_SERVER  = $1
#CLSCTX_INPROC_HANDLER = $2
#CLSCTX_LOCAL_SERVER   = $4
#CLSCTX_REMOTE_SERVER  = $10
#CLSCTX_ALL = (#CLSCTX_INPROC_SERVER|#CLSCTX_INPROC_HANDLER|#CLSCTX_LOCAL_SERVER|#CLSCTX_REMOTE_SERVER)
#DISPID_PROPERTYPUT = -3
#DISPATCH_METHOD          = 1
#DISPATCH_PROPERTYGET     = 2
#DISPATCH_PROPERTYPUT     = 4
#DISPATCH_PROPERTYPUTREF  = 8
;}
Structure xBRECORD
  *pvRecord.l
  *pRecInfo.IRecordInfo
EndStructure
Structure xVARIANT
  vt.w
  wReserved1.w
  wReserved2.w
  wReserved3.w
  StructureUnion
    llVal.LARGE_INTEGER
    lVal.l
    bVal.b
    iVal.b
    fltVal.f
    dblVal.LARGE_INTEGER
    boolVal.l
    bool.l
    scode.l
    cyVal.l
    date.l
    bstrVal.l
    *punkVal.IUnknown
    ;punkVal.l
    *pdispVal.IDispatch
    parray.l
    pbVal.b
    piVal.b
    plVal.l
    pllVal.LARGE_INTEGER
    pfltVal.f
    pdblVal.LARGE_INTEGER
    pboolVal.l
    pbool.l
    pscode.l
    pcyVal.l
    pdate.l
    pbstrVal.b
    ppunkVal.l;.IUnknown
    ppdispVal.IDispatch
    pparray.l
    pvarVal.l;.xVARIANT
    *byref
    cVal.b
    uiVal.b
    ulVal.l
    ullVal.LARGE_INTEGER
    intVal.l
    uintVal.l
    *pdecVal.f
    *pcVal.b
    *puiVal.b
    *pulVal.l
    *pullVal.LARGE_INTEGER
    *pintVal.l
    *puintVal.l
    *record.xBRECORD
  EndStructureUnion
EndStructure 
Structure DISPPARAMS
  *rgvarg.l               ;array of arguments xVARIANT
  ;*rgvarg.Variant[0]
  *rgdispidNamedArgs.l  ;array of Dispatch IDs of named arguments (argument 0 index)
  ; rgdispidNamedArgs.l
  cArgs.l               ;Number of arguments
  cNamedArgs.l          ;Number of named arguments
EndStructure
Structure EXCEPINFO 
    wCode.w;
    wReserved.w;
    bstrSource.s;
    bstrDescription.s;
    bstrHelpFile.s;
    dwHelpContext.l;
    pvReserved.l ;
    pfnDeferredFillIn.l
    scode.l ;
EndStructure
Structure SAFEARRAYBOUND
  cElements.l ;ULONG
  lLbound.l ;LONG
EndStructure
;{-Globals
Global pApp.IDispatch
Global pvResult.xVARIANT
Global IID_NULL.GUID
;}
Dim varArr.xVARIANT(0)
Procedure AutoWrap(autoTyp.l, *pDisp.IDispatch, name.s, nArgs.l)
  dispID.l
  exception.EXCEPINFO
  
  dp.DISPPARAMS
  dispidNamed = #DISPID_PROPERTYPUT
  
  ;Convert to Uni
  ptUniName = Ansi2Uni(name)
  Debug "getting IDs of names"
  ;Get DISPID for name passed...
  hr = *pDisp\GetIDsOfNames(IID_NULL, @ptUniName, 1, #LOCALE_USER_DEFAULT, @dispID) 
  Debug "hr GetIDsOfNames: " + Str(hr)
  Debug "dispID from " + name + " = " + Str(dispID)
  
  ;Build DISPPARAMS
  dp\cArgs  = nArgs
  dp\rgvarg = @varArr(0) ;ArgsArr;pArgs;*var;
  
  ;Handle special-case for property-puts!
  If autoTyp & #DISPATCH_PROPERTYPUT
    dp\cNamedArgs = 1
    dp\rgdispidNamedArgs = @dispidNamed
  EndIf
  
  ;Make the call!
  hr = *pDisp\Invoke(dispID, IID_NULL, #LOCALE_SYSTEM_DEFAULT, autoTyp, @dp, @pvResult, @exception, #Null)
  Debug "hr Invoke: " + Str(hr)
  Debug "##########"
  Select hr
    Case #DISP_E_EXCEPTION
      Debug "exception\scode: " + Str(exception\scode) + " -> " + exception\bstrDescription
  EndSelect
  ; Invoke return values: 
  ; #S_OK	                      = 0            ; Success.
  ; #DISP_E_BADPARAMCOUNT	      = -21473525 62 ; The number of elements provided to DISPPARAMS is different from the number of arguments accepted by the method or property.
  ; #DISP_E_BADVARTYPE	        = -21473525 68 ; One of the arguments in rgvarg is not a valid variant type.
  ; #DISP_E_EXCEPTION	          = -21473525 67 ; The application needs to raise an exception. In this case, the structure passed in pExcepInfo should be filled in.
  ; #DISP_E_MEMBERNOTFOUND	    = -21473525 73 ; The requested member does not exist, or the call to Invoke tried to set the value of a read-only property.
  ; #DISP_E_NONAMEDARGS	        = -21473525 69 ; This implementation of IDispatch does not support named arguments.
  ; #DISP_E_OVERFLOW	          = -21473525 66 ; One of the arguments in rgvarg could not be coerced to the specified type.
  ; #DISP_E_PARAMNOTFOUND	      = -21473525 72 ; One of the parameter DISPIDs does not correspond to a parameter on the method. In this case, puArgErr should be set to the first argument that contains the error.
  ; #DISP_E_TYPEMISMATCH	      = -21473525 71 ; One or more of the arguments could not be coerced. The index within rgvarg of the first parameter with the incorrect type is returned in the puArgErr parameter.
  ; #DISP_E_UNKNOWNINTERFACE	  = -21473525 75 ; The interface identifier passed in riid is not IID_NULL.
  ; #DISP_E_UNKNOWNLCID	        = -21473525 64 ; The member being invoked interprets string arguments according to the LCID, and the LCID is not recognized. If the LCID is not needed to interpret arguments, this error should not be returned.
  ; #DISP_E_PARAMNOTOPTIONAL	  = -21473525 61 ; A required parameter was omitted.
  ;                               -2147024809  ; The parameter is incorrect (80070057)
  FreeMemory(ArgsArr)
  ProcedureReturn hr
EndProcedure
;{ get application object
CLSID.GUID 
hr = CLSIDFromProgID_(Ansi2Uni("Excel.Application"), @CLSID)
Debug hr
Debug CLSID\data1 ;148736 for Excel
pCf.IClassFactory = NULL
IID_IClassFactory.GUID
IID_IClassFactory\data1 = $1
IID_IClassFactory\data4[0] = $C0
IID_IClassFactory\data4[7] = $46
hr = CoGetClassObject_(@CLSID, #CLSCTX_LOCAL_SERVER, #Null, @IID_IClassFactory, @pCf)
Debug "hr CoGetClassObject: " + Hex(hr)
riid.GUID
riid\data1 = $20400
riid\data4[0] = $C0
riid\data4[7] = $46
pApp.IDispatch
ppApp=@pApp
hr = pCf\CreateInstance(#Null, @riid, @pApp)
Debug "hr CreateInstance: " + Hex(hr)
pCf\Release()
;}
;{ make application visible
Dim varArr.xVARIANT(1)
varArr(0)\vt = #VT_I4
varArr(0)\lVal = 1
AutoWrap(#DISPATCH_PROPERTYPUT, pApp, "Visible", 1)
VariantClear_(varArr(0))
;}
;{ get workbooks object, VBA-Code: Set pXlBooks = Application.Workbooks
pXlBooks.IDispatch
VariantInit_(@pvResult);
AutoWrap(#DISPATCH_PROPERTYGET, pApp, "Workbooks", 0)
Debug "Variant Typ: " + Str(pvResult\vt)
Debug "Workbooks, pvresult\pdispVal: " + Str(pvResult\pdispVal)
Debug "##"
pXlBooks = pvResult\pdispVal
;}
;{ add a workbook, VBA-Code: pXlBooks.Add
pXlBook.IDispatch
pvResult.xVARIANT
VariantInit_(@pvResult);
AutoWrap(#DISPATCH_PROPERTYGET, pXlBooks, "Add", 0)
pXlBook = pvResult\pdispVal
;}
;{ Get ActiveSheet object, VBA-Code: Set pXlSheet = Application.ActiveSheet
pXlSheet.IDispatch
VariantInit_(@pvResult);
AutoWrap(#DISPATCH_PROPERTYGET, pApp, "ActiveSheet", 0);
pXlSheet = pvResult\pdispVal
;}
;{ fill 15 x15 Range with Values at a single blow, VBA-Code: don´t know how to do it with VBA
;Get Range object for the Range A1:O15...
pXlRange.IDispatch
varArr(0)\vt = #VT_BSTR
varArr(0)\bstrVal = Ansi2Uni("A1:O15")
pvResult.xVARIANT
VariantInit_(@pvResult)
AutoWrap(#DISPATCH_PROPERTYGET, pXlSheet, "Range", 1)
VariantClear_(@varArr(0))
pXlRange = pvResult\pdispVal
;Create a 15x15 safearray of variants...
varArr(0)\vt = #VT_ARRAY | #VT_VARIANT
Dim sab.SAFEARRAYBOUND(1)
sab(0)\lLbound = 1
sab(0)\cElements = 15
sab(1)\lLbound = 1
sab(1)\cElements = 15
varArr(0)\parray = SafeArrayCreate_(#VT_VARIANT, 2, @sab(0))
Debug "arr\parray: " + Str(varArr(0)\parray)
;Fill safearray with some values...
Dim indices.l(1)
tmp.xVARIANT
For i = 1 To 15
  For j = 1 To 15
    ;Create entry value for (i,j)
    tmp\vt = #VT_I4
    tmp\lVal = i*j
    ;Add to safearray...
    indices(0) = i
    indices(1) = j
    hr = SafeArrayPutElement_(varArr(0)\parray, @indices(0), @tmp)
    ;Debug "hr from SafeArrayPutElement: " + Str(hr)
    ; -2147024809 = #E_INVALIDARG     ;An argument is invalid.
    ; -2147352565 = #DISP_E_BADINDEX  ;The specified index was invalid.
    ; -2147024882 = #E_OUTOFMEMORY    ;Memory could not be allocated for the element.
    VariantClear_(@tmp)
  Next
Next
;Set range with our safearray...
AutoWrap(#DISPATCH_PROPERTYPUT, pXlRange, "Value", 1)
;}
;{ put text to single cell in row 4, column 15, VBA-Code: Set pXlCells4_15 = Cells(4, 15): pXlCells4_15.Value = "COM-Test with Excel"
;arguments for column and row, cells(row,column)
;take care! arguments are handeled reverse
Dim varArr.xVARIANT(2)
varArr(0)\vt = #VT_I4
varArr(0)\lVal = 15
varArr(1)\vt = #VT_I4
varArr(1)\lVal = 4
;get cell-object
pXlCells4_15.IDispatch
pvResult.xVARIANT
VariantInit_(@pvResult)
If AutoWrap(#DISPATCH_PROPERTYGET, pXlSheet, "Cells", 2) = 0
  pXlCells4_15 = pvResult\pdispVal
EndIf
;set value
Dim varArr.xVARIANT(1)
varArr(0)\vt = #VT_BSTR
varArr(0)\bstrVal = Ansi2Uni("COM-Test with Excel")
AutoWrap(#DISPATCH_PROPERTYPUT,  pXlCells4_15, "Value", 1)
;}
;{ fit the width of all cells to their content, VBA-Code: Cells.EntireColumn.AutoFit
;get cells object
pXlCells.IDispatch
VariantInit_(@pvResult)
AutoWrap(#DISPATCH_PROPERTYGET, pXlSheet, "Cells", 0)
pXlCells = pvResult\pdispVal
;get EntireColumn-object
pXlEntireColumn.IDispatch
VariantInit_(@pvResult)
AutoWrap(#DISPATCH_PROPERTYGET, pXlCells, "EntireColumn", 0)
pXlEntireColumn = pvResult\pdispVal
;fit them, Cells.EntireColumn.AutoFit
AutoWrap(#DISPATCH_METHOD, pXlEntireColumn, "AutoFit", 0)
If pXlCells
  pXlCells\Release()
EndIf
;}
;{ set background color to single cell, row 4, column 15, VBA-Code: pXlCells4_15.Interior.ColorIndex = 36
pXlInterior.IDispatch
VariantInit_(@pvResult)
AutoWrap(#DISPATCH_PROPERTYGET, pXlCells4_15, "Interior", 0)
pXlInterior = pvResult\pdispVal
Dim varArr.xVARIANT(1)
varArr(0)\vt = #VT_I4
varArr(0)\lVal = 36
AutoWrap(#DISPATCH_PROPERTYPUT, pXlInterior, "ColorIndex", 1)
;}
; pXlCells4_15.Select
AutoWrap(#DISPATCH_METHOD, pXlCells4_15, "Select", 0)
If pXlCells4_15
  pXlCells\Release()
EndIf
varArr(0)\vt = #VT_I4
varArr(0)\lVal = 1
AutoWrap(#DISPATCH_PROPERTYPUT, pXlBook, "Saved", 1)
; AutoWrap(#DISPATCH_METHOD, pApp, "Quit", 0, 0)
; MessageRequester("Info", "Excel switched off")
;{ cleaning up
pXlInterior\Release()
pXlEntireColumn\Release()
pXlRange\Release()
pXlSheet\Release()
pXlBook\Release()
pXlBooks\Release()
pApp\Release()
CoUninitialize_()
;}
End
aber dafür deutlich schneller.
Es wäre zu überlegen die Objekte in einer LinkedList mit String-Namen
und Zeiger zu sammeln. Wenn man eins weitere Male benötigt,
kann das dann aus der Liste gesucht werden.
Wie man PB-Typen (long, Word, String etc.) automatisiert und komfortabel
in Variants umwandelt, oder umgekehrt, dazu habe ich noch keine Idee.
Müsste sich aber auch realisieren lassen.
_____
schic

 
 
 den invalid memory-access habe ich unter 3.94 bekommen.
  den invalid memory-access habe ich unter 3.94 bekommen.