[ Python và ứng dụng ] Lập trình thư viện cho VBA bằng Python

Liên hệ QC

befaint

|||||||||||||
Tham gia
6/1/11
Bài viết
14,374
Được thích
19,335
Mình đọc tiêu đề là đã thấy hấp dẫn rồi á. :)

Mình có tìm hiểu qua vụ này thì thấy có vẻ rất ít thông tin, có thể Python vốn là mã nguồn mở, hoặc có thể đã dùng Python rồi thì không mấy ai để ý tới VBA nữa.
Đã có một số chương trình tích hợp Python với Excel, VBA nhưng đều cần cài đặt Python mới chạy được.

Mình vọc một hồi (hồi khá lâu...) ra cách tạo thư viện cho VBA bằng Python mà không khi phân phối không cần cài đặt Python trên máy tính sử dụng thư viện.
Đại khái một số thông tin như thế này:
* Đầu tiên, được gọi là "thư viện" vì không cần cài đặt Python trên máy tính sử dụng chúng.
* Bảo mật: tương đương Windows DLL.
Tìm hiểu qua thông tin thấy nó cũng là mã máy gì gì đó.
* Tốc độ: tùy vào khả năng viết code. Về cơ bản nó là Python mà.

Mình vọc hồi khá lâu vì vụ bảo mật kia. Hình như chưa có ai làm, hoặc không có gì đáng quan tâm, hoặc ai đó làm rồi mà họ không đăng lên internet nên mình chưa tìm thấy.

Mình làm một ví dụ, coi như động lực để bạn nào có hứng thú thì tự tìm hiểu nha. Tự khám phá ra mới hay mà.

Bài ví dụ: Lấy dữ liệu tỷ giá ngoại tệ từ trang web Vietcombank theo khoảng thời gian.
(Tiếp ví dụ ở bài https://www.giaiphapexcel.com/diendan/threads/lập-trình-trong-power-query-và-các-ví-dụ.157214/)

Chạy thử lấy dữ liệu 01 tháng trên máy tính của mình hết cỡ 1.8 giây.
Ai biết code Delphi thử làm bài ví dụ này xem ra sao nhỉ.

Các bạn tải file về nhớ đọc và làm theo hướng dẫn nhé. >> Tải File.

1633165995368.png
 
Lần chỉnh sửa cuối:
Cái này dễ mà, chẳng qua mới đầu mình không định up file để vậy cho dễ phân biệt

hihhi chạy multi thear thì cao cấp rồi anh nhưng mà để sync Display thì cũng mệt ah

View attachment 267323

Multi thread là chuyện quá bình thường thôi bạn, có gì mà cao cấp đâu. Tất cả mấy thứ đó đều là giải thuật, ứng dụng thành phần lập trình, những cái này thì ngôn ngữ lập trình nào cũng có cả (trừ code thuần VBA, nhưng làm DLL goi trong VBA vẫn multi thread được nhé). File của bạn còn chưa ứng dụng multi thread mà đã vậy, nếu ứng dụng nó thì sao nhỉ. Bạn xem tạm ví dụ đơn giản lập trình multi thread với Delphi để phát triển các ví dụ khác.
 
Upvote 0
Multi thread là chuyện quá bình thường thôi bạn, có gì mà cao cấp đâu. Tất cả mấy thứ đó đều là giải thuật, ứng dụng thành phần lập trình, những cái này thì ngôn ngữ lập trình nào cũng có cả (trừ code thuần VBA, nhưng làm DLL goi trong VBA vẫn multi thread được nhé). File của bạn còn chưa ứng dụng multi thread mà đã vậy, nếu ứng dụng nó thì sao nhỉ. Bạn xem tạm ví dụ đơn giản lập trình multi thread với Delphi để phát triển các ví dụ khác.
Vâng cái dll em post lên chưa viết multi thread. Cái multi thread là em mới viết trên Form à anh.
 
Upvote 0
Lần chỉnh sửa cuối:
Upvote 0
Úp File cho mình thử chút xem có như bạn nói không 0.5s

Lưu ý máy mình ko cài Python
Tôi đã nói chạy thẳng trên Python, tức là dùng trình biên dịch của Python (đang dùng extension jupyter trong vs code) thì nó đạt tốc độ như vậy, bạn muốn kiểm tra thì cài Python mà thử chứ tôi chế làm gì, còn nén thành exe nó chạy chậm hơn cũng không chừng
Cái này dễ mà, chẳng qua mới đầu mình không định up file để vậy cho dễ phân biệt

hihhi chạy multi thear thì cao cấp rồi anh nhưng mà để sync Display thì cũng mệt ah

View attachment 267323
Bạn chạy thử dữ liệu 2 năm xem máy tôi mất khoảng 9s, chạy đơn luông mất 142s , multithread khi dùng để crawl lấy càng nhiều thì tốc độ nó mói rõ rệt so với chạy đơn luồng1633585215828.png1633584445826.png
 
Lần chỉnh sửa cuối:
Upvote 0
Tôi đã nói chạy thẳng trên Python, tức là dùng trình biên dịch của Python (đang dùng extension jupyter trong vs code) thì nó đạt tốc độ như vậy, bạn muốn kiểm tra thì cài Python mà thử chứ tôi chế làm gì, còn nén thành exe nó chạy chậm hơn cũng không chừng

Bạn chạy thử dữ liệu 2 năm xem máy tôi mất khoảng 9s, chạy đơn luông mất 142s , multithread khi dùng để crawl lấy càng nhiều thì tốc độ nó mói rõ rệt so với chạy đơn luồngView attachment 267326View attachment 267325
Cả hai hãy thử lấy 10 năm xem sao là biết thôi ... vì viết trên môi trường nào cũng thế ... dữ liệu lớn mới có thể xem xét được ( phụ thuộc mạng thì xem xét ở góc độ khác )
 
Upvote 0
Mình lại tưởng chưa ứng dụng multi thread. Sao thời gian thực hiện lại là số 0 vậy? Em tăng số liệu 10 năm lên xem số nhảy là bao nhiêu? :D
Em xử lý add vào array trong luồng luôn anh, khi mà array có dữ liệu là nó display lên. Trong khi đó luồng nó vẫn tiếp tục xử lý, em đang đau đầu cái chỗ xử lý nối tiếp array
 
Upvote 0
Em xử lý add vào array trong luồng luôn anh, khi mà array có dữ liệu là nó display lên. Trong khi đó luồng nó vẫn tiếp tục xử lý, em đang đau đầu cái chỗ xử lý nối tiếp array

Muốn so sánh thì phải đưa về một kiểu mới nên so sánh. Ở các môi trường IDE, các nhà sản xuất họ lập trình dùng thủ thuật hoặc sử dụng controls đặc biệt để vẽ dữ liệu vào với tốc độ nhanh nên không phản ánh tốc độ sau biên dịch của sản phẩm lập trình sau khi build. Muốn so sánh hãy đẩy dữ liệu ra bảng tính Excel.

Vấn đề nạp danh sách trong quá trình chạy đa luồng - multi thread. Hãy nạp dữ liệu vào TThreadList. Cách dùng TThreadList tại đây.
Để chạy đa luồng, đợi cho tất cả các luồng kết thúc rồi điền dữ liệu từ TThreadList ra đâu đó thì dùng TTask. Cách làm trong Delphi như sau:
1. Thêm unit "Threading"
2. Sử dụng TTask.WaitForAll(array of ITask) để đợi cho tất cả các luồng hoàn thành, tức TThreadList đã nhận đủ dữ liệu.
3. Đẩy dữ liệu từ TThreadList ra Excel hay control nào đó.

Không biết bạn đang dùng component nào để download dữ liệu từ web, nếu trong luồng bạn chạy trang web mà gặp vấn đề thì dùng TidHTTP hoặc THTTPClient nó hỗ trợ tốt trong đa luồng.

Đó là kiến trúc lập trình còn cụ thể ở khúc nào bạn tìm kiếm là ra đầy link tham khảo.

Nếu đã lập trình được như mình chỉ thì chơi hẳn 10 năm hoặc hơn cho máu nhé. :D
 
Lần chỉnh sửa cuối:
Upvote 0
Nếu làm như cách thông thường khi Thread kết thúc dữ liệu 1 năm, em code nó chạy khoản 75 s.
Hic sửa tới, sửa lui sai rồi. Hihi để tối rảnh em làm lại
 
Lần chỉnh sửa cuối:
Upvote 0
Nếu làm như cách thông thường khi Thread kết thúc dữ liệu 1 năm, em code nó chạy khoản 75 s
multi thread dll :p

Thế là làm tận 11 năm thật luôn à? Vậy chính thức với 11 năm thì Delphi bạn làm chạy hết bao nhiêu giây? Tính cả thời gian điển ra Excel chứ?
 
Upvote 0
Máy tôi chạy thời gian như bạn 11 năm mất tầm 50s tính luôn xuất excel, khi crawl data web dùng multithread thì các khả năng sau có thể ảnh hưởng đến tốc độ: tốc độ mạng (thời gian gửi request, thời gian phản hồi của server), số lượng request cùng lúc quá nhiều có thể làm thời gian gửi và server phản hồi chậm hơn, sức mạnh của CPU (số lượng luồng tối đa mà con CPU có thể gửi cùng lúc, ví dụ con I3 có thể gửi 10 luồng cùng lúc, I7 có thể gửi 20 luồng cùng lúc như vậy I7 có thể nhanh hơn gấp đôi I3, mặc dù có thể set I3 gửi 20 luồng được nhưng chất lượng mỗi luồng sẽ giảm đi phân nữa do tài nguyên không đủ), tôi nghĩ khả năng là con CPU bạn yếu + code chưa tối ưu lấy 2 năm mất có 22s mà 11 năm mất 187s (tôi thường làm với multithread thấy khi lấy càng nhiều dữ liệu thì thời gian trung bình mỗi luồng sẽ giảm xuống), tôi nghĩ nếu viết chuẩn trên Delphi có thể nhanh hơn Python vì Python mặc định chỉ sử dụng có 1 nhân CPU thôi1633635480482.png
 
Upvote 0
Máy tôi chạy thời gian như bạn 11 năm mất tầm 50s tính luôn xuất excel, khi crawl data web dùng multithread thì các khả năng sau có thể ảnh hưởng đến tốc độ: tốc độ mạng (thời gian gửi request, thời gian phản hồi của server), số lượng request cùng lúc quá nhiều có thể làm thời gian gửi và server phản hồi chậm hơn, sức mạnh của CPU (số lượng luồng tối đa mà con CPU có thể gửi cùng lúc, ví dụ con I3 có thể gửi 10 luồng cùng lúc, I7 có thể gửi 20 luồng cùng lúc như vậy I7 có thể nhanh hơn gấp đôi I3, mặc dù có thể set I3 gửi 20 luồng được nhưng chất lượng mỗi luồng sẽ giảm đi phân nữa do tài nguyên không đủ), tôi nghĩ khả năng là con CPU bạn yếu + code chưa tối ưu lấy 2 năm mất có 22s mà 11 năm mất 187s (tôi thường làm với multithread thấy khi lấy càng nhiều dữ liệu thì thời gian trung bình mỗi luồng sẽ giảm xuống), tôi nghĩ nếu viết chuẩn trên Delphi có thể nhanh hơn Python vì Python mặc định chỉ sử dụng có 1 nhân CPU thôiView attachment 267351
Vâng anh phân tích em thấy đúng, hihi em không quan tâm cái chương trình nào lẹ hơn đâu, chẳng qua em thấy hứng thú, với lại có mục tiêu phải đạt được số giây như vậy em cảm thấy hứng thú code để so sánh thôi. Em lý thuyết em yếu, với lại ít có cơ hội đụng vào Wed nữa. Nên chắc có nhiều cái thủ thuật em chưa biết.
Cái chương trình này, em cũng nghĩ là nó bị thắt nút tại cái chỗ code xử lý, do tập trung quá nhiều luồng mà nó xử lý không kịp, nên nó chậm chỗ này. Em có ý định xử lý trực tiếp trên địa chỉ luồng luôn.
 
Upvote 0
Máy tôi chạy thời gian như bạn 11 năm mất tầm 50s tính luôn xuất excel,
.
Code multi thread thì CPU load cỡ 70-80%.
Mình thử chèn multi process vào multi thread để kéo hết 100% CPU thì cho kết quả nhanh hơn.
Python có thể dùng GPU để chạy script, vậy kết hợp thêm GPU thì chắc có thể tằng tốc nữa.
 
Upvote 0
.
Code multi thread thì CPU load cỡ 70-80%.
Mình thử chèn multi process vào multi thread để kéo hết 100% CPU thì cho kết quả nhanh hơn.
Python có thể dùng GPU để chạy script, vậy kết hợp thêm GPU thì chắc có thể tằng tốc nữa.
sáng này lướt qua tài liệu py thấy nó nói thế ... hình như py chỉ hổ trợ có 1 nhân CPU thôi thì phải ... nếu máy nhiều nhân có vẻ phí ... cũng đang hóc hớt py một chút xem sao .. nếu ok vọc vài tháng là chơi tạm ok thôi
 
Upvote 0
sáng này lướt qua tài liệu py thấy nó nói thế ... hình như py chỉ hổ trợ có 1 nhân CPU thôi thì phải ... nếu máy nhiều nhân có vẻ phí ... cũng đang hóc hớt py một chút xem sao .. nếu ok vọc vài tháng là chơi tạm ok thôi
Code đơn thuần thì chỉ chạy 1 nhân CPU, nên nếu CPU có tốc độ đơn nhân cao thì sẽ chạy tốt hơn CPU có nhiều nhân nhưng tốc độ mỗi nhân thấp.

Để sử dụng tối đa sức mạnh phần cứng thì Python có multithreading, multiprocessing, chưa kể dùng được GPU để tính toán (nếu máy có GPU hỗ trợ).
 
Upvote 0
.
Code multi thread thì CPU load cỡ 70-80%.
Mình thử chèn multi process vào multi thread để kéo hết 100% CPU thì cho kết quả nhanh hơn.
Python có thể dùng GPU để chạy script, vậy kết hợp thêm GPU thì chắc có thể tằng tốc nữa.
Tôi thường dùng multiprocess để chạy những case nặng để tận dụng hết khả năng của CPU, GPU thì chưa thử, lúc trước cũng từng thử kết hợp giữa Threads và process để crawl data web nhưng không thể đẩy CPU lên 100% thậm chí nó còn chậm hơn khi chỉ chạy threads riêng, nếu như bạn nói có thể kết hợp để đẩy cpu lên 100% thì để tôi xem lại cách code, hiện tại không thể test do web nó bị out hoài
 
Upvote 0
Mò tài liệu python vài ngày thì thấy như sau

1/ học py sẻ rất nhanh thôi vì thư viện họ viết cho gần như hết còn mình chỉ call ... :D :p

2/ cài py có lẻ khá vất vả ... nhiều nơi la làng khi lỗi + cài nó

3/ khó khăn nhất là phân phối ứng dụng nhỏ lẻ mà ko phải cài py thì làm như bài số 1 cũng ok đóng gói hết vào đó

xong call thì tốc độ nó cũng giảm theo + file to quá cũng hơi bất tiện chút ==> ko sao cả quan trọng là ứng dụng viết ra có đặc biệt hay ko thôi
....
 
Upvote 0
Tôi thường dùng multiprocess để chạy những case nặng để tận dụng hết khả năng của CPU, GPU thì chưa thử, lúc trước cũng từng thử kết hợp giữa Threads và process để crawl data web nhưng không thể đẩy CPU lên 100% thậm chí nó còn chậm hơn khi chỉ chạy threads riêng, nếu như bạn nói có thể kết hợp để đẩy cpu lên 100% thì để tôi xem lại cách code, hiện tại không thể test do web nó bị out hoài
Hôm nay rảnh nên ngồi test lại vụ threads và process, thì có các trường hợp như vầy:
- Kết hợp cả threads và process sẽ chậm hơn threads nếu lấy dữ liệu ít như tôi test lúc trước có thể giải thích là lấy dữ liệu ít thì đơn nhân đa luồng có thể xử lý ổn chậm hơn do phải mở nhiều process và đóng, nếu lấy nhiều thì sẽ nhanh hơn, với bài này thì nhanh hơn 10s (tức là chạy full 11 năm khoảng 40s) nhưng máy tôi chỉ mở được có 2 process, mở nhiều bị time out web phải đợi hết time out mới chạy tiếp được, trường hợp này CPU chỉ dùng được 23%
- Sử dụng process không dùng threads có thể mở tối đa số process là 61 nhưng tốc độ chỉ bằng với threads
- Sử dụng process không dùng threads+ giữ phiên (cookie) cho mỗi process+phân bổ số request như nhau cho mỗi process, máy tôi đạt tốc độ tốt nhất là 11-12s lấy dữ liệu 11 năm với 56 luồng xử lý được mở CPU sẽ lên tầm 80%1633756353144.png
 
Upvote 0
Web KT
Back
Top Bottom