Automate Tdxw

Posted duan-qs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Automate Tdxw相关的知识,希望对你有一定的参考价值。

Automate Tdxw

Code



# coding: utf-8 
"""
Created on Thu Dec 07 10:57:45 2017

@author: duanqs
"""

#import pywinauto
from pywinauto import application, findwindows, findbestmatch
from pywinauto import clipboard
from pywinauto.application import Application
import SendKeys
#import win32gui
#import win32api
#import win32con
import os, sys, time

import pandas as pd


class Tdxw:
    u‘‘‘
    简介:
        使用pywinauto对应用程序进行自动化操作的步骤以及方法:
            1. 初始化一个application实例app:
                app = application.Application()
            2. 用该app实例启动目标应用程序
            或者将该app实例连接到正在运行的目标程序:
                app.start() or
                app.connect(handle=xl_handle)
            3. 开始操作程序的主窗口(mainDlg):
                mainDlg = app.Notepad or
                mainDlg = app[‘Notepad‘]
            4. 进一步操作窗口里的控件, 比如TreeView控件:
                tv = mainDlg.TreeView
                tv.get_item().click_input()
            FAQ:
                1. 如何查看GUI里的窗口或者控件信息?
                A: 用au3info.exe程序 或者 调用:
                    .print_control_identifier()方法
                2. 查找窗口的方法有哪些?
                A: findwindows.find_window()
                   findwindows.find_windows()
        
#==============================================================================
#         print u‘现在需要把app对象连接到GUI程序上, 以实现两个进程(python脚本/GUI程序)间通信‘
#         print u‘通常分两步走:‘
#         print u‘1. 找到GUI程序的窗口: 通常有两种方法来找到目标窗口的句柄‘
#         print u‘    1. 用目标窗口的类名, 传值给class_name参数, 比如:‘
#         print u‘       pywinauto.findwindows.find_windows(class_name=‘Chrome_WidgetWin_1‘)[0]‘
#         print u‘    2. 用目标窗口的标题, 传值给title_re参数, 比如:‘
#         print u‘       pywinauto.findwindows.find_windows(title_re=u‘无标题‘)[0]‘
#         print u‘2. 用app.connect方法建立连接‘
#         print u‘但是, 如果GUI程序是单个进程的话, 一步就可建立连接了. ‘
#         print u‘利用已经打开的GUI程序的路径或者句柄或者进程号三者之一, 比如:‘
#         print u‘- app.connect(path=‘notepad‘)  # 传值给path参数‘ 
#         print u‘- app.connect(handle=1442350)  # 传值给handle参数‘ 
#         print u‘- app.connect(process=4224)  # ‘ 
#==============================================================================
                
                
    功能:
        automation class for 海通证券版通达信下单程序
    ‘‘‘
    program_tdx = u‘D:\new_haitong\TdxW.exe‘
    program_notepad = ‘Notepad‘
    program = program_tdx
    loginWinTitle   = u‘.*海通证券彩虹投资.*‘
    mm = ‘xxxxxxxxx‘
    SLEEP_TIME = 1
    DICT1 = {‘mmjp‘:‘AfxWnd42‘, #密码键盘
             ‘dl‘:‘AfxWnd422‘, #登录
             ‘tj‘:‘AfxWnd424‘, #脱机
             ‘qx‘:‘AfxWnd425‘, #取消
             ‘txsz‘:‘AfxWnd426‘, #通讯设置
             ‘syzn‘:‘AfxWnd427‘, #使用指南
             ‘xtjc‘:‘AfxWnd428‘, #系统检测
             ‘wskh‘:‘AfxWnd429‘, #网上开户
             ‘hqjjy‘:‘AfxWnd4210‘,      #行情加交易
             ‘dlhq‘:‘AfxWnd4211‘,       #独立行情
             ‘dljy‘:‘AfxWnd4212‘,       #独立交易
             }
    XD_DICT = {u‘查询‘:8,
               u‘资金股份‘:0,
               u‘当日委托‘:1,
               u‘当日成交‘:2,
               u‘历史委托‘:3,
               u‘历史成交‘:4,
               u‘成交汇总‘:5,
               u‘资金流水‘:6,
               u‘交割单‘:7, 
               }
    class_tdx_xd = ‘Afx:400000:8:10011:0:0‘
    class_tdxw = ‘TdxW_MainFrame_Class‘
    class_explore = ‘ExploreWClass‘
    
    # TreeView控件 操作子条目时的路径:
    # 不知为何用中文文本方式的路径时, codec出错!!!
    cx_zjgf = [8,0] #查询 资金股份 
    cx_drwt = [8,1] #查询 当日委托
    cx_drcj = [8,2] #查询 当日成交
    cx_lswt = [8,3] #查询 历史委托
    cx_lscj = [8,4] #查询 历史成交
    cx_cjhz = [8,5] #查询 成交汇总
    cx_zjls = [8,6] #查询 资金流水
    cx_jgd  = [8,7] #查询 交割单

    fname=‘‘
    
    def __init__(self):
        pass

    def startup(self):    
        print u‘...实例化pywinauto App对象, 用缺省的构造函数‘
        app = Application()
#        app = Application(backend=‘uia‘)
        print u‘...启动本机的GUI程序‘%s‘, 通过app对象来启动, 以便后续进行自动化操作‘ %(self.program)
        app.start(self.program) # , timeout=5)
    
        # 等待登录窗口出现:
        #    处理异常情况: 有可能出现第二次登录, 这时候应该点击"取消",然后退出脚本
        mainDlg=app.window(title=‘‘,class_name=‘#32770‘)
        if mainDlg.exists():
            print mainDlg.Static2.window_text()
            mainDlg[u‘取消‘].click_input()
            # exit
            sys.exit(0)
        #time.sleep(5) # 1 sec 这种傻傻地等待的方法最安全了, 可以获取到pid
        #app.WaitCPUUsageLower(threshold=25, timeout=10)
        mainDlg=app.window(title_re=self.loginWinTitle, class_name=‘#32770‘)
        while not mainDlg.Exists():
        #while not app.windows_() or not app.TdxW_MainFrame_Class.Exists():
            time.sleep(.5)
        print u‘...GUI程序已经启动, and its pid= %s, pid将用来建立进程间通信‘ %(app.process)
        
        # 把此时的重要变量/数据保存给类实例的属性, 以便后续的方法里使用
        # 注意属性名字 不要与方法同名
        # 将app对象, app.window()对象:主窗口
        self.app = app
        self.mainDlg = app.window() # 获取 目标应用程序的主窗口(): 登录界面
#        mainDlg = app.window(handle=w_handle)
#        self.mainDlg.Close() # 关闭主窗口
#==============================================================================

    def login_mode(self, mode=‘T‘):
        u‘‘‘
        login with specific mode
        param mode:
            str, one of (‘T‘, ‘HQ‘, ‘HQT‘)
            分别表示: 独立交易 独立行情 交易+行情 模式
        example:
            tdx.login_mode(‘HQ‘)
        ‘‘‘
        if mode == ‘T‘:
            self.loginTradeOnly()
        elif mode == ‘HQ‘:
            self.loginHQOnly()
        elif mode == ‘HQT‘:
            self.loginHQ_Trade()
        
        
    def login(self):
        u‘‘‘ login HQ + trade 
        背景知识:
            海通证券连接柜台中间件失败:
            - 出现这个问题,很可能是证券公司系统测试,或者系统维护,
            - 周六周日证券公司会搞系统测试,等周一就会好了。
            - 再有就是看看您的网络连接,如果连接没问题就是在系统测试。
            - 没事的周一就好了。
        ‘‘‘
        self.mainDlg.Edit2.ClickInput()  # Edit2  交易密码编辑框
        SendKeys.SendKeys(self.mm)
        SendKeys.SendKeys(‘{ENTER}‘)
        
        #self.mainDlg.Edit4.ClickInput()  # Edit4 通选密码编辑框
        SendKeys.SendKeys(self.mm)
        SendKeys.SendKeys(‘{ENTER}‘)
        
        time.sleep(3)

    def loginHQ_Trade(self):
        u‘‘‘
        行情+交易 登录
        
        ‘‘‘
#        self.mainDlg.Edit.SetFocus();  # Edit : zjzh Edit Box
#        SendKeys.SendKeys(‘1300148453{ENTER}‘)
        
        #tdx.mainDlg[DICT1[‘hqjjy‘]].print_control_identifiers() 
        #tdx.mainDlg[DICT1[‘hqjjy‘]].DrawOutline() # 用来识别控件是否正确, 画个外框
        self.mainDlg[self.DICT1[‘hqjjy‘]].Click()
        time.sleep(self.SLEEP_TIME)        
        self.input_mm()
        self.input_txmm() #通讯密码 , 然后回车就登录了
        
        

    def loginHQOnly(self):
        self.mainDlg[self.DICT1[‘dlhq‘]].Click()
        time.sleep(self.SLEEP_TIME)        


    def loginTradeOnly(self):
        self.mainDlg[self.DICT1[‘dljy‘]].Click()
        self.input_mm()
        self.input_txmm() #通讯密码 , 然后回车就登录了



    def input_mm(self):
        #self.mainDlg.SaveEdit1.print_control_identifiers()  #交易密码 编辑框
        self.mainDlg.Edit2.SetFocus()
        SendKeys.SendKeys(self.mm)        
        SendKeys.SendKeys( ‘{ENTER}‘,pause=0.5, with_newlines=True) # 0.05 sec by default
        time.sleep(self.SLEEP_TIME)
#==============================================================================
#         # 另一种输入密码的方法: TypeKeys()        
#         ttt=2        
#         self.mainDlg.SaveEdit2.TypeKeys(‘4‘);time.sleep(ttt)   
#         self.mainDlg.SaveEdit2.TypeKeys(‘1‘);time.sleep(ttt)      
#         self.mainDlg.SaveEdit2.TypeKeys(‘6‘);time.sleep(ttt)      
#         self.mainDlg.SaveEdit2.TypeKeys(‘5‘);time.sleep(ttt)      
#         self.mainDlg.SaveEdit2.TypeKeys(‘8‘);time.sleep(ttt)      
#         self.mainDlg.SaveEdit2.TypeKeys(‘9{ENTER}‘)  
#==============================================================================
        print u‘
==> 交易密码已经输入完毕! entered!‘

    def input_txmm(self):
        #self.mainDlg.SaveEdit3.print_control_identifiers()  #通信密码 编辑框
        self.mainDlg.Edit4.SetFocus()
        SendKeys.SendKeys(self.mm)        
        SendKeys.SendKeys(‘{ENTER}‘, pause=0.5, with_newlines=True)
        time.sleep(self.SLEEP_TIME)
        print u‘
==> 通讯密码已经输入完毕!‘
        # 通讯密码输入之后,应该预留片刻时间, 
        # 等待 连接服务器/身份认证/下载权息信息等等事项
        #     一直到出现交易界面窗口
        #time.sleep(6)
        while not self.app.TdxW_MainFrame_Class.exists():
            time.sleep(0.5)
            self.handle_login_failure()




    def close_tsxx(self):
        u‘‘‘
        登录之后, 关闭‘提示信息‘窗口
        备注: 
            1. 首次登录之后, 经常会遇到服务器发来的提示消息, 有时还不只1个消息窗口.
            这些提示消息窗口的类名均为 #32770, 比如窗口名为"发现了新版本", 
            或者"发行新股提示"等待. 所以需要逐个关闭之.
            
         >>> l_dlg= tdx.app.windows(class_name=‘#32770‘)
         >>> print "|".join([d.texts()[0] for d in l_dlg])   
         >>> print "|".join([d.window_text() for d in l_dlg])
         即时播报|发现了新版本|新股提示||滚动资讯|刷新行情
         
         由此可见: tdx软件还有4个内置的消息窗口(Dialog控件)是不应该关闭的
         
             2. texts() 与 window_text()方法的区别:
                 前者返回文本列表, 后者返回文本
             3. app.windows() app.window()的区别:
                 前者返回封装了的对话框列表, 后者窗口规格对象
                 Dlgs    =tdx.app.windows()
                 winSpec =tdx.app.window()
                 appWins == appWin  # False
                 
                 xxDlgs    =tdx.app.windows(class_name=‘#32770‘)
                 xxWinSpec =tdx.app.window(class_name=‘#32770‘)
        ‘‘‘
        # close 提示信息窗口
        # 查找独立(非内嵌的)的消息窗口
        handles = findwindows.find_windows(class_name=‘#32770‘)#[0]
        if len(handles) > 0 :
            for h in handles:
                msgWin= self.app.window(handle=h)
                print u‘...关闭该窗口: "%s" ‘%(msgWin.window_text())
                msgWin.Close()
        print( u‘
==> 所有提示信息窗口 已经关闭!‘)

    def close_client(self):
        u‘‘‘ close tdx交易客户端
        ‘‘‘
        self.app.window(class_name=self.class_tdxw).Close()


    def real_login_trade(self,closeTSXX=True):
        u‘‘‘
        
        ‘‘‘
        self.startup()
    #    tdx.login() # 登录到:  行情 + 交易 模式
    #    tdx.loginHQ_Trade()
    #    tdx.loginHQOnly()
    #    tdx.loginTradeOnly()
        self.login_mode(‘T‘) # ‘HQT‘  ‘T‘   ‘HQ‘ 
        
        time.sleep(self.SLEEP_TIME)
        
        if closeTSXX:
            self.close_tsxx()
        
        # save 交易客户端的主界面
        # 用au3info工具: 查看窗口信息: 窗口类名为 TdxW_MainFrame_Class
        # mainFrame = tdx.app.window(class_name=tdx.class_tdx_xd)
        self.mainDlg = self.app.window(class_name=‘TdxW_MainFrame_Class‘)

    def connect_to(self, l_handle):   
        u‘‘‘
        
        ‘‘‘
        app=Application().connect(handle=l_handle[0])
        self.app=app
        self.mainDlg=app.window(class_name=self.class_tdxw)


    def modify_date_range(self, ymd1=(2017,7,1), ymd2=(2017,7,31)):
        u‘‘‘修改查询日期: 起始日期, 结束日期  
        
        # 设置查询的起始日期 终止日期 然后 查询 输出
        # 注意日期必须设置正确
        mainDlg=tdx.app.window()
        # 可以借助下面的方法,查找出时间拾取控件的独一无二的/没有分歧的 控件名
        # mainDlg.print_control_identifiers(depth=2)
        mainDlg.DateTimePicker.get_time()
        mainDlg.DateTimePicker2.get_time()
        # 或者更加明确的日期拾取控件名:
        mainDlg[u‘起始日期:DateTimePicker‘].get_time()
        mainDlg[u‘终止日期:DateTimePicker2‘].get_time()
        
        mainDlg.DateTimePicker.wrapper_object().set_time(2019,1,0,1, 0,0,0,0)
        mainDlg.DateTimePicker2.wrapper_object().set_time(2019,1,0,25, 0,0,0,0)
        tdx.app.window()[u‘查询‘].click_input()
        tdx.app.window()[u‘输出‘].click_input()
        
        # 假如日期设置不正确, 会得到运行时错误, 比如2月份没有第31号
        mainDlg.DateTimePicker2.wrapper_object().set_time(2018,2,0,31, 0,0,0,0)
        RuntimeError: Failed to set time in Date Time Picker
        
        ‘‘‘
        # based on dt1,dt2, create fileName  变量, 然后保存到实例对象里
        self.yy1, self.mm1, self.dd1 = yy1,mm1,dd1 = ymd1 #(2017, 8, 1)
        self.yy2, self.mm2, self.dd2 =yy2,mm2,dd2 = ymd2 #(2017, 8, 31)
        #fname = u‘d:\DB\tdxw\‘ 
        #self.fname = u‘%s%02d%02d-%s%02d%02d‘%(yy1,mm1,dd1, yy2,mm2,dd2)
        self.fname = u‘%s%02d‘%(yy1,mm1)

        mainDlg = self.mainDlg = self.app.window(class_name=self.class_tdxw)
        #mainDlg[u‘起始日期:DateTimePicker‘].get_time()
        #mainDlg[u‘终止日期:DateTimePicker2‘].get_time()
        dtp1=mainDlg[u‘起始日期:DateTimePicker‘] #.get_time()
        dtp2=mainDlg[u‘终止日期:DateTimePicker2‘] #.get_time()
        #dtp1_ = mainDlg.DatetimePick.wrapper_object()
        #dtp2_ = mainDlg.DatetimePick2.wrapper_object()
        dtp1.set_time(yy1,mm1,0,dd1, 0,0,0,0)#Year,M,DayOfWeek,D, H,M,S,ms
        dtp2.set_time(yy2,mm2,0,dd2, 0,0,0,0)
        mainDlg[u‘查询‘].ClickInput() #点击确定: 执行新的查询
        #mainDlg[u‘输出‘].ClickInput() #点击确定: 执行新的查询
        time.sleep(3) # 需要足够长才行, 否则结果没有出来

             
    def get_query_result(self, content=87, yyyymm=201707,closeAppFlag=False):
        u‘‘‘
        86: 资金流水
        87: 交割单
        Example:
            >>> tdx=Tdxw()
            >>> tdx.get_query_result(content=86, yyyymm=201707 )   

        ‘‘‘
        l_handle=findwindows.find_windows(class_name=self.class_tdxw)
        if len(l_handle)==1:
            # 只需要connect to 应用程序就可以了
            self.connect_to(l_handle)
            pass
        else:
            self.real_login_trade()
        
        main = self.mainDlg
        cdic={
                80:‘zjgf.txt‘,
                81:‘drwt.txt‘,
                82:‘drcj.txt‘,
                84:‘lscj.txt‘,
                86:‘zjls.txt‘,
                87:‘jgd.txt‘,
                }
        idic={
                80:self.cx_zjgf,
                81:self.cx_drwt,
                82:self.cx_drcj,
                84:self.cx_lscj,
                86:self.cx_zjls,
                87:self.cx_jgd,
                }
        item_c = idic[content]
        #     
        tv = main.TreeView
        # 文本格式的路径, 不干活. 可见pywinauto对listview可见的支持不够完善!!!
        #tv.get_item(u‘\市价委托\买入‘).ClickInput()
        #tv.get_item(u‘\\	查询\\交割单‘).ClickInput() #执行查询
        #tv.get_item([u‘	查询‘, u‘交割单‘]).ClickInput() #执行查询
#        tv.get_item(self.cx_zjgf).ClickInput() #执行查询
#        time.sleep(2)
#    
#        tv.get_item(self.cx_zjls).ClickInput() #执行查询
#        time.sleep(2)
#    
        tv.get_item(item_c).ClickInput() #执行查询
        time.sleep(2)
        
        # 处理异常情况: "()通信失败, DrtpSend: 目的网关无法到达 "
        #w=tdx.app.window(handle=findwindows.find_windows(class_name=‘#32770‘)[0])
        w=self.app.window(title=u‘提示‘,class_name=‘#32770‘)
        if w.exists():
            print u‘...  有异常情况  ...‘
            print u‘... %s ...‘%w.window_text()
            #Static2 很奇怪: 这样就是取不到 静态标签的文本
            #print w.Static3.window_text() 
            # 只能这样才可以取得 该标签的文本
            print w.children()[4].window_text()
            w[u‘确认‘].click_input()
            self.close_client()
            sys.exit(0)
        else:
            lv = main.ListView
            #     #Allow the calling code to get the HwndWrapper object
            #     lv_hwnd_wr = lv.wrapper_object()
        
            # 查看交割单列表视图的列名
            # Why pywinauto fail to get ListView item from a 32-bit app? - Stack Overflow  
            # https://stackoverflow.com/questions/46337375/why-pywinauto-fail-to-get-listview-item-from-a-32-bit-app?r=SearchResults
            print ‘|‘.join([dic[‘text‘] for dic in lv.columns()])
            
            #lv.click(button=‘right‘)  # 会触发一个 弹出菜单: PopupMenu
            ##tdx.app.window(class_name=‘#32768‘) # 弹单的类名
            #self.app.PopupMenu.MenuItem(u‘输出‘).click_input()
            #time.sleep(2) # 2sec
            #self.app[u‘输出‘][u‘输出到Excel表格‘].click()
            
            # 选取时间段, 然后查询
            yyyymm=str(yyyymm)
            y,m=int(yyyymm[:4]), int(yyyymm[-2:])
            ymd1,ymd2 = (y,m,1),self.get_end_of_month(yyyymm)
            self.modify_date_range(ymd1,ymd2)
            outFile = ‘_‘.join([self.fname, cdic[content]])

            
            #也可以直接点击mainDlg里的输出按钮
            main[u‘输出Button‘].click_input()  #会弹出一个"输出"窗口
            
            print self.app[u‘输出‘].Edit.get_line(0)
            self.app[u‘输出‘].Edit.set_edit_text(outFile)
            print self.app[u‘输出‘].Edit.get_line(0)
            # 如何得到 输出文件名 编辑框 控件的id?
            # 用 它的mainDlg的PrintCtrlId()方法来查看:
            # self.app[u‘输出‘].print_control_identifiers()
            
            self.app[u‘输出‘][u‘确定Button‘].click_input() # 保存文件,然后调用Excel读取之
            time.sleep(2)
            close_app(className=‘Notepad‘) #close excel
            if closeAppFlag:
                self.close_client() #close tdx app
            pass
                
            
    def print_ctrl_window_text(self, mainDlg):
        u‘‘‘
        打印主窗口里的控件的明面文本
        ‘‘‘
        ctrl_window_text = [ctrl.window_text() for ctrl in mainDlg.children()]
        for i, txt in enumerate(ctrl_window_text):
            print i, txt
        
    def print_ctrl_fClassName(self, mainDlg):
        u‘‘‘   
        打印主窗口里的控件昵称(控件小名/控件亲切称呼)和控件文本
        备注:
            1. 枚举子控件的方法: children()
            2. 获取控件昵称的方法: .friendly_class_name()
            3. 获取控件文本的方法: .window_text()
        示例: 比如当出现‘发现了新版本‘提示信息窗口时, 
            想知道这个主窗口里面的每一个控件的昵称和控件明面文本.
            >>> tdx=Tdxw()
            >>> tdx.real_login_trade(closeTXSS=False)
            >>> mainDlg=tdx.app.window(title=u‘发现了新版本‘)
            >>> tdx.print_ctrl_fClassName(mainDlg)

Num 控件昵称             控件明面文本    
----------------------------------------          
  0 Button               升级到新版本              
  1 Button               关闭                  
  2 Static               [海通证券彩虹投资(通达信)]新版本V2.13
  3 CheckBox             一星期内不要提醒我           
  4 RICHEDIT   
尊敬的投资者,您好!
    海通证券彩虹投资(通达信)网上交易客户端已发布2.13最新版本,新增支持股转指数、优化资金股份高速刷新等,请您尽快升级。
    同时,我司将于近期停止使用2.03及其以下版本,由此给您带来的不便,敬请谅解!
    详情请咨询海通全国统一客服热线:95553、4008888001(联通用户)或海通e海通财在线客服。
   
    海通证券股份有限公司
    2019-01-15
            
        ‘‘‘
        ctrl_fcns = [ctrl.friendly_class_name() for ctrl in mainDlg.children()]
        ctrl_window_text = [ctrl.window_text() for ctrl in mainDlg.children()]
        print ‘%3s %-16s %-20s‘%(‘Num‘, u‘控件昵称‘, u‘控件明面文本‘)
        print ‘--‘*20
        for i, c in enumerate(ctrl_fcns):
            print ‘%3d %-20s %-20s‘%(i, c , ctrl_window_text[i]    )

    def get_end_of_month(self, yyyymm):
        u‘‘‘
        获取‘某年某月‘的最后一天的日期
        Example:
            >>> get_end_of_month(1, 201902)
            >>> get_end_of_month(1, 201802)
            >>> get_end_of_month(1, 201702)
            >>> get_end_of_month(1, 201602)
            >>> get_end_of_month(1, 201502)
            (2015, 2, 28)
        ‘‘‘
#        yyyymm=201902
        yyyymm=str(yyyymm)
        yyyy,mm=yyyymm[:4], yyyymm[-2:]
        s=str(yyyy)+str(mm)+str(‘05‘)
        fmt=‘%Y%m%d‘
        dt=pd.datetime.strptime(s,fmt)
        e_o_m=dt + pd.tseries.offsets.DateOffset(months=1, days= -dt.day)
        y=e_o_m.year
        m=e_o_m.month
        d=e_o_m.day
        return y,m,d


    def handle_login_failure(self):
        u‘‘‘
        
        ‘‘‘
        h=findwindows.find_windows(class_name=‘#32770‘,process=self.app.process)
        if len(h)>=2:
            print u‘... 登录时有异常情况 ...‘
            dlg=self.app.window(handle=h[0])
            if dlg.exists():
                print dlg.window_text()
                self.print_ctrl_fClassName(dlg)
                print dlg.Static2.window_text()
                dlg[u‘确定‘].click_input()
            
            h=findwindows.find_windows(class_name=‘#32770‘,process=self.app.process)
            dlg=self.app.window(handle=h[0])
            if dlg.exists():
                print dlg.window_text()
                dlg.close()
            
            sys.exit(0)
    

            
    def get_jgd_fwf_width(self):# ifile=r‘d:DB	dxw201707_jgd.txt‘):
        u‘‘‘
        获取交割单txt文件,fwf固定宽度的格式化的表格文件的每列宽度
        >>> get_jgd_fwf_width(1,1)
        ‘‘‘    
        #of=r‘d:DB	dxw201707_jgd.txt‘
        of=self.ifile
    
        with open(of) as fh: # mode的默认为: ‘rb‘
            # 抛弃前两行垃圾    
            line=fh.readline()
            line=fh.readline()
            ss=line=fh.readline()
            print line
            type(line) #str 字节串
            u=line.decode(‘gbk‘) #unicode 字符串
            print len(line), len(u) #不相等的, 如果有中文的话
            assert len(line) != len(u)        
            
            for i,line in enumerate(fh):
                print i, len(line), len(line.decode(‘gbk‘))
                
        # 退出with语句块, (fh会被自动关闭), with语句的好处
        s=‘xb9xc9xb6xabxb4xfaxc2xeb          xb3xc9xbdxbbxc8xd5xc6xda        xd6xa4xc8xafxb4xfaxc2xeb        xd6xa4xc8xafxc3xfbxb3xc6        xbaxcfxcdxacxb1xe0xbaxc5        xb2xd9xd7xf7        xb9xc9xc6xb1xd3xe0xb6xee        xb3xc9xbdxbbxcaxfdxc1xbf        xb3xc9xbdxbbxbcxdbxb8xf1        xb3xc9xbdxbbxbdxf0xb6xee         xd3xb6xbdxf0         xd3xa1xbbxa8xcbxb0        xb9xfdxbbxa7xb7xd1        xbdxe1xcbxe3xb7xd1        xc6xe4xcbxfbxb7xd1        xb1xe4xb6xafxbdxf0xb6xee          xd7xcaxbdxf0xd3xe0xb6xee         xb1xd2xd6xd6          
‘
        assert s==ss
        print s.decode(‘gbk‘)
    #"股东代码          成交日期        证券代码        证券名称        合同编号        操作        股票余额        成交数量        成交价格        成交金额         佣金         印花税        过户费        结算费        其他费        变动金额          资金余额         币种          "
    # 123456789012345678
    #                  1234567890123456
    #                                 1234567890123456   
    #                                                1234567890123456   
    #                                                               1234567890123456   
    #                                                                              123456789012 
    #"股东代码          成交日期        证券代码        证券名称        合同编号        操作        股票余额        成交数量        成交价格        成交金额         佣金         印花税        过户费        结算费        其他费        变动金额          资金余额         币种          "
    #                                                                                          1234567890123456
    #                                                                                                         1234567890123456
    #                                                                                                                        1234567890123456
    #                                                                                                                                       12345678901234567
    #                                                                                                                                                       1234567890123
    #                                                                                                                                                                   12345678901234
        me=[c for c in s.strip().split(‘ ‘) if c !=‘‘]
        print me
        colspecs=[]
        for i,c in enumerate(me):
            if i==0:
                pos1=s.find(c)
            else:
                pos2=s.find(c)
                col= (pos1,pos2)
                print col
                colspecs.append(col)
                pos1=pos2
            
        colspecs.append((pos2,len(s)-1))
    #    print colspecs
    #    print len(colspecs)
        width= [t[1]-t[0] for t in colspecs]
        print width
        
        #return colspecs, width
        self.colspecs,self.width=colspecs,width

    
    def read_jgd_fwf_txt(self, ifile=r‘d:DB	dxw201707_jgd.txt‘):
        u‘‘‘
        >>> tdx=Tdxw()
        >>> tdx.read_jgd_fwf_txt()
        >>> df=tdx.df_jgd
        
        #https://stackoverflow.com/questions/19472566/python-read-fwf-error-dtype-is-not-supported-with-python-fwf-parser
        ‘‘‘
        of=self.ifile=ifile
        self.colspecs=[] # 必须先初始化该 实例变量
        
        #colspecs, width = self.get_jgd_fwf_width()
        self.get_jgd_fwf_width() # will fill colspecs
        to_gbk=lambda x: x.decode(‘gbk‘)
        conver={0:str, 2:str,3:to_gbk, 5:to_gbk, }
        df=pd.read_fwf(of, skiprows=[0,1],
                       colspecs=self.colspecs, 
                       header=0, 
                       converters=conver, 
                       #encoding=‘gbk‘, #没有起作用
                       ) # c 
        
        # 用传递width参数列宽的方式, 读取数据时, 还是有问题???
    #    dfw=pd.read_fwf(of, skiprows=[0,1],width=width, header=0, converters={0:str, 2:str},) # c 
    #    assert df.values==dfw.values
    #    assert df.shape == dfw.shape
    
        df.columns= [c.decode(‘gbk‘) for c in df.columns]
        
        df=df.drop(labels=[u‘结算费‘,u‘其他费‘,u‘币种‘], axis=1)
        #array2d = df.values
    
    # 在读取时, 利用converter参数, 传值一个转换函数的字典, 可以避免之后的列数据转换
    #    df[u‘证券名称‘] = [v.decode(‘gbk‘) for v in df[u‘证券名称‘]]
    #    df[u‘操作‘] = [v.decode(‘gbk‘) for v in df[u‘操作‘]]
        # dtype 再搞一搞就行了!!!
        
        self.df_jgd=df
    
#%%    
def close_app(className=‘XLMAIN‘):    
    u‘‘‘
    close excel app started within tdx app
    Note:
        ‘XLMAIN‘ for excel app
        ‘Notepad‘ for 记事本app
    ‘‘‘
    xl_handle=findwindows.find_window(class_name=className)
    if xl_handle:
        xlsApp=Application().connect(handle=xl_handle)
        xlsApp.window().close()
        
        
#%%
#def query_jgd():
#    tdx=Tdxw()
#    tdx.get_query_result(content=86, yyyymm=201707 )   
#    tdx.get_query_result(content=87, yyyymm=201707)    
#    tdx.get_query_result(content=84, yyyymm=201707,)    
#    tdx.get_query_result(content=84, yyyymm=201707,closeAppFlag=True)    
        
#%%
#query_jgd()






以上是关于Automate Tdxw的主要内容,如果未能解决你的问题,请参考以下文章

Power Automate 创建 SharePoint Online 列表项目

Power Automate 创建 SharePoint Online 列表项目

一文讲透为Power Automate for Desktop (PAD) 实现自定义模块

Power automate怎么看批到哪里了?

power automate回响

power automate 怎么暂停