python SAP自动化并发送html outlook邮件

import time
import win32com.client
import pandas as pd
import locale
import sys
from datetime import datetime
import win32com.client as win32


# 获取当前日期和时间
now = datetime.now()
# 将日期格式化为 "dd.mm.yyyy"
formatted_date = now.strftime("%d.%m.%Y")


def output_session():
    # 获取SAP GUI对象
    SapGuiAuto = win32com.client.GetObject("SAPGUI")
    # 获取SAP应用程序对象
    application = SapGuiAuto.GetScriptingEngine
    # 获取连接对象
    connection = application.Children(0)
    # 获取会话对象
    session = connection.Children(0)
    return session


def is_clear_item(session):
    # 此函数取消使用
    # 判断是否只有一条数据
    all_number = session.findById("wnd[0]/usr/tabsTS/tabpREST/ssubPAGE:SAPDF05X:6102/txtRF05A-ANZPO").text
    print("Number of items: " + all_number)
    if all_number == "1":
        print("No items to clear")
        return "No items to clear"
    # 判断是否有可清项
    haveNegativeItem = False
    havePositiveItem = False
    row_count = 0
    for index in range(int(all_number)):
        if row_count == 20:
            # 点击Next Page
            session.findById("wnd[0]").maximize
            session.findById("wnd[0]").sendVKey(23)
            time.sleep(2)
            row_count = 0
        # 读取日期
        Amount = session.findById(f"wnd[0]/usr/tabsTS/tabpREST/ssubPAGE:SAPDF05X:6102/tblSAPDF05XTC_6106/txtDF05B-PSBET[9,{str(row_count)}]").text
        print("Amount: " + Amount)
        if "-" in str(Amount):
            haveNegativeItem = True
        elif "-" not in str(Amount):
            havePositiveItem = True
        elif haveNegativeItem and havePositiveItem:
            break
        else:
            pass
        row_count += 1
    if not haveNegativeItem:
        print("No negative items to clear")
        return haveNegativeItem
    if not havePositiveItem:
        print("No positive items to clear")
        return havePositiveItem


def net_data(session):
    # 选择第六列第0行日期-点击排序
    session.findById("wnd[0]/usr/tabsTS/tabpREST").select()
    session.findById("wnd[0]/usr/tabsTS/tabpREST/ssubPAGE:SAPDF05X:6106/tblSAPDF05XTC_6106/ctxtRFOPS_DK-NETDT[7,0]").setFocus()
    session.findById("wnd[0]/usr/tabsTS/tabpREST/ssubPAGE:SAPDF05X:6106/btnICON_SORT_UP").press()


def do_clear_item(session):
    """
    如果总金额为负数,先选择所有正数
    :param session:
    :return:
    """
    # 总条数
    row_count = 0
    all_number = session.findById("wnd[0]/usr/tabsTS/tabpMAIN/ssubPAGE:SAPDF05X:6102/txtRF05A-ANZPO").text
    all_money = session.findById("wnd[0]/usr/tabsTS/tabpMAIN/ssubPAGE:SAPDF05X:6102/txtRF05A-NETTO").text
    if float(str(all_money).replace("-", "").strip().replace(",","")) == 0:
        print("amount is 0")
        # 点击 charge off dis
        session.findById("wnd[0]/tbar[1]/btn[7]").press()
        # reference
        session.findById("wnd[0]/usr/txtBKPF-XBLNR").text = "JD_AR_CLEARING"
        # PstKy
        session.findById("wnd[0]/usr/ctxtRF05A-NEWBS").text = ""
        # Account
        session.findById("wnd[0]/usr/ctxtRF05A-NEWKO").text = ""
        time.sleep(1)

    else:
        is_click = False
        # 不选中所有行
        session.findById("wnd[0]/usr/tabsTS/tabpMAIN/ssubPAGE:SAPDF05X:6102/btnICON_SELECT_ALL").press()
        session.findById("wnd[0]/usr/tabsTS/tabpMAIN/ssubPAGE:SAPDF05X:6102/btnIC_Z-").press()

        if "-" in all_money:
            # 正数先排序
            session.findById("wnd[0]/usr/tabsTS/tabpREST/ssubPAGE:SAPDF05X:6102/tblSAPDF05XTC_6102/txtDF05B-PSBET[9,0]").setFocus()
            session.findById("wnd[0]/usr/tabsTS/tabpREST/ssubPAGE:SAPDF05X:6102/btnICON_SORT_DOWN").press()
        else:
            # 负数先排序
            session.findById("wnd[0]/usr/tabsTS/tabpREST/ssubPAGE:SAPDF05X:6102/tblSAPDF05XTC_6102/txtDF05B-PSBET[9,0]").setFocus()
            session.findById("wnd[0]/usr/tabsTS/tabpREST/ssubPAGE:SAPDF05X:6102/btnICON_SORT_UP").press()

        for index in range(int(all_number)):
            # 选中所有正数
            if row_count == 20:
                # 点击Next Page
                session.findById("wnd[0]").maximize
                session.findById("wnd[0]").sendVKey(23)
                row_count = 0
            Amount = session.findById(f"wnd[0]/usr/tabsTS/tabpREST/ssubPAGE:SAPDF05X:6102/tblSAPDF05XTC_6102/txtDF05B-PSBET[9,{row_count}]").text

            # 如果总金额为负数,先选中所有正数;如果总金额为正数,先选中所有负数
            if "-" in all_money:
                if "-" not in str(Amount):
                    session.findById(f"wnd[0]/usr/tabsTS/tabpREST/ssubPAGE:SAPDF05X:6102/tblSAPDF05XTC_6102/txtDF05B-PSBET[9,{row_count}]").setFocus()
                    session.findById("wnd[0]").sendVKey(2)
                    is_click = True
                else:
                    net_data(session)
                    break

            else:
                if "-" in str(Amount):
                    session.findById(f"wnd[0]/usr/tabsTS/tabpREST/ssubPAGE:SAPDF05X:6102/tblSAPDF05XTC_6102/txtDF05B-PSBET[9,{row_count}]").setFocus()
                    session.findById("wnd[0]").sendVKey(2)
                    is_click = True
                else:
                    net_data(session)
                    break

            row_count += 1

        if is_click:
            print("Have items to clear")
        else:
            print("Clearing is not supported")
            return "NO Clearing is not supported"

        # 恢复到第一行
        session.findById("wnd[0]/usr/tabsTS/tabpREST/ssubPAGE:SAPDF05X:6106/txtRF05A-ABPOS").text = "1"
        session.findById("wnd[0]/usr/tabsTS/tabpREST/ssubPAGE:SAPDF05X:6106/txtRF05A-ABPOS").setFocus()
        session.findById("wnd[0]").sendVKey(2)

        row_count = 0

        for index in range(int(all_number)):
            # 选中所有负数
            if row_count == 20:
                # 点击Next Page
                session.findById("wnd[0]").maximize
                session.findById("wnd[0]").sendVKey(23)
                row_count = 0
            Amount = session.findById(f"wnd[0]/usr/tabsTS/tabpREST/ssubPAGE:SAPDF05X:6106/tblSAPDF05XTC_6106/txtDF05B-PSBET[9,{row_count}]").text
            if "-" in all_money:
                # 选中所有负数
                if "-" in str(Amount):
                    session.findById(f"wnd[0]/usr/tabsTS/tabpREST/ssubPAGE:SAPDF05X:6106/tblSAPDF05XTC_6106/txtDF05B-PSBET[9,{row_count}]").setFocus()
                    session.findById("wnd[0]").sendVKey(2)

                    # 判断当前差额
                    Assigned = session.findById("wnd[0]/usr/tabsTS/tabpREST/ssubPAGE:SAPDF05X:6106/txtRF05A-NETTO").text
                    print(Assigned)
                    if float(str(Assigned).replace("-", "").strip().replace(",","")) <= 1 and float(str(Assigned).replace("-", "").strip().replace(",","")) != 0:
                        # 点击 charge off dis
                        session.findById("wnd[0]/tbar[1]/btn[7]").press()
                        # PstKy
                        session.findById("wnd[0]/usr/ctxtRF05A-NEWBS").text = "50"
                        # Account
                        session.findById("wnd[0]/usr/ctxtRF05A-NEWKO").text = "67432000"
                        # reference
                        session.findById("wnd[0]/usr/txtBKPF-XBLNR").text = "JD_AR_CLEARING"
                        session.findById("wnd[0]").sendVKey(2)
                        # Amount
                        session.findById("wnd[0]/usr/txtBSEG-WRBTR").text = float(str(Assigned).replace("-", "").strip().replace(",",""))
                        # Cost Center
                        session.findById("wnd[0]/usr/subBLOCK:SAPLKACB:1015/ctxtCOBL-KOSTL").text = "S105"

                        break
                    if "-" in Assigned:
                        session.findById(f"wnd[0]/usr/tabsTS/tabpREST/ssubPAGE:SAPDF05X:6106/tblSAPDF05XTC_6106/txtDF05B-PSDIF[10,{row_count}]").setFocus()
                        session.findById("wnd[0]").sendVKey(2)
                        # 点击 charge off dis
                        session.findById("wnd[0]/tbar[1]/btn[7]").press()
                        # reference
                        session.findById("wnd[0]/usr/txtBKPF-XBLNR").text = "JD_AR_CLEARING"
                        # PstKy
                        session.findById("wnd[0]/usr/ctxtRF05A-NEWBS").text = ""
                        # Account
                        session.findById("wnd[0]/usr/ctxtRF05A-NEWKO").text = ""
                        time.sleep(1)
                        break

            else:
                # 选中所有正数
                if "-" not in str(Amount):
                    session.findById(f"wnd[0]/usr/tabsTS/tabpREST/ssubPAGE:SAPDF05X:6106/tblSAPDF05XTC_6106/txtDF05B-PSBET[9,{row_count}]").setFocus()
                    session.findById("wnd[0]").sendVKey(2)
                    # 判断当前差额
                    Assigned = session.findById("wnd[0]/usr/tabsTS/tabpREST/ssubPAGE:SAPDF05X:6106/txtRF05A-NETTO").text
                    print(Assigned)
                    if float(str(Assigned).replace("-", "").strip().replace(",","")) <= 1 and float(str(Assigned).replace("-", "").strip().replace(",","")) != 0:
                        # 点击 charge
                        session.findById("wnd[0]/tbar[1]/btn[7]").press()
                        # PstKy
                        session.findById("wnd[0]/usr/ctxtRF05A-NEWBS").text = "50"
                        # Account
                        session.findById("wnd[0]/usr/ctxtRF05A-NEWKO").text = "67432000"
                        # reference
                        session.findById("wnd[0]/usr/txtBKPF-XBLNR").text = "JD_AR_CLEARING"
                        session.findById("wnd[0]").sendVKey(2)
                        # Amount
                        session.findById("wnd[0]/usr/txtBSEG-WRBTR").text = float(str(Assigned).replace("-", "").strip().replace(",", ""))
                        # Cost Center
                        session.findById("wnd[0]/usr/subBLOCK:SAPLKACB:1015/ctxtCOBL-KOSTL").text = "S105"
                        break
                    if "-" not in Assigned:
                        session.findById(f"wnd[0]/usr/tabsTS/tabpREST/ssubPAGE:SAPDF05X:6106/tblSAPDF05XTC_6106/txtDF05B-PSDIF[10,{row_count}]").setFocus()
                        session.findById("wnd[0]").sendVKey(2)
                        # 点击 charge off difference
                        session.findById("wnd[0]/tbar[1]/btn[7]").press()
                        # reference
                        session.findById("wnd[0]/usr/txtBKPF-XBLNR").text = "JD_AR_CLEARING"
                        # PstKy
                        session.findById("wnd[0]/usr/ctxtRF05A-NEWBS").text = ""
                        # Account
                        session.findById("wnd[0]/usr/ctxtRF05A-NEWKO").text = ""
                        break

            row_count += 1

    # 点击save
    session.findById("wnd[0]/tbar[0]/btn[11]").press()
    time.sleep(1)
    status = session.findById("wnd[0]/sbar/pane[0]").text
    # status = "YES TEST SUCCESSFUL"
    if "was posted in company" in status:
        return "YES" + status
    else:
        return "NO" + status


def handling_clear_5523(excel_BL5N, Tomail):
    # 创建结果表
    column_names = ["Execute Result in SAP including Document", "Sequence", "Account"]
    error_DT = pd.DataFrame(columns=column_names)
    correct_DT = pd.DataFrame(columns=column_names)

    # 初始时间
    start_time = datetime.now()
    # 连接sap
    session = output_session()
    # 读取BL5N数据
    BL5N_DT = pd.read_excel(excel_BL5N)
    # 获取所有account,并去重
    Accounts = BL5N_DT["Account"].values.tolist()
    unique_accounts = list(set(Accounts))

    error_sequence = 1
    correct_sequence = 1

    for account in unique_accounts:
        lst = BL5N_DT[BL5N_DT["Account"] == account]["Amount in doc. curr."].tolist()
        all_positive = all(float(str(x).replace(",", "")) > 0 for x in lst)
        all_negative = all(float(str(x).replace(",", "")) < 0 for x in lst)
        if all_positive or all_negative:
            print("All items are positive or negative")
            continue
        session.findById("wnd[0]/tbar[0]/okcd").text = "/nf-32"
        session.findById("wnd[0]/tbar[0]/btn[0]").press()
        # Account
        session.findById("wnd[0]/usr/ctxtRF05A-AGKON").text = account
        # Clearing Date
        session.findById("wnd[0]/usr/ctxtBKPF-BUDAT").text = formatted_date
        # Company Code
        session.findById("wnd[0]/usr/ctxtBKPF-BUKRS").text = "5523"
        # Currency
        session.findById("wnd[0]/usr/ctxtBKPF-WAERS").text = "CNY"
        # Special G/L Ind
        session.findById("wnd[0]/usr/ctxtRF05A-AGUMS").text = "A"
        # click Additional Selection
        session.findById("wnd[0]/usr/sub:SAPMF05A:0131/radRF05A-XPOS1[0,0]").select()
        # click Process Open Items
        session.findById("wnd[0]/tbar[1]/btn[16]").press()
        time.sleep(1)
        status = session.findById("wnd[0]/sbar/pane[0]").text
        print(status)
        if "items were selected" not in status:
            print("No open items were found")
            new_rows = pd.Series([status, error_sequence, account], index=column_names)
            error_DT = pd.concat([error_DT, new_rows.to_frame().T], ignore_index=True)
            error_sequence += 1
            continue

        res = do_clear_item(session)

        if "YES" in res:
            new_rows = pd.Series([res.replace("YES", ""), correct_sequence, account], index=column_names)
            correct_DT = pd.concat([correct_DT, new_rows.to_frame().T], ignore_index=True)
            correct_sequence += 1
        else:
            new_rows = pd.Series([res.replace("NO", ""), error_sequence, account], index=column_names)
            error_DT = pd.concat([error_DT, new_rows.to_frame().T], ignore_index=True)
            error_sequence += 1

    # 结束时间
    end_time = datetime.now()
    # 计算运行时间
    gap_time = end_time - start_time
    # 获取差异的总秒数
    total_seconds = int(gap_time.total_seconds())
    # 计算小时、分钟和秒
    hours, remainder = divmod(total_seconds, 3600)
    minutes, seconds = divmod(remainder, 60)
    # 格式化为时:分:秒
    time_str = f"{hours:02}:{minutes:02}:{seconds:02}"

    html_produce(time_str, error_DT, correct_DT, Tomail)


def html_produce(gap_time, error_DT, correct_DT, Tomail):
    html_table = []
    html_table.append("""  
      
      
          
          
        JD Clearing Result  
          
     """)
    html_table.append(f'

JD Clearing Result 清账用时{gap_time}

') html_table.append(f'

处理异常: {error_DT.shape[0]} 条, 处理成功: {correct_DT.shape[0]} 条

') html_table.append('') # 添加表头 html_table.append("") for col in error_DT.columns: html_table.append(f"") html_table.append("") for index, row in error_DT.iterrows(): html_table.append("") for col in error_DT.columns: html_table.append(f"") html_table.append("") # 添加表头 html_table.append("") for col in correct_DT.columns: html_table.append(f"") html_table.append("") for index, row in correct_DT.iterrows(): html_table.append("") for col in correct_DT.columns: html_table.append(f"") html_table.append("") html_table.append("
{col}
{row[col]}
{col}
{row[col]}
") # 将列表转换为字符串 html_result = ''.join(html_table) send_html_email(html_result, Tomail) def send_html_email(html_body, Tomail): outlook = win32.Dispatch('outlook.application') mail = outlook.CreateItem(0) mail.To = Tomail mail.Subject = "5523 Clearing Result" mail.HTMLBody = html_body mail.Send() if __name__ == '__main__': locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') excel_BL5N = sys.argv[1] Tomail = sys.argv[2] # excel_BL5N = "D:\\project\\clear\\local FBL5N\\5523\\FBL5N__5523_24年10月30日_10点24分06秒.xlsx" # Tomail = "[email protected]" handling_clear_5523(excel_BL5N, Tomail)

你可能感兴趣的:(python,自动化,html)