告别重复操作:用SAP Scripting Tracker + Python实现F-02凭证自动录入(附完整代码)
SAP财务自动化实战用PythonSAP Scripting Tracker实现F-02凭证批量录入财务部门的同事每个月都要重复录入数百张会计凭证这种枯燥的手工操作不仅效率低下还容易出错。作为一名SAP自动化顾问我最近用PythonSAP Scripting Tracker为某客户开发了一套自动化解决方案将凭证录入时间从8小时缩短到15分钟。下面分享这个项目的完整实现过程。1. 环境准备与工具链搭建1.1 SAP Scripting Tracker的安装与配置SAP Scripting Tracker是替代传统SAP GUI Scripting的轻量级工具支持多种编程语言输出。安装时需注意从官网下载最新版本当前为2.3.1解压后仔细阅读Tracker.pdf文档确保SAP GUI已安装Scripting组件关键配置步骤# 验证SAP GUI脚本功能是否启用 import win32com.client gui win32com.client.Dispatch(SAPGUI.ScriptingCtrl.1) print(gui.IsScriptingEnabled) # 应返回True1.2 Python环境准备推荐使用Anaconda管理Python环境需安装以下包conda create -n sap-auto python3.8 conda activate sap-auto pip install pandas pywin32 openpyxl2. 凭证数据标准化处理2.1 Excel数据模板设计设计合理的输入模板是自动化的前提。我们的模板包含以下字段字段名类型必填示例值凭证编号文本是F20230001过账日期日期是2023-07-15公司代码文本是1000货币文本是CNY行项目数字是1过账码数字是40科目文本是10010100金额数字是5000.002.2 数据预处理代码使用pandas进行数据清洗和校验import pandas as pd from datetime import datetime def validate_data(df): # 检查必填字段 required_cols [凭证编号,过账日期,公司代码,货币,行项目,过账码,科目,金额] if not all(col in df.columns for col in required_cols): raise ValueError(缺少必填字段) # 日期格式转换 try: df[过账日期] pd.to_datetime(df[过账日期]).dt.strftime(%Y.%m.%d) except: raise ValueError(日期格式错误) # 金额校验 if (df[金额] 0).any(): raise ValueError(金额必须大于0) return df3. SAP操作脚本开发3.1 基础会话管理模块创建SapSession.py作为核心工具模块import sys import win32com.client from functools import wraps def sap_connection_check(func): wraps(func) def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except Exception as e: print(f操作失败: {str(e)}) return None return wrapper sap_connection_check def get_session(): SapGuiAuto win32com.client.GetObject(SAPGUI) application SapGuiAuto.GetScriptingEngine() connection application.Children(0) return connection.Children(0) def back_to_home(session): session.findById(wnd[0]/tbar[0]/okcd).text /n session.findById(wnd[0]).sendVKey(0)3.2 F-02凭证录入脚本基于录制的脚本进行增强开发from SapSession import get_session, back_to_home import pandas as pd class SAPF02Automation: def __init__(self, excel_path): self.data self.load_data(excel_path) self.session get_session() def load_data(self, path): df pd.read_excel(path) return df.groupby(凭证编号).apply(lambda x: x.to_dict(records)).to_dict() def enter_header(self, doc_data): self.session.findById(wnd[0]/usr/ctxtBKPF-BLDAT).text doc_data[0][过账日期] self.session.findById(wnd[0]/usr/ctxtBKPF-BUKRS).text doc_data[0][公司代码] self.session.findById(wnd[0]/usr/ctxtBKPF-BUDAT).text doc_data[0][过账日期] self.session.findById(wnd[0]/usr/ctxtBKPF-WAERS).text doc_data[0][货币] def enter_line_item(self, item): self.session.findById(wnd[0]/usr/ctxtRF05A-NEWBS).text str(item[过账码]) self.session.findById(wnd[0]/usr/ctxtRF05A-NEWKO).text item[科目] self.session.findById(wnd[0]).sendVKey(0) self.session.findById(wnd[0]/usr/txtBSEG-WRBTR).text f{item[金额]:.2f} def process_all(self): try: for doc_id, items in self.data.items(): back_to_home(self.session) self.session.findById(wnd[0]/tbar[0]/okcd).text F-02 self.session.findById(wnd[0]).sendVKey(0) self.enter_header(items) for item in items: self.enter_line_item(item) # 模拟并过账 self.session.findById(wnd[0]/mbar/menu[0]/menu[3]).select() self.session.findById(wnd[0]/tbar[0]/btn[11]).press() finally: back_to_home(self.session)4. 异常处理与日志系统4.1 常见错误处理方案在实际运行中可能遇到的典型问题会话超时定期发送空操作保持连接字段校验错误捕获特定错误消息系统响应延迟增加智能等待机制改进后的错误处理代码def safe_sap_call(func): def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except Exception as e: if No object found in str(e): print(界面元素未找到请检查屏幕状态) elif is busy in str(e): print(系统响应超时) else: print(f未知错误: {str(e)}) raise return wrapper4.2 操作日志记录使用Python标准库实现日志记录import logging from logging.handlers import RotatingFileHandler def setup_logger(): logger logging.getLogger(sap_auto) logger.setLevel(logging.INFO) handler RotatingFileHandler( sap_automation.log, maxBytes1024*1024, backupCount5 ) formatter logging.Formatter( %(asctime)s - %(levelname)s - %(message)s ) handler.setFormatter(formatter) logger.addHandler(handler) return logger5. 性能优化与批量处理5.1 多凭证并行处理方案对于大批量凭证可采用以下优化策略凭证分组按公司代码/货币分组处理缓存重用重复使用的字段值只设置一次延迟提交积累多个凭证后批量提交优化后的处理逻辑def batch_process(docs, batch_size10): for i in range(0, len(docs), batch_size): batch docs[i:ibatch_size] try: with SAPSession() as session: processor DocumentProcessor(session) processor.process_batch(batch) except Exception as e: log_error(f批处理失败: {str(e)}) continue5.2 执行效率对比测试数据100张凭证每张2行处理方式耗时错误率手工录入240分钟3-5%基础脚本45分钟1-2%优化方案12分钟0.1%6. 项目部署与维护6.1 打包为可执行文件使用PyInstaller创建独立exepyinstaller --onefile --iconsap.ico sap_auto.py6.2 创建配置文件config.ini示例[paths] input_folder C:\sap_input archive_folder C:\sap_archive log_file C:\logs\sap_auto.log [sap] default_company 1000 default_currency CNY7. 实际应用案例在某制造业客户实施时我们遇到了特殊需求需要根据成本中心自动分配税务科目某些凭证需要添加特定的文本说明对银行科目需要额外校验解决方案是在数据预处理阶段添加业务规则def apply_business_rules(df): # 成本中心税务映射 tax_mapping { 1001: 22210101, 2001: 22210102 } df[税务科目] df[成本中心].map(tax_mapping) # 添加默认文本 df.loc[df[科目].str.startswith(6), 文本] 费用类科目 return df8. 扩展应用方向这套框架还可用于物料主数据维护MM01供应商发票校验MIRO销售订单创建VA01报表自动导出各种事务码只需修改核心处理逻辑基础框架可完全复用。例如物料创建的类结构class SAPMM01Automation(SAPBase): def __init__(self): super().__init__() def create_material(self, mat_data): self.start_transaction(MM01) self.set_value(MATNR, mat_data[物料编号]) # ...其他字段设置 self.save()9. 安全注意事项凭证管理不要在代码中硬编码SAP密码访问控制限制脚本执行权限日志脱敏敏感信息需过滤版本管理使用Git管理代码变更推荐的安全实践from dotenv import load_dotenv import os load_dotenv() SAP_CREDENTIALS { user: os.getenv(SAP_USER), pass: os.getenv(SAP_PASS) }10. 持续改进建议在实际运行三个月后我们收集了以下优化点增加邮件通知功能当处理完成或出错时自动发送报告开发Web界面方便财务人员自助上传文件集成OCR模块支持扫描件识别添加自动化测试套件确保脚本可靠性改进后的架构示意图[Excel上传] → [预处理服务] → [SAP自动化引擎] → [结果通知] ↑ ↓ ↓ [Web界面] [日志分析] [异常处理]这套方案在某集团企业实施后财务部门每月节省了超过200人工小时准确率提升到99.9%以上。最大的收获不是技术本身而是通过自动化释放了财务人员的创造力让他们能专注于更有价值的分析工作。