Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

COM Object Reference [AutoHotkey v1.1+]


  • Please log in to reply
233 replies to this topic
silveredge78
  • Members
  • 499 posts
  • Last active: Mar 14 2014 03:19 AM
  • Joined: 25 Jul 2006
Frankie> That's pretty awesome. It is a LOT less code! It works to pull out the basic data that I had been getting before.

Why is there a comma on the second line here:
pField:= pFields.Item(A_Index-1) 
   ,   sData .= pField.Name . ": " . pField.Value . "`r`n"
Is AHK_L's handling of COM more efficient? As in, faster for big searches, etc?

And now the issue that I really need addressed... How can I extract a file from inside an SQL database? It is stored as an 'image' type. I need to query that information out, and write it back as the same file. That can be a *.doc, *.xls, *.tif, etc. I imagine whatever routine would be able to write it as a file and if it has the right extension it will come up fine.

Is this something anyone can help me with this in AHK_L?

Here is my attempt at coding this:
Parse = ","
ParseComma = ,
ParseQuote = "
ParseEnd = "`r`n

sQuery  := "SELECT * FROM " . "atlas" . " WHERE country LIKE 'A%'" 
sConnect := "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" . "C:\Database\atlas.mdb" 

SQL_L_SaveToFile(sQuery, sConnect, SaveFileNameIndex = "1", SaveFileValueIndex = "2")   ; 04/07/2011
{
  Global Parse, ParseComma, ParseQuote, ParseEnd
  prs :=  ComObjCreate("ADODB.Recordset")
  prs.Open(sQuery, sConnect)
  While !prs.EOF
  {
    pFields :=  prs.Fields
    Loop, % pFields.Count
    {
      pField:= pFields.Item(A_Index-1)
MsgBox, % "Debug:`nValue:`n" . pField.Value
      If A_Index = 1
      {
        HeaderRow := pField.Name
        WriteRecord := pField.Value
      }
      Else
      {
        HeaderRow .= Parse . pField.Name
        WriteRecord .= Parse . pField.Value
      }
      If A_Index = %SaveFileNameIndex%
        FileName := RegExReplace(pField.Value, "/", " or ")
      If A_Index = %SaveFileValueIndex%
      {
        pmstream.ActiveXObject("ADODB.STREAM")	;Create and open a binary stream
        pmstream.Type(adTypeBinary)
        pmstream.Write(pField.Value)

        FileContents := pField.Value		
        Count = 1
        Loop
        {
          Count++
          If A_Index = 1
            FileNameMod := FileName
          IfExist, %FileNameMod%
          {
            SplitPath, FileName, , , FileNameExt, FileNameNoExt
            FileNameMod := FileNameNoExt . " (" . Count . ")." . FileNameExt
          }
          Else
            Break
        }
        pmstream.SavetoFile(FileNameMod, 1)
;		  COM_Invoke(pField, "SavetoFile", FileNameMod, adSaveCreateOverWrite)
      }
    }
    prs.MoveNext()
	
    HeaderRow := ParseQuote . HeaderRow . ParseEnd
    Data .= ParseQuote . WriteRecord . ParseEnd
    RecordCount := A_Index
;MsgBox, Debug:`nRecordCount: %RecordCount%`n`nHeaderRow: %HeaderRow%`n`nWriteRecord:`n%WriteRecord%`n`nData:`n%Data% ; For testing, enabled
  }
  prs.Close()
  Result := HeaderRow . Data
  Return Result
}

SilverEdge78

ruespe
  • Members
  • 567 posts
  • Last active: Dec 01 2014 07:59 PM
  • Joined: 17 Jun 2008

get SAP GUI controls

I tried with AHK_L (under winXP) to get SAP GUI controls,
with the mouse over coordiantes, but AHK_L could 'see' any control
means:
could not see the Control ID and could not see it's TEXT value

is there any tool in AHK that I can override this problem ?

I saw in internet, that with autoit, in some way, it can be achieved.
so why not with AHK_L ?

JAVA Forms
same problem I got with JAVA Forms( in winXP), that does not see any control, do I need another tool for that ?

any help will be appreciated

rgrds
rani

Just give this code a try. Unfortunately I don't have access to a SAP-App tonight, so I couldn't test it.
^+1::
CoordMode, Mouse,Screen 
Loop 
{ 
	IfWinActive,ahk_class SAP_FRONTEND_SESSION
	{
		If	!IsObject(_oSAP)
		{
			_oSAP := ComObjGet("SAPGUI").GetScriptingEngine  ; Get the Already Running Instance 
			Session := _oSAP.ActiveSession 
		}
		MouseGetPos,X, Y 
		SapCollection := Session.FindByPosition(X, Y) 
		If   (IsObject(SapCollection) ) 
		{ 
				If (SapCollection.Count > 0) 
				{ 
					Id := SapCollection.Item(0)
					If (SapCollection.Count > 1) 
					{ 
						Descr := SapCollection.Item(1)
					}
					Else
						Descr := ""
						
					Name := Session.FindById(Id).Name 
					Text := Session.FindById(Id).Text 
					ToolTip,% Id "`n" Descr "`n" Name "`n" Text
				} 
		} 
	}
	Else
		_oSAP := Session := ""
	Sleep 500 
}
Return
Edit: Tested. Works.

jethrow
  • Moderators
  • 2854 posts
  • Last active: May 17 2017 01:57 AM
  • Joined: 24 May 2009

COM Object: Excel.Sheet

Purpose: Hold MS Excel Data - represents a MS Excel workbook

System Requirements: MS Excel

Documentation Link: WorkBook Object

Other Links: Excel Constants, Sort Method

Code Example:

;// Excel Constants
xlMaximized := -4137
xlAsc := xlYes := 1

;// Create WorkBook
XLBook := ComObjCreate("Excel.Sheet")
XLSht := XLBook.ActiveSheet

;// Maximize the WorkBook Control
XLBook.Windows(1).WindowState := xlMaximized
XLBook.Application.Visible := true

;// Fill in Data & Sort
for cell in XLSht.Range("A1:C10")
   if (cell.row = 1)
      cell.value := "Header " [color=brown]A_Index
   else {
      Random, num, 0, 1
      cell.value := num
   }

;// Sort Data
MsgBox, Sorting by Column 1, then 2, then 3...
XLSht.Cells.Sort(   XLSht.Columns(1), xlAsc
                  , XLSht.Columns(2), ComObjMissing(), xlAsc
                  , XLSht.Columns(3), xlAsc
                  , xlYes )

;// Save WorkBook
MsgBox, 4, , The Workbook will close once the object is released - would you like to save it to the scirpt directory?
IfMsgBox, Yes
   XLBook.SaveAs(A_ScriptDir "\Excel.Sheet Example.xls")

Note - the Excel.Sheet object will open in the Active Excel Process (accessed by ComObjActive) - or will create a new Excel Process - and it will close when the pointer is released.



Occasional AHKer
  • Members
  • 10 posts
  • Last active: Jul 01 2011 01:38 AM
  • Joined: 23 Mar 2011
I was curious if someone could help me with adding a chart to an excel workbook? I've tried a number of things but always get an exception when trying to add the chart.

---------------------------
VGAGE Data Automation.ahk
---------------------------
Error: 0x800A03EC -
Source: Microsoft Office Excel
Description: Unable to get the Add property of the Sheets class
HelpFile: C:\Program Files\Microsoft Office\OFFICE11\1033\xlmain11.chm
HelpContext: 0

Specifically: Add

Line#
029: StringMid,Letter,InputVar,%A_Index%,1,L
030: Cell := oSheet.Range(Letter . 2).Value
031: if (Cell = "")
032: Break
033: XLWidth := A_Index
034: }
037: xlLineMarkersStacked := "xlChart"
---> 038: oWorkbook.Sheets.Add(xlLineMarkersStacked, oWorkbook.Sheets(oWorkbook.Sheets.Count), ComObjMissing())
061: Loop
062: {
063: Process,Exist,Excel.exe
064: if ErrorLevel
065: Process,Close,Excel.exe
066: Else
067: Break

Continue running the script?
---------------------------
Yes No
---------------------------


Does anyone know the correct syntax for adding a chart?

EDIT:Nevermind. Sorry noob mistake.

To add a chart to an excel workbook.

; <COMPILER: v1.0.90.0>
SetBatchLines, -1
#SingleInstance force
DetectHiddenWindows, On
SetTitleMatchMode, 2
Loop
{
    Process, Exist, Excel.exe
    If ErrorLevel
        Process, Close, Excel.exe
    Else
        Break
}

FileSelectFile, File, 1, %A_ScriptDir%,,*.xls
If Not File
	Return


SplitPath, File, OutFileName, OutDir, OutExt, OutNameNoExt, OutDrive
FileName = %OutDir%\[%OutFileName%]%OutNameNoExt%

oExcel := ComObjCreate("Excel.Application")
oWorkBook:= oExcel.Workbooks.Add(File)
oSheet := oWorkBook.ActiveSheet
Loop,
{
	Cell:= oSheet.Range("B" . A_Index).Value
	If (Cell = "") 
		Break
	XLHeight:= A_Index
}
InputVar:="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
Loop
{
   StringMid, Letter, InputVar, %A_Index%, 1, L
   Cell:= oSheet.Range(Letter . 2).Value
   If (Cell = "") 
      Break
   XLWidth:= A_Index
}

oWorkbook.Sheets.Add(ComObjMissing(), oWorkbook.Sheets(oWorkbook.Sheets.Count), ComObjMissing(), A_Desktop . "\xlChart.xls") 
oChart:=oWorkBook.ActiveChart
oChart.SetSourceData(oSheet.Range("A:A"), ComObjMissing())
oExcel.Visible := 1
Return

I still havent figured out how to add an empty chart type right from excel but this will load a chart from Chart.xls on the desktop

a4u
  • Guests
  • Last active:
  • Joined: --
first, did you define the variable xlLineMarkersStacked ?

rani
  • Members
  • 217 posts
  • Last active: Jul 21 2016 12:53 PM
  • Joined: 18 Mar 2008
Hi ruespe

sorry for my late response, I am not plug-in all the time to this forum.

I'll check if I can 'see' the SAP GUI control's, first with mouse over script

win grid+cells controls
in many cases, in desktop window applications the AHK_L don't 'see' grid controls and it's cells
the grid can be in many cases third party control as devExpress, or some
other unknown grid,
is there some 'class' defintion for grid , or are there some extension's
for getControl , so with mouse over (X,Y) I can get get cell ID and TextValue in grid ?


rani

ludamo
  • Members
  • 13 posts
  • Last active: Jan 29 2015 08:36 AM
  • Joined: 12 Jul 2008
Hi. I have just moved from AHK (basic) to AHK_L (with integrated COM). Many thanks for all the hard work you guys do. I have an old script which acts on MS CHM help files to change the font size in the viewer. Pressing Ctrl and using the mousewheel changes the text font size (this doesn't work on all help files) and Pressing Ctrl and Win and mousewheel zooms the page (more reliable). The code still works in AHK_L after changing to COM_L (took me a while to figure that one out - searching the forums). I couldn't find anything similar to my code so I was wondering if anyone would care to suggest a way of converting it to run more natively (so to speak) under the new AHK_L? In particular getting a pointer to an already running CHM file and interface. Am on XPSP3, AHK_L 1.1.00.00.

mStr:= "Smallest Smaller Medium Large Largest"
Loop, Parse, mStr, %A_Space%		; sets txtsz0 = Smallest, txtsz1 = Smaller, txtsz2 = Medium etc
	{  t := A_Index-1
		txtsz%t% := A_LoopField
	}
nZ := 2        ; Initial Zoom Factor
txtSize := 2	; Initial Text Size Factor
optZoom := 150	; Initial Optical Zoom Factor (IE 8) ? 150 because of DPI


<^WheelUp::mLCtrlWheel(1,4)        		; Text Size in IE ; param1 determines wheelup or down ;  param2 is the UPPER or LOWER limit
<^WheelDown::mLCtrlWheel(-1,0)      	; consider using XButton1 & WheelUp/WheelDown. Don't use Alt as interferes with shortcut menu

dm_getPtrIESrv1()
{
   ControlGet, hIESvr, hWnd, , Internet Explorer_Server1, A		; Get handle of ACTIVE Help Window
   If Not hIESvr
      Return
   DllCall("SendMessageTimeout", "uint", hIESvr, "uint", DllCall("RegisterWindowMessage", "str", "WM_HTML_GETOBJECT"), "uint", 0, "uint", 0, "uint", 2, "uint", 1000, "UintP", lResult)
   DllCall("oleacc\ObjectFromLresult", "uint", lResult, "uint", COM_GUID4String(IID_IHTMLDocument2,"{332C4425-26CB-11D0-B483-00C04FD90119}"), "int", 0, "UintP", pdoc)
   IID_IWebBrowserApp := "{0002DF05-0000-0000-C000-000000000046}"
	
   pIESrv1 := COM_QueryService(pdoc,IID_IWebBrowserApp,IID_IWebBrowserApp)
   COM_Release(pdoc)
	; ToolTip, %hIESvr%   %pIESrv1%   %pdoc%
   Return pIESrv1
}

mLCtrlWheel(d, TxtSizeLimit)
{	
	global
	Critical
	IfNotEqual,txtSize,%TxtSizeLimit%			; if current TEXT SIZE out of bounds then don't Run
	{	
		If Not pIESrv1
		{	; only run this once each zoom session
			COM_CoInitialize()
			If Not pIESrv1 := dm_getPtrIESrv1()		; I think this tests the return value if any which is made = to a local variable 
				Exit
		}
		txtSize := txtSize + d
		COM_Invoke(pIESrv1, "ExecWB", 19, 2, txtSize, 0)		; nCmdID, nCmdExecOpt, pvaIn, pvaOut
		; nCmdID: OLECMDID_OPTICAL_ZOOM = 63 (Zoom as %);  OLECMDID_ZOOM = 19 (Text Size = 0,1,2,3,4)
		; nCmdExecOpt: OLECMDEXECOPT_DODEFAULT = 0, OLECMDEXECOPT_PROMPTUSER = 1, OLECMDEXECOPT_DONTPROMPTUSER = 2, OLECMDEXECOPT_SHOWHELP = 3
		; textsize := txtsz%txtSize%
		; Tooltip, Font size is %textsize%		; Smallest | Smaller | Medium | Larger | Largest
		Tooltip % "Font size is " . txtsz%txtSize%		;%; Smallest | Smaller | Medium | Larger | Largest
		If Not IsRun_mZoomKeyup
			SetTimer, mZoomKeyup, -100		; Turn off Tooltip & Release COM etc when key released. 
	}
}

<^#WheelUp::mRCtrlWheel(10)								; Page Zoom in IE; Parameter is change in zoom level; Win key interferes with VWD 2008 Shortcut menu
<^#WheelDown::mRCtrlWheel(-10)							; consider using XButton2 & WheelUp/WheelDown

mRCtrlWheel(d)
{	
	global
	Critical
	If Not pIESrv1
	{	; only run this once each zoom session
		COM_CoInitialize()
		If Not pIESrv1 := dm_getPtrIESrv1()		; I think this tests the return value if any which is made = to a local variable 
			Exit
	}
	optZoom := optZoom + d
	COM_Invoke(pIESrv1, "ExecWB", 63, 2, optZoom, 0)	; nCmdID: OLECMDID_OPTICAL_ZOOM = 63 (Zoom as %)
	Tooltip, Zoom factor %optZoom%`%							;%;
	If Not IsRun_mZoomKeyup
		SetTimer, mZoomKeyup, -100		; Turn off Tooltip & Release COM etc when key released. 
}

mZoomKeyup:
	IsRun_mZoomKeyup := 1				; need this flag otherwise runs twice - use MsgBox to test
	KeyWait, Control						; waits till Hotkey modifier released before turning tooltip off
		COM_Release(pIESrv1)				; only run this once each zoom session
		pIESrv1 := 0
		COM_CoUninitialize()
		Gosub, mTipClose
		IsRun_mZoomKeyup := 0
	Return


ludamo
  • Members
  • 13 posts
  • Last active: Jan 29 2015 08:36 AM
  • Joined: 12 Jul 2008
Think I just found the answer in the GetWebBrowser()
example of the ComObjQuery() page of the AHK_L Help file!!

Tyrsius
  • Members
  • 140 posts
  • Last active: Jun 20 2011 10:08 PM
  • Joined: 09 Jul 2009
having some issues with the ScriptControl and windows 7. This script works fine in XP.

I have a ScriptControl created as VBScript to connect to a sql server. In windows 7, it hangs for quite some time until a box asking if I want to end or continue pops up. It only pops up for a second (Had to screenshot to read it) before disappearing, but after it disappears it seems to finish properly and load all the SQL data is was supposed to. Its like it isn't running until that box pops up, and then it finishes instantly. Setting the script to run in compatability or as admin doesn't seem to have an effect.

On XP, it takes from 1-2 seconds to finish.

Any idea what is going on?

Tyrsius
  • Members
  • 140 posts
  • Last active: Jun 20 2011 10:08 PM
  • Joined: 09 Jul 2009
Nvm, turned out to be a larger issue with windows 7 and sql access. Disable multicast fixed it.

jethrow
  • Moderators
  • 2854 posts
  • Last active: May 17 2017 01:57 AM
  • Joined: 24 May 2009

COM Object: Shell.Application [Folder & FolderItems object]

Purpose: Extract Files From/Unzip a Zip Directory

System Requirements: General

Documentation Link: Shell Object, Folder Object, FolderItems

Other Links: CopyHere Method

Code Example:

ZipFolder := A_Desktop "\folder.zip"
NewDir := A_Desktop "\New Folder"

FileCreateDir, %NewDir%

shell := ComObjCreate("Shell.Application")
Folder := shell.NameSpace(ZipFolder)
NewFolder := shell.NameSpace(NewDir)

;// extract all
NewFolder.CopyHere(Folder.items, 4|16)
return

;// extract 1-by-1
for item in Folder.items
   NewFolder.CopyHere(item)


Deo
  • Members
  • 199 posts
  • Last active: Jan 31 2014 03:19 PM
  • Joined: 16 May 2010
hey, guys
i need your help to get selected items and their paths on desktop
i didn't found exact steps to get this done, only this tip:

SHGetDesktopFolder gets you the IShellFolder object for the desktop. Once you have the folder you can get a view for it using CreateViewObject. From the IShellView you can then use GetItemObject with SVGIO_SELECTION to get the list of selected items. All this involves working with PIDLs.

i was able only to get IShellFolder object, but not IShellView because ahk crashing for me when i trying to do this, please help:
DllCall("Shell32\SHGetDesktopFolder","Ptr*",pIShellFolder)
oIShellFolder := ComObjEnwrap(pIShellFolder)
refiid := GUID(IID_IShellView, "{000214E3-0000-0000-C000-000000000046}")
VarSetCapacity(pIShellView,A_PtrSize,0)
oIShellFolder.CreateViewObject(0,refiid,ComObjParameter(0x4000 | 0x15, pIShellView)) ;it crashes here, whats wrong?

GUID(ByRef GUID, sGUID) ; Converts a string to a binary GUID and returns its address.
{
    VarSetCapacity(GUID, 16, 0)
    return DllCall("ole32\CLSIDFromString", "wstr", sGUID, "ptr", &GUID) >= 0 ? &GUID : ""
}


maul.esel
  • Members
  • 790 posts
  • Last active: Jan 05 2013 09:26 PM
  • Joined: 28 Feb 2011
oIShellFolder := ComObjEnwrap(pIShellFolder)
This won't work as ComObjEnwrap only works with IDispatch-inherited interfaces - which IShellFolder is not.
To work with it, see my tutorial: <!-- m -->http://www.autohotke... ... e_tutorial<!-- m -->

Or see here (especially sinkfaze's post)
Edit: seems to be different from what you want :?
Join the discussion on The future of AutoHotkey
Posted Image Visit me on github Posted Image
Win7 HP SP1 64bit | AHK_L U 64bit

Deo
  • Members
  • 199 posts
  • Last active: Jan 31 2014 03:19 PM
  • Joined: 16 May 2010
thank you for tutorial, it revealed a few basic things about COM for me
though, how ca i get to know which index at vtable refer to which interface method?
i've tried this to call CreateViewObject method of IShellFolder, and it seems like dllcall succesfull (returns 0), but iShellView pointer is set to 0

	DllCall("Shell32\SHGetDesktopFolder","Ptr*",pIShellFolder)
	vt := NumGet(pIShellFolder + 0)
	CreateViewObject := NumGet(vt + [color=red]6[/color]*A_PtrSize) ;which index of this method can be?
;http://msdn.microsoft.com/en-us/library/bb775075%28v=VS.85%29.aspx
	refiid := GUID(IID_IShellView, "{000214E3-0000-0000-C000-000000000046}")
	VarSetCapacity(pIShellView,8,0)
	gui,1:+LastFoundExist
	hw := WinExist()
	ret := DllCall(CreateViewObject,"Ptr", pIShellFolder,"Ptr",hw, "Ptr", refiid, "Ptr*", pIShellView)
	msgbox % errorformat(ret) "`n" pIShellView


jethrow
  • Moderators
  • 2854 posts
  • Last active: May 17 2017 01:57 AM
  • Joined: 24 May 2009
One step ahead of ya :wink: - check this out from maul.esel.