AI muốn lập trình DLL cho Excel và các loại bằng Delphi thì xem video này nhé!

Liên hệ QC

Nguyễn Duy Tuân

Nghị Hách
Thành viên danh dự
Tham gia
13/6/06
Bài viết
4,649
Được thích
10,138
Giới tính
Nam
Nghề nghiệp
Giáo viên, CEO tại Bluesofts
Lần chỉnh sửa cuối:
Bạn @kieu manh đang làm theo hàm rctTypeName chứ không phải hàm InStrRev anh @batman1 a. Code cả project em để full không che ấy. EM chạy không lỗi gì.
Tôi biết chứ. Vì kieu manh viết rõ là thử nghiệm code bài #811 mà.
Trích bài #821
Mạnh Copy y trang Code bài 811 và làm như hình sau:

Theo tôi với code bài #811 thì chắc chắn có lỗi "EOleSysError: CoInitialize has not been called"

Tôi chạy trên XP Home + Delphi 5 cũng có lỗi "EOleSysError: CoInitialize has not been called" - xem AVI
Bài đã được tự động gộp:

Chạy tới lui các kiểu nó cũng báo cái dòng màu đỏ đó Anh còn lại ko thấy chi hết ... còn tại sao Em Tịt ....!
Em thử chạy cái File Delphi *.exe Run As nó cũng thế
Tôi đã viết rồi. Nếu Excel có khởi động mà vẫn còn lỗi thì lỗi không nằm ở code nữa. Tôi chạy code thấy bình thường - xem AVI của tôi ở bài #841. Tất nhiên tôi phải thêm if InitProc <> nil then TProcedure(InitProc); để loại bỏ lỗi "EOleSysError: CoInitialize has not been called"

Nếu không thêm if InitProc <> nil then TProcedure(InitProc); thì như hình sau

sau.JPG

Code sau khi thêm

test.JPG
 

File đính kèm

  • test.rar
    289.3 KB · Đọc: 6
Lần chỉnh sửa cuối:
Upvote 0
Office bạn mạnh là 2013 x32, thế exe delphi bạn Mạnh build ở 32 hay 64 đấy?
 
Upvote 0
@Nguyễn Duy Tuân: đây cũng bị giống Tuân nè, kiểu Double thôi đó
Lỗi quá tinh vi, quá hiểm, kg phải dân "rờ chim em" thì thua :p
Tạm thời xin can bác @kiều mạnh build và dùng cái VBLibrary.dll trên mode 64bit nhé.
 
Lần chỉnh sửa cuối:
Upvote 0
@Nguyễn Duy Tuân: đây cũng bị giống Tuân nè, kiểu Double thôi đó
Lỗi quá tinh vi, quá hiểm, kg phải dân "rờ chim em" thì thua :p
Tạm thời xin can bác @kiều mạnh build và dùng cái VBLibrary.dll trên mode 64bit nhé.

Quả dùng function mà declare trực tiếp trên 64-bit căng đây. Em đang tính làm thử cái DLL trên VC rồi thử có bị vấn đề giống nhau không?
 
Upvote 0
Cứ bình tĩnh, qua VC là bước cuối cùng rồi. Để debug, rờ em kỹ xem có phải bug của Delphi compiler kg đã. Nếu đúng thì nâng cấp Rad studio lên Tokyo luôn. Nếu vẫn bị thì phải qua Vc hay C# thôi
 
Upvote 0
Cứ bình tĩnh, qua VC là bước cuối cùng rồi. Để debug, rờ em kỹ xem có phải bug của Delphi compiler kg đã. Nếu đúng thì nâng cấp Rad studio lên Tokyo luôn. Nếu vẫn bị thì phải qua Vc hay C# thôi

Em đang tò mò và nghi VC hay C# cũng vậy vì đây là cách dùng function từ declare mới bị vậy, em chưa thấy tài liệu nào từ MS nói về cách làm này?! Compiler của Delphi vẫn chuẩn theo cách call thông thường.
 
Upvote 0
mình chợt nghĩ tại sao từ VBA call hàm trong Dll x64 thì đúng, vba 64 sinh code asm truyền param đúng, mà từ Excel 64 call lại bị sai???
Vậy nên phải debug cả từ Excel và VBA, cả 2,để xem khác nhau chỗ nào.
Trên 32 thì stdcall là đơn giản, standard rồi, thằng vc, delphi, gcc 32 đều sinh mã đúng, như nhau.
Trên 64 thì chỉ còn fastcall nhưng Vc64 và gcc64 sinh code khác nhau đó. Hồi sáng mình có nói à Delphi nay dùng GCC 64 compiler à đó. Đây cũng là điểm cần kiểm tra. Vì Excel 64 build = VC64, còn dll của mình là GCC64
 
Lần chỉnh sửa cuối:
Upvote 0
Chả lẽ do align stack sai chăng, vì thấy Delphi dùng các thanh ghi RCX, RDX, R8,R9 đúng mà, còn stack của hàm thì thấy hơi dị dị ???
 
Upvote 0
Ẩu quá đáng lẻ nó ko phát sinh một mớ bài ... cứ Copy nguyên bài 811 cho nên nó sai

Path DLL bài 811 là
Mã:
h := LoadLibrary('C:\Program Files (x86)\Common Files\Microsoft Shared\VBA\VBA7\VBE7.DLL');
Path DLL thực tế trên máy Mạnh là
Mã:
h := LoadLibrary('C:\Program Files (x86)\Common Files\Microsoft Shared\VBA\VBA7.1\VBE7.DLL');
Như vậy cho nên nó cứ sai tè le ra mặc dù Anh @batman1 có hướng dẫn rất chi tiết làm y trang mà nó cứ linh tinh là thế :p
=========== khúc trên coi như xong bạn nào test thì sửa lại Path DLL thực tế trên máy mình =============

1/ vần đề đặt ra là nếu nay nó VBA7.1 mai nó 7.2 + n thì sao ??!!!
2/ Office x32 và x64 ????

Anh @batman1 cho Em hỏi chút

1/ Có cách nào lấy cái Path đặc biệt của DLL đó theo bộ Office mà mình cài đặt hay ko ???
2/ nếu có Viết cho nó vào đó 1 cái Hàm là xong khỏi mất công khai báo thủ công rồi lại thay đổi theo Ver của nó thì mêt lắm
3/ hoặc có cách nào khác ko cần path DLL của nó mà vẫn load được DLL đó ( Em nghỉ khó )
.....
Em hình dung ra cách ứng dụng nó một chút rồi :p

cảm ơn tất cả mọi người
OK.JPG
Bài đã được tự động gộp:

Office bạn mạnh là 2013 x32, thế exe delphi bạn Mạnh build ở 32 hay 64 đấy?
Mạnh xài Windows10x64 - Office2016x32
 
Lần chỉnh sửa cuối:
Upvote 0
Chả lẽ do align stack sai chăng, vì thấy Delphi dùng các thanh ghi RCX, RDX, R8,R9 đúng mà, còn stack của hàm thì thấy hơi dị dị ???

EM vừa có một thí nghiệm và tạm khá yên tâm. EM tạo hàm trả về số Long thì mọi nguyên đẹp đẽ :). Như vậy khoanh vùng vấn đề ở OleVariant.
 
Upvote 0
Anh @batman1 cho Em hỏi chút

1/ Có cách nào lấy cái Path đặc biệt của DLL đó theo bộ Office mà mình cài đặt hay ko ???
2/ nếu có Viết cho nó vào đó 1 cái Hàm là xong khỏi mất công khai báo thủ công rồi lại thay đổi theo Ver của nó thì mêt lắm
3/ hoặc có cách nào khác ko cần path DLL của nó mà vẫn load được DLL đó ( Em nghỉ khó )
Tôi nghĩ là cứ tìm trong csdl của system là Registry thôi. Chả nhẽ csdl mà lại không có?

Trên XP Home của tôi thì là khóa HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VBA

Nếu tôi đoán được những trò "voc" của bạn thì bạn muốn tạo DLL để nhúng vào Excel. Nếu thế thì bạn chỉ cần tên DLL: VBE6.dll hoặc VBE7.dll. Để có được HMODULE thì bạn nhập tên DLL thôi. Muốn thế thì bạn dùng GetModuleHandle

Help của Delphi 5


help.JPG

Từ đỏ đỏ bạn thấy là bạn có thể nhập tên DLL thôi. Hàm sẽ tìm DLL bạn cần trong các module được ánh xạ vào không gian địa chỉ của process Excel.

Tóm lại
Mã:
h := GetModuleHandle('VBE7.DLL');

Tất nhiên với Excel thấp thì chỉ có VBE6, với phiên bản mới thì có cả VBE6 và VBE7. Vậy thì trước tiên nhập VBE7.dll. Nếu h = 0 thì gọi lại và nhập VBE6.dll. Nếu cũng h = 0 thì "dọn đồ chơi". Nhưng chắc chắn là 1 trong 2 module này được load.

Từ xanh xanh thì bạn bỏ không gọi (xóa đi)
Mã:
FreeLibrary(h);

Tôi ra cho bạn bài tập nhé.

1. Code của bài dùng 'rtcTypeName' bạn cho vào MyDll.dll
2. DLL exports 1 hàm GetTypeName trả về PWideChar.
3. Hàm GetTypeName gọi hàm rtcTypeName trong VBE7.dll để lấy kết quả và trả về kết quả ấy cho caller trong VBA.

Ở trên tôi nói là bạn không phải gọi FreeLibrary. Nếu bạn cố tình gọi FreeLibrary thì trước khi trả về kết quả cho caller, tức trước khi result := ... thì bạn phải từ kết quả do rtcTypeName trả về "soạn" kết quả cho caller. Nếu không "soạn" mà trả về cho caller cái mà rtcTypeName trả về thì Excel sẽ bị chết đột ngột - Excel bị đóng mà không có thông báo gì. Nguyên nhân thì đọc kỹ chỗ xanh xanh.

Khai báo bên Excel
Mã:
Declare Function GetTypeName Lib "MyDll.dll" () As String
 
Upvote 0
Bạn Mạnh mà nắm vững debug trên Delphi thì mấy cái lỗi này là muỗi. Ai biểu chỉ biết F9 Run làm chi thì ráng chịu.
Code đó của bạn Tuân bị memory leak đó, chưa dùng được đâu. Và return string về cho VBA bị ông VBA lanh chanh thọt võ làm sai.
Bài đã được tự động gộp:

Vậy 90% là do stack align rồi Tuân ơi. Lỗi do mình chứ kg phải do Delphi compiler.
Tuân tiếp tục thử với hàm có kiểu trả về có SizeOf lớn hơn 8 nhé, như record, double, real, single...
Của bạn kia là kiểu Double đó.
Tuân nhớ x64 dll, MyCaller, nếu truyền V: OleVariant , truyền nguyên 3 Param mỗi cái 24 byte vào stack, bị văng ngay _VarAddRef không?
 
Lần chỉnh sửa cuối:
Upvote 0
return PWideChar thôi. Tất nhiên rtcTypeName cũng return PWideChar chứ không như Tuân mong muốn là WideString. Thế thôi.

Và dĩ nhiên phải convert String mà GetTypeName trả về - from Unicode.
 
Upvote 0
Bạn Mạnh mà nắm vững debug trên Delphi thì mấy cái lỗi này là muỗi. Ai biểu chỉ biết F9 Run làm chi thì ráng chịu.
Code đó của bạn Tuân bị memory leak đó, chưa dùng được đâu. Và return string về cho VBA bị ông VBA lanh chanh thọt võ làm sai.
Bài đã được tự động gộp:

Vậy 90% là do stack align rồi Tuân ơi. Lỗi do mình chứ kg phải do Delphi compiler.
Tuân tiếp tục thử với hàm có kiểu trả về có SizeOf lớn hơn 8 nhé, như record, double, real, single...
Của bạn kia là kiểu Double đó.
Tuân nhớ x64 dll, MyCaller, nếu truyền V: OleVariant , truyền nguyên 3 Param mỗi cái 24 byte vào stack, bị văng ngay _VarAddRef không?
memory leak là sao. Anh có thể giải thích rõ chúc đựợc không?
 
Upvote 0
Cái hình Winhex tui post bên kia các bác chưa nhìn kỹ rồi. Khổ.
Memory leak nghĩa là nếu hàm đó được gọi cỡ triệu lần thì Excel văng luôn đó em gái. Chịu khó đọc source C của rtcTyName mà tui đã post, khúc cuối hàm đó.
Bài đã được tự động gộp:

Nhỏ hơn hoặc = 8 thì trả về qua RAX, hôm qua mình nói rồi, lớn hơn thì qua stack hay RDX:RAX.
Nên mình có nói stack nó dị dị, còn dị ra sao thì debug kỹ.
Chắc vì vậy nên mấy cái pointer POleViant trỏ sai hết
 
Lần chỉnh sửa cuối:
Upvote 0
Rất rất nhiều bạn code Delphi mà hầu như không hề quan tâm tới internal của biến, kiểu trong Delphi nó "nà như thế lào". Ví dụ rõ nhất là kiểu string. Cứ var xxx:string rồi xài tẹt ga. Hay các kiểu record, array, dynamic array...
Thật ra cũng không sao, cứ có cho thì tui xài, quan tâm xuống dưới "nàm" chi cho mệt óc. Nhưng rồi từ từ sẽ tới lúc sẽ bắt buộc phải đào xuống, ví dụ khi dùng API, dùng Pointer, hay gặp bug tinh vi, memory leak, crash, dập, tràn trên tràn dưới bộ nhớ... hay "rờ em" Delphi app tìm bug, exploit, "mèo què", hì hì và cả cờ rắc nữa :p
Vì vậy cu anh tui thành thực khuyên các bạn, bỏ chút ít thời gian đọc và tìm hiểu về internal data type của Delphi, xem, biết cách nó tổ chức, nằm trong bộ nhớ ra sao, phải thao tác như thế nào với nó cho đúng.
Trong Delphi document, help, đã có nói rất rõ về vấn đề này, nhưng hầu như ít ai đọc kỹ, hầu như lướt qua cho xong.
Minh "ngu phép" đăng lại ở đây để các bạn đọc, nhất là các bạn đang bắt đầu học Delphi, như bạn ở Dĩ An chẵng hạn, hay em gái xinh đẹp làm GUI ngon lành đấy: :)
Gác chân lên bàn, hay mang lap ra ban công đều được, kkk.
1. http://docwiki.embarcadero.com/RADStudio/Rio/en/Internal_Data_Formats_(Delphi)
2. http://docwiki.embarcadero.com/RADStudio/Rio/en/Unicode_in_RAD_Studio
Đọc đi đọc lại, đọc tới đọc lui, đọc xuôi đọc ngược, khi nào thuộc thì thôi,
Có gì "thét mét" cứ đừng ngại ngùng mà đăng lên nhé, mọi người cùng trao đổi.
Cứ từ từ, căn bản từ gốc đã rồi sẽ có ngày hái quả ngon.Đừng nôn nóng.
 
Upvote 0
Nói đi thì cũng suy lại 1 tẹo !!!!

1/ Khi Mạnh với vọc VBA thấy người ta code vậy mà mình copy để dùng hoài mà sao ko có chạy được ( vì chưa biết bật mắt rô )
sau này vọc hoài mới biết .... nói chung copy code cho nó chạy được là mừng hết lớn nuôn chứ chưa nói viết code

Ngày trước Anh quanghai1969 khi rảnh ghé chơi chỉ cho mạnh viết mấy cái hàm rất đơn giản như abc ấy thế mà ko biết nó ra làm sao cả ... giờ nhìn lại thấy phì cười tại sao nó đơn giản thế mà khi đó mình ngu thế ko biết là nàm sao ???!!!

Code két hay cái chi đó nó phải có quá trình hấp thụ nó ... Nếu quá trình thu nạp 1 số lượng nhất định khi vượt giới hạn của nó thì chất nó sẻ biến đổi đó là cái quy luật muôn đời nó vẫn cứ thế ???!!!

2/ Mạnh vọc Delphi cũng thế biến khai báo sao hiện tại kệ bà nó miễn sao nó chạy là mừng hết lớn luôn ... sau này kiến thức khá thêm chút nhìn lại khắc tự biết tại sao mình ko khai báo như thế lày mà lại khai báo như thế lọ .... sao ngơ ngơ thế nhỉ
....
Cảm ơn cái tấm chân tình tốt của @ThangCuAnh đã chỉ cho Mạnh học nhưng phải có thời gian mà thu nạp nó chứ nói khơi khơi kiểu cao cấp thế thì còn lâu lắm lắm Mạnh mới theo kịp

Nói chi xa xôi chỉ cho Mạnh Kỹ thuật Debug trong Delphi khi viết DLL cho Excel như cái VBlibray ấy .... chi tiết chút thì tốt .... chứ cứ keo khơi khơi Debug ....Debug ....Debug đi thì cũng thua ===\. -0-0-0-
 
Upvote 0
Khổ ghê, cao xa cái gì trời, nó nằm ngay trong Help của RAD Studio của cậu đó, chứ ở đâu xa. Hình như phần Object Pascal Language Guide, nếu tôi nhớ không lầm.
Còn cái debug thì cái hình hôm qua tôi đã nói rõ rồi, nó chình ình ra đó, chỉ click vào và đọc thôi chứ ở đâu xa.
Sao cậu không tự thân vận động nhỉ, cái gì cũng phải có người khác làm giùm, chỉ giùm 100% mới chịu.
Đến phát bực với cậu "nuôn, nắm nắm" rồi đó.
 

File đính kèm

  • Capture.JPG
    Capture.JPG
    509.8 KB · Đọc: 20
Upvote 0
Lưu nó vô đây để nhớ sau này quên thì vô coi lại đầy code mẫu ....!!???
Nếu cứ coi sách mà ai cũng học được thì mấy tay giáo sư, tiến sĩ đứng bục thất nghiệp hết ... đói ăn ra làm bốc xếp dễ ko chừng mấy tay mặt ác chân tay to nó keo : người đâu ấy chứ xếp mấy cục gạch mà làm ko xong thì làm nên cái trò chi ko biết !!!???
Mạnh coi các mẫu code là mới hình dung ra được còn nói sáo rỗng như con két thì thua toàn tập -0-0-0-

Ngày xưa rất xưa có Ông hàng xóm hay nói câu "Nhân Vô Thập toàn mà cháu" ... mấy chục năm sau nhớ lại thấy Ông ấy Nói đúng
 
Lần chỉnh sửa cuối:
Upvote 0
Người học VBA cũng vậy. Nếu chỉ làm việc với RANGE, Worksheet, Array thì trên GPE này cả rừng người, trên mạng thì vô số. Nhưng số người biết ứng dụng khá tốt lập trình Windows API trên GPE thì đếm trên đầu ngón tay, không hết một bàn tay đâu nhé. Mình nói lại, nó là một lĩnh vực rộng.

Kiến thức Delphi rộng lắm nhé. Nếu lan man bạn sẽ lấn vào một lĩnh mà không phải ai cũng biết đâu -> đó là lập trình hàm API cho môi trường Windows. API là giao tiếp với môi trường chung của Windows mà các phần mềm hỗ trợ lập trình có thể giao tiếp được với nhau ->Đó là chuẩn khai báo Interface, data type... API là lĩnh vực can thiệp rộng tới mọi ngõ ngách của hệ điều hành. Nên việc này khó hiểu là đương nhiên. Ngay cả với người chuyên lập trình phần mềm trên nền tảng VCL của Winform trên Delphi động đến nó còn phải mất ăn mất ngủ để tra cứu tư liệu gốc của Microsoft và Delphi. Bạn nào tự học theo thói quen trải nghiệm bản thân rồi tự đúc rút qua một tá ví dụ thì nó khó là đương nhiên. Liệu cần có bao nhiêu ví dụ để đủ trải nghiệm?

Topic này mình kỳ vọng các bạn biết thêm được hướng tự tạo hàm API cơ bản chuyên để phân tích dữ liệu phục vụ cho xử lý dữ liệu (DATA) trên Excel là chính, nên nếu học ngôn ngữ Delphi/Pascal/Object Pascal cùng với phương pháp lập trình API dễ như bài đầu thì sẽ học được thôi. Nhưng nếu lan rộng ra lập trình các ngõ ngách của Windows là to chuyện đấy. Mình nói vậy để các bạn mới vào topic này đừng xem các bài viết trên mà nản vì các câu hỏi và trả lời đó đang đi vào khu vực khai thác rộng chứ không phải chỉ DATA trên Excel. Nên tôi khuyên những ai mới biết đến Delphi và muốn lập trình DLL tạo hàm API hãy tập trung và xử lý DATA trước cùng Delphi và đừng quên học ngôn ngữ, đọc ngấm từng chữ trong tài liệu Object Pascal nhé. Các vấn đề khác dần dần tính tiếp khi đã nắm được ngôn ngữ khá tốt.
 
Lần chỉnh sửa cuối:
Upvote 0
Web KT
Back
Top Bottom