AutoHotkey Community

It is currently May 25th, 2012, 12:29 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 132 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6 ... 9  Next
Author Message
 Post subject:
PostPosted: July 24th, 2007, 3:52 am 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
tfcahm wrote:
Code:
Invoke_(pmstream, "Write", 12,Invoke(Invoke(Invoke(prs, "Fields"), "Item", "logo"), "Value"))
 \_ 0/8                         \_ 8209/8

8209 = 0x2011 is VT_ARRAY | VT_UI1, i.e., an array of bytes.
So, try after replacing 12 with 8209.
If it still doesn't work, I'd like to know what value was returned for Invoke(Invoke(Invoke(prs, "Fields"), "Item", "logo"), "Value").


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 24th, 2007, 4:00 am 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
erictheturtle wrote:
According to the VARIANT specification, VT_I8 and VT_UI8 should not appear in a VARIANT.
http://msdn2.microsoft.com/en-us/library/ms221170.aspx
http://www.marin.clara.net/COM/variant_ ... itions.htm

Oh, I see. But, actually I succeeded to use VT_I8 and VT_UI8 in the variant, specifically with Excel sheet. Excel correctly converted the data as 1.3E+18, etc.

Quote:
I had one example of a property returning a value that wouldn't fit in I4:
Code:
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oDrive = oFSO.GetDrive("C:")
oDrive.FreeSpace

The FreeSpace property was returning a VT_R8 on my computer that had dozens of GB of free space.

VT_R4 and VT_R8 would not be a problem, both as a parameter and as a result. They can be type-coerced from/to BString.

Code:
#Include CoHelper.ahk

CoInitialize()
pfso := ActiveXObject("Scripting.FileSystemObject")
pdrv := Invoke(pfso, "GetDrive", "C:")
MsgBox, % Invoke(pdrv, "FreeSpace")
Release(pdrv)
Release(pfso)
CoUninitialize()


So, the simplest solution when need to specify an integer greater than 2**32 may be just using a floating number (string), like 12345678900.0 etc.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 24th, 2007, 5:13 am 
Offline

Joined: May 20th, 2007, 7:48 pm
Posts: 48
Sean wrote:
8209 = 0x2011 is VT_ARRAY | VT_UI1, i.e., an array of bytes.
So, try after replacing 12 with 8209.
An array of bytes certainly makes sense, but 8209 gave the same result.
Quote:
If it still doesn't work, I'd like to know what value was returned for Invoke(Invoke(Invoke(prs, "Fields"), "Item", "logo"), "Value").
There is binary in the database field "logo". Msgbox shows this (with some new lines added to keep it from being excessively wide)
Code:
????????‰‰‰‰??????‹'‰‰'‰????????????????????????????????A????????????????????????d??????
?A?????????????????????????????????y??????????????????????????c????????A????????????????????????
??e??????????   ????????°?????????????????????????????A?????????????????????????????????????????
?????e????????4????????????????????????????7??????


A couple other data points: I tried changing the stream object type to adTypeText and to write the stream object with the value from a text field.
Code:
pmstream := ActiveXObject("ADODB.STREAM")
Invoke(pmstream, "Type=", adTypeText)
Invoke(pmstream, "Open")
Invoke_(pmstream, "Write", 8209,Invoke(Invoke(Invoke(prs, "Fields"), "Item", "caption"), "Value")) ;doesn't work
Invoke(pmstream, "SavetoFile", "c:\temp\pms.txt", adSaveCreateOverWrite)
Invoke(Invoke(Invoke(prs, "Fields"), "Item", "Caption"), "Value") returns the proper text string ("Test string" in this case) but the stream object remains empty.

Next I tried using this line
Code:
Invoke_(pmstream, "WriteText", 8,"Test string")
and the stream object and disk file are properly written with "Test string".


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 24th, 2007, 5:30 am 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
tfcahm wrote:
Sean wrote:
8209 = 0x2011 is VT_ARRAY | VT_UI1, i.e., an array of bytes.
So, try after replacing 12 with 8209.
An array of bytes certainly makes sense, but 8209 gave the same result.

The problem is that the type change into bstring was really occured.
Then, the Invoke() tried to convert it to the ANSI string, so all garbages was returned as a result...

I didn't expect that the OLE would really type-coerce an array into a bstring.
As a matter of fact, the fear about these unexpected outcomes prevented me from doing any user-friendly refinement into Invoke(), which I'm doing currently.

As a temporary workaround, replace the following part in varResult

Code:
NumGet(varResult,0,"Ushort")=8||NumGet(varResult,0,"Ushort")<>9&&

with

Code:
NumGet(varResult,0,"Ushort")=8||NumGet(varResult,0,"Ushort")<>9&&NumGet(varResult,0,"Ushort")<0x1000&&


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 24th, 2007, 6:20 am 
Offline

Joined: May 20th, 2007, 7:48 pm
Posts: 48
Quote:
As a temporary workaround, replace the following part in varResult
Code:
NumGet(varResult,0,"Ushort")=8||NumGet(varResult,0,"Ushort")<>9&&

with
Code:
NumGet(varResult,0,"Ushort")=8||NumGet(varResult,0,"Ushort")<>9&&NumGet(varResult,0,"Ushort")<0x1000&&
That fixed it! Thanks again Sean for all the help.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 24th, 2007, 9:00 am 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
tfcahm wrote:
That fixed it!

Good to know, and don't forget to release the array after finished:

Code:
DllCall("oleaut32\SafeArrayDestroy", "Uint", pSafeArray)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 24th, 2007, 11:06 pm 
Offline

Joined: May 20th, 2007, 7:48 pm
Posts: 48
Sean wrote:
Good to know, and don't forget to release the array after finished:
Thanks for that.

Should Release() be called on every type IDispatch? For example:
Code:
...
Invoke_(pmstream, "Write", 8209,pSafearray:=Invoke(pfld:=Invoke(pflds:=Invoke(prs, "Fields"), "Item", "logo"), "Value"))
...
Release(pmstream)
DllCall("oleaut32\SafeArrayDestroy", "Uint", pSafeArray)
Release(pfld)
Release(pflds)
Release(prs)
I'll post the scripts to read and write binary objects between disk and database shortly. They work great and are good examples, just want to be sure there are no subtle memory issues.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 25th, 2007, 1:58 am 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
tfcahm wrote:
Should Release() be called on every type IDispatch?

If the script is running for quite a while and creating constantly new objects, it may be the most resource-friendly way.
Otherwise, however, just CoUninitialize() at the exit of the app will be enough, I suppose.

Quote:
I'll post the scripts to read and write binary objects between disk and database shortly. They work great and are good examples, just want to be sure there are no subtle memory issues.

You seem to be an expert on the database manipulation.
Eagerly waiting and thanks for sharing them.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 25th, 2007, 9:25 am 
Offline

Joined: May 20th, 2007, 7:48 pm
Posts: 48
Sorry for the delay in posting the promised script. I ran into a problem with the most recent CoHelper.ahk (edit 33). The change from "Int64" to "Uchar" to this statement of Invoke_()
Code:
NumPut(type%A_Index%,varg,16*(nParams-A_Index),"Uchar")
causes this line to fail:
Code:
Invoke_(pmstream, "Write", 8209,pSafearray)
Should I adjust the script somehow, or is the behaviour not what you intended? The example database script works fine with that change reversed, but to avoid confusion I'll wait to post it until everything works together.


Sean wrote:
If the script is running for quite a while and creating constantly new objects, it may be the most resource-friendly way.
Otherwise, however, just CoUninitialize() at the exit of the app will be enough, I suppose.
I'll take the conservative approach.
Quote:
You seem to be an expert on the database manipulation.
Eagerly waiting and thanks for sharing them.
Hardly an expert, but I have written several database applications. I had been waiting for an ODBC solution in AHK. While that would still be nice, it is no longer necessary. Your CoHelper provides an excellent solution.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 25th, 2007, 11:13 am 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
tfcahm wrote:
I ran into a problem with the most recent CoHelper.ahk (edit 33). The change from "Int64" to "Uchar" to this statement of Invoke_()

Oops, why Uchar was entered there... It should've been Ushort.
Sorry for the inconvenience, and I updated it.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 25th, 2007, 4:43 pm 
Offline

Joined: May 20th, 2007, 7:48 pm
Posts: 48
Here's an example script that uses ADO COM to do some Access database manipulations. The script by itself does not do anything particularly useful, but it does demonstrate several basic operations. Before running the script you may need to adjust the three filename values at the top to match your environment. The script requires CoHelper.

Code:
/*
Sample script using ADO COM that will create an Access database, create a
table in the database, populate the table, read binary data from a
file into a database field, and then write a file with binary data from
a database field.  Error checking has been ommitted.
*/      

#NoEnv
#SingleInstance
#Include CoHelper.ahk
CoInitialize()


;Change these values for your specific environment.  Only file required to
;exist at the start is sFileIn.  The others are created if they don't exist.
sFileIn  = c:\windows\system32\setup.bmp    ;can use any file as input
sFileOut = %A_Temp%\test_out.bmp   ;output file, will be overwritten if exists
sDbFile  = %A_Temp%\test_db.mdb    ;database to be created, deleted if exists at start
 
 
;Some useful constants
Jet3x:=4, Jet4x:=5
adOpenKeyset:=1, adLockOptimistic:=3, adTypeBinary:=1
adSaveCreateOverWrite:=2, adInteger:=3, adKeyPrimary:=1
VT_I4:=0x3, VT_BSTR:=0x8, VT_DISPATCH:=0x9, VT_UI1:=0x11, VT_ARRAY:=0x2000 

;Delete the database if it exists so we start fresh each time
IfExist, %sDbFile%
  FileDelete, %sDbFile%

 
;::::::::::::::::::::::::::::::::::::
;  Create a new database
;::::::::::::::::::::::::::::::::::::

;Define the connection string
sConn := "Provider=Microsoft.Jet.OLEDB.4.0; Jet OLEDB:Engine Type=" . Jet4x . "; Data Source=" . sDbFile . ";"

;Create a new database using ADOX.Catalog
pcat := ActiveXObject("ADOX.Catalog")
pDbase := Invoke(pcat, "Create", sConn)
Release(pDbase)
Release(pcat)
 
;Create a new Connection object and open a connection to the database
pcn := ActiveXObject("ADODB.CONNECTION")
Invoke(pcn, "Open", sConn)

;Create a table in the new database
sCreate := "CREATE TABLE Photos(PhotoId INTEGER NOT NULL
                        ,Title     TEXT(40)  NOT NULL
                        ,Location  TEXT(40) 
                        ,Photo_1   OLEOBJECT)"
Invoke(pcn, "Execute", sCreate)

;Store some values into the table
Invoke(pcn, "Execute", "INSERT INTO Photos VALUES (1,'Grand Canyon', 'Arizona','')")

;At this point if we were finished we would close the connection
;and clean things up, but instead we will reuse the connection
;to open the recordset below.


;::::::::::::::::::::::::::::::::::::::::::::::::::
;  Read binary data from a file into the database
;::::::::::::::::::::::::::::::::::::::::::::::::::

;Create a recordset object and open it with a query the database
prs := ActiveXObject("ADODB.RECORDSET")
Invoke_(prs, "Open", VT_BSTR,"SELECT * FROM Photos WHERE PhotoID=1;"
                   , VT_DISPATCH,pcn
                   , VT_I4,adOpenKeyset
                   , VT_I4,adLockOptimistic)

;Create a binary stream object to hold the data
pmstream := ActiveXObject("ADODB.STREAM")
Invoke(pmstream, "Type=", adTypeBinary)
Invoke(pmstream, "Open")

;Read the disk file into the stream object
Invoke(pmstream, "LoadFromFile", sFileIn)
pSafearray:=Invoke(pmstream, "Read")
 
;Set the value of the Photo_1 field to the binary data
pFields := Invoke(prs, "Fields")
pField := Invoke(pFields, "Item", "Photo_1")
Invoke_(pField, "Value=", VT_ARRAY|VT_UI1,pSafeArray)
Invoke(prs, "Update")

;Cleanup, conservative - release every IDispatch
DllCall("oleaut32\SafeArrayDestroy", "Uint", pSafeArray)
Release(pField) 
Release(pFields)
Invoke(pcn, "Close")
Invoke(prs, "Close")
Release(pmstream)
Release(prs)
Release(pcn)


;::::::::::::::::::::::::::::::::::::::::::::::::::
;  Write binary data from the database into a file 
;::::::::::::::::::::::::::::::::::::::::::::::::::

;We could have reused the connection, recordset, and stream objects
;from above, but for this example we will create new objects.
 
;Create and open a connection
pcn := ActiveXObject("ADODB.CONNECTION")
Invoke(pcn, "Open", sConn)

;Create and open the recordset with a query
prs := ActiveXObject("ADODB.RECORDSET")
Invoke_(prs, "Open", VT_BSTR,"SELECT * FROM Photos WHERE PhotoID=1;"
                   , VT_DISPATCH,pcn
                   , VT_I4,adOpenKeyset
                   , VT_I4,adLockOptimistic)

;Create and open a binary stream
pmstream := ActiveXObject("ADODB.STREAM")
Invoke(pmstream, "Type=", adTypeBinary)
Invoke(pmstream, "Open")

;Write the value of the Photo_1 field to the stream object and then save it to a file with overwrite
pFields := Invoke(prs, "Fields")
pField := Invoke(pFields, "Item", "Photo_1")
pSafearray:=Invoke(pField, "Value")
Invoke_(pmstream, "Write", VT_ARRAY|VT_UI1,pSafearray)
Invoke(pmstream, "SavetoFile", sFileOut, adSaveCreateOverWrite)

;Cleanup, conservative - release every IDispatch
DllCall("oleaut32\SafeArrayDestroy", "Uint", pSafeArray)
Release(pField)
Release(pFields)
Invoke(pcn, "Close")
Invoke(prs, "Close")
Release(pmstream)
Release(prs)
Release(pcn)

CoUninitialize()
Msgbox, Done!
ExitApp


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 25th, 2007, 7:21 pm 
Thanks for the script.
I like th part of writing/reading binary files to DB.

I remeber there is a way of compressing MDB(access file).
Do you know what it is(maybe method name)?

And I take it that you are very active about COM related subject, so can you recommend or list free activeXs and the websites where they are?


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: July 26th, 2007, 12:13 am 
Offline

Joined: May 20th, 2007, 7:48 pm
Posts: 48
ABCYourWay wrote:
Thanks for the script.
I like th part of writing/reading binary files to DB.
Glad you found it useful.

ABCYourWay wrote:
I remeber there is a way of compressing MDB(access file).
Do you know what it is(maybe method name)?
Please refer to http://support.microsoft.com/kb/230501
Code:
#Include CoHelper.ahk
CoInitialize()
jro := ActiveXObject("JRO.JETENGINE")
Invoke(jro, "Compact"
        , "Provider=Microsoft.Jet.OLEDB.4.0; Jet OLEDB:Engine Type=5; Data Source=<SOURCE MDB>;"
        , "Provider=Microsoft.Jet.OLEDB.4.0; Jet OLEDB:Engine Type=5; Data Source=<TARGET.MDB>;")
Release(jro)
CoUninitialize()

ABCYourWay wrote:
And I take it that you are very active about COM related subject, so can you recommend or list free activeXs and the websites where they are?
Most apps come with the necessary components already (if they support COM). If the app you are interested in does not have COM you could try searching the web to see if a plug-in or something exists for it.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 26th, 2007, 9:43 am 
Thanks tfcahm! I love Autohotkey community!


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: August 7th, 2007, 4:23 pm 
Offline

Joined: March 16th, 2005, 10:33 pm
Posts: 968
Location: Frisia
Can anybody create a simple script that demonstrates how to get Excel contents, a single cell, or a range? A variation of this example script?

_________________
Image mirror 1mirror 2mirror 3ahk4.me • PM or Image


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 132 posts ]  Go to page Previous  1, 2, 3, 4, 5, 6 ... 9  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: maul.esel, Morpheus and 74 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group