Showing posts with label #Python. Show all posts
Showing posts with label #Python. Show all posts

Sunday, August 31, 2014

Internet Explorer 9 Save Dialog - SendKeys Last Resort

At work we use Internet Explorer 9 on Windows 7 Enterprise.  SharePoint is the favored software for filesharing inside organizational groups.  Our mine planning office is in the States; the mine operation whose data I work is in a remote, poorly connected location of the world.

Recently Sharepoint was updated to a new version at the mine.  The SharePoint server configuration there no longer allows Windows Explorer view or mapping of the site to a Windows drive letter.  I've put in a trouble ticket to regain this functionality, but that may take a while if it's possible.  Without it it is difficult to automate file retrieval or get more than one file at a time.

In the meantime I've been able to get the text based files over using win32com automation in Python to run Internet Explorer and grab the innerHTML object.  innerHTML is essentially the text of the files with tags around it.  I rip out the tags, write the text to a file on my harddrive and I'm good to go.

Binary files proved to be more difficult to download.  Shown below is a screenshot of the Internet Explorer 9 dialog box that goes by the generic name Notification Bar:

 
I googled and could nowhere find how this thing fit into the Internet Explorer 9 Document object hierarchy.  Then I came upon this colorful exchange between Microsoft Certified MVP's from 2012 that made things a little more clear.
 
It turns out you can't access the Notification Bar programatically per se.  What you can do is activate the specific Internet Explorer window and tab you're interested in, then send keystrokes to get where you want to, click, and download your file.
 
I'm not a web programmer nor am I a dedicated Windows programmer (I'm actually a geologist).  IEC is a small module that wraps some useful functionality - in my case identifying and clicking on the link on the SharePoint page by it's text identifier:
 
# C Python 2.7
 
# Internet Explorer module.
import IEC as iec
 
import time
 
ie = iec.IEController()
 
ie.Navigate(<URL of SharePoint page>)
# Give the page time to load (7 seconds).
time.sleep(7)
# I want to download file 11.msr.
ie.ClickLink('11')
# Give 5 seconds for the Notification Bar to show up.
time.sleep(5)
 
I'm fortunate in that our mine planning vendor, MineSight, ships Python 2.7 and associated win32com packages along with their software (their API's are written for Python).  If you don't have win32com and friends installed, they are necessary for this solution.
 
At this point I've just got to deal with that pesky Internet Explorer 9 Notification Bar.  As it turns out, SendKeys makes it doable (although neither elegant nor robust :-(   ):
 
# Activate the SharePoint page.
from win32com.client import Dispatch as dispx
shell = dispx('WScript.Shell')
shell.AppActivate(<name of IE9 tab>)
# Little pause.
time.sleep(0.5)
# Keyboard combination for the Notification Bar selection
# is ALT-N or '%n'
shell.SendKeys('%n', True)
# The Notification Bar goes to "Open" by default.
# You need to tab over to the "Save" button.
shell.SendKeys('{TAB}')
# Another little pause.
time.sleep(0.1)
# Space bar clicks on this control.
shell.SendKeys(' ', True)
 
The key combinations for accessing the Notification Bar are in Microsoft's documentation here
 
One link showing use of SendKeys is a German site (mostly English text) here.
 
And that's pretty much it.  There's another dialog that pops up in Internet Explorer 9 after the file is downloaded.  I've been able to blow that off so far and it hasn't gotten in the way as I move to the next download.  I give these files (about 300 kb) 15 seconds to download over a slow connection.  I may have to adjust that.
 
This solution is an abomination by any coding/architecture/durability standard.  Still, it's the abomination that is getting the job done for the time being.
 
Thanks for stopping by.
 
 

Friday, August 28, 2009

Unicode - Arabic

There had been some discussion on the Python Diversity list about foreign languages and making finding Python resources that are available in them easier. The foreign language page on the Python Wiki shows a number of languages, but some of the more prominent ones are missing. In addition, all the languages are listed in English in ASCII compatible characters.

It was my thought that the languages should also be listed in a manner that a native speaker who is not fluent in English could recognize.

I started alphabetically and came across Arabic. Arabic is a language written in a bidi, or bidirectional, manner (letters go right to left; numers go left to right - not an official definition, but it describes bidi well enough for this post). Letters in the middle of a word can change shape depending on what other letters are around them.

Vim does a good job of documenting this. It was an important tool in how I got around the challenge of letters only defined outside of the 128 member ASCII set.

How I got the Arabic word for "Arabic" onto the Python Wiki:

1) go to the Wikipedia page for Arabic (language).

2) open gvim (I didn't do this in the console) and set encoding to UTF-8 (:se encoding=UTF-8).

3) copy the Arabic word for "Arabic" from the Wikipedia page for the Arabic language and paste it into gvim

4) navigate across the characters (they may not show up at all, or may blink, or may look like perforated boxes - don't worry about that); on each one type in the command(s) 'ga'. The Unicode character code should appear for that letter at the bottom of the screen. Write each one down on paper or type them in in another window (this is crude, but for six characters, it's not too bad).

5) use an adaptation of the code from Andrew Kuchling's Unicode page to find codes suitable for a web page, the first character to last should be listed left to right, but should render right to left in a web browser.

how to get codes out of Python:

%/usr/local/bin/python3.0
Python 3.0.1 (r301:69556, Jul 16 2009, 21:08:20)
[GCC 4.2.1 20070719 [FreeBSD]] on freebsd7
Type "help", "copyright", "credits" or "license" for more information.

>>> charsx = ['\u0627', '\u0644', '\u0639', '\u0631', '\u0628', '\u064A','\u0629']

>>> import pprint
>>> XMLCD = 'xmlcharrefreplace'
>>> xmlcodes = [charx.encode('ascii', XMLCD) for charx in charsx]
>>> pprint.pprint(xmlcodes)
[b'&#1575;',
 b'&#1604;',
 b'&#1593;',
 b'&#1585;',
 b'&#1576;',
 b'&#1610;',
 b'&#1577;']
>>> exit()
%


In the moinmoin based Wiki the Python Wiki uses, simply listing the character codes in the following fashion allows them to render correctly on the page:

 &#1575;&#1604;&#1585;&#1585;&#1576;&#1610;&#1577;

It may or may not render correctly in your web browser; hopefully, for people who regularly work in Arabic on the computer, it will:

الرربية

Discussion:

It's harder to get Unicode to show up in desktop applications than it is in the web browser. I found this out the hard way.

There are definitely more elegant and efficient ways of doing this. This was more of a "Watch Carl learn UTF-8 and Unicode" post.

Code:

I'm a list comprehension freak. I probably go overboard at times.

'xmlcharrefreplace' really doesn't need its own constant. It's for me. The word 'xmlcharrefreplace' is just too alliterative and tongue twisting for me not to misspell or mistype it. Your mileage may vary.

I have a bias towards using pretty print (pprint) whenever I can.  It just makes viewing numbers and data easier for me.  Again, your mileage may vary.

The only thing harder than getting xml character codes to render correctly is getting them to show up as plain codes.  I'm pretty much an html newb.  If you need to represent &#, you can substitute &#38;&#35; (in order to just do that I had to substitute twice :-)

I used vim for this.  EMACS people, I don't know, but I suspect you have something similar for bidi and Arabic. Feel free to share that in the comments (no flaming, please.)

Carl T.