Lấy dữ liệu Foxpro (1 người xem)

Liên hệ QC

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

viethung78

Thành viên chính thức
Tham gia
3/6/16
Bài viết
88
Được thích
53
Chào các anh chị, mình cần lấy dữ liệu từ phần mềm kế toán foxpro ra Excel bằng cách Import, để khi dữ liệu thay đổi thì refresh sẽ có dữ liệu cập nhật.
Dữ liệu foxpro ở dạng thư mục, được nén trong file kèm theo, trong file CT.dbf.
Mình đã thử đủ các kiểu dùng Power Query, ODBC, A-Tools của anh Tuân nhưng vẫn chưa được, nên đành post lên đây nhờ sự trợ giúp của cộng đồng GPE.

Trân trọng cảm ơn!
 

File đính kèm

Chào các anh chị, mình cần lấy dữ liệu từ phần mềm kế toán foxpro ra Excel bằng cách Import, để khi dữ liệu thay đổi thì refresh sẽ có dữ liệu cập nhật.
Dữ liệu foxpro ở dạng thư mục, được nén trong file kèm theo, trong file CT.dbf.
Mình đã thử đủ các kiểu dùng Power Query, ODBC, A-Tools của anh Tuân nhưng vẫn chưa được, nên đành post lên đây nhờ sự trợ giúp của cộng đồng GPE.

Trân trọng cảm ơn!
Cái này cũ quá rồi, bạn dùng power query connect thông qua query OLE DB, sau đó nhập connectString như vầy, Data source thì là folder chứa file, tuy nhiên cái bảng DBF của foxpro phải convert về dạng foxplus mới connect được
ví dụ query trong foxpro:
use table
copy to d:\File.dbf type foxplus
Tôi đang dùng office 365, nên bạn tìm cái Microsoft.ACE.OLEDB phù hợp với phiên bản office của bạn
 

File đính kèm

  • 1645173352932.png
    1645173352932.png
    131.4 KB · Đọc: 37
Cái này cũ quá rồi, bạn dùng power query connect thông qua query OLE DB, sau đó nhập connectString như vầy, Data source thì là folder chứa file, tuy nhiên cái bảng DBF của foxpro phải convert về dạng foxplus mới connect được
ví dụ query trong foxpro:
use table
copy to d:\File.dbf type foxplus
Tôi đang dùng office 365, nên bạn tìm cái Microsoft.ACE.OLEDB phù hợp với phiên bản office của bạn
Convert về dạng foxplus là convert thế nào hả bạn?
 
đoán 1 tí thôi nhé ... ko chắc chắn lắm
Cài cái Driver của nó xong dùng ADODB mà lấy ... kiểu như SQLite muốn sử dụng nó cũng thế
1645235991677.png
Delphi họ vẫn viết đấy ... có điều đồ cổ quá ... ko đáng mò lại code ngày xưa
 
Lần chỉnh sửa cuối:
mò chút cũng ra à

1645245963866.png
 
Chào các anh chị, mình cần lấy dữ liệu từ phần mềm kế toán foxpro ra Excel bằng cách Import, để khi dữ liệu thay đổi thì refresh sẽ có dữ liệu cập nhật.
Dữ liệu foxpro ở dạng thư mục, được nén trong file kèm theo, trong file CT.dbf.
Mình đã thử đủ các kiểu dùng Power Query, ODBC, A-Tools của anh Tuân nhưng vẫn chưa được, nên đành post lên đây nhờ sự trợ giúp của cộng đồng GPE.

Trân trọng cảm ơn!
- Theo tôi biết thì cái VFP ODBC driver nó không còn hỗ trợ nữa nên chuyển sang dùng OLEDB.
- Vô đây download cái driver OLEDB cho FoxPro (VfpOleDB.dll): https://github.com/VFPX/VFP9SP2Hotfix3/blob/master/VFPOLEDBSetup.msi
hoặc tải thẳng từ trang của Microsoft: https://www.microsoft.com/en-us/download/details.aspx?id=32602
- Cài xong thì đăng ký nó: nhớ chạy CMD với quyền Administrator.
regsvr32 /s "C:\Program Files (x86)\Common Files\system\ole db\vfpoledb.dll
- Dùng ADODB kết nối lấy dữ liệu thôi.

Mã:
Sub getDataFoxpro()

    Dim sConnectString, oRS, oConn, sSQL
    sConnectString = "Provider=VFPOLEDB;Data Source=C:\Temp\2021A\CT.dbf;"
    Set oConn = CreateObject("ADODB.Connection")
    oConn.ConnectionString = sConnectString
    oConn.ConnectionTimeout = 30
    oConn.Open
    sSQL = "select * from CT"
    Set oRS = oConn.Execute(sSQL)
    If oRS.EOF Then
        oRS.Close
        oConn.Close
        Set oRS = Nothing
        Set oConn = Nothing
    End If

    Do While Not oRS.EOF
        Debug.Print oRS.Fields("ong_ba").Value & " - " & _
                       oRS.Fields("dia_chi").Value & vbCrLf
        oRS.MoveNext
    Loop

    oRS.Close
    oConn.Close
    Set oRS = Nothing
    Set oConn = Nothing
  
End Sub
 
Lần chỉnh sửa cuối:
- Theo tôi biết thì cái VFP ODBC driver nó không còn hỗ trợ nữa nên chuyển sang dùng OLEDB.
- Vô đây download cái driver OLEDB cho FoxPro (VfpOleDB.dll): https://github.com/VFPX/VFP9SP2Hotfix3/blob/master/VFPOLEDBSetup.msi
hoặc tải thẳng từ trang của Microsoft: https://www.microsoft.com/en-us/download/details.aspx?id=32602
- Cài xong thì đăng ký nó: nhớ chạy CMD với quyền Administrator.
regsvr32 /s "C:\Program Files (x86)\Common Files\system\ole db\vfpoledb.dll
- Dùng ADODB kết nối lấy dữ liệu thôi.

Mã:
Sub getDataFoxpro()

    Dim sConnectString, oRS, oConn, sSQL
    sConnectString = "Provider=VFPOLEDB;Data Source=C:\Temp\2021A\CT.dbf;"
    Set oConn = CreateObject("ADODB.Connection")
    oConn.ConnectionString = sConnectString
    oConn.ConnectionTimeout = 30
    oConn.Open
    sSQL = "select * from CT"
    Set oRS = oConn.Execute(sSQL)
    If oRS.EOF Then
        oRS.Close
        oConn.Close
        Set oRS = Nothing
        Set oConn = Nothing
    End If

    Do While Not oRS.EOF
        Debug.Print oRS.Fields("ong_ba").Value & " - " & _
                       oRS.Fields("dia_chi").Value & vbCrLf
        oRS.MoveNext
    Loop

    oRS.Close
    oConn.Close
    Set oRS = Nothing
    Set oConn = Nothing
 
End Sub
Tôi thử trên office 64 bít ko sử dụng được
 
Mình sẽ cố gắng thử test các giải pháp cộng đồng trợ giúp. Có thể được có theerr không, cảm ơn giúp đỡ của mọi người.
 
Tôi thử trên office 64 bít ko sử dụng được
Cái Provider cho Visual Foxpro (vfpoledb.dll) đã lâu lắm rồi, không có hỗ trợ cho Office 64 bit nhe. Còn không muốn phụ thuộc Office thì cứ Python mà đọc thôi, nó có quá trời thư viện hỗ trợ đọc DBF.
 
Cái Provider cho Visual Foxpro (vfpoledb.dll) đã lâu lắm rồi, không có hỗ trợ cho Office 64 bit nhe. Còn không muốn phụ thuộc Office thì cứ Python mà đọc thôi, nó có quá trời thư viện hỗ trợ đọc DBF.
có 1 vài cái mà tôi quan tâm Foxpro một chút đó là

1/ Hiện tại còn nhiều cty vẫn sử dụng phần mềm kế toán viết trên FoxPro
2/ tôi có quen 1 cty chuyên làm dịch vụ kế toán lớn cũng sử dụng phần mềm kế toán viết trên FoxPro mà hàng năm nếu có vấn đề gì phát sinh họ vẫn bảo trì
3/ mặc dù nó rất cổ nhưng hiện tại đâu đó vẫn còn sử dụng ....
....
Vì vậy tôi quan tâm 1 chút muốn bảo tồn nó nếu cần thiết sau này chuyển qua Tools khác ta có thể lấy dữ liệu trước đó tham khảo vào Excel .... xong tùy xử lý nó ....
....
Tôi mới phát hiện ra

1/ không cần thiết cài đặt Driver của FoxPro Hoặc File VFPOLEDBSetup.msi
2/ vẫn sử dụng tốt trên Office 64 bit
3/ chỉ cần VB6 cổ điển cũng viết tốt rồi ....
4/ Code thì tôi copy y trang code bài số 7 thử thôi .... ko phải là ko biết viết mà lười chút ... Copy cho nhanh
5/ tại ta chưa biết thực hiện đúng cách .... hay lách nó mà thôi
6/ xem hình trong cài đặt của tôi ko có sự hiển diện của Fox Pro

1645334671780.png

xem video

Liên kết: https://youtu.be/E_xNP1TOjhI
 
Lần chỉnh sửa cuối:
1/ không cần thiết cài đặt Driver của FoxPro Hoặc File VFPOLEDBSetup.msi
2/ vẫn sử dụng tốt trên Office 64 bit
3/ chỉ cần VB6 cổ điển cũng viết tốt rồi ....
4/ Code thì tôi copy y trang code bài số 7 thử thôi .... ko phải là ko biết viết mà lười chút ... Copy cho nhanh
5/ tại ta chưa biết thực hiện đúng cách .... hay lách nó mà thôi
6/ xem hình trong cài đặt của tôi ko có sự hiển diện của Fox Pro

:D kiểu gì thì cũng phải cần thêm thư viện bên ngoài thôi.
 
có 1 vài cái mà tôi quan tâm Foxpro một chút đó là

1/ Hiện tại còn nhiều cty vẫn sử dụng phần mềm kế toán viết trên FoxPro
2/ tôi có quen 1 cty chuyên làm dịch vụ kế toán lớn cũng sử dụng phần mềm kế toán viết trên FoxPro mà hàng năm nếu có vấn đề gì phát sinh họ vẫn bảo trì
3/ mặc dù nó rất cổ nhưng hiện tại đâu đó vẫn còn sử dụng ....
....
Vì vậy tôi quan tâm 1 chút muốn bảo tồn nó nếu cần thiết sau này chuyển qua Tools khác ta có thể lấy dữ liệu trước đó tham khảo vào Excel .... xong tùy xử lý nó ....
....
Tôi mới phát hiện ra

1/ không cần thiết cài đặt Driver của FoxPro Hoặc File VFPOLEDBSetup.msi
2/ vẫn sử dụng tốt trên Office 64 bit
3/ chỉ cần VB6 cổ điển cũng viết tốt rồi ....
4/ Code thì tôi copy y trang code bài số 7 thử thôi .... ko phải là ko biết viết mà lười chút ... Copy cho nhanh
5/ tại ta chưa biết thực hiện đúng cách .... hay lách nó mà thôi
6/ xem hình trong cài đặt của tôi ko có sự hiển diện của Fox Pro

View attachment 272318

xem video

Liên kết: https://youtu.be/E_xNP1TOjhI


CẢM ƠN ANH, ANH ĐÃ LÀM THẾ NÀO VẬY?
 
Cách của các anh hay quá ạ ! Em Vân toàn phải dùng phân mềm chuyển từ File dbf sang excel thôi ạ.
 
Chào các anh chị, mình cần lấy dữ liệu từ phần mềm kế toán foxpro ra Excel bằng cách Import, để khi dữ liệu thay đổi thì refresh sẽ có dữ liệu cập nhật.
Dữ liệu foxpro ở dạng thư mục, được nén trong file kèm theo, trong file CT.dbf.
Mình đã thử đủ các kiểu dùng Power Query, ODBC, A-Tools của anh Tuân nhưng vẫn chưa được, nên đành post lên đây nhờ sự trợ giúp của cộng đồng GPE.

Trân trọng cảm ơn!

Khi bạn muốn kết nối CSDL Foxpro vào Excel thì làm theo hướng dẫn của tôi dưới đây. Bạn hãy dùng DBKEY để tạo kết nối đến folder có các file DBF, sau đó dùng hàm BS_SQL để truy vấn dữ liệu theo câu lệnh SQL. Chỉ thế là xong. Toàn bộ quá trình làm không cần phải lập trình. Nếu bạn tìm hiểu kỹ hơn hàm BS_SQL thì còn làm rất nhiều báo cáo phức tạp và tốc độ nhanh.

 
Lần chỉnh sửa cuối:
Khi bạn muốn kết nối CSDL Foxpro vào Excel thì làm theo hướng dẫn của tôi dưới đây. Bạn hãy dùng DBKEY để tạo kết nối đến folder có các file DBF, sau đó dùng hàm BS_SQL để truy vấn dữ liệu theo câu lệnh SQL. Chỉ thế là xong. Toàn bộ quá trình làm không cần phải lập trình. Nếu bạn tìm hiểu kỹ hơn hàm BS_SQL thì còn làm rất nhiều báo cáo phức tạp và tốc độ nhanh.

Mạnh đoán 1 chút nếu sai thì bỏ qua he :D
Hình như chỉ chạy trên Office 32 bít
 
Mạnh đoán 1 chút nếu sai thì bỏ qua he :D
Hình như chỉ chạy trên Office 32 bít

Đúng rồi. Vì Foxpro ODBC Driver hay Microsoft Visual FoxPro OLE DB Provider hiện nay chỉ hỗ trợ 32-bit nên Office và các add-in nhúng theo buộc phải là 32-bit mới chạy được.
 
Đúng rồi. Vì Foxpro ODBC Driver hay Microsoft Visual FoxPro OLE DB Provider hiện nay chỉ hỗ trợ 32-bit nên Office và các add-in nhúng theo buộc phải là 32-bit mới chạy được.
Vậy đoán thêm tí nữa
Hàm trong Atools là hàm mở rộng dùng ADODB lấy dữ liệu ... muốn lấy CSDL nào thì thêm cái Driver của nó + cái chuỗi kết nối là lấy khi SQLbuilder tạo và lưu nó ở đâu đó ...

trong trường hợp này FoxPro nó là 32 bít nên ko xử lý được là chính xác
....
Mạnh xử lý bài số 11 = ok kèm Video chạy tốt cho Excel 64 bít
 
mới làm lại chút cho nó thân thiện nhất có thể
chỉ bấm button và chọn file .... mọi cái đã có code lo rồi
chạy tốt trên Excel 32 bít và 64 bít

Liên kết: https://youtu.be/mVBBoIxv-tk
 
Vậy đoán thêm tí nữa
Hàm trong Atools là hàm mở rộng dùng ADODB lấy dữ liệu ... muốn lấy CSDL nào thì thêm cái Driver của nó + cái chuỗi kết nối là lấy khi SQLbuilder tạo và lưu nó ở đâu đó ...

trong trường hợp này FoxPro nó là 32 bít nên ko xử lý được là chính xác
....
Mạnh xử lý bài số 11 = ok kèm Video chạy tốt cho Excel 64 bít

Bạn viết ActiveX EXE trong trường hợp làm việc với driver, ole db 32-bit là ok. Tôi cũng viết nhanh một service phục vụ cho kết nối tới loại driver 32 bit này.
 
Lần chỉnh sửa cuối:
mới làm lại chút cho nó thân thiện nhất có thể
chỉ bấm button và chọn file .... mọi cái đã có code lo rồi
chạy tốt trên Excel 32 bít và 64 bít
Cũng mới cài cái VB6 bảng Portable để test thử vụ đi đường vòng, tạo ActiveX EXE.
Tôi thấy thư viện FireDAC đọc tốt nhiều loại CSDL sao bạn KM không lấy nó tạo tool nhỉ.
 
Cũng mới cài cái VB6 bảng Portable để test thử vụ đi đường vòng, tạo ActiveX EXE.
Tôi thấy thư viện FireDAC đọc tốt nhiều loại CSDL sao bạn KM không lấy nó tạo tool nhỉ.
có hết rồi mấy cái DLL úp trên này là thuần FireDAC đấy ... giờ thích CSDL nào nó hổ trợ là thêm cái chuỗi kết nối là xong thôi

Thuần FireDAC nè
 
Cũng mới cài cái VB6 bảng Portable để test thử vụ đi đường vòng, tạo ActiveX EXE.
Tôi thấy thư viện FireDAC đọc tốt nhiều loại CSDL sao bạn KM không lấy nó tạo tool nhỉ.
hỏi thăm chút .... thế bạn thử trên VB6 sao rùi ???
 
Rảnh vọc mấy ngày chốt lại 2 mục sau

1/ Viết SQLbuilder cho Foxpro = ok
2/ Thích nhích thêm 1 chút lấy Qua Internet cũng ok .... kiểu SQLTCP/IP cho FoxPro
.....
Cất kho lưu trữ thôi .................. ai cần thì có thể la nhỏ thôi nha :D

Cảm ơn chủ thớt đã mở chủ đề này ... cho Tôi có cảm hứng code két khi rảnh chơi cho vui là chính
 
Lần chỉnh sửa cuối:
hỏi thăm chút .... thế bạn thử trên VB6 sao rùi ???

À..chưa thành công vụ tạo Dll, rồi ActiveX EXE để chạy trên 64 bit. Tôi chưa biết cách tích hợp dll bên ngoài vô nên chạy vẫn báo lỗi thiếu component. Để rảnh ngâm cứu tài liệu tiếp.
 
lỡ chơi rồi thì chơi tới bến luôn ...
Xin giới thiệu với các tình yêu .... Tôi đang tiến hành phục chế tái hiện lại món đồ cổ mà Ms bỏ đi lâu rồi
để chạy nó trong thời đại số 4.0 .... mọi cái chỉ nhấn nút .... rất đơn giản ... vì thấy tây nó làm cái DBF View .... nên ghét tôi cũng bắt trước làm thôi ...

xong cái này tôi sẻ cho nó thành cái SQLTCP/IP cho Visual Fox Pro luôn ... cảm giác sẻ máu lửa hơn tây 1 chút thôi :D

Liên kết: https://youtu.be/_-2k5kaB008
 
hỏi thăm chút .... thế bạn thử trên VB6 sao rùi ???
Cách tôi làm cho Office 64bit là:
- Đăng ký driver vfpoled.dll vào C:\SysWOW64
- Tạo ActiveX Exe trên VB6 để kết nối lấy dữ liệu từ Foxpro.
- Trong Excel, khai báo Reference tới cái file Exe mới tạo. Vì ActiveX Exe sẽ tạo một phiên làm việc riêng trên nền 32bit của nó rồi lấy kết quả đưa vào Excel.


Screen Shot 2022-02-24 at 15.13.23.png

Screen Shot 2022-02-24 at 15.14.50.png
 
Lần chỉnh sửa cuối:
có hết rồi mấy cái DLL úp trên này là thuần FireDAC đấy ... giờ thích CSDL nào nó hổ trợ là thêm cái chuỗi kết nối là xong thôi

Thuần FireDAC nè
Mình chỉ biết Excel thuần túy thôi
Bài đã được tự động gộp:

CẢM ƠN CÁC ANH CHỊ ĐÃ HỖ TRỢ TÍCH CỰC
 
Mình chỉ biết Excel thuần túy thôi
Bài đã được tự động gộp:

CẢM ƠN CÁC ANH CHỊ ĐÃ HỖ TRỢ TÍCH CỰC

Vậy tại sao bạn không cài Office 32-bit rồi dùng công cụ để làm bình thường. Lập trình không phải ai cũng làm được tốt, mà nếu làm tốt phải có nhiều năm tháng học liên tục đấy.

Các bạn tạo xxxEXE 32 bit rồi nhúng trong Office 64-bit có để ý tốc độ bị chậm hơn rất nhiều không? Tôi làm thấy chậm gấp ít nhất 4 lần. Nếu dữ liệu nhiều chắc còn có thể hơn nữa.
 
Các bạn tạo xxxEXE 32 bit rồi nhúng trong Office 64-bit có để ý tốc độ bị chậm hơn rất nhiều không? Tôi làm thấy chậm gấp ít nhất 4 lần. Nếu dữ liệu nhiều chắc còn có thể hơn nữa.
Tốc độ chắn chắn là bị chậm hơn so với dùng DLL trực tiếp rồi đó bác Tuân, chưa cần đo cũng có thể suy ra được. Khi chương trình chính chạy, gọi ActiveX EXE thì nó phải chạy riêng một tiến trình (process) khác chương trình chính, rồi còn phải truyền, biên dịch tham số từ chương trình chính sang xxEXE, sau đó lại phải làm ngược chuyển kết quả từ xxEXE sang chương trình chính. Đây chỉ là giải pháp dã chiến, tình thế thôi. :)
 
Tốc độ chắn chắn là bị chậm hơn so với dùng DLL trực tiếp rồi đó bác Tuân, chưa cần đo cũng có thể suy ra được. Khi chương trình chính chạy, gọi ActiveX EXE thì nó phải chạy riêng một tiến trình (process) khác chương trình chính, rồi còn phải truyền, biên dịch tham số từ chương trình chính sang xxEXE, sau đó lại phải làm ngược chuyển kết quả từ xxEXE sang chương trình chính. Đây chỉ là giải pháp dã chiến, tình thế thôi. :)
Thử vậy xem có khác hơn không
1/ Viết 1 ActiveX DLL chỉ hàm kết nối cho Foxpro thôi
2/ còn lại từ ActiveX EXE load kết nối DLL xong xử lý nó

1645709071692.png
 
Lần chỉnh sửa cuối:
Thử vậy xem có khác hơn không
1/ Viết 1 ActiveX DLL chỉ hàm kết nối cho Foxpro thôi
2/ còn lại từ ActiveX EXE load kết nối DLL xong xử lý nó
Đây là cái cách đầu tiên tôi thử, sau đó thấy không cần thiết phải qua một cái Dll rồi mới tới EXE nên bỏ luôn bước 1.
 
Đây là cái cách đầu tiên tôi thử, sau đó thấy không cần thiết phải qua một cái Dll rồi mới tới EXE nên bỏ luôn bước 1.
Nhiều code trong Exe sẽ báo đầy virus mà exe chỉ viết 1 dòng code thôi xong nó load hết hàm trong dll Check viết gõ y trang đang load hàm trong dll
 
Nói về tốc độ thực thi và ứng dụng giữa DLL và EXE:

Screen Shot 2022-02-25 at 06.12.00.png

Screen Shot 2022-02-25 at 06.15.42.png

Cho google dịch:

An ActiveX EXE's code is run in a separate process. When the main program calls an ActiveX EXE's method, the system marshalls the call to translate the parameters into the ActiveX EXE's address space, calls the method, translates the results back into the main program's address space, and returns the result. This is slower than running an ActiveX DLL's method inside the main program's address space.
Because of the difference in speed, an ActiveX DLL is almost always preferable. The reason ActiveX EXEs are useful is they can run on a different computer than the main program while an ActiveX DLL must run on the same computer as the main program.
f you want a centralized server library, use an ActiveX EXE. The EXE can sit on a central computer and work directly with that computer's resources. If you need to frequently change how the code works, you can easily change it in one place.
 
Lần chỉnh sửa cuối:
úp dùm chữ lên thì Google mới dịch dịch ... còn chụp anh úp = thua:p
Đã thêm ở bài trên. Lưu ý là google dịch nó cũng trời thần lắm nhé. Tôi không giỏi tiếng Anh lắm nhưng đôi khi đọc các từ chuyên ngành của nó trực tiếp có thể sẽ hiểu đúng hơn là đọc bản dịch của Google.
 
1/ ActiveX DLL chạy nhanh hơn ActiveX EXE
2/ Vì vậy tôi code hết vào ActiveX DLL .... còn ActiveX EXE chỉ viết 1 dòng code duy nhất load nó thôi
nếu 32 bít thì sử dụng trực tiếp DLL còn 64 bit thì sử dụng ActiveX EXE

trong ActiveX EXE Viết 1 dòng code đại ý như sau ... xong từ Excel check nó gõ chấm ... nó có list của Hàm trong DLL

Mã:
Function GetCOM()
 1 dòng code viết vào đây nha .... thong thả tìm hiểu xem nếu kẹt lắm thì la tôi he
End Function
 
1/ ActiveX DLL chạy nhanh hơn ActiveX EXE
2/ Vì vậy tôi code hết vào ActiveX DLL .... còn ActiveX EXE chỉ viết 1 dòng code duy nhất load nó thôi
nếu 32 bít thì sử dụng trực tiếp DLL còn 64 bit thì sử dụng ActiveX EXE

trong ActiveX EXE Viết 1 dòng code đại ý như sau ... xong từ Excel check nó gõ chấm ... nó có list của Hàm trong DLL

Mã:
Function GetCOM()
 1 dòng code viết vào đây nha .... thong thả tìm hiểu xem nếu kẹt lắm thì la tôi he
End Function
:) vấn đề chính là nằm ở việc gọi EXE từ chương trình chính (Excel) để thực thi mà không phải là gọi trực tiếp từ DLL. Còn việc file EXE lại gọi hàm xử lý từ file DLL khác nó càng đi đường vòng nữa chứ không cải thiện tốc độ gì cả. Đối với ví dụ trên là kết nối với Foxpro database thì nó code đơn giản, nên tôi viết trực tiếp trong EXE luôn chứ không cần phải qua một DLL cho nó rườm rà.

Screen Shot 2022-02-25 at 09.55.34.png
 
:) vấn đề chính là nằm ở việc gọi EXE từ chương trình chính (Excel) để thực thi mà không phải là gọi trực tiếp từ DLL. Còn việc file EXE lại gọi hàm xử lý từ file DLL khác nó càng đi đường vòng nữa chứ không cải thiện tốc độ gì cả. Đối với ví dụ trên là kết nối với Foxpro database thì nó code đơn giản, nên tôi viết trực tiếp trong EXE luôn chứ không cần phải qua một DLL cho nó rườm rà.

View attachment 272452
thì tùy thôi tại thấy keo EXE nó chạy chậm hơn nên tôi mới vẻ ra vậy
Nhưng có 1 thực tế là nếu viết code nhiều thật nhiều vào ActiveX EXE thì trình code phải đạt theo tiêu chí X ... nếu không nó báo vài chục em Virus là thường ... nếu cũng Files đó chuyển qua ActiveX DLL thì lại ko có em nào cả

Cơ bản khác nhau vài dòng trên thôi ... còn tùy mình thích kiểu gì ??!!!

Tôi viết thêm vào cho nó lấy qua Internet luôn cho máu chút ... như nói bài trước
xong cái này nghiên cứu viết thêm cái Co và giản ============== là xong thôi -0-0-0-

Liên kết: https://youtu.be/MTOBzP72hOI
 
Lần chỉnh sửa cuối:
Chia sẻ thư viện BSDataService32 để kết nối database 32-bit trong ứng dụng 64-bit
(Hướng dẫn trong video này lấy ví dụ CSDL Foxpro tại bài đầu tiên)
Thư viện BSDataService32 là miễn phí, hỗ trợ cho những người chỉ dùng hàm và công cụ mà không biết lập trình (làm theo các bước trong video dưới đây) ; với người lập trình cũng có thể viết code để tùy biến lấy dữ liệu.
(*) Download thư viện BSDataService32
(*) Video hướng dẫn chi tiết ứng dụng
 
Chia sẻ thư viện BSDataService32 để kết nối database 32-bit trong ứng dụng 64-bit
(Hướng dẫn trong video này lấy ví dụ CSDL Foxpro tại bài đầu tiên)
Thư viện BSDataService32 là miễn phí, hỗ trợ cho những người chỉ dùng hàm và công cụ mà không biết lập trình (làm theo các bước trong video dưới đây) ; với người lập trình cũng có thể viết code để tùy biến lấy dữ liệu.
(*) Download thư viện BSDataService32
(*) Video hướng dẫn chi tiết ứng dụng
2 File viết = VB6 ... rảnh cũng bắt trước làm 1 cái dùng thôi :D
1.PNG2.PNG
 
2 File viết = VB6 ... rảnh cũng bắt trước làm 1 cái dùng thôi :D
View attachment 272477View attachment 272478

Trong tình huống viết ứng dụng với dữ liệu 32-bit thì mình viết VB6 rất nhanh gọn. Vì chỉ làm với data 32-bit chứ không đụng chạm hệ thống khác nên yên tâm làm VB6. Dung lượng nhỏ tí teo. Cái file "setup.exe" để cài đặt thư viện cũng làm luôn trong VB6 cho người dùng tiện cài đặt và nhìn có vẻ chuyên nghiệp :).
 
Trong tình huống viết ứng dụng với dữ liệu 32-bit thì mình viết VB6 rất nhanh gọn. Vì chỉ làm với data 32-bit chứ không đụng chạm hệ thống khác nên yên tâm làm VB6. Dung lượng nhỏ tí teo. Cái file "setup.exe" để cài đặt thư viện cũng làm luôn trong VB6 cho người dùng tiện cài đặt và nhìn có vẻ chuyên nghiệp :).
Thử nghĩ cách load cái vfpoledb.dll Từ trong tài nguyên VB6 xem có được không ... thay vì dùng File Setup xả nén nó vào system xong đăng ký no với Run As khi chạy file setup
 
Cách cài đặt thư viện "vfpoledb.dll" trong VB6

Khai báo hàm API:
Tôi dùng unicode nên code sẽ dài hơn chút nhưng sẽ an toàn nếu đường dẫn file DLL chứa ký tự có dấu.
C#:
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteW" (ByVal hwnd As Long, _
                                                                               ByVal lpOperation As String, _
                                                                               ByVal lpFile As String, _
                                                                               ByVal lpParameters As String, _
                                                                               ByVal lpDirectory As String, _
                                                                               ByVal nShowCmd As Long) As Long

Lệnh chạy install:

C#:
Private Sub InstallVFPOLEDB()
    Dim x&, sFile As String, sParam As String
    sFile = StrConv("Regsvr32.exe", vbUnicode)
   'Đường dẫn DLL tùy bạn chọn. Nếu lấy từ chính file exe đang chạy thì là:  App.Path & "\vfpoledb.dll"
    sParam = StrConv("""C:\Program Files (x86)\Common Files\System\Ole DB\vfpoledb.dll"" /s", vbUnicode)
    x = ShellExecute(hwnd, StrConv("runas", vbUnicode), sFile, sParam, "", 0)
    If x <= 32 Then
        AlertIfError x
    Else
        MsgBox "Install successful." & vbNewLine & _
               "Application can use classes in this library.", vbInformation
        Unload Me
    End If
End Sub
'-------------------------------------------------------------------------------------
Private Sub UninstallVFPOLEDB()
    Dim x&, sFile As String, sParam As String
    sFile = StrConv("Regsvr32.exe", vbUnicode)
    sParam = StrConv("""C:\Program Files (x86)\Common Files\System\Ole DB\vfpoledb.dll""  /u/s", vbUnicode)
    x = ShellExecute(hwnd, StrConv("runas", vbUnicode), sFile, sParam, "", 0)
    If x <= 32 Then
        AlertIfError x
    Else
        MsgBox "Uninstall successful." & vbNewLine & _
               "Application can not use classes in this library.", vbInformation
        Unload Me
    End If
End Sub

Mã nguồn trên là VB6 nhưng dùng mẫu định dạng C# của GPE cho đẹp. Các bạn không nhầm lẫn loại code nhé.
 
Lần chỉnh sửa cuối:
vẫn phải đăng ký nó với windows ... ít ngày nữa rảnh mạnh thử cách ko cần đăng ký xem có dc ko ... dùng hàm load nó
 
Tôi thấy có cái hàm của người Nga viết bằng VB6 để làm việc với thư viện COM mà không cần đăng ký (register). Tôi không rành mấy vụ này nên post lên đây xem có giúp được gì không.
- module load thư viện COM.
- cái tool đọc thông tin thư viện - Library Info

Screen Shot 2022-02-26 at 08.22.54.png


Mã:
' The module modTrickUnregCOM.bas - for working with COM libraries without registration.
' © Krivous Anatolii Anatolevich (The trick), 2015

Option Explicit

Public Type GUID
    data1       As Long
    data2       As Integer
    data3       As Integer
    data4(7)    As Byte
End Type

Private Declare Function CLSIDFromString Lib "ole32.dll" ( _
                         ByVal lpszCLSID As Long, _
                         ByRef clsid As GUID) As Long
Private Declare Function GetMem4 Lib "msvbvm60" ( _
                         ByRef src As Any, _
                         ByRef dst As Any) As Long
Private Declare Function SysFreeString Lib "oleaut32" ( _
                         ByVal lpbstr As Long) As Long
Private Declare Function LoadLibrary Lib "kernel32" _
                         Alias "LoadLibraryW" ( _
                         ByVal lpLibFileName As Long) As Long
Private Declare Function GetModuleHandle Lib "kernel32" _
                         Alias "GetModuleHandleW" ( _
                         ByVal lpModuleName As Long) As Long
Private Declare Function FreeLibrary Lib "kernel32" ( _
                         ByVal hLibModule As Long) As Long
Private Declare Function GetProcAddress Lib "kernel32" ( _
                         ByVal hModule As Long, _
                         ByVal lpProcName As String) As Long
Private Declare Function DispCallFunc Lib "oleaut32" ( _
                         ByVal pvInstance As Any, _
                         ByVal oVft As Long, _
                         ByVal cc As Integer, _
                         ByVal vtReturn As Integer, _
                         ByVal cActuals As Long, _
                         ByRef prgvt As Any, _
                         ByRef prgpvarg As Any, _
                         ByRef pvargResult As Variant) As Long
Private Declare Function LoadTypeLibEx Lib "oleaut32" ( _
                         ByVal szFile As Long, _
                         ByVal regkind As Long, _
                         ByRef pptlib As IUnknown) As Long
Private Declare Function memcpy Lib "kernel32" _
                         Alias "RtlMoveMemory" ( _
                         ByRef Destination As Any, _
                         ByRef Source As Any, _
                         ByVal Length As Long) As Long
Private Declare Function CreateStdDispatch Lib "oleaut32" ( _
                         ByVal punkOuter As IUnknown, _
                         ByVal pvThis As IUnknown, _
                         ByVal ptinfo As IUnknown, _
                         ByRef ppunkStdDisp As IUnknown) As Long
                        
Private Const IID_IClassFactory   As String = "{00000001-0000-0000-C000-000000000046}"
Private Const IID_IUnknown        As String = "{00000000-0000-0000-C000-000000000046}"
Private Const CC_STDCALL          As Long = 4
Private Const REGKIND_NONE        As Long = 2
Private Const TKIND_COCLASS       As Long = 5
Private Const TKIND_DISPATCH      As Long = 4
Private Const TKIND_INTERFACE     As Long = 3

Dim iidClsFctr      As GUID
Dim iidUnk          As GUID
Dim isInit          As Boolean

' // Get all co-classes described in type library.
Public Function GetAllCoclasses( _
                ByRef path As String, _
                ByRef listOfClsid() As GUID, _
                ByRef listOfNames() As String, _
                ByRef countCoClass As Long) As Boolean
                
    Dim typeLib As IUnknown
    Dim typeInf As IUnknown
    Dim ret     As Long
    Dim count   As Long
    Dim index   As Long
    Dim pAttr   As Long
    Dim tKind   As Long
    
    ret = LoadTypeLibEx(StrPtr(path), REGKIND_NONE, typeLib)
    
    If ret Then
        Err.Raise ret
        Exit Function
    End If
    
    count = ITypeLib_GetTypeInfoCount(typeLib)
    countCoClass = 0
    
    If count > 0 Then
    
        ReDim listOfClsid(count - 1)
        ReDim listOfNames(count - 1)
        
        For index = 0 To count - 1
        
            ret = ITypeLib_GetTypeInfo(typeLib, index, typeInf)
                        
            If ret Then
                Err.Raise ret
                Exit Function
            End If
            
            ITypeInfo_GetTypeAttr typeInf, pAttr
            
            GetMem4 ByVal pAttr + &H28, tKind
            
            If tKind = TKIND_COCLASS Then
            
                memcpy listOfClsid(countCoClass), ByVal pAttr, Len(listOfClsid(countCoClass))
                ret = ITypeInfo_GetDocumentation(typeInf, -1, listOfNames(countCoClass), vbNullString, 0, vbNullString)
                
                If ret Then
                    ITypeInfo_ReleaseTypeAttr typeInf, pAttr
                    Err.Raise ret
                    Exit Function
                End If
                
                countCoClass = countCoClass + 1
                
            End If
            
            ITypeInfo_ReleaseTypeAttr typeInf, pAttr
            
            Set typeInf = Nothing
            
        Next
        
    End If
    
    If countCoClass Then
        
        ReDim Preserve listOfClsid(countCoClass - 1)
        ReDim Preserve listOfNames(countCoClass - 1)
    
    Else
    
        Erase listOfClsid()
        Erase listOfNames()
        
    End If
    
    GetAllCoclasses = True
    
End Function

' // Create IDispach implementation described in type library.
Public Function CreateIDispatch( _
                ByRef obj As IUnknown, _
                ByRef typeLibPath As String, _
                ByRef interfaceName As String) As Object
                
    Dim typeLib As IUnknown
    Dim typeInf As IUnknown
    Dim ret     As Long
    Dim retObj  As IUnknown
    Dim pAttr   As Long
    Dim tKind   As Long
    
    ret = LoadTypeLibEx(StrPtr(typeLibPath), REGKIND_NONE, typeLib)
    
    If ret Then
        Err.Raise ret
        Exit Function
    End If
    
    ret = ITypeLib_FindName(typeLib, interfaceName, 0, typeInf, 0, 1)
    
    If typeInf Is Nothing Then
        Err.Raise &H80004002, , "Interface not found"
        Exit Function
    End If
    
    ITypeInfo_GetTypeAttr typeInf, pAttr
    GetMem4 ByVal pAttr + &H28, tKind
    ITypeInfo_ReleaseTypeAttr typeInf, pAttr
    
    If tKind = TKIND_DISPATCH Then
        Set CreateIDispatch = obj
        Exit Function
    ElseIf tKind <> TKIND_INTERFACE Then
        Err.Raise &H80004002, , "Interface not found"
        Exit Function
    End If
 
    ret = CreateStdDispatch(Nothing, obj, typeInf, retObj)
    
    If ret Then
        Err.Raise ret
        Exit Function
    End If
    
    Set CreateIDispatch = retObj

End Function

' // Create object by Name.
Public Function CreateObjectEx2( _
                ByRef pathToDll As String, _
                ByRef pathToTLB As String, _
                ByRef className As String) As IUnknown
                
    Dim typeLib As IUnknown
    Dim typeInf As IUnknown
    Dim ret     As Long
    Dim pAttr   As Long
    Dim tKind   As Long
    Dim clsid   As GUID
    
    ret = LoadTypeLibEx(StrPtr(pathToTLB), REGKIND_NONE, typeLib)
    
    If ret Then
        Err.Raise ret
        Exit Function
    End If
    
    ret = ITypeLib_FindName(typeLib, className, 0, typeInf, 0, 1)
    
    If typeInf Is Nothing Then
        Err.Raise &H80040111, , "Class not found in type library"
        Exit Function
    End If

    ITypeInfo_GetTypeAttr typeInf, pAttr
    
    GetMem4 ByVal pAttr + &H28, tKind
    
    If tKind = TKIND_COCLASS Then
        memcpy clsid, ByVal pAttr, Len(clsid)
    Else
        Err.Raise &H80040111, , "Class not found in type library"
        Exit Function
    End If
    
    ITypeInfo_ReleaseTypeAttr typeInf, pAttr
            
    Set CreateObjectEx2 = CreateObjectEx(pathToDll, clsid)
    
End Function
                
' // Create object by CLSID and path.
Public Function CreateObjectEx( _
                ByRef path As String, _
                ByRef clsid As GUID) As IUnknown
                
    Dim hLib    As Long
    Dim lpAddr  As Long
    Dim isLoad  As Boolean
    
    hLib = GetModuleHandle(StrPtr(path))
    
    If hLib = 0 Then
    
        hLib = LoadLibrary(StrPtr(path))
        If hLib = 0 Then
            Err.Raise 53, , Error(53) & " " & Chr$(34) & path & Chr$(34)
            Exit Function
        End If
        
        isLoad = True
        
    End If
    
    lpAddr = GetProcAddress(hLib, "DllGetClassObject")
    
    If lpAddr = 0 Then
        If isLoad Then FreeLibrary hLib
        Err.Raise 453, , "Can't find dll entry point DllGetClasesObject in " & Chr$(34) & path & Chr$(34)
        Exit Function
    End If

    If Not isInit Then
        CLSIDFromString StrPtr(IID_IClassFactory), iidClsFctr
        CLSIDFromString StrPtr(IID_IUnknown), iidUnk
        isInit = True
    End If
    
    Dim ret     As Long
    Dim out     As IUnknown
    
    ret = DllGetClassObject(lpAddr, clsid, iidClsFctr, out)
    
    If ret = 0 Then

        ret = IClassFactory_CreateInstance(out, 0, iidUnk, CreateObjectEx)
    
    Else
    
        If isLoad Then FreeLibrary hLib
        Err.Raise ret
        Exit Function
        
    End If
    
    Set out = Nothing
    
    If ret Then
    
        If isLoad Then FreeLibrary hLib
        Err.Raise ret

    End If
    
End Function

' // Unload DLL if not used.
Public Function UnloadLibrary( _
                ByRef path As String) As Boolean
                
    Dim hLib    As Long
    Dim lpAddr  As Long
    Dim ret     As Long
    
    If Not isInit Then Exit Function
    
    hLib = GetModuleHandle(StrPtr(path))
    If hLib = 0 Then Exit Function
    
    lpAddr = GetProcAddress(hLib, "DllCanUnloadNow")
    If lpAddr = 0 Then Exit Function
    
    ret = DllCanUnloadNow(lpAddr)
    
    If ret = 0 Then
        FreeLibrary hLib
        UnloadLibrary = True
    End If
    
End Function

' // Call "DllGetClassObject" function using a pointer.
Private Function DllGetClassObject( _
                 ByVal funcAddr As Long, _
                 ByRef clsid As GUID, _
                 ByRef iid As GUID, _
                 ByRef out As IUnknown) As Long
                
    Dim params(2)   As Variant
    Dim types(2)    As Integer
    Dim list(2)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
    
    params(0) = VarPtr(clsid)
    params(1) = VarPtr(iid)
    params(2) = VarPtr(out)
    
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
    
    resultCall = DispCallFunc(0&, funcAddr, CC_STDCALL, vbLong, 3, types(0), list(0), pReturn)
            
    If resultCall Then Err.Raise 5: Exit Function
    
    DllGetClassObject = pReturn
    
End Function

' // Call "DllCanUnloadNow" function using a pointer.
Private Function DllCanUnloadNow( _
                 ByVal funcAddr As Long) As Long
                
    Dim resultCall  As Long
    Dim pReturn     As Variant
    
    resultCall = DispCallFunc(0&, funcAddr, CC_STDCALL, vbLong, 0, ByVal 0&, ByVal 0&, pReturn)
            
    If resultCall Then Err.Raise 5: Exit Function
    
    DllCanUnloadNow = pReturn
    
End Function

' // Call "IClassFactory:CreateInstance" method.
Private Function IClassFactory_CreateInstance( _
                 ByVal obj As IUnknown, _
                 ByVal punkOuter As Long, _
                 ByRef riid As GUID, _
                 ByRef out As IUnknown) As Long
    
    Dim params(2)   As Variant
    Dim types(2)    As Integer
    Dim list(2)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
    
    params(0) = punkOuter
    params(1) = VarPtr(riid)
    params(2) = VarPtr(out)
    
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
    
    resultCall = DispCallFunc(obj, &HC, CC_STDCALL, vbLong, 3, types(0), list(0), pReturn)
          
    If resultCall Then Err.Raise resultCall: Exit Function
    
    IClassFactory_CreateInstance = pReturn
    
End Function

' // Call "ITypeLib:GetTypeInfoCount" method.
Private Function ITypeLib_GetTypeInfoCount( _
                 ByVal obj As IUnknown) As Long
    
    Dim resultCall  As Long
    Dim pReturn     As Variant

    resultCall = DispCallFunc(obj, &HC, CC_STDCALL, vbLong, 0, ByVal 0&, ByVal 0&, pReturn)
          
    If resultCall Then Err.Raise resultCall: Exit Function
    
    ITypeLib_GetTypeInfoCount = pReturn
    
End Function

' // Call "ITypeLib:GetTypeInfo" method.
Private Function ITypeLib_GetTypeInfo( _
                 ByVal obj As IUnknown, _
                 ByVal index As Long, _
                 ByRef ppTInfo As IUnknown) As Long
    
    Dim params(1)   As Variant
    Dim types(1)    As Integer
    Dim list(1)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
    
    params(0) = index
    params(1) = VarPtr(ppTInfo)
    
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
    
    resultCall = DispCallFunc(obj, &H10, CC_STDCALL, vbLong, 2, types(0), list(0), pReturn)
          
    If resultCall Then Err.Raise resultCall: Exit Function
    
    ITypeLib_GetTypeInfo = pReturn
    
End Function

' // Call "ITypeLib:FindName" method.
Private Function ITypeLib_FindName( _
                 ByVal obj As IUnknown, _
                 ByRef szNameBuf As String, _
                 ByVal lHashVal As Long, _
                 ByRef ppTInfo As IUnknown, _
                 ByRef rgMemId As Long, _
                 ByRef pcFound As Integer) As Long
    
    Dim params(4)   As Variant
    Dim types(4)    As Integer
    Dim list(4)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
    
    params(0) = StrPtr(szNameBuf)
    params(1) = lHashVal
    params(2) = VarPtr(ppTInfo)
    params(3) = VarPtr(rgMemId)
    params(4) = VarPtr(pcFound)
    
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
    
    resultCall = DispCallFunc(obj, &H2C, CC_STDCALL, vbLong, 5, types(0), list(0), pReturn)
          
    If resultCall Then Err.Raise resultCall: Exit Function
    
    ITypeLib_FindName = pReturn
    
End Function

' // Call "ITypeInfo:GetTypeAttr" method.
Private Sub ITypeInfo_GetTypeAttr( _
            ByVal obj As IUnknown, _
            ByRef ppTypeAttr As Long)
    
    Dim resultCall  As Long
    Dim pReturn     As Variant
    
    pReturn = VarPtr(ppTypeAttr)
    
    resultCall = DispCallFunc(obj, &HC, CC_STDCALL, vbEmpty, 1, vbLong, VarPtr(pReturn), 0)
          
    If resultCall Then Err.Raise resultCall: Exit Sub

End Sub

' // Call "ITypeInfo:GetDocumentation" method.
Private Function ITypeInfo_GetDocumentation( _
                 ByVal obj As IUnknown, _
                 ByVal memid As Long, _
                 ByRef pBstrName As String, _
                 ByRef pBstrDocString As String, _
                 ByRef pdwHelpContext As Long, _
                 ByRef pBstrHelpFile As String) As Long
    
    Dim params(4)   As Variant
    Dim types(4)    As Integer
    Dim list(4)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
    
    params(0) = memid
    params(1) = VarPtr(pBstrName)
    params(2) = VarPtr(pBstrDocString)
    params(3) = VarPtr(pdwHelpContext)
    params(4) = VarPtr(pBstrHelpFile)
    
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
    
    resultCall = DispCallFunc(obj, &H30, CC_STDCALL, vbLong, 5, types(0), list(0), pReturn)
          
    If resultCall Then Err.Raise resultCall: Exit Function
    
    ITypeInfo_GetDocumentation = pReturn
    
End Function

' // Call "ITypeInfo:ReleaseTypeAttr" method.
Private Sub ITypeInfo_ReleaseTypeAttr( _
            ByVal obj As IUnknown, _
            ByVal ppTypeAttr As Long)
    
    Dim resultCall  As Long
    
    resultCall = DispCallFunc(obj, &H4C, CC_STDCALL, vbEmpty, 1, vbLong, VarPtr(CVar(ppTypeAttr)), 0)
          
    If resultCall Then Err.Raise resultCall: Exit Sub

End Sub
 

File đính kèm

Tôi thấy có cái hàm của người Nga viết bằng VB6 để làm việc với thư viện COM mà không cần đăng ký (register). Tôi không rành mấy vụ này nên post lên đây xem có giúp được gì không.
- module load thư viện COM.
- cái tool đọc thông tin thư viện - Library Info

View attachment 272485


Mã:
' The module modTrickUnregCOM.bas - for working with COM libraries without registration.
' © Krivous Anatolii Anatolevich (The trick), 2015

Option Explicit

Public Type GUID
    data1       As Long
    data2       As Integer
    data3       As Integer
    data4(7)    As Byte
End Type

Private Declare Function CLSIDFromString Lib "ole32.dll" ( _
                         ByVal lpszCLSID As Long, _
                         ByRef clsid As GUID) As Long
Private Declare Function GetMem4 Lib "msvbvm60" ( _
                         ByRef src As Any, _
                         ByRef dst As Any) As Long
Private Declare Function SysFreeString Lib "oleaut32" ( _
                         ByVal lpbstr As Long) As Long
Private Declare Function LoadLibrary Lib "kernel32" _
                         Alias "LoadLibraryW" ( _
                         ByVal lpLibFileName As Long) As Long
Private Declare Function GetModuleHandle Lib "kernel32" _
                         Alias "GetModuleHandleW" ( _
                         ByVal lpModuleName As Long) As Long
Private Declare Function FreeLibrary Lib "kernel32" ( _
                         ByVal hLibModule As Long) As Long
Private Declare Function GetProcAddress Lib "kernel32" ( _
                         ByVal hModule As Long, _
                         ByVal lpProcName As String) As Long
Private Declare Function DispCallFunc Lib "oleaut32" ( _
                         ByVal pvInstance As Any, _
                         ByVal oVft As Long, _
                         ByVal cc As Integer, _
                         ByVal vtReturn As Integer, _
                         ByVal cActuals As Long, _
                         ByRef prgvt As Any, _
                         ByRef prgpvarg As Any, _
                         ByRef pvargResult As Variant) As Long
Private Declare Function LoadTypeLibEx Lib "oleaut32" ( _
                         ByVal szFile As Long, _
                         ByVal regkind As Long, _
                         ByRef pptlib As IUnknown) As Long
Private Declare Function memcpy Lib "kernel32" _
                         Alias "RtlMoveMemory" ( _
                         ByRef Destination As Any, _
                         ByRef Source As Any, _
                         ByVal Length As Long) As Long
Private Declare Function CreateStdDispatch Lib "oleaut32" ( _
                         ByVal punkOuter As IUnknown, _
                         ByVal pvThis As IUnknown, _
                         ByVal ptinfo As IUnknown, _
                         ByRef ppunkStdDisp As IUnknown) As Long
                       
Private Const IID_IClassFactory   As String = "{00000001-0000-0000-C000-000000000046}"
Private Const IID_IUnknown        As String = "{00000000-0000-0000-C000-000000000046}"
Private Const CC_STDCALL          As Long = 4
Private Const REGKIND_NONE        As Long = 2
Private Const TKIND_COCLASS       As Long = 5
Private Const TKIND_DISPATCH      As Long = 4
Private Const TKIND_INTERFACE     As Long = 3

Dim iidClsFctr      As GUID
Dim iidUnk          As GUID
Dim isInit          As Boolean

' // Get all co-classes described in type library.
Public Function GetAllCoclasses( _
                ByRef path As String, _
                ByRef listOfClsid() As GUID, _
                ByRef listOfNames() As String, _
                ByRef countCoClass As Long) As Boolean
               
    Dim typeLib As IUnknown
    Dim typeInf As IUnknown
    Dim ret     As Long
    Dim count   As Long
    Dim index   As Long
    Dim pAttr   As Long
    Dim tKind   As Long
   
    ret = LoadTypeLibEx(StrPtr(path), REGKIND_NONE, typeLib)
   
    If ret Then
        Err.Raise ret
        Exit Function
    End If
   
    count = ITypeLib_GetTypeInfoCount(typeLib)
    countCoClass = 0
   
    If count > 0 Then
   
        ReDim listOfClsid(count - 1)
        ReDim listOfNames(count - 1)
       
        For index = 0 To count - 1
       
            ret = ITypeLib_GetTypeInfo(typeLib, index, typeInf)
                       
            If ret Then
                Err.Raise ret
                Exit Function
            End If
           
            ITypeInfo_GetTypeAttr typeInf, pAttr
           
            GetMem4 ByVal pAttr + &H28, tKind
           
            If tKind = TKIND_COCLASS Then
           
                memcpy listOfClsid(countCoClass), ByVal pAttr, Len(listOfClsid(countCoClass))
                ret = ITypeInfo_GetDocumentation(typeInf, -1, listOfNames(countCoClass), vbNullString, 0, vbNullString)
               
                If ret Then
                    ITypeInfo_ReleaseTypeAttr typeInf, pAttr
                    Err.Raise ret
                    Exit Function
                End If
               
                countCoClass = countCoClass + 1
               
            End If
           
            ITypeInfo_ReleaseTypeAttr typeInf, pAttr
           
            Set typeInf = Nothing
           
        Next
       
    End If
   
    If countCoClass Then
       
        ReDim Preserve listOfClsid(countCoClass - 1)
        ReDim Preserve listOfNames(countCoClass - 1)
   
    Else
   
        Erase listOfClsid()
        Erase listOfNames()
       
    End If
   
    GetAllCoclasses = True
   
End Function

' // Create IDispach implementation described in type library.
Public Function CreateIDispatch( _
                ByRef obj As IUnknown, _
                ByRef typeLibPath As String, _
                ByRef interfaceName As String) As Object
               
    Dim typeLib As IUnknown
    Dim typeInf As IUnknown
    Dim ret     As Long
    Dim retObj  As IUnknown
    Dim pAttr   As Long
    Dim tKind   As Long
   
    ret = LoadTypeLibEx(StrPtr(typeLibPath), REGKIND_NONE, typeLib)
   
    If ret Then
        Err.Raise ret
        Exit Function
    End If
   
    ret = ITypeLib_FindName(typeLib, interfaceName, 0, typeInf, 0, 1)
   
    If typeInf Is Nothing Then
        Err.Raise &H80004002, , "Interface not found"
        Exit Function
    End If
   
    ITypeInfo_GetTypeAttr typeInf, pAttr
    GetMem4 ByVal pAttr + &H28, tKind
    ITypeInfo_ReleaseTypeAttr typeInf, pAttr
   
    If tKind = TKIND_DISPATCH Then
        Set CreateIDispatch = obj
        Exit Function
    ElseIf tKind <> TKIND_INTERFACE Then
        Err.Raise &H80004002, , "Interface not found"
        Exit Function
    End If
 
    ret = CreateStdDispatch(Nothing, obj, typeInf, retObj)
   
    If ret Then
        Err.Raise ret
        Exit Function
    End If
   
    Set CreateIDispatch = retObj

End Function

' // Create object by Name.
Public Function CreateObjectEx2( _
                ByRef pathToDll As String, _
                ByRef pathToTLB As String, _
                ByRef className As String) As IUnknown
               
    Dim typeLib As IUnknown
    Dim typeInf As IUnknown
    Dim ret     As Long
    Dim pAttr   As Long
    Dim tKind   As Long
    Dim clsid   As GUID
   
    ret = LoadTypeLibEx(StrPtr(pathToTLB), REGKIND_NONE, typeLib)
   
    If ret Then
        Err.Raise ret
        Exit Function
    End If
   
    ret = ITypeLib_FindName(typeLib, className, 0, typeInf, 0, 1)
   
    If typeInf Is Nothing Then
        Err.Raise &H80040111, , "Class not found in type library"
        Exit Function
    End If

    ITypeInfo_GetTypeAttr typeInf, pAttr
   
    GetMem4 ByVal pAttr + &H28, tKind
   
    If tKind = TKIND_COCLASS Then
        memcpy clsid, ByVal pAttr, Len(clsid)
    Else
        Err.Raise &H80040111, , "Class not found in type library"
        Exit Function
    End If
   
    ITypeInfo_ReleaseTypeAttr typeInf, pAttr
           
    Set CreateObjectEx2 = CreateObjectEx(pathToDll, clsid)
   
End Function
               
' // Create object by CLSID and path.
Public Function CreateObjectEx( _
                ByRef path As String, _
                ByRef clsid As GUID) As IUnknown
               
    Dim hLib    As Long
    Dim lpAddr  As Long
    Dim isLoad  As Boolean
   
    hLib = GetModuleHandle(StrPtr(path))
   
    If hLib = 0 Then
   
        hLib = LoadLibrary(StrPtr(path))
        If hLib = 0 Then
            Err.Raise 53, , Error(53) & " " & Chr$(34) & path & Chr$(34)
            Exit Function
        End If
       
        isLoad = True
       
    End If
   
    lpAddr = GetProcAddress(hLib, "DllGetClassObject")
   
    If lpAddr = 0 Then
        If isLoad Then FreeLibrary hLib
        Err.Raise 453, , "Can't find dll entry point DllGetClasesObject in " & Chr$(34) & path & Chr$(34)
        Exit Function
    End If

    If Not isInit Then
        CLSIDFromString StrPtr(IID_IClassFactory), iidClsFctr
        CLSIDFromString StrPtr(IID_IUnknown), iidUnk
        isInit = True
    End If
   
    Dim ret     As Long
    Dim out     As IUnknown
   
    ret = DllGetClassObject(lpAddr, clsid, iidClsFctr, out)
   
    If ret = 0 Then

        ret = IClassFactory_CreateInstance(out, 0, iidUnk, CreateObjectEx)
   
    Else
   
        If isLoad Then FreeLibrary hLib
        Err.Raise ret
        Exit Function
       
    End If
   
    Set out = Nothing
   
    If ret Then
   
        If isLoad Then FreeLibrary hLib
        Err.Raise ret

    End If
   
End Function

' // Unload DLL if not used.
Public Function UnloadLibrary( _
                ByRef path As String) As Boolean
               
    Dim hLib    As Long
    Dim lpAddr  As Long
    Dim ret     As Long
   
    If Not isInit Then Exit Function
   
    hLib = GetModuleHandle(StrPtr(path))
    If hLib = 0 Then Exit Function
   
    lpAddr = GetProcAddress(hLib, "DllCanUnloadNow")
    If lpAddr = 0 Then Exit Function
   
    ret = DllCanUnloadNow(lpAddr)
   
    If ret = 0 Then
        FreeLibrary hLib
        UnloadLibrary = True
    End If
   
End Function

' // Call "DllGetClassObject" function using a pointer.
Private Function DllGetClassObject( _
                 ByVal funcAddr As Long, _
                 ByRef clsid As GUID, _
                 ByRef iid As GUID, _
                 ByRef out As IUnknown) As Long
               
    Dim params(2)   As Variant
    Dim types(2)    As Integer
    Dim list(2)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
   
    params(0) = VarPtr(clsid)
    params(1) = VarPtr(iid)
    params(2) = VarPtr(out)
   
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
   
    resultCall = DispCallFunc(0&, funcAddr, CC_STDCALL, vbLong, 3, types(0), list(0), pReturn)
           
    If resultCall Then Err.Raise 5: Exit Function
   
    DllGetClassObject = pReturn
   
End Function

' // Call "DllCanUnloadNow" function using a pointer.
Private Function DllCanUnloadNow( _
                 ByVal funcAddr As Long) As Long
               
    Dim resultCall  As Long
    Dim pReturn     As Variant
   
    resultCall = DispCallFunc(0&, funcAddr, CC_STDCALL, vbLong, 0, ByVal 0&, ByVal 0&, pReturn)
           
    If resultCall Then Err.Raise 5: Exit Function
   
    DllCanUnloadNow = pReturn
   
End Function

' // Call "IClassFactory:CreateInstance" method.
Private Function IClassFactory_CreateInstance( _
                 ByVal obj As IUnknown, _
                 ByVal punkOuter As Long, _
                 ByRef riid As GUID, _
                 ByRef out As IUnknown) As Long
   
    Dim params(2)   As Variant
    Dim types(2)    As Integer
    Dim list(2)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
   
    params(0) = punkOuter
    params(1) = VarPtr(riid)
    params(2) = VarPtr(out)
   
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
   
    resultCall = DispCallFunc(obj, &HC, CC_STDCALL, vbLong, 3, types(0), list(0), pReturn)
         
    If resultCall Then Err.Raise resultCall: Exit Function
   
    IClassFactory_CreateInstance = pReturn
   
End Function

' // Call "ITypeLib:GetTypeInfoCount" method.
Private Function ITypeLib_GetTypeInfoCount( _
                 ByVal obj As IUnknown) As Long
   
    Dim resultCall  As Long
    Dim pReturn     As Variant

    resultCall = DispCallFunc(obj, &HC, CC_STDCALL, vbLong, 0, ByVal 0&, ByVal 0&, pReturn)
         
    If resultCall Then Err.Raise resultCall: Exit Function
   
    ITypeLib_GetTypeInfoCount = pReturn
   
End Function

' // Call "ITypeLib:GetTypeInfo" method.
Private Function ITypeLib_GetTypeInfo( _
                 ByVal obj As IUnknown, _
                 ByVal index As Long, _
                 ByRef ppTInfo As IUnknown) As Long
   
    Dim params(1)   As Variant
    Dim types(1)    As Integer
    Dim list(1)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
   
    params(0) = index
    params(1) = VarPtr(ppTInfo)
   
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
   
    resultCall = DispCallFunc(obj, &H10, CC_STDCALL, vbLong, 2, types(0), list(0), pReturn)
         
    If resultCall Then Err.Raise resultCall: Exit Function
   
    ITypeLib_GetTypeInfo = pReturn
   
End Function

' // Call "ITypeLib:FindName" method.
Private Function ITypeLib_FindName( _
                 ByVal obj As IUnknown, _
                 ByRef szNameBuf As String, _
                 ByVal lHashVal As Long, _
                 ByRef ppTInfo As IUnknown, _
                 ByRef rgMemId As Long, _
                 ByRef pcFound As Integer) As Long
   
    Dim params(4)   As Variant
    Dim types(4)    As Integer
    Dim list(4)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
   
    params(0) = StrPtr(szNameBuf)
    params(1) = lHashVal
    params(2) = VarPtr(ppTInfo)
    params(3) = VarPtr(rgMemId)
    params(4) = VarPtr(pcFound)
   
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
   
    resultCall = DispCallFunc(obj, &H2C, CC_STDCALL, vbLong, 5, types(0), list(0), pReturn)
         
    If resultCall Then Err.Raise resultCall: Exit Function
   
    ITypeLib_FindName = pReturn
   
End Function

' // Call "ITypeInfo:GetTypeAttr" method.
Private Sub ITypeInfo_GetTypeAttr( _
            ByVal obj As IUnknown, _
            ByRef ppTypeAttr As Long)
   
    Dim resultCall  As Long
    Dim pReturn     As Variant
   
    pReturn = VarPtr(ppTypeAttr)
   
    resultCall = DispCallFunc(obj, &HC, CC_STDCALL, vbEmpty, 1, vbLong, VarPtr(pReturn), 0)
         
    If resultCall Then Err.Raise resultCall: Exit Sub

End Sub

' // Call "ITypeInfo:GetDocumentation" method.
Private Function ITypeInfo_GetDocumentation( _
                 ByVal obj As IUnknown, _
                 ByVal memid As Long, _
                 ByRef pBstrName As String, _
                 ByRef pBstrDocString As String, _
                 ByRef pdwHelpContext As Long, _
                 ByRef pBstrHelpFile As String) As Long
   
    Dim params(4)   As Variant
    Dim types(4)    As Integer
    Dim list(4)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
   
    params(0) = memid
    params(1) = VarPtr(pBstrName)
    params(2) = VarPtr(pBstrDocString)
    params(3) = VarPtr(pdwHelpContext)
    params(4) = VarPtr(pBstrHelpFile)
   
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
   
    resultCall = DispCallFunc(obj, &H30, CC_STDCALL, vbLong, 5, types(0), list(0), pReturn)
         
    If resultCall Then Err.Raise resultCall: Exit Function
   
    ITypeInfo_GetDocumentation = pReturn
   
End Function

' // Call "ITypeInfo:ReleaseTypeAttr" method.
Private Sub ITypeInfo_ReleaseTypeAttr( _
            ByVal obj As IUnknown, _
            ByVal ppTypeAttr As Long)
   
    Dim resultCall  As Long
   
    resultCall = DispCallFunc(obj, &H4C, CC_STDCALL, vbEmpty, 1, vbLong, VarPtr(CVar(ppTypeAttr)), 0)
         
    If resultCall Then Err.Raise resultCall: Exit Sub

End Sub
Em nhìn là thấy chống mặt rồi
 
Tôi viết hàm sau để check 1 COM sử dụng chung cho VBA và VB6... chia sẻ cho ai cần nó
tối qua tới nay tôi thử với File vfpoledb.dll thì ko thành công ... vì cái gì đó thì tôi ko có biết
xem trong Registry thì ... khó nói lắm

Hàm sau trả về True nếu cái ActiveX COM đó đã đăng ký với Windows cấu trúc như sau
1/ VisualFoxProSQL = tên DLL
2/ FoxPro = tên Class
3/ Hoàn chỉnh là: Debug.Print CheckRegActiveX("VisualFoxProSQL.FoxPro")

Mã:
Function CheckRegActiveX(ByVal ProgID As String) As Boolean
    Rem Su dung Debug.Print CheckRegActiveX("VBLibraryLoad.cCOM")
    Rem Ham tra ve: True = Da dang Ky ; False = Chua Dang Ky
    Rem Ap dung cho ActiveX EXE va DLL
    Rem Debug.Print CheckRegActiveX("VBLibraryLoad.cCOM")
    On Error GoTo NextErr
    Debug.Assert Not CreateObject(ProgID) Is Nothing
NextErr:
    Rem If Err Then MsgBox Err.Description Else CheckRegActiveX = True
    If Err Then CheckRegActiveX = False Else CheckRegActiveX = True
End Function

Sub Main()
Debug.Print CheckRegActiveX("vfpoledb.ConnectionPage")
''Debug.Print CheckRegActiveX("VisualFoxProSQL.FoxPro")
End Sub

Mục đích hàm trên kiểm tra 1 cái COM DLL nào đó đã đăng ký hay chưa ... nếu chưa thì tùy ai đó xử lý bước tiếp theo vvv....

Tôi mới thử cho Python cũng ok luôn

Mã:
Debug.Print CheckRegActiveX("PythonImportDBF2Excel.Application")
 
Lần chỉnh sửa cuối:
Tôi thấy có cái hàm của người Nga viết bằng VB6 để làm việc với thư viện COM mà không cần đăng ký (register). Tôi không rành mấy vụ này nên post lên đây xem có giúp được gì không.
- module load thư viện COM.
- cái tool đọc thông tin thư viện - Library Info

View attachment 272485


Mã:
' The module modTrickUnregCOM.bas - for working with COM libraries without registration.
' © Krivous Anatolii Anatolevich (The trick), 2015

Option Explicit

Public Type GUID
    data1       As Long
    data2       As Integer
    data3       As Integer
    data4(7)    As Byte
End Type

Private Declare Function CLSIDFromString Lib "ole32.dll" ( _
                         ByVal lpszCLSID As Long, _
                         ByRef clsid As GUID) As Long
Private Declare Function GetMem4 Lib "msvbvm60" ( _
                         ByRef src As Any, _
                         ByRef dst As Any) As Long
Private Declare Function SysFreeString Lib "oleaut32" ( _
                         ByVal lpbstr As Long) As Long
Private Declare Function LoadLibrary Lib "kernel32" _
                         Alias "LoadLibraryW" ( _
                         ByVal lpLibFileName As Long) As Long
Private Declare Function GetModuleHandle Lib "kernel32" _
                         Alias "GetModuleHandleW" ( _
                         ByVal lpModuleName As Long) As Long
Private Declare Function FreeLibrary Lib "kernel32" ( _
                         ByVal hLibModule As Long) As Long
Private Declare Function GetProcAddress Lib "kernel32" ( _
                         ByVal hModule As Long, _
                         ByVal lpProcName As String) As Long
Private Declare Function DispCallFunc Lib "oleaut32" ( _
                         ByVal pvInstance As Any, _
                         ByVal oVft As Long, _
                         ByVal cc As Integer, _
                         ByVal vtReturn As Integer, _
                         ByVal cActuals As Long, _
                         ByRef prgvt As Any, _
                         ByRef prgpvarg As Any, _
                         ByRef pvargResult As Variant) As Long
Private Declare Function LoadTypeLibEx Lib "oleaut32" ( _
                         ByVal szFile As Long, _
                         ByVal regkind As Long, _
                         ByRef pptlib As IUnknown) As Long
Private Declare Function memcpy Lib "kernel32" _
                         Alias "RtlMoveMemory" ( _
                         ByRef Destination As Any, _
                         ByRef Source As Any, _
                         ByVal Length As Long) As Long
Private Declare Function CreateStdDispatch Lib "oleaut32" ( _
                         ByVal punkOuter As IUnknown, _
                         ByVal pvThis As IUnknown, _
                         ByVal ptinfo As IUnknown, _
                         ByRef ppunkStdDisp As IUnknown) As Long
                     
Private Const IID_IClassFactory   As String = "{00000001-0000-0000-C000-000000000046}"
Private Const IID_IUnknown        As String = "{00000000-0000-0000-C000-000000000046}"
Private Const CC_STDCALL          As Long = 4
Private Const REGKIND_NONE        As Long = 2
Private Const TKIND_COCLASS       As Long = 5
Private Const TKIND_DISPATCH      As Long = 4
Private Const TKIND_INTERFACE     As Long = 3

Dim iidClsFctr      As GUID
Dim iidUnk          As GUID
Dim isInit          As Boolean

' // Get all co-classes described in type library.
Public Function GetAllCoclasses( _
                ByRef path As String, _
                ByRef listOfClsid() As GUID, _
                ByRef listOfNames() As String, _
                ByRef countCoClass As Long) As Boolean
             
    Dim typeLib As IUnknown
    Dim typeInf As IUnknown
    Dim ret     As Long
    Dim count   As Long
    Dim index   As Long
    Dim pAttr   As Long
    Dim tKind   As Long
 
    ret = LoadTypeLibEx(StrPtr(path), REGKIND_NONE, typeLib)
 
    If ret Then
        Err.Raise ret
        Exit Function
    End If
 
    count = ITypeLib_GetTypeInfoCount(typeLib)
    countCoClass = 0
 
    If count > 0 Then
 
        ReDim listOfClsid(count - 1)
        ReDim listOfNames(count - 1)
     
        For index = 0 To count - 1
     
            ret = ITypeLib_GetTypeInfo(typeLib, index, typeInf)
                     
            If ret Then
                Err.Raise ret
                Exit Function
            End If
         
            ITypeInfo_GetTypeAttr typeInf, pAttr
         
            GetMem4 ByVal pAttr + &H28, tKind
         
            If tKind = TKIND_COCLASS Then
         
                memcpy listOfClsid(countCoClass), ByVal pAttr, Len(listOfClsid(countCoClass))
                ret = ITypeInfo_GetDocumentation(typeInf, -1, listOfNames(countCoClass), vbNullString, 0, vbNullString)
             
                If ret Then
                    ITypeInfo_ReleaseTypeAttr typeInf, pAttr
                    Err.Raise ret
                    Exit Function
                End If
             
                countCoClass = countCoClass + 1
             
            End If
         
            ITypeInfo_ReleaseTypeAttr typeInf, pAttr
         
            Set typeInf = Nothing
         
        Next
     
    End If
 
    If countCoClass Then
     
        ReDim Preserve listOfClsid(countCoClass - 1)
        ReDim Preserve listOfNames(countCoClass - 1)
 
    Else
 
        Erase listOfClsid()
        Erase listOfNames()
     
    End If
 
    GetAllCoclasses = True
 
End Function

' // Create IDispach implementation described in type library.
Public Function CreateIDispatch( _
                ByRef obj As IUnknown, _
                ByRef typeLibPath As String, _
                ByRef interfaceName As String) As Object
             
    Dim typeLib As IUnknown
    Dim typeInf As IUnknown
    Dim ret     As Long
    Dim retObj  As IUnknown
    Dim pAttr   As Long
    Dim tKind   As Long
 
    ret = LoadTypeLibEx(StrPtr(typeLibPath), REGKIND_NONE, typeLib)
 
    If ret Then
        Err.Raise ret
        Exit Function
    End If
 
    ret = ITypeLib_FindName(typeLib, interfaceName, 0, typeInf, 0, 1)
 
    If typeInf Is Nothing Then
        Err.Raise &H80004002, , "Interface not found"
        Exit Function
    End If
 
    ITypeInfo_GetTypeAttr typeInf, pAttr
    GetMem4 ByVal pAttr + &H28, tKind
    ITypeInfo_ReleaseTypeAttr typeInf, pAttr
 
    If tKind = TKIND_DISPATCH Then
        Set CreateIDispatch = obj
        Exit Function
    ElseIf tKind <> TKIND_INTERFACE Then
        Err.Raise &H80004002, , "Interface not found"
        Exit Function
    End If
 
    ret = CreateStdDispatch(Nothing, obj, typeInf, retObj)
 
    If ret Then
        Err.Raise ret
        Exit Function
    End If
 
    Set CreateIDispatch = retObj

End Function

' // Create object by Name.
Public Function CreateObjectEx2( _
                ByRef pathToDll As String, _
                ByRef pathToTLB As String, _
                ByRef className As String) As IUnknown
             
    Dim typeLib As IUnknown
    Dim typeInf As IUnknown
    Dim ret     As Long
    Dim pAttr   As Long
    Dim tKind   As Long
    Dim clsid   As GUID
 
    ret = LoadTypeLibEx(StrPtr(pathToTLB), REGKIND_NONE, typeLib)
 
    If ret Then
        Err.Raise ret
        Exit Function
    End If
 
    ret = ITypeLib_FindName(typeLib, className, 0, typeInf, 0, 1)
 
    If typeInf Is Nothing Then
        Err.Raise &H80040111, , "Class not found in type library"
        Exit Function
    End If

    ITypeInfo_GetTypeAttr typeInf, pAttr
 
    GetMem4 ByVal pAttr + &H28, tKind
 
    If tKind = TKIND_COCLASS Then
        memcpy clsid, ByVal pAttr, Len(clsid)
    Else
        Err.Raise &H80040111, , "Class not found in type library"
        Exit Function
    End If
 
    ITypeInfo_ReleaseTypeAttr typeInf, pAttr
         
    Set CreateObjectEx2 = CreateObjectEx(pathToDll, clsid)
 
End Function
             
' // Create object by CLSID and path.
Public Function CreateObjectEx( _
                ByRef path As String, _
                ByRef clsid As GUID) As IUnknown
             
    Dim hLib    As Long
    Dim lpAddr  As Long
    Dim isLoad  As Boolean
 
    hLib = GetModuleHandle(StrPtr(path))
 
    If hLib = 0 Then
 
        hLib = LoadLibrary(StrPtr(path))
        If hLib = 0 Then
            Err.Raise 53, , Error(53) & " " & Chr$(34) & path & Chr$(34)
            Exit Function
        End If
     
        isLoad = True
     
    End If
 
    lpAddr = GetProcAddress(hLib, "DllGetClassObject")
 
    If lpAddr = 0 Then
        If isLoad Then FreeLibrary hLib
        Err.Raise 453, , "Can't find dll entry point DllGetClasesObject in " & Chr$(34) & path & Chr$(34)
        Exit Function
    End If

    If Not isInit Then
        CLSIDFromString StrPtr(IID_IClassFactory), iidClsFctr
        CLSIDFromString StrPtr(IID_IUnknown), iidUnk
        isInit = True
    End If
 
    Dim ret     As Long
    Dim out     As IUnknown
 
    ret = DllGetClassObject(lpAddr, clsid, iidClsFctr, out)
 
    If ret = 0 Then

        ret = IClassFactory_CreateInstance(out, 0, iidUnk, CreateObjectEx)
 
    Else
 
        If isLoad Then FreeLibrary hLib
        Err.Raise ret
        Exit Function
     
    End If
 
    Set out = Nothing
 
    If ret Then
 
        If isLoad Then FreeLibrary hLib
        Err.Raise ret

    End If
 
End Function

' // Unload DLL if not used.
Public Function UnloadLibrary( _
                ByRef path As String) As Boolean
             
    Dim hLib    As Long
    Dim lpAddr  As Long
    Dim ret     As Long
 
    If Not isInit Then Exit Function
 
    hLib = GetModuleHandle(StrPtr(path))
    If hLib = 0 Then Exit Function
 
    lpAddr = GetProcAddress(hLib, "DllCanUnloadNow")
    If lpAddr = 0 Then Exit Function
 
    ret = DllCanUnloadNow(lpAddr)
 
    If ret = 0 Then
        FreeLibrary hLib
        UnloadLibrary = True
    End If
 
End Function

' // Call "DllGetClassObject" function using a pointer.
Private Function DllGetClassObject( _
                 ByVal funcAddr As Long, _
                 ByRef clsid As GUID, _
                 ByRef iid As GUID, _
                 ByRef out As IUnknown) As Long
             
    Dim params(2)   As Variant
    Dim types(2)    As Integer
    Dim list(2)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
 
    params(0) = VarPtr(clsid)
    params(1) = VarPtr(iid)
    params(2) = VarPtr(out)
 
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
 
    resultCall = DispCallFunc(0&, funcAddr, CC_STDCALL, vbLong, 3, types(0), list(0), pReturn)
         
    If resultCall Then Err.Raise 5: Exit Function
 
    DllGetClassObject = pReturn
 
End Function

' // Call "DllCanUnloadNow" function using a pointer.
Private Function DllCanUnloadNow( _
                 ByVal funcAddr As Long) As Long
             
    Dim resultCall  As Long
    Dim pReturn     As Variant
 
    resultCall = DispCallFunc(0&, funcAddr, CC_STDCALL, vbLong, 0, ByVal 0&, ByVal 0&, pReturn)
         
    If resultCall Then Err.Raise 5: Exit Function
 
    DllCanUnloadNow = pReturn
 
End Function

' // Call "IClassFactory:CreateInstance" method.
Private Function IClassFactory_CreateInstance( _
                 ByVal obj As IUnknown, _
                 ByVal punkOuter As Long, _
                 ByRef riid As GUID, _
                 ByRef out As IUnknown) As Long
 
    Dim params(2)   As Variant
    Dim types(2)    As Integer
    Dim list(2)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
 
    params(0) = punkOuter
    params(1) = VarPtr(riid)
    params(2) = VarPtr(out)
 
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
 
    resultCall = DispCallFunc(obj, &HC, CC_STDCALL, vbLong, 3, types(0), list(0), pReturn)
       
    If resultCall Then Err.Raise resultCall: Exit Function
 
    IClassFactory_CreateInstance = pReturn
 
End Function

' // Call "ITypeLib:GetTypeInfoCount" method.
Private Function ITypeLib_GetTypeInfoCount( _
                 ByVal obj As IUnknown) As Long
 
    Dim resultCall  As Long
    Dim pReturn     As Variant

    resultCall = DispCallFunc(obj, &HC, CC_STDCALL, vbLong, 0, ByVal 0&, ByVal 0&, pReturn)
       
    If resultCall Then Err.Raise resultCall: Exit Function
 
    ITypeLib_GetTypeInfoCount = pReturn
 
End Function

' // Call "ITypeLib:GetTypeInfo" method.
Private Function ITypeLib_GetTypeInfo( _
                 ByVal obj As IUnknown, _
                 ByVal index As Long, _
                 ByRef ppTInfo As IUnknown) As Long
 
    Dim params(1)   As Variant
    Dim types(1)    As Integer
    Dim list(1)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
 
    params(0) = index
    params(1) = VarPtr(ppTInfo)
 
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
 
    resultCall = DispCallFunc(obj, &H10, CC_STDCALL, vbLong, 2, types(0), list(0), pReturn)
       
    If resultCall Then Err.Raise resultCall: Exit Function
 
    ITypeLib_GetTypeInfo = pReturn
 
End Function

' // Call "ITypeLib:FindName" method.
Private Function ITypeLib_FindName( _
                 ByVal obj As IUnknown, _
                 ByRef szNameBuf As String, _
                 ByVal lHashVal As Long, _
                 ByRef ppTInfo As IUnknown, _
                 ByRef rgMemId As Long, _
                 ByRef pcFound As Integer) As Long
 
    Dim params(4)   As Variant
    Dim types(4)    As Integer
    Dim list(4)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
 
    params(0) = StrPtr(szNameBuf)
    params(1) = lHashVal
    params(2) = VarPtr(ppTInfo)
    params(3) = VarPtr(rgMemId)
    params(4) = VarPtr(pcFound)
 
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
 
    resultCall = DispCallFunc(obj, &H2C, CC_STDCALL, vbLong, 5, types(0), list(0), pReturn)
       
    If resultCall Then Err.Raise resultCall: Exit Function
 
    ITypeLib_FindName = pReturn
 
End Function

' // Call "ITypeInfo:GetTypeAttr" method.
Private Sub ITypeInfo_GetTypeAttr( _
            ByVal obj As IUnknown, _
            ByRef ppTypeAttr As Long)
 
    Dim resultCall  As Long
    Dim pReturn     As Variant
 
    pReturn = VarPtr(ppTypeAttr)
 
    resultCall = DispCallFunc(obj, &HC, CC_STDCALL, vbEmpty, 1, vbLong, VarPtr(pReturn), 0)
       
    If resultCall Then Err.Raise resultCall: Exit Sub

End Sub

' // Call "ITypeInfo:GetDocumentation" method.
Private Function ITypeInfo_GetDocumentation( _
                 ByVal obj As IUnknown, _
                 ByVal memid As Long, _
                 ByRef pBstrName As String, _
                 ByRef pBstrDocString As String, _
                 ByRef pdwHelpContext As Long, _
                 ByRef pBstrHelpFile As String) As Long
 
    Dim params(4)   As Variant
    Dim types(4)    As Integer
    Dim list(4)     As Long
    Dim resultCall  As Long
    Dim pIndex      As Long
    Dim pReturn     As Variant
 
    params(0) = memid
    params(1) = VarPtr(pBstrName)
    params(2) = VarPtr(pBstrDocString)
    params(3) = VarPtr(pdwHelpContext)
    params(4) = VarPtr(pBstrHelpFile)
 
    For pIndex = 0 To UBound(params)
        list(pIndex) = VarPtr(params(pIndex)):   types(pIndex) = VarType(params(pIndex))
    Next
 
    resultCall = DispCallFunc(obj, &H30, CC_STDCALL, vbLong, 5, types(0), list(0), pReturn)
       
    If resultCall Then Err.Raise resultCall: Exit Function
 
    ITypeInfo_GetDocumentation = pReturn
 
End Function

' // Call "ITypeInfo:ReleaseTypeAttr" method.
Private Sub ITypeInfo_ReleaseTypeAttr( _
            ByVal obj As IUnknown, _
            ByVal ppTypeAttr As Long)
 
    Dim resultCall  As Long
 
    resultCall = DispCallFunc(obj, &H4C, CC_STDCALL, vbEmpty, 1, vbLong, VarPtr(CVar(ppTypeAttr)), 0)
       
    If resultCall Then Err.Raise resultCall: Exit Sub

End Sub
sử dụng nó như sau ... bản thân hàm đó sử dụng tốt ...
tuy nhiên hàm đó sẻ lỗi trong 1 vài trường hợp xx... nếu biết fix lại chút

hãy tự khám phá nó mới vui
Mã:
dim xx As Object
Set XX = CreateObjectEx2("D:\MyDLL.dll","D:\MyDLL.dll", className)

Còn tôi lại ko sử dụng hàm đó ... thế giới code với két nó bao la lắm ... bước ra ngoài kia mới thấy mình
bé bỏng làm sao ??!!! -0-0-0-
 
Lần chỉnh sửa cuối:
Gửi BQT, anh @ptm0412. Nhờ anh cắt từ bài số #43 sang chủ để mới với một cái tên kiểu như là "Cách đăng ký, làm việc với thư viện COM bằng code VBA/VB6" để những ai quan tâm lập trình tập trung trao đổi, còn những ai có nhu cầu ứng dụng như chủ topic này thì vẫn theo topic này thì sẽ trọng tâm hơn. Nếu được vậy em nghĩ sẽ tốt hơn. Cảm ơn anh.
 
Gửi BQT, anh @ptm0412. Nhờ anh cắt từ bài số #43 sang chủ để mới với một cái tên kiểu như là "Cách đăng ký, làm việc với thư viện COM bằng code VBA/VB6" để những ai quan tâm lập trình tập trung trao đổi, còn những ai có nhu cầu ứng dụng như chủ topic này thì vẫn theo topic này thì sẽ trọng tâm hơn. Nếu được vậy em nghĩ sẽ tốt hơn. Cảm ơn anh.
vậy thì cắt hết những gì ko liên quan thớt này đi cho gọn luôn ... nên làm thế
Bài đã được tự động gộp:

Cách cài đặt thư viện "vfpoledb.dll" trong VB6

Khai báo hàm API:
Tôi dùng unicode nên code sẽ dài hơn chút nhưng sẽ an toàn nếu đường dẫn file DLL chứa ký tự có dấu.
C#:
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteW" (ByVal hwnd As Long, _
                                                                               ByVal lpOperation As String, _
                                                                               ByVal lpFile As String, _
                                                                               ByVal lpParameters As String, _
                                                                               ByVal lpDirectory As String, _
                                                                               ByVal nShowCmd As Long) As Long

Lệnh chạy install:

C#:
Private Sub InstallVFPOLEDB()
    Dim x&, sFile As String, sParam As String
    sFile = StrConv("Regsvr32.exe", vbUnicode)
   'Đường dẫn DLL tùy bạn chọn. Nếu lấy từ chính file exe đang chạy thì là:  App.Path & "\vfpoledb.dll"
    sParam = StrConv("""C:\Program Files (x86)\Common Files\System\Ole DB\vfpoledb.dll"" /s", vbUnicode)
    x = ShellExecute(hwnd, StrConv("runas", vbUnicode), sFile, sParam, "", 0)
    If x <= 32 Then
        AlertIfError x
    Else
        MsgBox "Install successful." & vbNewLine & _
               "Application can use classes in this library.", vbInformation
        Unload Me
    End If
End Sub
'-------------------------------------------------------------------------------------
Private Sub UninstallVFPOLEDB()
    Dim x&, sFile As String, sParam As String
    sFile = StrConv("Regsvr32.exe", vbUnicode)
    sParam = StrConv("""C:\Program Files (x86)\Common Files\System\Ole DB\vfpoledb.dll""  /u/s", vbUnicode)
    x = ShellExecute(hwnd, StrConv("runas", vbUnicode), sFile, sParam, "", 0)
    If x <= 32 Then
        AlertIfError x
    Else
        MsgBox "Uninstall successful." & vbNewLine & _
               "Application can not use classes in this library.", vbInformation
        Unload Me
    End If
End Sub

Mã nguồn trên là VB6 nhưng dùng mẫu định dạng C# của GPE cho đẹp. Các bạn không nhầm lẫn loại code nhé.
bài này cũng nên cắt đi + nhiều bài khác cho công = he .... cho vào thớt đăng ký nó mới phù hợp
 
Lần chỉnh sửa cuối:
vậy thì cắt hết những gì ko liên quan thớt này đi cho gọn luôn ... nên làm thế
Bài đã được tự động gộp:


bài này cũng nên cắt đi + nhiều bài khác cho công = he .... cho vào thớt đăng ký nó mới phù hợp

Thì chính là từ bài #43 đó.
 
trước đó có rồi ... nên làm thế ... dọn sạch đi cho công =
nếu nói thì nói ngay từ đầu còn ko thì nên thôi sẻ tốt hơn

Tôi sống công = và sòng phẳng mọi cái

Chỉ là chuyển nội dung sang một chủ đề mới sẽ khoa học thôi chứ có gì to tát đâu, bất cứ nội dung nào có thể chuyển qua thì chuyển. Đây không phải là vi phạm nội quy và là làm cho nội dung và hướng người tham gia được trọng tâm theo mỗi chủ đề. Không có gì liên quan đến cái gọi là công bằng cả.
 
Chỉ là chuyển nội dung sang một chủ đề mới sẽ khoa học thôi chứ có gì to tát đâu, bất cứ nội dung nào có thể chuyển qua thì chuyển. Đây không phải là vi phạm nội quy và là làm cho nội dung và hướng người tham gia được trọng tâm theo mỗi chủ đề. Không có gì liên quan đến cái gọi là công bằng cả.
thôi ko trình bày qua lại nữa ... hehehehehe
những bài nào ko liên quan thớt này nên chuyển qua thới khác sẻ phù hợp hơn hoặc cho vào thùng Rác tùy mod xử lý
thế thôi -0-0-0-

nếu đã cầm cân thì nên cho nó thăng = ????!!!!
 
Lần chỉnh sửa cuối:
thôi ko trình bày qua lại nữa ... hehehehehe
những bài nào ko liên quan thớt này nên chuyển qua thới khác sẻ phù hợp hơn hoặc cho vào thùng Rác tùy mod xử lý
thế thôi -0-0-0-

nếu đã cầm cân thì nên cho nó thăng = ????!!!!

Tách bài ra là đúng rồi chứ có gì mà lăn tăn, công với chả bằng bạn KM???
Bài chủ thớt thì hỏi về kết nối FoxproDB, thì đã xong tới bài #43, còn sau đó là bàn về mặt kỹ thuật chuyên sâu, không chỉ áp dụng cho thư viện Foxpro mà còn các thư viện khác cùng cách làm thì nên tạo bài mới để thảo luận nó tập trung hơn chứ có vấn đề gì ở đây nhỉ!
 
Tách bài ra là đúng rồi chứ có gì mà lăn tăn, công với chả bằng bạn KM???
Bài chủ thớt thì hỏi về kết nối FoxproDB, thì đã xong tới bài #43, còn sau đó là bàn về mặt kỹ thuật chuyên sâu, không chỉ áp dụng cho thư viện Foxpro mà còn các thư viện khác cùng cách làm thì nên tạo bài mới để thảo luận nó tập trung hơn chứ có vấn đề gì ở đây nhỉ!
thì cứ cho là từ 43 đi ... còn sau bài đó sao ko nói ... ai thèn lăn tăn
còn vấn đề gì ở đây nhỉ! ... thong thả sẻ hiểu thôi :p

chốt lại Mạnh dừng ở đây he
 
Lần chỉnh sửa cuối:
Mọi thứ rất tuyệt vời rồi. Chỉ không hiểu cái đoạn "tranh thủ" cài cắm quảng cáo vào thôi.

Theo "thông lệ" diễn đàn đã ban hành thì cần "cắt/ tách" ngay và luôn phần đó sang mục này, ngược lại thì phải xóa.

1645850197595.png

-----
Ngoài ra, BQT cũng nên xem lại điều khoản và cách kiểm duyệt điều khoản về chữ ký. Theo như hiện tại thì nick thành viên có chữ ký là nội dung quảng cáo to tướng, dài thoòng lòong, hễ cứ đăng bài ở bất kỳ đâu là được quảng cáo miễn phí ở đó.
Vậy theo đó thì nên xóa bỏ ngay điều khoản hạn chế quảng cáo đi cho rồi. Nếu không hài lắm.
 
Chia sẻ thư viện BSDataService32 để kết nối database 32-bit trong ứng dụng 64-bit
(Hướng dẫn trong video này lấy ví dụ CSDL Foxpro tại bài đầu tiên)
Thư viện BSDataService32 là miễn phí, hỗ trợ cho những người chỉ dùng hàm và công cụ mà không biết lập trình (làm theo các bước trong video dưới đây) ; với người lập trình cũng có thể viết code để tùy biến lấy dữ liệu.
(*) Download thư viện BSDataService32
(*) Video hướng dẫn chi tiết ứng dụng
Anh Tuân cho em hỏi thư viện này có dùng để truy vấn các loại dữ liệu khác như Excel, SQL bằng cách thay đổi ConnectionString không hả anh?
 
Anh Tuân cho em hỏi thư viện này có dùng để truy vấn các loại dữ liệu khác như Excel, SQL bằng cách thay đổi ConnectionString không hả anh?

Giải pháp của mình để mở, tức áp dụng cho tất cả các loại csdl 32-bit, chỉ cần khai báo đúng ConnectionString và các csdl đó Windows cho phép là được.
 
code két cơ bản khó khăn ở chỗ khai phá và mở đường ... khi hiểu phương thức hoạt động của nó rồi thì mọi cái nó trở nên đơn giản nhất có thể

Tùy biến và viết sao là do mình thích .... với code sau thấy họ viết cũng bắt trước viết cho có thôi .. trong VB6 chỉ kết nối xong trả lại kết quả VBA

Chịu khó đọc kỹ lại các bài trước + 1 chút kiến thức ADODB là làm tốt .... à quên biết 1 tí VB6 nữa là xong thôi

Mã:
Sub CopyRecordset_ADODB()
    Dim rst As Object
    Dim Fox As New VisualFoxProSQL.FoxPro
    ''Set rst = Fox.GetRecordset("D:\Database_Server\Database_FoxPro\CT.DBF") ''ok 1
    Set rst = Fox.CopyRecordset("D:\Database_Server\Database_FoxPro\CT.DBF", "SELECT * FROM CT") ''ok 2
    Cells.Clear
    Range("A6").CopyFromRecordset rst
    rst.Close
    Set Fox = Nothing
End Sub

Bài cuối tại đây ... ko tham gia thớt này nữa .... nếu có Tôi sẻ lập thớt mới chơi cho vui vẻ thôi
 
@Thớt:
Cái đó chỉ có tác dụng liên kết thư viện đã có để dùng thôi. Cái lõi vẫn là cái FoxPro OLE DB Provider của Microsoft ấy (chi tiết ở mấy bài đầu rồi).
Hàng miễn phí người ta chỉ cho nhiêu đó thôi, muốn truy vấn Excel , SQL gì gì nữa thì không có đâu, phải bỏ tiền ra mua.
Còn ở GPE hàng miễn phí, ngon cũng có ở ngay trang chủ đó bạn.

 
Cái dụ connect 64 với 32 này viết delphi với vb6 dễ ẹc có gì mà ghê gớm đâu nhỉ
 
Anh Tuân cho em hỏi thư viện này có dùng để truy vấn các loại dữ liệu khác như Excel, SQL bằng cách thay đổi ConnectionString không hả anh?

Đọc kỹ toàn bộ các câu trả lời của tôi để không hoang mang nhé. Việc sử dụng các thư viện ODBC hay OLE DB để kết kết nối tới các CSDL trên Windows phần lớn là miễn phí (Excel, SQL Server, MySQL, Oracle, Access, Foxpro, ....) là miễn phí. Thông qua cách khai báo ConnectionString để chỉ định CSDL cụ thể là xong.
Các câu lệnh khai báo ConnectionString tại đây:
 
Cái dụ connect 64 với 32 này viết delphi với vb6 dễ ẹc có gì mà ghê gớm đâu nhỉ
Tài nguyên code đã có rất nhiều trên mạng, quan trọng là biết gõ từ khoá để tìm kiếm đúng cái mình cần thôi.
Anh thấy trong Delphi mấy cái framework kết nối có thằng FireDAC là được đánh giá cao nhất và sử dụng được cho các hệ thống khác như Mac OS, iOS, Android. Mà Delphi lại là ngôn ngữ complied nên tốc độ xử lý của nó sẽ nhanh hơn interpreted rồi. Thấy cũng mê mà làm biếng học quá.

dbconnections.png

0201_1set.png
 
Tài nguyên code đã có rất nhiều trên mạng, quan trọng là biết gõ từ khoá để tìm kiếm đúng cái mình cần thôi.
Anh thấy trong Delphi mấy cái framework kết nối có thằng FireDAC là được đánh giá cao nhất và sử dụng được cho các hệ thống khác như Mac OS, iOS, Android. Mà Delphi lại là ngôn ngữ complied nên tốc độ xử lý của nó sẽ nhanh hơn interpreted rồi. Thấy cũng mê mà làm biếng học quá.

View attachment 272496

View attachment 272497
Hihi mỗi cái có 1 cái thế mạnh mà em cũng chưa biết sử dụng hết, mà dạo này nhiều việc quá em bỏ mò code rồi. Cái vụ conect 64 qua 32 phải có 1 chút xíu thủ thuật chứ không có làm bước đó là không connect được.
 
Chào các anh chị, mình cần lấy dữ liệu từ phần mềm kế toán foxpro ra Excel bằng cách Import, để khi dữ liệu thay đổi thì refresh sẽ có dữ liệu cập nhật.
Dữ liệu foxpro ở dạng thư mục, được nén trong file kèm theo, trong file CT.dbf.
Thảo luận quá trời mà chưa đưa file, đây là file xử lý lấy dữ liệu Foxpro chạy trong Excel 64bit đây. (Đính kèm bên dưới)

Screen Shot 2022-02-27 at 10.06.23.png

1. Chạy file [register_foxproDLL.bat] (Run as Administrator) để đăng ý cái Driver FoxPro OLED (vfpoledb.dll).
2. Kéo thả file [FoxproDBConn.exe] vào file [register.vbs] để tiến hành đăng ký cái phiên làm việc trung gian này (viết trên VB6).
3. Mở file Excel [Test _FoxproDB.xlsb], vào màn hình code -> Tool - Reference -> Tìm và bấm chọn thư viện "FoxProDbConnection" ->OK
 

File đính kèm

Thảo luận quá trời mà chưa đưa file, đây là file xử lý lấy dữ liệu Foxpro chạy trong Excel 64bit đây. (Đính kèm bên dưới)

View attachment 272504

1. Chạy file [register_foxproDLL.bat] (Run as Administrator) để đăng ý cái Driver FoxPro OLED (vfpoledb.dll).
2. Kéo thả file [FoxproDBConn.exe] vào file [register.vbs] để tiến hành đăng ký cái phiên làm việc trung gian này (viết trên VB6).
3. Mở file Excel [Test _FoxproDB.xlsb], vào màn hình code -> Tool - Reference -> Tìm và bấm chọn thư viện "FoxProDbConnection" ->OKth

thật tuyệt vời, cách này lấy được dữ liệu không giới hạn bản ghi
 
Đọc kỹ toàn bộ các câu trả lời của tôi để không hoang mang nhé. Việc sử dụng các thư viện ODBC hay OLE DB để kết kết nối tới các CSDL trên Windows phần lớn là miễn phí (Excel, SQL Server, MySQL, Oracle, Access, Foxpro, ....) là miễn phí. Thông qua cách khai báo ConnectionString để chỉ định CSDL cụ thể là xong.
Các câu lệnh khai báo ConnectionString tại đây:

CnnString cũng lấy từ trang web trên.
Em thử nhiều lần không được mới post hỏi đấy anh Tuân à.

1645936462733.png
 
Thớt đọc kỹ lại câu chữ của người ta đi, viết gì gì đó chứ có trả lời cụ tỉ là truy vấn Excel, SQL như thớt hỏi đâu.

Hàng siêu ngon đây này, không phải thao tác rườm rà gì cả, chỉ click 2-3 phát là xong rồi.
 
CnnString cũng lấy từ trang web trên.
Em thử nhiều lần không được mới post hỏi đấy anh Tuân à.

View attachment 272508

Vấn đề kết nối dữ liệu Foxpro chắc bạn đã giải quyết xong và không còn thắc mắc? Còn câu hỏi mới của bạn là kết nối file Excel thì lại càng dễ và tiện vì sẵn được Office hỗ trợ. Bạn làm báo lỗi gì thì gửi thông báo lỗi lên. Cần thiết lắm mới phỉa gửi file Excel nguồn của bạn lên đây (xóa dữ liệu thật đi) tôi hay các bạn trên GPE hỗ trợ. không cần thư viện ngoài mà kết nối từ trong chính Office thôi. Hãy nhớ các vấn đề của bạn đã được nhiều người giải quyết từ nhiều năm nay và nó rất dễ.

Bạn hãy tải lại thư viện và quan trọng là, file Excel ví dụ trong đó tôi đã sửa lại, trong code tôi cập nhật địa chỉ ô chưa câu lệnh SQL và chuỗi ConnectionString. File cũ tôi gửi là câu lệnh cố định nên có thể bạn không ứng dụng được với file hay thư mục khác nếu không sửa code. File tôi update có cả ví dụ kết nối dữ liệu Excel với ConnectionString đúng như bạn đã làm.
(Nhấn mạnh thêm chỉ với dữ liệu 32-bit như là với Foxpro mới cần phải dúng thư viện BSDataService32 hay thư viện người khác làm tương đương. Còn với các CSDL hỗ trợ cho cả 32 hay 64-bit thì nên dùng cách làm với ADO ngay trong mã nguồn sẽ nhanh hơn. Tạm thời bạn cứ test với việc không phải lập trình cho chạy đã. Sau muốn mã nguồn kết nối Excel thì mã nguồn tôi gửi tiếp hawocj bạn tìm trên mạng ra ngay nhưng chịu khó làm vài thao tác insert, copy code cho đúng.

Download file ví dụ cùng BSDataService32

ketnoiexcel.gif
 
Lần chỉnh sửa cuối:
Vấn đề kết nối dữ liệu Foxpro chắc bạn đã giải quyết xong và không còn thắc mắc? Còn câu hỏi mới của bạn là kết nối file Excel thì lại càng dễ và tiện vì sẵn được Office hỗ trợ. Bạn làm báo lỗi gì thì gửi thông báo lỗi lên. Cần thiết lắm mới phỉa gửi file Excel nguồn của bạn lên đây (xóa dữ liệu thật đi) tôi hay các bạn trên GPE hỗ trợ. không cần thư viện ngoài mà kết nối từ trong chính Office thôi. Hãy nhớ các vấn đề của bạn đã được nhiều người giải quyết từ nhiều năm nay và nó rất dễ.

Bạn hãy tải lại thư viện và quan trọng là, file Excel ví dụ trong đó tôi đã sửa lại, trong code tôi cập nhật địa chỉ ô chưa câu lệnh SQL và chuỗi ConnectionString. File cũ tôi gửi là câu lệnh cố định nên có thể bạn không ứng dụng được với file hay thư mục khác nếu không sửa code. File tôi update có cả ví dụ kết nối dữ liệu Excel với ConnectionString đúng như bạn đã làm.
(Nhấn mạnh thêm chỉ với dữ liệu 32-bit như là với Foxpro mới cần phải dúng thư viện BSDataService32 hay thư viện người khác làm tương đương. Còn với các CSDL hỗ trợ cho cả 32 hay 64-bit thì nên dùng cách làm với ADO ngay trong mã nguồn sẽ nhanh hơn. Tạm thời bạn cứ test với việc không phải lập trình cho chạy đã. Sau muốn mã nguồn kết nối Excel thì mã nguồn tôi gửi tiếp hawocj bạn tìm trên mạng ra ngay nhưng chịu khó làm vài thao tác insert, copy code cho đúng.

Download file ví dụ cùng BSDataService32


Dữ liệu PDF thì em lấy được rồi, cảm ơn anh Tuân và GPE. Vì xem trong clip ví dụ của anh Tuân với dữ liệu Foxpro trong Excel 365 thì kết quả được trả về ở dạng hàm mảng động mới rất hay.

1645954460121.png

Nhưng em thử với dữ liệu Excel (đã thay connection string) thì không được, chỉ trả về số 0 thôi.
1645954529402.png

Vì Excel không có hàm truy vấn bằng SQL mà chỉ có một vài hàm mảng động như FILTER, nó không toàn diện và năng động như sử dụng truy vấn SQL. Nên nếu cũng làm được hàm truy vấn dữ liệu SQL, lấy dữ liệu Excel, kết quả trả về hàm mảng động như với Foxpro thế thì tuyệt vời.

Em gửi file dữ liệu TEMP em đã test không được để anh có thể check giúp nhé !
 

File đính kèm

Dữ liệu PDF thì em lấy được rồi, cảm ơn anh Tuân và GPE. Vì xem trong clip ví dụ của anh Tuân với dữ liệu Foxpro trong Excel 365 thì kết quả được trả về ở dạng hàm mảng động mới rất hay.

View attachment 272517

Nhưng em thử với dữ liệu Excel (đã thay connection string) thì không được, chỉ trả về số 0 thôi.
View attachment 272518

Vì Excel không có hàm truy vấn bằng SQL mà chỉ có một vài hàm mảng động như FILTER, nó không toàn diện và năng động như sử dụng truy vấn SQL. Nên nếu cũng làm được hàm truy vấn dữ liệu SQL, lấy dữ liệu Excel, kết quả trả về hàm mảng động như với Foxpro thế thì tuyệt vời.

Em gửi file dữ liệu TEMP em đã test không được để anh có thể check giúp nhé !
chủ đề này lấy File DBF thì tôi ko quan tâm nữa vì thấy bạn hỏi lấy dữ liệu khác thì tôi giới thiệu cho bạn 1 Thư viện hàm miễn phí và hơn thế nữa nếu tôi thích thêm các chuỗi kết nối khác vào mà FireDAC trên Delphi nó hổ trợ là xong thôi

1/ Vào link sau tải tất cả các File đó về

2/ Copy code sau vào Worksheet
Mã:
Private Sub Worksheet_Change(ByVal Target As Range)
    On Error GoTo Next_Error
    Static Fso  As New FileSystemObject
    Dim DbPath As String, SQL As String, HDR As Boolean
    DbPath = Range("B1").Value
    SQL = Range("B2").Value
    HDR = Range("B3").Value
    Rem ==========
    If Not Fso Is Nothing Then Set Fso = New FileSystemObject
    If Fso.FileExists(DbPath) = False Then Exit Sub
    Rem ==========
    If Target.Address = "$B$2" Or Target.Address = "$B$3" Then
        Range("A5:CE65536").ClearContents
        Call GetSQLDataBaseA(DbPath, SQL, [A5], HDR)
    End If
    Exit Sub
Next_Error:
    Rem If Err Then MsgBox Err.Number & vbLf & Err.Description: Err.Clear
End Sub
Rem ==========
Private Sub ComboBox1_Change()
    Range("B2").Value = "select * from " & ComboBox1.Text
End Sub
Rem ==========
Private Sub SelectFile_Click()
    Dim aPath As Variant
    Dim Arr As Variant
    Dim i As Long
    Dim sArr() As String
    aPath = SelectFilesDialogA()
    Range("B1").Value = aPath
    Rem =========
    Arr = ListTableNamesA(aPath)
    sArr = Split(Arr, vbLf)
    ActiveSheet.ComboBox1.Clear
    Rem ========= Cach 2
    For i = LBound(sArr) To UBound(sArr) - 1
       Rem Debug.Print sArr(i)
       ActiveSheet.ComboBox1.AddItem sArr(i)
    Next
End Sub

3/ Vào linhk sau tham khảo thêm cách tổng hợp tất cả các Sheet + TableName trong 1 File lên Sheet

4/ Lấy dữ liệu Ms Server cách sử dụng tương tự
5/ nếu Rảnh tôi sẻ thêm CSDL FoxPro vào nữa ... chức năng tương tự như trên

....
....
Nếu bạn đang sử dụng Office 365 thì mấy hàm công thức Mảng ko thể xóa được của bất cứ ai nên từng bước bỏ đi vì nó nặng và ì ạch lắm

VD: hãy thử lấy 10 Sheet mỗi Sheet có vùng dữ liệu 1048000 dòng x 50 cột là nó chết đơ và thoát ngay lập tức ... ko tin thử xem

Xem video cách sử dụng Hàm
1/ nhấn nút chọn File Excel - Access - SQLtie
2/ nhấn ComboBox1 chọn Sheetname Or TableName
3/ Tùy chỉnh SQL và Tiêu đề ...
Liên kết: https://youtu.be/CKmtYfmUtCw


Thưởng thức Thư viện miễn phí ... và tùy chỉnh phấn phối lại nếu bạn thích $
 
Lần chỉnh sửa cuối:
Vì Excel không có hàm truy vấn bằng SQL mà chỉ có một vài hàm mảng động như FILTER, nó không toàn diện và năng động như sử dụng truy vấn SQL. Nên nếu cũng làm được hàm truy vấn dữ liệu SQL, lấy dữ liệu Excel, kết quả trả về hàm mảng động như với Foxpro thế thì tuyệt vời.

Muốn lấy dữ liệu nguồn từ Excel bằng câu lệnh truy vấn SQL thì chỉ đơn giản dùng ADODB để kết nối và truy vấn thôi.

Screen Shot 2022-02-27 at 23.55.27.png
 

File đính kèm

Ý mình đang đề cập là kết quả truy vấn trả về ở dạng hàm mảng động mới của Excel đời cao ấy (365 or 2021). Tks
 
Ý mình đang đề cập là kết quả truy vấn trả về ở dạng hàm mảng động mới của Excel đời cao ấy (365 or 2021). Tks

Bạn dùng Excel 365 thì tự trả về mảng động mà. Sự khác nhau các CSDL chỉ là ConnectionString trong tham số của hàm GetData().
 

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

Back
Top Bottom