 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
ramin Guest
|
Posted: Fri Apr 10, 2009 8:20 pm Post subject: |
|
|
Thank you so much erictheturtle. Your corrections give me some guidelines for the continuation of the project, which is basically to implement the following perl script:
| Code: | #! /usr/bin/perl
# exportCoursePDF.pl
# Generates PDF files from a list of PPT files
#
# To use:
#
# 1. Save this Perl script to a desired location. For instance, C:\course_resources\exportCoursePDF.pl
#
# 2. Install Perl. You can do this here: http://www.activestate.com/activeperl/
# You can check to ensure you have a Perl installation by entering
# >perl -v
# in a command window.
#
# 3. Open a command window and navigate to the directory containing the PPT files
#
# 4. Call this Perl script with the input argument *.ppt (or whichever PPT files you would like to generate). You may have to give the absolute path to the Perl script:
#
# >perl C:\course_resoures\exportCoursePDF.pl *.ppt
#
#
#use Microsoft Office Object Libraries
use Win32::OLE;
use Win32::OLE::Const "Microsoft PowerPoint 12.0 Object Library";
use Win32::OLE::Const "Microsoft Office 12.0 Object Library"; #mso constants
#use libraries for obtaining current working directory
use Cwd;
use Cwd 'abs_path';
# Process the input arguments
foreach $arg (@ARGV) {
# Expand into a list if necessary (e.g. if the filename contains a *)
@files = glob($arg);
foreach $file (@files) {
export_doc($file);
}
}
sub export_doc {
my $file = shift @_;
chomp $file;
#Microsoft office constant values
my $msTrue = -1;
my $msFalse = 0;
#swap .ppt with .pdf for output file name
my $abs_path = abs_path($file);
$pdfFile = $abs_path;
$pdfFile =~ s/\.ppt/\.pdf/g;
print "\nExporting " . $pdfFile . "...\n ";
# Open connection to Powerpoint
# Note: Use second argument of \&Quit for quit callback
$ppt = Win32::OLE->new('PowerPoint.Application')
|| die("Cannot open connection to PowerPoint.");
# Load the PowerPoint Contants from the Type Library
$Const = Win32::OLE::Const->Load($ppt);
# Constants for printing:
$formatType = $Const->{ppFixedFormatTypePDF};
$intent = $Const->{ppFixedFormatIntentPrint};
$frameSlides = $msFalse;
$slideOrder = $Const->{ppPrintHandoutVerticalFirst};
$printWhat = $Const->{ppPrintOutputNotesPages};
$printHidden = $msTrue;
# Attempt to open the presentation
my $pres = $ppt->Presentations->Open($abs_path,0,0,0) || die Win32::OLE->LastError();
#Export
$pres->ExportAsFixedFormat($pdfFile,$formatType, $intent, $frameSlides, $slideOrder,$printWhat, $printHidden, $pres->PrintOptions->Ranges->Add(1,1), $Const->{ppPrintAll}, '', 0, 0, 0, 1, 0);
print " ===> Done. \n";
# Quit PPT
$ppt->Quit;
# Shutdown COM connection
undef $ppt;
}
|
It converts the note page view of PPTs to PDF and I want to build the gui around it in AHK. Hopefully, I'm going the right direction! I guess my main challenge is to do the following line with WS_Exec:
| Code: |
$pres->ExportAsFixedFormat($pdfFile,$formatType, $intent, $frameSlides, $slideOrder,$printWhat, $printHidden, $pres->PrintOptions->Ranges->Add(1,1), $Const->{ppPrintAll}, '', 0, 0, 0, 1, 0); |
Any recommendations?
Thanks again! |
|
| Back to top |
|
 |
erictheturtle
Joined: 27 Jun 2007 Posts: 90 Location: California
|
Posted: Fri Apr 10, 2009 9:19 pm Post subject: |
|
|
Looks like it's a new function for Office 2007. This should help you with the parameters.
http://msdn.microsoft.com/en-us/library/bb231096.aspx
Edit: woops, fixed a memory leak in the code I posted in my previous post. _________________ -m35 |
|
| Back to top |
|
 |
ramin Guest
|
Posted: Fri Apr 10, 2009 10:26 pm Post subject: |
|
|
Thanks! I'm still trying to figure out how to send more than one parameter to a method using WS_Exec. The ExportAsFixedFormat method has 15 parameters and other than the path, they are all static. I already tried this but with no luck:
| Code: | Loop, Parse, FileList, |
{
StringReplace, pdfPath, A_LoopField, ppt, pdf
WS_Exec("ppApp.Presentations.Open(""" A_LoopField """)")
WS_Exec("ppApp.ExportAsFixedFormat(""" pdfPath ",ppFixedFormatTypePDF,ppFixedFormatIntentPrint,msoCFalse,ppPrintHandoutVerticalFirst,ppPrintOutputNotesPages,msoCTrue,,,,False,False,False,True,False"")")
} |
|
|
| Back to top |
|
 |
erictheturtle
Joined: 27 Jun 2007 Posts: 90 Location: California
|
Posted: Fri Apr 10, 2009 10:38 pm Post subject: |
|
|
Not tested, but this, or something very similar might work.
| Code: | Loop, Parse, FileList, |
{
StringReplace, pdfPath, A_LoopField, ppt, pdf
WS_Exec("Set ppPres = ppApp.Presentations.Open(""" A_LoopField """)")
sBigCode =
(
ppPres.ExportAsFixedFormat("%pdfPath%", ppFixedFormatTypePDF, _
ppFixedFormatIntentPrint, msoCFalse, _
ppPrintHandoutVerticalFirst, ppPrintOutputNotesPages, _
msoCTrue,,,,False, False, False, True, False)
)
WS_Exec(sBigCode)
} |
Also don't forget to check ErrorLevel for details of what's wrong. _________________ -m35 |
|
| Back to top |
|
 |
ramin Guest
|
Posted: Fri Apr 17, 2009 7:43 pm Post subject: |
|
|
Thanks again erictheturtle. I finally managed to create the tool and make it do what I wanted! I had to go to the Object Browser inside the VB editor and find the constant values for each of the parameter and hard code them in. The loop looks like this now:
| Code: | Loop, Parse, FileList, |
{
StringReplace, pdfPath, A_LoopField, ppt, pdf
openCode =
(
Set ppPres = ppApp.Presentations.Open("%A_LoopField%", 0, 0, 0)
)
If (!WS_Exec(openCode))
Msgbox Error in openig the presentations: ErrorLevel
sBigCode =
(
ppPres.ExportAsFixedFormat "%pdfPath%", 2, 2, 0, 1, 5, -1, ppPres.PrintOptions.Ranges.Add(1,1), 1,, 0, 0, 0, 1, 0
)
If (!WS_Exec(sBigCode))
Msgbox % A_LineFile ":`n" ErrorLevel
} |
I works like a charm. Now I love the capability of running VB code in AHK and got a bunch of other ideas!
Thanks again.[/code] |
|
| Back to top |
|
 |
AJohn Guest
|
Posted: Fri Aug 07, 2009 7:27 pm Post subject: |
|
|
Hey erictheturtle - first, thanks a million for your work and time spent at this. Its really an incredible way to extend autohotkey functionality.
I used this thread to set up ahk to run a short .vbs script, and encountered a minor issue - it seems I must wait a few milliseconds between calling WS_Eval and WS_Uninitialize in the following code, or windows gives me a "Autohotkey has encountered a problem and needs to close" error:
complete code:
| Code: | #Include ws4ahk.ahk
!a::
zipsource = C:\work\old
zipdest = C:\work\oldtest.zip
evalstring = fZip(`"%zipsource%`", `"%zipdest%`")
WS_Initialize()
Code =
(
Function fZip(sSourceFolder,sTargetZIPFile)
'This function will add all of the files in a source folder to a ZIP file
'using Windows' native folder ZIP capability.
'Returns an integer 0 if everything went ok.
Dim oShellApp, oFSO, iErr, sErrSource, sErrDescription
Set oShellApp = CreateObject("Shell.Application")
Set oFSO = CreateObject("Scripting.FileSystemObject")
'The source folder needs to have a \ on the End
If Right(sSourceFolder,1) <> "\" Then sSourceFolder = sSourceFolder & "\"
On Error Resume Next
'If a target ZIP exists already, delete it
If oFSO.FileExists(sTargetZIPFile) Then oFSO.DeleteFile sTargetZIPFile,True
iErr = Err.Number
On Error GoTo 0
If iErr <> 0 Then
fZip = iErr
Exit Function
End If
On Error Resume Next
'Write the fileheader for a blank zipfile.
oFSO.OpenTextFile(sTargetZIPFile, 2, True).Write "PK" & Chr(5) & Chr(6) & String(18, Chr(0))
iErr = Err.Number
On Error GoTo 0
If iErr <> 0 Then
fZip = iErr
Exit Function
End If
On Error Resume Next
'Start copying files into the zip from the source folder.
oShellApp.NameSpace(sTargetZIPFile).CopyHere oShellApp.NameSpace(sSourceFolder).Items
iErr = Err.Number
On Error GoTo 0
If iErr <> 0 Then
fZip = iErr
Exit Function
End If
'Because the copying occurs in a separate process, the script will just continue. Run a DO...LOOP to prevent the function
'from exiting until the file is finished zipping.
Do Until oShellApp.NameSpace(sTargetZIPFile).Items.Count = oShellApp.NameSpace(sSourceFolder).Items.Count
WScript.Sleep 500
Loop
fZip = 0
End Function
)
WS_Exec(Code)
WS_Eval(ret, evalstring)
Sleep, 1
WS_Uninitialize()
msgbox %ret%
return |
The "Sleep, 1" at the bottom has to be there (or a msgbox or something) or I get that error... doing WS_Uninit immediately after WS_Eval crashes it.
Its only a minor thing, and I didnt read the entire thread so Im sorry if this has been pointed out before, thanks again dude you rule! |
|
| Back to top |
|
 |
AJohn Guest
|
Posted: Fri Aug 07, 2009 8:09 pm Post subject: |
|
|
So, after more testing I'm not sure exactly what is going on, but when I call the .vbscript this way:
| Code: | WS_Exec(fzipCode)
WS_Eval(fzipret, evalstring)
Sleep, 100
WS_Uninitialize()
msgbox %fzipret% | %evalstring% |
and when I'm zipping hundreds of image files (500 .jpgs, 10 megs total), it runs the script, starts the zipping (the 'compressing files' dialog pops up - no way to hide that with XP's .zip function) and displays the messagebox while the .zip is being created. Does this mean the loop at the end of the vbscript is running in a different thread than the ahk sub that contains it? The weird thing is that ahk still crashes, but it waits until I close the message box to do it.... I had originally thought it crashed due to uninitializing too quickly but it seems something else is going on. Any ideas? |
|
| Back to top |
|
 |
YMP
Joined: 23 Dec 2006 Posts: 329 Location: Russia
|
Posted: Sat Aug 08, 2009 6:16 pm Post subject: |
|
|
I've noticed that placing "On Error Resume Next" before the loop prevents the error. In this case the return value is not blank, it shows 0, as expected.
There is also another trick — define evalstring like this:
| Code: |
evalstring = fZip "%zipsource%", "%zipdest%"
|
But here the return value still remains blank. |
|
| Back to top |
|
 |
erictheturtle
Joined: 27 Jun 2007 Posts: 90 Location: California
|
Posted: Tue Aug 11, 2009 4:48 am Post subject: |
|
|
@AJohn
Looking at your code, I can't quite tell what you are trying to do. It sounds like you want to use Windows Explorer to compress files. I don't understand how opening a binary file and writing a PK header is supposed to do that. Are you trying to zip several jpg files into one file, or each jpg in its own zip file?
Earlier in this thread someone was reporting a similar problem with crashing when WS_Uninitialize() is called. A call to Sleep solved his problem in that case, but it seems you're having another problem.
If you can clarify what you're trying to do, and maybe post another example, I'll see what I can do.
@YMP
Thanks for trying to help AJohn too :) _________________ -m35 |
|
| Back to top |
|
 |
cdjones
Joined: 15 Sep 2009 Posts: 46 Location: Ga, USA
|
|
| Back to top |
|
 |
Scratch
Joined: 22 Jan 2009 Posts: 72
|
Posted: Tue Oct 13, 2009 9:32 pm Post subject: Fooling around with WS4AHK.... |
|
|
First of all, thank you, thank you, thank you!
WS4AHK is the probably best thing to happen to AHK since the invention of sliced bread and DLLCALL...
I've been toying with ahk for 2 days and I asked myself, do we really need to use WS_Initialize() explicitly in AHK?
What if we incorporate it in the WS_Exec() function and do a little check if WS was already initialized, so that it won't reinitialize at encountering every WS_Exec(VBsnippet) in AHK ? After all a WS_Exec implies that you wan't to have a scripting host initialized, but you don't want to have it initialized over and over again...
Modified WS4AHKExec here:
| Code: |
WS_Exec(sCode)
{
if NOT WS_Initialized ; MODIFIED
WS_Initialize()
global __WS_iScriptControlObj__, __WS_iScriptErrorObj__
IfEqual __WS_iScriptControlObj__,
{
Msgbox % "Windows Scripting has not been initialized!`nExiting application."
ExitApp
}
; Run the code
Critical, On ; For thread safty
iErr := __WS_IScriptControl_ExecuteStatement(__WS_iScriptControlObj__, sCode)
If (iErr = "")
{
Critical, Off
; ErrorLevel has already been set to whatever error occured
Return False
}
Else
{
ErrLvl := ErrorLevel ; save ErrorLevel
blnIsErr := __WS_IsComError("IScriptControl::ExecuteStatement", iErr)
If (ErrorLevel = 0)
ErrorLevel := ErrLvl ; restore ErrorLevel
Else
ErrorLevel := ErrLvl "`n" ErrorLevel ; append ErrorLevel
If (blnIsErr)
{
; Probably an exception. Get the deatils.
; TODO: Find out what HRESULT code(s) mean there is an exception.
; FIXME: This call destroys whatever ErrorLevel is
__WS_HandleScriptError()
Critical, Off
Return False
}
Else ; success
{
Critical, Off
Return True
}
}
WS_Initialized := TRUE ; MODIFIED
}
|
This will do an implicit WS_Initialize at encountering your first WS_Exec
and remember that the WS was initialized..
Finally, WS_Initialized is reset when WS_Uninitialized is called:
| Code: |
WS_Uninitialize()
{
global __WS_iScriptControlObj__, __WS_iScriptErrorObj__
If __WS_iScriptErrorObj__ is Integer
If (__WS_iScriptErrorObj__ <> 0)
__WS_IUnknown_Release(__WS_iScriptErrorObj__)
If __WS_iScriptControlObj__ is Integer
If (__WS_iScriptControlObj__ <> 0)
__WS_IUnknown_Release(__WS_iScriptControlObj__)
ErrLvl := ErrorLevel ; save ErrorLevel
DllCall("ole32\CoUninitialize")
ErrorLevel := ErrLvl ; restore ErrorLevel
__WS_iScriptControlObj__ := ""
__WS_iScriptErrorObj__ := ""
WS_Initialized := FALSE ; MODIFIED
}
|
A bit quickndirty, but it seems to work...
I think your scriping client is such a valuable extension to AHK that it deserves to be incorporated as a function in AHK itselve, for instance as a block like:
| Code: |
Ahkvar = Hello World
[WSEXEC]
msgbox "%Ahkvar%"
[/WSEXEC]
|
Note that special care has to be taken by AHK to evaluate %Ahkvar% first before actually passing control to the scripting host, the current solution is to assign the vbscript to a ahkvariable first and then execute the ahkvariable:
| Code: |
Ws_Initialize()
Ahkvar = Hello World
vbscript =
(
msgbox "%Ahkvar%"
)
WS_Exec(vbscript)
|
It works, but a WS start/end block looks much cleaner and could potentially be
used as common placeholders for other future AHK scriptingclients for perl/python etc, like:
| Code: |
...ahkcode
...ahkcode
...some more
[PYTHON] ; Block of inline code, using HTML style
put your python code here....
some more...
[/PYTHON]
|
Anyway, I am really pleased with the way you extended the functionallity of AHK, here is a little testscript I made, demonstrating how WS4AHK can be a tool to prevent circular reference errors in excel when using iterations in cells.
| Code: |
A1 = 1 ; AHK Vars to be copied to Excel Cells
A2 = =A1*2
A3 = =A2*3
;
;
startexcel =
(
Dim Excel
Set Excel = CreateObject ("excel.application")
excel.visible = True
)
WS_Exec(startexcel)
;
;
AddWorkbookSheet =
(
Dim workbook
set workbook = excel.workbooks.add
Dim worksheet
set worksheet = excel.Sheets(1) 'The first worksheet
)
WS_Exec(AddWorkbookSheet)
;
;
;
CopyAHKvars2XL =
(
Worksheet.Cells(1, 1).Value = "%A1%"
Worksheet.Cells(2, 1).Value = "%A2%"
Worksheet.Cells(3, 1).Value = "%A3%"
)
WS_Exec(CopyAHKvars2XL)
;
;
;
; Do some math operations and have the cells outputresult returned to the cells input,
; (this would normally cause a circular reference error in Excel, but we can bypass it nicely by reading/writing from AHK using WS_Eval)
;
loop 10
{
WS_Eval(multiplier, "Worksheet.Cells(2, 1).Value")
pipe_output2input =
(
Worksheet.Cells(1, 1).Value = "%multiplier%"
)
WS_Exec(pipe_output2input)
sleep 500
}
WS_Uninitialize()
|
Note: There is no WS_Initialize in the script as it relies on the modiefied WS4AHK as posted above, you might want to add a WS_Initialize if running with the original WS4AHK. |
|
| Back to top |
|
 |
temp01
Joined: 09 Jul 2009 Posts: 120
|
Posted: Tue Oct 13, 2009 10:15 pm Post subject: Re: Fooling around with WS4AHK.... |
|
|
| Scratch wrote: | This will do an implicit WS_Initialize at encountering your first WS_Exec
and remember that the WS was initialized..
...
A bit quickndirty, but it seems to work... |
No, it'll call WS_Initialize() every time because you didn't declare the variable as global or static (static won't work if you want to change it from WS_Uninitialize).
| Scratch wrote: | | Anyway, I am really pleased with the way you extended the functionallity of AHK, here is a little testscript I made, demonstrating how WS4AHK can be a tool to prevent circular reference errors in excel when using iterations in cells. |
You could use COM.ahk and do it directly with AHK (instead of using VBS) or use COM + MSScript Control to execute JS/VBS code. |
|
| Back to top |
|
 |
Scratch
Joined: 22 Jan 2009 Posts: 72
|
Posted: Tue Oct 13, 2009 11:27 pm Post subject: |
|
|
That was the quickndirty part thx, i'll remember to declare my variables more carefully |
|
| Back to top |
|
 |
ILAN12346 Guest
|
Posted: Thu Nov 19, 2009 7:37 pm Post subject: |
|
|
| Code: | #Include ws4ahk.ahk
WS_Initialize()
gui, add, edit, vsay w200,VBScript in Autohotkey... For the win !!
gui, add, button, gsay,Say
gui, Show
Return
say:
gui, submit, NoHide
Sam(say)
Return
GuiClose:
WS_Uninitialize()
ExitApp
Sam(Text)
{
sam=
(
Function Sam(say)
set objVoice = CreateObject ("SAPI.spVoice")
ObjVoice.speak say
End Function
)
WS_Exec(sam)
Text = sam("%text%")
WS_Eval(Info,Text)
} |
MFG Ilan12346 |
|
| Back to top |
|
 |
ZLogic Guest
|
Posted: Wed Feb 03, 2010 6:04 pm Post subject: Excel Search |
|
|
This is amazing! I have been using this to script things in Excel nicely, but I can't figure out how to search for the range of a given string in an Excel file.
For example, if I want to use ws4ahk to add a certain value 2 cells to the left of a cell with "ABCD" in it, how would I do this? I can reference cells directly, but is there any way to get the address of a cell with a given value in it?
Thanks! |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|