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ỏ qua

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ỏ qua


