sửa code python (3 người xem)

Người dùng đang xem chủ đề này

  • Tôi tuân thủ nội quy khi đăng bài
    Có

    Hoale85

    Thành viên chính thức
    Tham gia
    2/8/24
    Bài viết
    99
    Được thích
    7
    Em nhờ anh chị sửa giúp em code sau với ạ: đoạn chỗ kiểm tra checkbok:
    import cv2
    import numpy as np
    import os
    import glob
    import time
    import traceback
    import gc
    import ctypes

    # =========================================================
    # 0. CỐ ĐỊNH DPI TRƯỚC KHI NẠP PYAUTOGUI
    # =========================================================

    try:
    ctypes.windll.shcore.SetProcessDpiAwareness(2)
    except Exception:
    try:
    ctypes.windll.user32.SetProcessDPIAware()
    except Exception:
    pass

    import pyautogui
    import pyperclip
    import win32gui
    import win32con
    import win32com.client as win32

    import cv2
    import numpy as np


    # =========================================================
    # 1. CẤU HÌNH
    # =========================================================

    pyautogui.FAILSAFE = False
    pyautogui.PAUSE = 0.3

    URL_DANG_NHAP = (
    "https://amisapp.misa.vn/login/?href="
    "L0FQSVMvSW50ZWdyYXRpb25BUEkvYXBwL3JlZGlyZWN0L0FjY291bnRpbmc="
    )

    URL_BAO_CAO = (
    "https://actapp.misa.vn/app/RP/ReportList/"
    "RPDynamicViewer/GLBookDetailPaymentByAccountNumber"
    )

    DOWNLOAD_DIR = r"C:\Users\admin\Downloads"
    FILE_TONG = r"D:\Hoa lv\Kiem soat\128-341.xlsm"

    # KÍCH THƯỚC MÀN HÌNH CHUẨN
    CHUAN_RONG = 1920
    CHUAN_CAO = 1200

    MAN_HINH_KHOI_DAU = pyautogui.size()

    TY_LE_X = MAN_HINH_KHOI_DAU.width / CHUAN_RONG
    TY_LE_Y = MAN_HINH_KHOI_DAU.height / CHUAN_CAO

    print("=" * 65)
    print("THÔNG TIN MÀN HÌNH")
    print("Chiều rộng:", MAN_HINH_KHOI_DAU.width)
    print("Chiều cao:", MAN_HINH_KHOI_DAU.height)
    print("Tỷ lệ X:", TY_LE_X)
    print("Tỷ lệ Y:", TY_LE_Y)
    print("=" * 65)

    # Thời gian chờ
    CHO_MO_CHROME = 3
    CHO_TAI_TRANG = 8
    CHO_GOI_Y_128 = 2
    CHO_TAI_FILE = 120

    # Ảnh chụp checkbox
    THU_MUC_CODE = os.path.dirname(os.path.abspath(__file__))

    FILE_ANH_CHECKBOX = os.path.join(
    THU_MUC_CODE,
    "checkbox_screenshot.png"
    )

    FILE_ANH_SAU_CHECKBOX = os.path.join(
    THU_MUC_CODE,
    "checkbox_screenshot_after.png"
    )

    # Ngưỡng màu nhận diện viền xanh trong ảnh HSV
    # OpenCV Hue có giá trị từ 0 đến 179
    BLUE_H_MIN = 90
    BLUE_H_MAX = 135
    BLUE_S_MIN = 65
    BLUE_V_MIN = 65

    # Ngưỡng nhận diện dấu tích xanh bên trong checkbox
    GREEN_H_MIN = 35
    GREEN_H_MAX = 90
    GREEN_S_MIN = 55
    GREEN_V_MIN = 55

    # Kích thước dự kiến của khung viền xanh quanh checkbox
    KHUNG_MIN = 12
    KHUNG_MAX = 70


    # =========================================================
    # 2. KIỂM TRA VÀ CỐ ĐỊNH TỌA ĐỘ
    # =========================================================

    def kiem_tra_man_hinh():

    man_hinh_hien_tai = pyautogui.size()

    if (
    man_hinh_hien_tai.width != MAN_HINH_KHOI_DAU.width
    or man_hinh_hien_tai.height != MAN_HINH_KHOI_DAU.height
    ):
    raise Exception(
    "ĐỘ PHÂN GIẢI MÀN HÌNH ĐÃ THAY ĐỔI!\n"
    f"Lúc chạy: {MAN_HINH_KHOI_DAU.width}x{MAN_HINH_KHOI_DAU.height}\n"
    f"Hiện tại: {man_hinh_hien_tai.width}x{man_hinh_hien_tai.height}\n"
    "Vui lòng giữ nguyên độ phân giải màn hình."
    )


    def toa_do(x, y):

    kiem_tra_man_hinh()

    px = int(x * TY_LE_X)
    py = int(y * TY_LE_Y)

    return px, py


    def click_xy(x, y, so_lan=1):

    px, py = toa_do(x, y)

    pyautogui.moveTo(px, py, duration=0.2)

    pyautogui.click(
    px,
    py,
    clicks=so_lan,
    interval=0.15
    )


    def nhap_url(url):

    pyautogui.hotkey("ctrl", "l")
    time.sleep(0.3)

    pyperclip.copy(url)
    pyautogui.hotkey("ctrl", "v")

    pyautogui.press("enter")


    def dan_chu(chu):

    pyperclip.copy(str(chu))
    pyautogui.hotkey("ctrl", "v")


    # =========================================================
    # 3. DANH SÁCH CÔNG TY
    # =========================================================

    DS_CONG_TY = [
    {
    "ten": "KHOÁNG SẢN VŨ GIA YÊN BÁI",
    "tab": 4,
    "sheet": "128-VG_YENBAI"
    },
    {
    "ten": "CÔNG TY CỔ PHẦN CHĂN NUÔI CÔNG NGHỆ CAO VACA MAXI",
    "tab": 3,
    "sheet": "128-VACA"
    },
    {
    "ten": "CÔNG TY CỔ PHẦN CÔNG NGHỆ EMBERA",
    "tab": 3,
    "sheet": "128-EMBERA_TECH"
    },
    {
    "ten": "CÔNG TY CỔ PHẦN TẬP ĐOÀN EMBERA",
    "tab": 3,
    "sheet": "128-EMBERA_TD"
    },
    {
    "ten": "CÔNG TY CỔ PHẦN TẬP ĐOÀN MIT VIỆT NAM",
    "tab": 6,
    "sheet": "128-MIT"
    }
    ]


    # =========================================================

    # =========================================================

    def kiem_tra_checkbox():
    print("Đang chuyển đến ô Check Book...")

    # 1. Tab đúng 3 lần sau khi Enter 128
    for i in range(3):
    pyautogui.press('tab')
    time.sleep(0.3)

    # Chờ giao diện ổn định hoàn toàn sau khi di chuyển tiêu điểm Tab
    time.sleep(0.6)

    # 2. SỬ DỤNG TỌA ĐỘ TUYỆT ĐỐI BẠN ĐÃ ĐO THỰC TẾ (CỐ ĐỊNH)
    x_chuan = 614
    y_chuan = 364

    # Lấy mã màu RGB trực tiếp tại tọa độ này từ màn hình
    # Định dạng trả về là một bộ 3 số (R, G, B)
    rgb_color = pyautogui.pixel(x_chuan, y_chuan)
    r, g, b = rgb_color[0], rgb_color[1], rgb_color[2]

    print(f" Màu sắc thực tế đo được tại vị trí (614, 364) là: R={r}, G={g}, B={b}")

    # 3. KHÓA CỨNG LOGIC BẢO VỆ DỰA TRÊN MÀU SẮC THỰC TẾ
    # Dấu tích xanh lá cây của MISA có đặc điểm: Kênh Green (Xanh lá) lớn hẳn so với Red và Blue
    # Đồng thời kênh Red của màu xanh lá cây này rất thấp (thường < 100)
    if g > 130 and r < 120:
    # TRẠNG THÁI ĐÃ CÓ TÍCH XANH (NHƯ HÌNH BẠN GỬI) -> BỎ QUA 100%
    print("====== KẾT QUẢ: ĐÃ CÓ DẤU TÍCH V XANH -> BỎ QUA HOÀN TOÀN (KHÔNG ẤN PHÍM CÁCH) ======")
    # Nhánh này hoàn toàn trống rỗng, không chứa bất kỳ mã lệnh tương tác bàn phím nào cả

    else:
    # TRẠNG THÁI Ô TRỐNG TRẮNG (Hoặc không phải màu tích xanh) -> TIẾN HÀNH TÍCH CHỌN
    print("====== KẾT QUẢ: Ô ĐANG TRỐNG -> TIẾN HÀNH NHẤN SPACE ĐỂ TÍCH CHỌN ======")
    pyautogui.press('space')

    return True


    # =========================================================
    # 5. TÌM VÀ MỞ TAB CHROME
    # =========================================================

    def lay_danh_sach_cua_so_chrome():

    ket_qua = []

    def callback(hwnd, extra):

    try:
    if not win32gui.IsWindowVisible(hwnd):
    return True

    ten = win32gui.GetWindowText(hwnd)

    if "Chrome" in ten:
    ket_qua.append(hwnd)

    except Exception:
    pass

    return True

    win32gui.EnumWindows(callback, None)

    return ket_qua


    def lay_cua_so_chrome_hien_tai():

    hwnd = win32gui.GetForegroundWindow()

    if hwnd and win32gui.IsWindow(hwnd):

    ten = win32gui.GetWindowText(hwnd)

    if "Chrome" in ten:
    return hwnd

    windows = lay_danh_sach_cua_so_chrome()

    if not windows:
    raise Exception("Không tìm thấy cửa sổ Chrome đang mở.")

    return windows[0]


    def kich_hoat_chrome(hwnd):

    kiem_tra_man_hinh()

    if hwnd and win32gui.IsWindow(hwnd):

    win32gui.ShowWindow(
    hwnd,
    win32con.SW_MAXIMIZE
    )

    win32gui.SetForegroundWindow(hwnd)

    time.sleep(1)

    pyautogui.hotkey("ctrl", "0")

    time.sleep(1)

    kiem_tra_man_hinh()


    def mo_chrome_misa():

    print("Đang mở tab Chrome MISA mới...")

    hwnd = lay_cua_so_chrome_hien_tai()

    kich_hoat_chrome(hwnd)

    pyautogui.hotkey("ctrl", "t")

    time.sleep(1)

    nhap_url(URL_DANG_NHAP)

    time.sleep(CHO_MO_CHROME)

    print("Đã mở trang đăng nhập MISA.")

    return hwnd


    def dong_chrome_misa(hwnd):

    if not hwnd or not win32gui.IsWindow(hwnd):

    print("Không tìm thấy cửa sổ Chrome để đóng tab.")

    return

    print("Đang đóng 2 tab Chrome MISA mới...")

    kich_hoat_chrome(hwnd)

    pyautogui.hotkey("ctrl", "w")

    time.sleep(1)

    pyautogui.hotkey("ctrl", "w")

    time.sleep(2)

    print("Đã đóng 2 tab Chrome MISA.")


    # =========================================================
    # 6. CHỌN CÔNG TY
    # =========================================================

    def chon_cong_ty(ten_cong_ty):

    print("Đang chọn công ty:", ten_cong_ty)

    time.sleep(3)

    click_xy(1828, 131)

    time.sleep(3)

    click_xy(1804, 417)

    time.sleep(2)

    click_xy(1816, 411)

    time.sleep(2)

    click_xy(769, 475)

    pyautogui.hotkey("ctrl", "a")

    dan_chu(ten_cong_ty)

    time.sleep(5)

    click_xy(636, 532)

    time.sleep(1)

    click_xy(1258, 863)

    time.sleep(1)

    print("Đã chọn công ty.")


    # =========================================================
    # 7. VÀO KẾ TOÁN VÀ MỞ BÁO CÁO
    # =========================================================

    def vao_bao_cao():

    print("Đang vào phân hệ Kế toán...")

    time.sleep(2)

    click_xy(32, 137)

    time.sleep(1)

    dan_chu("kế toán")

    time.sleep(1)

    click_xy(145, 283)

    time.sleep(3)

    nhap_url(URL_BAO_CAO)

    time.sleep(CHO_TAI_TRANG)

    print("Đã mở báo cáo.")


    # =========================================================
    # 8. CHỌN THAM SỐ VÀ KIỂM TRA CHECKBOX
    # =========================================================

    def chon_tham_so(so_lan_tab):

    print("Đang chọn tham số báo cáo...")

    click_xy(1746, 204)

    time.sleep(2)

    for i in range(so_lan_tab):

    pyautogui.press("tab")

    time.sleep(0.3)

    pyautogui.hotkey("ctrl", "a")

    dan_chu("128")

    time.sleep(CHO_GOI_Y_128)

    pyautogui.press("enter")

    time.sleep(1)

    # Sau Enter 128, Tab đúng 3 lần đến checkbox
    kiem_tra_checkbox()

    print("Đã hoàn thành chọn tham số.")


    # =========================================================
    # 9. KIỂM TRA FILE DOWNLOAD
    # =========================================================

    def lay_trang_thai_download():

    trang_thai = {}

    for duoi in ("*.xlsx", "*.xls", "*.xlsm"):

    for file in glob.glob(
    os.path.join(DOWNLOAD_DIR, duoi)
    ):

    try:

    trang_thai[file] = (
    os.path.getmtime(file),
    os.path.getsize(file)
    )

    except Exception:
    pass

    return trang_thai


    def cho_file_tai_xong(trang_thai_cu, timeout=120):

    print("Đang chờ tải Excel...")

    bat_dau = time.time()

    file_on_dinh = None
    dem_on_dinh = 0
    kich_thuoc_cu = -1

    while time.time() - bat_dau < timeout:

    dang_tai = glob.glob(
    os.path.join(DOWNLOAD_DIR, "*.crdownload")
    )

    if dang_tai:

    time.sleep(1)

    continue

    danh_sach_moi = []

    for duoi in ("*.xlsx", "*.xls", "*.xlsm"):

    for file in glob.glob(
    os.path.join(DOWNLOAD_DIR, duoi)
    ):

    try:

    mtime = os.path.getmtime(file)

    size = os.path.getsize(file)

    thong_tin_cu = trang_thai_cu.get(file)

    if (
    thong_tin_cu is None
    or mtime > thong_tin_cu[0]
    or size != thong_tin_cu[1]
    ):

    danh_sach_moi.append(
    (mtime, file, size)
    )

    except Exception:
    pass

    if danh_sach_moi:

    danh_sach_moi.sort(reverse=True)

    _, file_hien_tai, kich_thuoc = danh_sach_moi[0]

    if (
    file_hien_tai == file_on_dinh
    and kich_thuoc == kich_thuoc_cu
    ):

    dem_on_dinh += 1

    else:

    file_on_dinh = file_hien_tai

    kich_thuoc_cu = kich_thuoc

    dem_on_dinh = 0

    if dem_on_dinh >= 3 and kich_thuoc > 0:

    print("Đã tải xong:", file_on_dinh)

    return file_on_dinh

    time.sleep(1)

    raise TimeoutError(
    "Quá thời gian chờ tải file Excel."
    )


    # =========================================================
    # 10. TẢI BÁO CÁO
    # =========================================================

    def tai_bao_cao():

    print("Đang thực hiện tải báo cáo...")

    trang_thai_cu = lay_trang_thai_download()

    click_xy(1768, 1108)

    time.sleep(3)

    click_xy(1703, 276)

    time.sleep(2)

    click_xy(1252, 868)

    time.sleep(2)

    click_xy(1130, 313)

    time.sleep(15)

    file_excel = cho_file_tai_xong(
    trang_thai_cu,
    CHO_TAI_FILE
    )

    return file_excel


    # =========================================================
    # 11. MỞ FILE EXCEL Ổ D, DÁN DỮ LIỆU, LƯU VÀ ĐÓNG
    # =========================================================

    def dan_du_lieu_vao_excel(file_nguon, ten_sheet):

    print("\nĐANG MỞ EXCEL ĐỂ DÁN DỮ LIỆU")

    print("File nguồn:", file_nguon)

    print("File đích:", FILE_TONG)

    print("Sheet đích:", ten_sheet)

    if not os.path.exists(file_nguon):

    raise FileNotFoundError(
    "Không tìm thấy file Excel vừa tải."
    )

    if not os.path.exists(FILE_TONG):

    raise FileNotFoundError(
    "Không tìm thấy file tổng hợp ở ổ D: " + FILE_TONG
    )

    excel = None

    wb_nguon = None

    wb_tong = None

    try:

    excel = win32.DispatchEx("Excel.Application")

    excel.Visible = True

    excel.DisplayAlerts = False

    excel.ScreenUpdating = True

    excel.EnableEvents = False

    print("Đang mở file Excel vừa tải...")

    wb_nguon = excel.Workbooks.Open(
    os.path.abspath(file_nguon),
    ReadOnly=True
    )

    ws_nguon = wb_nguon.Worksheets(1)

    time.sleep(2)

    print("Đang mở file tổng hợp ở ổ D...")

    wb_tong = excel.Workbooks.Open(
    os.path.abspath(FILE_TONG)
    )

    excel.Visible = True

    excel.WindowState = -4137

    wb_tong.Activate()

    time.sleep(2)

    print("Đang hiện các sheet ẩn...")

    for ws in wb_tong.Worksheets:

    if ws.Visible != -1:

    ws.Visible = -1

    try:

    ws_dich = wb_tong.Worksheets(ten_sheet)

    except Exception:

    raise Exception(
    "Không tìm thấy sheet đích: " + ten_sheet
    )

    ws_dich.Activate()

    time.sleep(1)

    print("Đang xóa dữ liệu cũ...")

    ws_dich.Cells.Clear()

    vung_nguon = ws_nguon.UsedRange

    print("Đang dán dữ liệu...")

    vung_nguon.Copy(
    Destination=ws_dich.Range("A1")
    )

    time.sleep(2)

    print("Đang lưu file tổng hợp...")

    wb_tong.Save()

    time.sleep(2)

    print("ĐÃ LƯU THÀNH CÔNG:", ten_sheet)

    finally:

    if wb_nguon is not None:

    try:
    wb_nguon.Close(SaveChanges=False)
    except Exception:
    pass

    if wb_tong is not None:

    try:
    wb_tong.Close(SaveChanges=True)
    except Exception:
    pass

    if excel is not None:

    try:
    excel.DisplayAlerts = False
    excel.Quit()
    except Exception:
    pass

    wb_nguon = None

    wb_tong = None

    excel = None

    gc.collect()

    time.sleep(1)

    print("ĐÃ ĐÓNG EXCEL HOÀN TOÀN.")


    # =========================================================
    # 12. XỬ LÝ TỪNG CÔNG TY
    # =========================================================

    def xu_ly_cong_ty(cong_ty):

    ten_cong_ty = cong_ty["ten"]

    so_lan_tab = cong_ty["tab"]

    ten_sheet = cong_ty["sheet"]

    hwnd_misa = None

    print("\n")

    print("=" * 65)

    print("BẮT ĐẦU:", ten_cong_ty)

    print("=" * 65)

    try:

    hwnd_misa = mo_chrome_misa()

    kich_hoat_chrome(hwnd_misa)

    chon_cong_ty(ten_cong_ty)

    vao_bao_cao()

    chon_tham_so(so_lan_tab)

    file_excel = tai_bao_cao()

    if not file_excel or not os.path.exists(file_excel):

    raise Exception(
    "Không tìm thấy file Excel sau khi tải."
    )

    dan_du_lieu_vao_excel(
    file_excel,
    ten_sheet
    )

    # Chỉ đóng Chrome sau khi Excel đã lưu và đóng xong
    kich_hoat_chrome(hwnd_misa)

    dong_chrome_misa(hwnd_misa)

    print("HOÀN THÀNH:", ten_cong_ty)

    return True

    except Exception as e:

    print("\nLỖI KHI XỬ LÝ:", ten_cong_ty)

    print("Chi tiết:", str(e))

    traceback.print_exc()

    print("Giữ nguyên tab Chrome để kiểm tra lỗi.")

    return False


    # =========================================================
    # 13. CHẠY TOÀN BỘ DANH SÁCH
    # =========================================================

    def main():

    print("\nBẮT ĐẦU CHẠY DANH SÁCH CÔNG TY")

    print("File tổng hợp:", FILE_TONG)

    print(
    "Màn hình đang sử dụng:",
    MAN_HINH_KHOI_DAU.width,
    "x",
    MAN_HINH_KHOI_DAU.height
    )

    if not os.path.exists(FILE_TONG):

    print("KHÔNG TÌM THẤY FILE TỔNG HỢP Ở Ổ D.")

    return

    if not os.path.isdir(DOWNLOAD_DIR):

    print("KHÔNG TÌM THẤY THƯ MỤC DOWNLOAD.")

    return

    kiem_tra_man_hinh()

    thanh_cong = 0

    that_bai = 0

    for i, cong_ty in enumerate(DS_CONG_TY, start=1):

    print("\n")

    print("#" * 65)

    print(
    "CÔNG TY",
    i,
    "/",
    len(DS_CONG_TY)
    )

    print("#" * 65)

    ket_qua = xu_ly_cong_ty(cong_ty)

    if ket_qua:

    thanh_cong += 1

    else:

    that_bai += 1

    time.sleep(2)

    print("\n")

    print("=" * 65)

    print("ĐÃ KẾT THÚC TOÀN BỘ CHƯƠNG TRÌNH")

    print("Thành công:", thanh_cong)

    print("Thất bại:", that_bai)

    print("=" * 65)


    # =========================================================
    # 14. KHỞI CHẠY
    # =========================================================

    if __name__ == "__main__":

    try:

    main()

    except Exception:

    print("\nLỖI CHƯƠNG TRÌNH:")

    traceback.print_exc()

    finally:

    input("\nNhấn ENTER để đóng chương trình...")
    đoạn check book ko dùng tọa độ mà kiểm tra tại vị trí tab 3 lần sau khi enter 128 để đảm bảo luôn chọn tất cả. nếu đã chọn tất cả thì bỏ qua1794134638462.png1794134591535.png
     
    Vụ này sao bạn không hỏi bên Misa có cung cấp API để tra cứu dữ liệu của họ không chứ dùng phương pháp thủ công này thấy bất tiện dữ à.

    Screenshot 2026-11-09 at 15.19.10.png
     
    Lần chỉnh sửa cuối:

    Bài viết mới nhất

    Back
    Top Bottom