Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How can you use VFP to access a specific page in a PDF file and make it visible 2

Status
Not open for further replies.

german12

Programmer
Nov 12, 2001
563
0
16
DE
I receive a lot of PDF-files and want to search in them by using VFP.
Example: page 13 of xyp.pdf is to make visible.

Is that possible?

Thanks
Klaus



Peace worldwide - it starts here...
 
Hello Klaus.

There are probably several ways of doing this. One that comes to mind is to use SendKeys() with Windows Scripting.

Something like this:

Code:
* First, use ShellExecute() to launch the PDF in the user's default viewer.
* I assume you already know how to do this.

* Instantiate Windows Scripting Host
owsh = CREATEOBJECT("wscript.shell")

* Switch to the PDF viewer
owsh.AppActivate("My Document")
  && Substitute the name of the PDF file (as it appears in the viewer's title bar)

owsh.SendKeys(< keystrokes here >)

In place of "< keystrokes here >", insert whatever keystrokes are needed to reach the target page. This will vary with the viewer app, but most often it will be a series of right arrow keys. So to go to page 4, you would send three right arrows, for example.

The above is only meant to give you a rough idea. And it might not be the best way. Have a think about it, and come back if you need more details.

Mike



__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
It's also worth checking to see if the PDF viewer has command-line parameters. Many of them do.

For example, in the Sumatra viewer, you can add [tt]-page[/tt] followed by the page number to the command line, to go to that specific page. That way, you only need to ShellExecute the document, passing the filename and the above parameter.

It's likely that other viewers have a similar ability.

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
To give you a concrete example, if you use Foxit:

So to translate this:
Code:
"…Foxit Reader.exe" "C:test.pdf" /A page=5
The VFP equivalent is
Code:
RUN /N "…Foxit Reader.exe" "C:test.pdf" /A page=5

In general, if you want to do automation I'd rather opt for AutoIt:
In itself it's ja programmer tool, not an intuitively usable application. It's mainly a scripting tool for automation and so you start from zero with learning the AutoIt scripting language, but you find a very active community managing very many automation tasks you never thought of automating. You're better off using that than VFP for automation, especially if it's not OLE automation.

I advocate for this, for a simple reason, anything you can do from VFP to cause something in the external world is mainly three things:

a) CREATEOBJECT() of OLE automation servers, mainly Office applications or other OLE automation servers like Wscript.Shell
b) ShellExecute(), after you declare that Windows API function
c) RUN /N some.exe parameters

b) and c) are even quite equivalent in that respect and do quite the same, i.e. you can do most anything with RUN that you can do with ShellExecute. ShellExecute just has one little edge over what RUN /N offers with doing things with other verbs than the default "open", like "print". But there is nothing like "open page 3" to use as a verb, so you depend on the specific PDF viewer EXE to have command line options that allow specifying a page.

There are a few more things, like DDE, but that would be like talking about making fire with flint stones. The only thing that DDE offers is sending commands to an already running executable aka process and that in itself is something VFP can also do, but I fear I don't know even only one PDF viewer that has a DDE interface to send DDE commands to it. There's more in other usual interface like ODBC, interprocess communication, etc, but all these things are either specific to only certain types of connection/queries and even less probable to be offered for external control of PDF viewers.

Last not least, as Mike's sample shows, which I file under OLE automation, the actual automation doable is emulating what a user would do, i.e. what keys he would press. It often has its difficulties in timings, it's not the first thing I'd try, but if it's the only way of automation, then it can be done better with autoit than with wscript.shells' Sendkeys() method, which closes the circle to recommending autoit, unless you find the command line option for your PDF viewer or use Foxit now you know it offers that option. I guess Acrobat Reader will also have a similar command line option and other PDF viewers, too, as it's a natural functionality.

What's a limit of command line options like that of Foxit is that you don't control where and in what size the Foxit reader starts, so you only have limited control. Autoit very much specializes on controlling windows, so that aspect is easier to control. Not that you can't use API functions to control windows (forms) in VFP, too, but then that's still easier to do with autoit.

Chriss
 
Chris, it's interesting that you mentioned AutoIT. I use AutoHotKey ( which I think has a similar purpose and works in a similar way, although the scripting languages look quite different. It would be interesting to do a full comparison of the two products (but not in this thread, of course).

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mike, could even be I already used both without recognizing, as they both have auto in the name. I wonder about their history now.

Chriss
 
I have now managed to write a program that automatically creates a complete VFP file by transferring the tables of contents from several magazines.
Thanks for all the help I received up to now from here.

The following image shows an example of a company which is included in the file

firma_bwdn0r.jpg


My pdf-reader is Foxitpdfreader.
The command
RUN /N "…Foxitpdfreader.exe" "EURAMS_2410_LR.PDF" /A page=48
for the first line in the example works well, when it is coded like that in the program.

However, I want this command be done by my program (as a scan/endscan), so that I dont have to write it 3 times for different pdf's as seen in the above image
I have difficulties with that because obviously only a direct statement of the pdf is always necessary in a RUN command.
The RUN command doesn't seem to work with wildcards.
(Or I code it wrong?)

Is there a way?

Thanks
Klaus





Peace worldwide - it starts here...
 
Klaus,

The question isn't whether the RUN command works with wildcards, but whether the Foxit PDF viewer does. I've just run a quick test, like this:

RUN /n "C:\Program Files (x86)\Foxit Software\Foxit PDF Reader\FoxitPDFReader.exe" "c:\work\[highlight #FCE94F]test*[/highlight].pdf"

Foxit gives a message saying "test*.pdf" cannot be found, so obviously that won't work. (No doubt you already knew this.)

What are trying to achieve? Do you want to launch Foxit with all three PDFs open at the same time? If you run the above command three times, that's what you will get - with each document open in its own tab? (No doubt you already knew that as well.)

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
You can always use macrosubstitution, which is done before execution, also before execution of RUN, you just have to think about what the result of macro substitution is. The file name, for example, should be within quotes even after the macro substitution, so the quotes around the filename must be part of the expression:

Code:
lcPDFFilename = alltrim(query.pdf)
lcSeite = Alltrim(Str(Seite))
RUN /N "...Foxitppdfreader.exe" "&lcPDFFilename" /A page=&lcSeite

There is one reason why this still won't work, The Foxit PDF reader is only given the filename without path. You start a new process by running foxitpdfreader.exe, and even though that exe becomes a child process, that new process doesn't share the current/default folder/directry with your Foxpro process. While the command in VFP to change that default folder also can be CD, Windows is not DOS, in a dos windows you have a system/DOS wide default folder. But in Windows you can run multiple executables in parallal and they each have their own current/default folder, that's not inherited from a parent process.

Besides that, do yourself a favor and make any SQL requests with the clause INTO CURSOR cursorname with varying cursornames that give results a descriptive name. If you have many queries without the result cursor name, you get a result cursor "query" and multiple queries will overwrite the previous result, you'll easily sabotage yourself. Giving everything a descriptive name is not just a good virtue and is not limited to alias names of query results.

Chriss
 
myself said:
The file name, for example, should be within quotes even after the macro substitution, so the quotes around the filename must be part of the expression:

Well, it's only halfways true, but in conjunction of needing to provide the full path with the pdf filename, you will often have a space somewhere in the path name and then need the quotes around it. Plus, it never hurts to quote a filename, whether or ont it needs quotes.

The fact that you don't have the path to the PDF files in your data means you need to address that problem, and you can't do that by first CDing into the pdf files directory, that will make VFP/your own process find a file by name only, but not a new process.

Chriss
 
Thank you very much Mike and Chriss for your quick response.
Mike I must have done an error by using macro-substition to open a pdf-file via Foxit-pdf-reader.
With the command which Chriss wrote
RUN /N "...Foxitpdfreader.exe" "&lcPDFFilename" /A page=&lcSeite
it works happily.
My fault was that I did not use the page-no as part of a string, but as numeric in the call-command.

Chriss
Thanks for your correct macrosubstituion based command.
Also for the hint to lead every call in a separately named cursor.
I will take it into account - and will be back here when everything works fine.

Klaus

Peace worldwide - it starts here...
 
Chriss,
your last answer crossed my response.
I have had no problem with the path, because I copied the vfp-tables into the same path where Foxitpdfreader resides.
I admit that is not a clean separation between data and programs but will take your hint into account.
Thanks.

Klaus



Peace worldwide - it starts here...
 
Klaus said:
My fault was that I did not use the page-no as part of a string

I see, well, that's where RUN doesn't act like any other command, but even other commands suffer from early decisions about how the Foxpro programming language should work, the best design is done for commands that you wouldn't even think of commands, as they are filed under SQL/query/SQL statement:

Code:
nPage = 3
Select * from book WHERE page=nPage

Something like that works, so why does something like that not work?
Code:
nPage = 3
RUN /N "…Foxitpdfreader.exe" "EURAMS_2410_LR.PDF" /A page=nPage
It's the syntax/grammar/usage of a numeric variable in a command.

Well, RUN leaves the "playground" of VFP. The reason nPage is known and interpreted as 3 from the SQL-Select is that the SELECT command is still VFP code., the VFP runtime executes it within the VFP process and it knows all things related to it, including the variable nPage.

RUN, on the other hand, just translates to "execute whatever is configured into the system environment variable %COMSPEC%", which in most (if not all) Windows versions used today is cmd.exe. The rest of the line after /N, which is still falling under the governance of VFP is just forwarded to cmd.exe. That's where VFP related variable names become useless and just literally interpreted as the text they are. cmd.exe and even less so foxitpdfreader have no idea that your VFP process has a variable npage defined, nor that it is 3, it wouldn't even know which data type. It just sees the text npage.

That all culminates in the stetement "You can always use macrosubstitution". Since you can't use VFP variables within other processes, just like other processes don't share the default directory with your process, you have to forward anything you want to forward literally. And macrosubstitution does that. Since you can't do &nPage as macrosubstitution only works with string variables, you have to first convert a number to a string.

Besides that, "You can always use macrosubstitution" als means that although everything after /N is not under the governance of the VFP process, before RUN is even executed any & (except the double && starting a comment) means VFP has to first use the macro substituion concept and then compile/execute the code line resulting from the macrosubstitution, so macro substitution is the only VFP thing that's usable after the RUN or RUN /N in the rest of the line, because it is looked for even before looking at the RUN, VFGP alweays first looks for any macrosubtitition in a code line to substitute it and then execute it.

Chriss
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top