首页 > 编程语言 >python 通过直接操控窗口实现开票软件的快速辅助输入工具。

python 通过直接操控窗口实现开票软件的快速辅助输入工具。

时间:2022-11-23 19:37:48浏览次数:49  
标签:辅助输入 python 开票 VK value grid win32con SendMessage WM


背景: 深增值税开票软件在填入发票的明细时(2016年),没有从exce导入的功能,只能手工一个一个输入,对于明细清单数量多的情况,给财务人员带来过多的工作量。所以考虑做一个辅助输入工具。减轻财务的工作量,降低手工输入的出错率。

思路如下: 发票清单 Excel 格式如下, 因为开票的清单来自于销售的出货清单,都是excel格式(从sap导出的),处理起来很方便,所以也延续用Excel格式。

python 通过直接操控窗口实现开票软件的快速辅助输入工具。_实现原理

软件功能需要,实现将上面的清单,自动填入到,深增开软件的 清单填开 表格内。 实现原理也很简单,用程序来模拟手工输入过程,控制光标移动。 同一客户,可以连续打印发票。

选好 excel文件,然后层入。看以下效果图:  

python 通过直接操控窗口实现开票软件的快速辅助输入工具。_实现原理_02

python 通过直接操控窗口实现开票软件的快速辅助输入工具。_python_03

完整代码如下。用了pywin32 来操作窗口,完成光标移动,数据输入。

#!/usr/bin/python
# -*- coding: gbk -*-

# KaiPiaoHaoPengYou.py
#
# Copyright (C) 2016 - xulong <[email protected]>
#

import sys
from ctypes import *
import time
import win32con
import win32api
import win32ui
import wx
import xlrd
import win32gui
import sys
wildcard = "Excel (*.xls)|*.xls"

class MainFrame(wx.Frame):
def __init__(self,*agrs,**kw):
wx.Frame.__init__(self,size=(480,200),*agrs,**kw)
l1=wx.StaticText(self,-1,u"提示:请先启动开票软件,并确定打开了'清单填开' 窗口!!!",(30,100))
l1.SetForegroundColour("Red")
self.t1=wx.TextCtrl(self,-1,"",(30,50),size=(200,-1))

b1=wx.Button(self,-1,u"选择清单文件(EXCEL)",(230,50))
self.Bind(wx.EVT_BUTTON,self.b1Click,b1)

b2=wx.Button(self,-1,u"开始填写",(370,50))
self.Bind(wx.EVT_BUTTON,self.b2Click,b2)


def b1Click(self,evt):
text = self.t1.GetValue()
dlg = wx.FileDialog(self,message=u"选择清单Excel文件",
defaultFile=text , wildcard=wildcard,style=wx.FD_OPEN |wx.FD_CHANGE_DIR)
if dlg.ShowModal() == wx.ID_OK:
text = dlg.GetPath()
self.t1.SetValue(text)

dlg.Destroy()



def b2Click(self,evt):
self.parsexsl(self.t1.GetValue())


def parsexsl(self,filename):
book = None
try:
book=xlrd.open_workbook(filename)
except IOError as e:
pass;

#print ("数据提示:")
if book == None :
wx.MessageBox(message=u"Excel文件不能正常读,确认格式,文件名有误!!",caption=u"提示",parent=self)
return

sheet1 = book.sheet_by_index(0)

#清单行数
nrows = sheet1.nrows
#清单列数
ncols = sheet1.ncols



for rownum in range(1,nrows):
#print ('row',rownum )


#print ("行:",rownum + 1," ",rowline,"\r")
if "%s"%sheet1.cell(rownum,0).value == '---':
message = u"遇到换票标识行(---),需要换票,请检查当前发票无误后,重新填写新发票回到'清单填开'界面,点[确定]后继续\r"
dlg = wx.MessageDialog(self, message, u"提2示", wx.OK|wx.STAY_ON_TOP)
dlg.ShowModal()
continue

f=None
try:
f=win32ui.FindWindow(None,"清单填开")
except win32ui.error as e:
wx.MessageBox(message=u"提示:请先启动开票软件,并确定打开了'清单填开' 窗口",caption=u"提示",parent=self)
return

#取开票软件的窗口类名,此开票软件的类名后辍部分会随机的变化。故需动态取后辍,后续用其拼接其它子窗口的类名。
cln=win32gui.GetClassName(f.GetSafeHwnd())
prex=cln[29:]
#print (prex)


#get main window handle.
win=win32ui.FindWindow("WindowsForms10.Window.8.app.0"+prex,u"清单填开")

#get second level window handle
win2=win32ui.FindWindowEx(win,None,"WindowsForms10.Window.8.app.0"+prex,u"清单填开")


#get grid's parent window
win3=win32ui.FindWindowEx(win2,None,"WindowsForms10.Window.8.app.0"+prex,"")

#get grid's handle
grid=win32ui.FindWindowEx(win3,None,"WindowsForms10.Window.8.app.0"+prex,"")

print 'grid:%x,win3:%x'%(grid.GetSafeHwnd(),win3.GetSafeHwnd())

#fill one line of grid
#move the cursor back to firt cell ,using allow left key
grid.SendMessage(win32con.WM_KEYDOWN, win32con.VK_LEFT, 0)
grid.SendMessage(win32con.WM_KEYUP, win32con.VK_LEFT, 0)

grid.SendMessage(win32con.WM_KEYDOWN, win32con.VK_LEFT, 0)
grid.SendMessage(win32con.WM_KEYUP, win32con.VK_LEFT, 0)

grid.SendMessage(win32con.WM_KEYDOWN, win32con.VK_LEFT, 0)
grid.SendMessage(win32con.WM_KEYUP, win32con.VK_LEFT, 0)

grid.SendMessage(win32con.WM_KEYDOWN, win32con.VK_LEFT, 0)
grid.SendMessage(win32con.WM_KEYUP, win32con.VK_LEFT, 0)

grid.SendMessage(win32con.WM_KEYDOWN, win32con.VK_LEFT, 0)
grid.SendMessage(win32con.WM_KEYUP, win32con.VK_LEFT, 0)

grid.SendMessage(win32con.WM_KEYDOWN, win32con.VK_LEFT, 0)
grid.SendMessage(win32con.WM_KEYUP, win32con.VK_LEFT, 0)

grid.SendMessage(win32con.WM_KEYDOWN, win32con.VK_LEFT, 0)
grid.SendMessage(win32con.WM_KEYUP, win32con.VK_LEFT, 0)

grid.SendMessage(win32con.WM_KEYDOWN, win32con.VK_LEFT, 0)
grid.SendMessage(win32con.WM_KEYUP, win32con.VK_LEFT, 0)





#first column
grid.SendMessage(win32con.WM_KEYDOWN, win32con.VK_F2, 0)
grid.SendMessage(win32con.WM_KEYUP, win32con.VK_F2, 0)
cp1=win32ui.FindWindowEx(grid,None,"WindowsForms10.Window.8.app.0"+prex,"")
tb=win32ui.FindWindowEx(cp1,None,"WindowsForms10.EDIT.app.0"+prex,None)
print 'tb:%x,cpl:%x'%(tb.GetSafeHwnd(),cp1.GetSafeHwnd())
tb.SendMessage(win32con.WM_SETTEXT,sheet1.cell(rownum,0).value.encode('gbk','ignore'))
#tb.SendMessage(win32con.WM_SETTEXT,'测试1')
#print (sheet1.cell(rownum,0).value)

#second
grid.SendMessage(win32con.WM_KEYDOWN, win32con.VK_TAB, 0)
grid.SendMessage(win32con.WM_KEYUP, win32con.VK_TAB, 0)
grid.SendMessage(win32con.WM_KEYDOWN, win32con.VK_F2, 0)
grid.SendMessage(win32con.WM_KEYUP, win32con.VK_F2, 0)

print 'grid:%x,cpl:%x'%(grid.GetSafeHwnd(),cp1.GetSafeHwnd())
cp2=win32ui.FindWindowEx(grid,cp1,"WindowsForms10.Window.8.app.0"+prex,"")
print '2'
tb2=win32ui.FindWindowEx(cp2,None,"WindowsForms10.EDIT.app.0"+prex,None)
#tb2.SendMessage(win32con.WM_SETTEXT,'测试2')
value = sheet1.cell(rownum,1).value.encode('gbk','ignore')
if value.endswith(".0"):
value = value[:-2]
if value.endswith(".00"):
value = value[:-3]
tb2.SendMessage(win32con.WM_SETTEXT,value)
#print (sheet1.cell(rownum,1).value)

#3th
grid.SendMessage(win32con.WM_KEYDOWN, win32con.VK_TAB, 0)
grid.SendMessage(win32con.WM_KEYUP, win32con.VK_TAB, 0)
grid.SendMessage(win32con.WM_KEYDOWN, win32con.VK_F2, 0)
grid.SendMessage(win32con.WM_KEYUP, win32con.VK_F2, 0)
cp2=win32ui.FindWindowEx(grid,cp1,"WindowsForms10.Window.8.app.0"+prex,"")
tb2=win32ui.FindWindowEx(cp2,None,"WindowsForms10.EDIT.app.0"+prex,None)

#tb2.SendMessage(win32con.WM_SETTEXT,'测试3')
tb2.SendMessage(win32con.WM_SETTEXT,sheet1.cell(rownum,2).value.encode('gbk','ignore'))
#print (sheet1.cell(rownum,2).value)

#4th
grid.SendMessage(win32con.WM_KEYDOWN, win32con.VK_TAB, 0)
grid.SendMessage(win32con.WM_KEYUP, win32con.VK_TAB, 0)
grid.SendMessage(win32con.WM_KEYDOWN, win32con.VK_F2, 0)
grid.SendMessage(win32con.WM_KEYUP, win32con.VK_F2, 0)
cp2=win32ui.FindWindowEx(grid,cp1,"WindowsForms10.Window.8.app.0"+prex,"")
tb2=win32ui.FindWindowEx(cp2,None,"WindowsForms10.EDIT.app.0"+prex,None)
#tb2.SendMessage(win32con.WM_SETTEXT,'4')
value = str(sheet1.cell(rownum,3).value).encode('gbk','ignore')
if value.endswith(".0"):
value = value[:-2]
if value.endswith(".00"):
value = value[:-3]
tb2.SendMessage(win32con.WM_SETTEXT,value)
#print (sheet1.cell(rownum,3).value)

#5th
grid.SendMessage(win32con.WM_KEYDOWN, win32con.VK_TAB, 0)
grid.SendMessage(win32con.WM_KEYUP, win32con.VK_TAB, 0)
grid.SendMessage(win32con.WM_KEYDOWN, win32con.VK_F2, 0)
grid.SendMessage(win32con.WM_KEYUP, win32con.VK_F2, 0)
cp2=win32ui.FindWindowEx(grid,cp1,"WindowsForms10.Window.8.app.0"+prex,"")
tb2=win32ui.FindWindowEx(cp2,None,"WindowsForms10.EDIT.app.0"+prex,None)
#tb2.SendMessage(win32con.WM_SETTEXT,'5')
tb2.SendMessage(win32con.WM_SETTEXT,str(sheet1.cell(rownum,4).value).encode('gbk','ignore'))
#print (sheet1.cell(rownum,4).value)

grid.SendMessage(win32con.WM_KEYDOWN, win32con.VK_TAB, 0)
grid.SendMessage(win32con.WM_KEYUP, win32con.VK_TAB, 0)

grid.SendMessage(win32con.WM_KEYDOWN, win32con.VK_TAB, 0)
grid.SendMessage(win32con.WM_KEYUP, win32con.VK_TAB, 0)

grid.SendMessage(win32con.WM_KEYDOWN, win32con.VK_TAB, 0)
grid.SendMessage(win32con.WM_KEYUP, win32con.VK_TAB, 0)

#fill one line of grid

#move the cursor to next line . using RETURN key
if rownum < ( nrows -1 ):
win32api.Sleep(3)
grid.PostMessage(win32con.WM_KEYDOWN, win32con.VK_RETURN, 0)
grid.PostMessage(win32con.WM_KEYUP, win32con.VK_RETURN, 0)
win32api.Sleep(3)

class MyApp(wx.App):
pass






if __name__ == '__main__':
app=MyApp()
frame=MainFrame(None,title=u"开票助手")
frame.Show(True)
app.MainLoop()

标签:辅助输入,python,开票,VK,value,grid,win32con,SendMessage,WM
From: https://blog.51cto.com/fangkailove/5881710

相关文章

  • Python:企业微信批量发工资条工具 -应用消息发送模块
    16年python练手,开发了采用企业微信批量发工资条的程序,其中对企业微信发消息的功能做了包装。在此记录和分享一下。整体程序,使用了wxPythonGUI,以excel来存放数据和消息......
  • Python 爬虫2例:爬网络小说
    程序逻辑:按给出的第一章节URL,抓HTML,然后通过正则表达式,取出小说章节的标题、正文、下章节的URL,然后跳转到下一章节,不断循环处理。取出的正文写入文本文件。同时记录每......
  • Python 爬虫:喜马拉雅FM音频(这个还能不载,试了一下其它下载工具都不行了)
    现在是3:35分,花了整晚时间,写了个喜马拉雅FM音频爬虫,顺便熟悉了一下tkinterGUI效果图:已打包的工具可以在下面下载:链接:​​https://pan.baidu.com/s/1jJ50I4vlJyRtVFXR......
  • python 爬虫 试了五种爬喜马的方法并做了测试代码(爬虫系列研究告一段落了...)
    先介绍一下我想到和测试了的五种方法: 方法1,使用下面接口:    通过web_api'http://m.ximalaya.com/m-revision/page/album/queryAlbumPage/%s?pageSize=1000'%al......
  • Python 处理输入法字库(五笔极点字库转小鸭字库)
    一直都是用的小鸭五笔,091新字库是极点格式的,刚开始懒得动,直接用极点五笔了,用了一段时间碰到很多问题.其中最坑的是.在tkinterGui里极点输入不能退格,一退格就乱码( ......
  • Python 统计学生总分
    输入学生的学号、姓名以及语文、数学、外语成绩,统计每个学生的总分,并按总分升序输出所有学生的学号、姓名和总分。输入格式:输入若干行数据,每一行数据分别为学号、姓名以......
  • vim-python全能补全与python环境变量设置
    vim针对python的万能补全对于python自带的模块库都能够正常使用全能补全,但一些自定义的模块却不行,这是因为vim当前进程需要找到相应模块并做导入分析获取补全用的词......
  • Python的GET和POST请求
    引入requests包注:发送请求(包括请求行、方法类型、头、体)&常见的请求方式有get、post、put、delete一、发送get请求格式:requests.get()(内容:url必填;params选填:u......
  • 6. python和Redis交互
    1安装包pipinstallredis2引入模块fromredisimport*这个模块中提供了StrictRedis对象(Strict严格),用于连接redis服务器,并按照不同类型提供了不同方法,进行交互操作......
  • Python 性能检测分析方法 - 时间、空间衡量方法
    性能检测分析方法-时间、空间衡量方法Python自带模块importtime点击查看代码#仅仅是示范time模块的用法,此段不能直接运行,运行请看测试项目源码importtime......