Đây là video hướng dẫn cách tạo DLL trên Delphi nhưng sử dụng trong VBA, Excel. Đây là phương pháp lập trình chuyên nghiệp nhưng không phải là khó. Giúp bạn bảo mật code của phần mềm tốt hơn.
Viết DLL = Delphi cũng có nhiều chiêu, tips nho nhỏ. Ví dụ không phải chỉ export được hàm/procedure, mà có thể export cả biến, kiểu record, pointer, object..., cách thưc hiện các code ở DllMain proc.
Tặng bạn Mạnh 1 code tui code cho IDA plugin, port từ C/C++ qua Delphi, export 1 biến kiểu record, và dùng API để search, patch memory của application mẹ.
Code này chỉ chạy đúng trên app 32bit thôi nhé, 64 bit phải sữa lại vài điểm nhỏ. Hì hì, trên chục năm rồi, từ thời IDA v6.1, giờ nó lên tới 7.3 rồi.
Viết DLL = Delphi cũng có nhiều chiêu, tips nho nhỏ. Ví dụ không phải chỉ export được hàm/procedure, mà có thể export cả biến, kiểu record, pointer, object..., cách thưc hiện các code ở DllMain proc.
Tặng bạn Mạnh 1 code tui code cho IDA plugin, port từ C/C++ qua Delphi, export 1 biến kiểu record, và dùng API để search, patch memory của application mẹ.
Code này chỉ chạy đúng trên app 32bit thôi nhé, 64 bit phải sữa lại vài điểm nhỏ. Hì hì, trên chục năm rồi, từ thời IDA v6.1, giờ nó lên tới 7.3 rồi.
đang coi qua coi lại mà không biết xài nó như thế nào và ứng dụng vào thực tế của Mạnh ra làm sao ???!!!
Cho mạnh rồi thì chỉ cho Mạnh học cách xài nó và ứng dụng nó ... nếu được bạn có thể điều chỉnh viết lại code cho nó sử dụng được cả trên 32 & 64 được không ?
Đây là video hướng dẫn cách tạo DLL trên Delphi nhưng sử dụng trong VBA, Excel. Đây là phương pháp lập trình chuyên nghiệp nhưng không phải là khó. Giúp bạn bảo mật code của phần mềm tốt hơn. Loạt video hướng dẫn lập trình Delphi cơ bản của mình tại đây...
Mà bạn có đọc các vd. của Delphi, tìm kiếm trên mạng? Không có chỗ nào bạn thấy trường hợp một unit sử dụng một unit khác? Thế thì bạn may mắn đấy. Người khác "va chạm" với nó thường xuyên. Còn bạn "vọc" khá lâu mà không gặp thì cũng lạ.
Ngoài các unit của Delphi thì bạn có thể có những unit của mình chứ. Nếu không thì sao Delphi lại cho bạn khả năng thêm unit mới và viết code cho unit ấy??? Mà khi có rồi thì không phải để đấy làm cảnh. Mà muốn dùng thì cho vào uses thôi.
Đây là video hướng dẫn cách tạo DLL trên Delphi nhưng sử dụng trong VBA, Excel. Đây là phương pháp lập trình chuyên nghiệp nhưng không phải là khó. Giúp bạn bảo mật code của phần mềm tốt hơn. Loạt video hướng dẫn lập trình Delphi cơ bản của mình tại đây...
Mà bạn có đọc các vd. của Delphi, tìm kiếm trên mạng? Không có chỗ nào bạn thấy trường hợp một unit sử dụng một unit khác? Thế thì bạn may mắn đấy. Người khác "va chạm" với nó thường xuyên. Còn bạn "vọc" khá lâu mà không gặp thì cũng lạ.
Ngoài các unit của Delphi thì bạn có thể có những unit của mình chứ. Nếu không thì sao Delphi lại cho bạn khả năng thêm unit mới và viết code cho unit ấy??? Mà khi có rồi thì không phải để đấy làm cảnh. Mà muốn dùng thì cho vào uses thôi.
Đây là video hướng dẫn cách tạo DLL trên Delphi nhưng sử dụng trong VBA, Excel. Đây là phương pháp lập trình chuyên nghiệp nhưng không phải là khó. Giúp bạn bảo mật code của phần mềm tốt hơn. Loạt video hướng dẫn lập trình Delphi cơ bản của mình tại đây...
Mà bạn có đọc các vd. của Delphi, tìm kiếm trên mạng? Không có chỗ nào bạn thấy trường hợp một unit sử dụng một unit khác? Thế thì bạn may mắn đấy. Người khác "va chạm" với nó thường xuyên. Còn bạn "vọc" khá lâu mà không gặp thì cũng lạ.
Ngoài các unit của Delphi thì bạn có thể có những unit của mình chứ. Nếu không thì sao Delphi lại cho bạn khả năng thêm unit mới và viết code cho unit ấy??? Mà khi có rồi thì không phải để đấy làm cảnh. Mà muốn dùng thì cho vào uses thôi.
Từ ngày Em vào Nam đến giờ 20 Năm rồi vẫn ở cái nhà đó, ngõ đó, đường đó thế mà có người hỏi Em nhà Anh ở đường nào Em keo ko biết ... chỉ biết cổng 16 - dĩ an - bình dương
hàng ngày Em vẫn coi code Delphi vẫn Add thêm Unit để viết code mới và sử dung nó ... thế mà đùng 1 cái hỏi nó mới ghê
Tại em thấy khi em thêm 1 cái Unit thì trong Delphi tự động nó sinh ra như vầy trong Uses: ADO_Excel in 'ADO_Excel.pas',
còn bài 259 Anh chỉ Em như vậy mà em học xong quên mất tiêu ... giờ em lại nhớ tránh tham chiếu vòng vv ...
Còn thấy cái đó khai báo ngắn gọn vậy nên lại nhầm nhọt sang trồng trọt ..........
quả là code két diết nhớ nhớ xong quên quên nó làm đơ người ra đó Anh
Trong VBA có hàm TypeName() để lấy tên của class hay tên của lớp khai báo control hay các object. Khi các bạn lập trình Delphi cho Excel muốn dùng hàm TypeName không thể được vì nó không cùng môi trường VBA. Giải pháp chúng ta phải biết hàm API nào trong thư viên VBAxxx xuất nó ra đồng thời phải biết tham số để sử dụng. Chúng ta thực sự khó nếu không có tài liệu cung cấp từ nhà lập trình ra vbaxxx.
Nhân chủ đề Undocument API VBA ở bài số #10 tại đây
Cái laptop hư lâu lắc, phải gởi vào thành hồ chứa mưa sữa, mới lấy về. Nên quay lại tiếp với cái gọi là "rờ chxx em" Windows và VBA. Topic này tui sẽ đăng lần lượt những gì cu anh tui phát hiện ra trong quá trình "rờ em" Windows API, DLLs và VBAxxx.dll. Các tips, tricks này sẽ bảo đảm không có...
www.giaiphapexcel.com
Code mà bác CU Anh moi ra nó là C và rất phức tạp đây:
Điều quan trọng là bác @ThangCuAnh đã giúp lấy được tên hàm API của hàm TypeName cùng prototype, tôi viết lại code để chúng ta dùng trong Delphi như sau.
1. Các bạn thao khảo cách dùng bên VB/VBA (mang tính học tập vì trong VBA hàm TypeName đã có.
Option Explicit
#If VBA7 Then
Declare PtrSafe Function rtcTypeName Lib "VBE7.DLL" (v As Variant) As String
#Else
Declare Function rtcTypeName Lib "VBE6.DLL" (v As Variant) As String
#End If
Sub TestTypeNameAPI()
Dim sName As String
sName = rtcTypeName(ActiveCell)
MsgBox StrConv(sName, vbFromUnicode)
End Sub
2. Cách khai báo API hàm rtcTypeName() để dùng trong Delphi. Nếu chúng ta tạo Add-in thì đây là tư liệu quý.
Code dưới đây tôi viết trong chương trình chính dạng Console (màn hình đen trắng). Các bạn làm trình tự như sau.
1. Từ Delphi, tạo application dạng Console (nếu ai có add-in rồi thì chỉ cần code chính của nó).
2. Paste đoạn code dưới đây.
3. Chạy Excel với quyền "Run as administrator"
4. Chạy progam trong Delphi (F9)
Mã:
program Test_VBA_API.dproj;
//This code call function API in VBAxxx "rtcTypeName()". In VBA its name is TypeName()
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
Winapi.Windows,
ComObj,
System.Variants;
type
TFuncVBAPI_rtcTypeName = function(var v: OleVariant): PWideChar; stdcall;
var sName: WideString;
h: HMODULE;
pFunc: TFuncVBAPI_rtcTypeName;
App: OleVariant;
v: OleVariant;
begin
try
App := GetActiveOleObject('Excel.Application');
Writeln('Ung dung da ma la', ': ', App.Name);
h := LoadLibrary('C:\Program Files (x86)\Common Files\Microsoft Shared\VBA\VBA7\VBE7.DLL');
try
pFunc := GetProcAddress(h, 'rtcTypeName');
v := App.ActiveCell;
sName := PWideChar(TFuncVBAPI_rtcTypeName(pFunc)(v));
Writeln('Gia tri bien la', ': ', sName);
finally
FreeLibrary(h);
App := Unassigned;
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
Trong VBA có hàm TypeName() để lấy tên của class hay tên của lớp khai báo control hay các object. Khi các bạn lập trình Delphi cho Excel muốn dùng hàm TypeName không thể được vì nó không cùng môi trường VBA. Giải pháp chúng ta phải biết hàm API nào trong thư viên VBAxxx xuất nó ra đồng thời phải biết tham số để sử dụng. Chúng ta thực sự khó nếu không có tài liệu cung cấp từ nhà lập trình ra vbaxxx.
Nhân chủ đề Undocument API VBA ở bài số #10 tại đây
Cái laptop hư lâu lắc, phải gởi vào thành hồ chứa mưa sữa, mới lấy về. Nên quay lại tiếp với cái gọi là "rờ chxx em" Windows và VBA. Topic này tui sẽ đăng lần lượt những gì cu anh tui phát hiện ra trong quá trình "rờ em" Windows API, DLLs và VBAxxx.dll. Các tips, tricks này sẽ bảo đảm không có...
www.giaiphapexcel.com
Code mà bác CU Anh moi ra nó là C và rất phức tạp đây:
Điều quan trọng là bác @ThangCuAnh đã giúp lấy được tên hàm API của hàm TypeName cùng prototype, tôi viết lại code để chúng ta dùng trong Delphi như sau.
1. Các bạn thao khảo cách dùng bên VB/VBA (mang tính học tập vì trong VBA hàm TypeName đã có.
Option Explicit
#If VBA7 Then
Declare PtrSafe Function rtcTypeName Lib "VBE7.DLL" (v As Variant) As String
#Else
Declare Function rtcTypeName Lib "VBE6.DLL" (v As Variant) As String
#End If
Sub TestTypeNameAPI()
Dim sName As String
sName = rtcTypeName(ActiveCell)
MsgBox StrConv(sName, vbFromUnicode)
End Sub
2. Cách khai báo API hàm rtcTypeName() để dùng trong Delphi. Nếu chúng ta tạo Add-in thì đây là tư liệu quý.
Code dưới đây tôi viết trong chương trình chính dạng Console (màn hình đen trắng). Các bạn làm trình tự như sau.
1. Từ Delphi, tạo application dạng Console (nếu ai có add-in rồi thì chỉ cần code chính của nó).
2. Paste đoạn code dưới đây.
3. Chạy Excel với quyền "Run as administrator"
4. Chạy progam trong Delphi (F9)
Mã:
program Test_VBA_API.dproj;
//This code call function API in VBAxxx "rtcTypeName()". In VBA its name is TypeName()
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
Winapi.Windows,
ComObj,
System.Variants;
type
TFuncVBAPI_rtcTypeName = function(var v: OleVariant): PWideChar; stdcall;
var sName: WideString;
h: HMODULE;
pFunc: TFuncVBAPI_rtcTypeName;
App: OleVariant;
v: OleVariant;
begin
try
App := GetActiveOleObject('Excel.Application');
Writeln('Ung dung da ma la', ': ', App.Name);
h := LoadLibrary('C:\Program Files (x86)\Common Files\Microsoft Shared\VBA\VBA7\VBE7.DLL');
try
pFunc := GetProcAddress(h, 'rtcTypeName');
v := App.ActiveCell;
sName := PWideChar(TFuncVBAPI_rtcTypeName(pFunc)(v));
Writeln('Gia tri bien la', ': ', sName);
finally
FreeLibrary(h);
App := Unassigned;
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
Vâng, viết thế chuẩn đó anh. Vì code trước em test để khai báo pFunc: TFarProc; nên lúc dùng thì lại bao lớp cấu trúc hàm, sau em chỉnh ở trên thì dưới lại chưa chình a.
Thôi thôi bác Tuân ơi, InStr với InStrRev ẹ lắm, dài dòng, chậm, không bằng mấy hàm PChar của Delphi đâu. Bác tính dùng cho việc gì ?
Nó là 3 hàm rtcInStr, rtcInStrRev với rtcInStrChar đó.
Hầu như 100% các hàm của VBA đều được export hết đó bạn Tuân.
Thôi thôi bác Tuân ơi, InStr với InStrRev ẹ lắm, dài dòng, chậm, không bằng mấy hàm PChar của Delphi đâu. Bác tính dùng cho việc gì ?
Nó là 3 hàm rtcInStr, rtcInStrRev với rtcInStrChar đó.
Hầu như 100% các hàm của VBA đều được export hết đó bạn Tuân.
Vâng. Hàm InStr có thể dùng bởi hàm Pos hoặc PosEx cảu Delphi rất nhanh, code nguồn Delphi hàm Pos() viết bằng Assemble rất ngọt. Tuy nhiên hàm InStrRev Delphi không viết giúp, mình phải tự viết và dùng vòng lặp và duyệt PChar nên cảm thấy chưa ưng. Nếu lấy được InStrRev em sẽ test để so sánh tốc độ với Delphi. Khi viết Delphi cho Office thì cứ thằng nào ngon nhất ta dùng. Ý em là vậy đó bác .
Hạn chế dùng mấy hàm và kiểu string của Delphi bác Tuân ơi, chậm lắm, dùng các hàm và trực tiếp trên kiểu PChar luôn. Vd StrPos, StrScan, StrRScan...
Dùng kiểu string, compiler của Delphi phải nhét rất nhiều code của các hàm internal vào, chuyển kiểu, thao tác ngầm trong đó.
Bác Tuân, bác Mạnh bật option build with debug dcu đi, debug vào từng lệnh 1 sẽ thấy. Nightmare đó.
Vâng. Hàm InStr có thể dùng bởi hàm Pos hoặc PosEx cảu Delphi rất nhanh, code nguồn Delphi hàm Pos() viết bằng Assemble rất ngọt. Tuy nhiên hàm InStrRev Delphi không viết giúp, mình phải tự viết và dùng vòng lặp và duyệt PChar nên cảm thấy chưa ưng. Nếu lấy được InStrRev em sẽ test để so sánh tốc độ với Delphi. Khi viết Delphi cho Office thì cứ thằng nào ngon nhất ta dùng. Ý em là vậy đó bác .
Lỗi {$ *.Res} không phải là lỗi nghiêm trọng.
Khi bạn tạo project mới thì Delphi tự thêm {$R *.RES}. Bạn chon Save All rồi đóng Delphi. Trên đĩa sẽ có project.res. Nếu bạn xóa project.res rồi mở lại project.dpr thì Delphi sẽ thông báo là không tìm thấy project.res. Nó tìm vì trong unit project.dpr có {$R *.RES}. Và nó hỏi có tạo lại project.res không. Chỉ cần gật đầu là xong. Đây không phải là lỗi nghiêm trọng.
-------
Bạn có nhìn thấy thông báo "CoInitialize has not been called" không?
Thực ra tôi chỉ cài Delphi 5 vì máy 18 tuổi, C có 10 GB, XP Home. Bạn hãy thử như sau.
Trước dòng
Mã:
App := GetActiveOleObject('Excel.Application');
thì thêm dòng
Mã:
if InitProc <> nil then TProcedure(InitProc);
------
Mà chỉ thêm như sau cũng được
Mã:
TProcedure(InitProc);
vì trong ComObj có
Mã:
initialization
begin
...
if not IsLibrary then
begin
SaveInitProc := InitProc;
InitProc := @InitComObj;
end;
end;
Tức InitProc <> nil (InitProc := @InitComObj)
Tức sẽ thực hiện InitComObj
Mã:
procedure InitComObj;
begin
if SaveInitProc <> nil then TProcedure(SaveInitProc);
if (CoInitFlags <> -1) and Assigned(ComObj.CoInitializeEx) then
begin
NeedToUninitialize := Succeeded(ComObj.CoInitializeEx(nil, CoInitFlags));
IsMultiThread := IsMultiThread or
((CoInitFlags and COINIT_APARTMENTTHREADED) <> 0) or
(CoInitFlags = COINIT_MULTITHREADED); // this flag has value zero
end
else
NeedToUninitialize := Succeeded(CoInitialize(nil));
end;
Trường hợp này (nếu tôi không lầm thì trong trường hợp đang nói thì CoInitFlags =-1
Mã:
var
CoInitFlags: Integer = -1; // defaults to no threading model, call CoInitialize()
Lỗi {$ *.Res} không phải là lỗi nghiêm trọng.
Khi bạn tạo project mới thì Delphi tự thêm {$R *.RES}. Bạn chon Save All rồi đóng Delphi. Trên đĩa sẽ có project.res. Nếu bạn xóa project.res rồi mở lại project.dpr thì Delphi sẽ thông báo là không tìm thấy project.res. Nó tìm vì trong unit project.dpr có {$R *.RES}. Và nó hỏi có tạo lại project.res không. Chỉ cần gật đầu là xong. Đây không phải là lỗi nghiêm trọng.
-------
Bạn có nhìn thấy thông báo "CoInitialize has not been called" không?
Thực ra tôi chỉ cài Delphi 5 vì máy 18 tuổi, C có 10 GB, XP Home. Bạn hãy thử như sau.
Trước dòng
Mã:
App := GetActiveOleObject('Excel.Application');
thì thêm dòng
Mã:
if InitProc <> nil then TProcedure(InitProc);
------
Mà chỉ thêm như sau cũng được
Mã:
TProcedure(InitProc);
vì trong ComObj có
Mã:
initialization
begin
...
if not IsLibrary then
begin
SaveInitProc := InitProc;
InitProc := @InitComObj;
end;
end;
Tức InitProc <> nil (InitProc := @InitComObj)
Tức sẽ thực hiện InitComObj
Mã:
procedure InitComObj;
begin
if SaveInitProc <> nil then TProcedure(SaveInitProc);
if (CoInitFlags <> -1) and Assigned(ComObj.CoInitializeEx) then
begin
NeedToUninitialize := Succeeded(ComObj.CoInitializeEx(nil, CoInitFlags));
IsMultiThread := IsMultiThread or
((CoInitFlags and COINIT_APARTMENTTHREADED) <> 0) or
(CoInitFlags = COINIT_MULTITHREADED); // this flag has value zero
end
else
NeedToUninitialize := Succeeded(CoInitialize(nil));
end;
Trường hợp này (nếu tôi không lầm thì trong trường hợp đang nói thì CoInitFlags =-1
Mã:
var
CoInitFlags: Integer = -1; // defaults to no threading model, call CoInitialize()
Làm gì có server Excel nào đang hoạt động mà đòi Get?
Tôi không tin là Tuân không gặp lỗi. Vì Tuân có thể cho code không hẳn như có trên đĩa (vụ vbTextCompare), không hẳn là đúng thực tế, nên khó đoán. Nếu là code đưa trên GPE thì nhất định có lỗi 1.
Debug thì thấy lỗi "EOleSysError: CoInitialize has not been called" nhưng trên cơ sở "Đọc kỹ hdsd trước khi dùng" thì có đến tết Công Gô kieu manh cũng không đoán được phải thêm cái gì. "Đọc kỹ hdsd trước khi dùng" là chung chung chả nói lên cái gì cụ thể.
Làm gì có server Excel nào đang hoạt động mà đòi Get?
Tôi không tin là Tuân không gặp lỗi. Vì Tuân có thể cho code không hẳn như có trên đĩa (vụ vbTextCompare), không hẳn là đúng thực tế, nên khó đoán. Nếu là code đưa trên GPE thì nhất định có lỗi 1.
Debug thì thấy lỗi "EOleSysError: CoInitialize has not been called" nhưng trên cơ sở "Đọc kỹ hdsd trước khi dùng" thì có đến tết Công Gô kieu manh cũng không đoán được phải thêm cái gì. "Đọc kỹ hdsd trước khi dùng" là chung chung chả nói lên cái gì cụ thể.
Cái dòng màu đem như dân quãng ninh kia nhột lắm Anh ... Em mò học mà cứ quăng thế tết tây quá !!!
Mạnh Phán xanh dì 1 câu trên cung trăng có đầy vàng mi cứ lên đó mà lấy ........... vãi kinh hồn nuôn !!!
kieu manh không làm đúng thì sẽ có lỗi "EOleSysError: Operation unavailable". Chỉ cần "Đọc kỹ hdsd trước khi dùng" một lần nữa thì sẽ hết lỗi này.
Nhưng còn lỗi khó hơn là "EOleSysError: CoInitialize has not been called" mà chỉ trên cơ sở "Đọc kỹ hdsd trước khi dùng" thì có đọc đến tết Công Gô kieu manh vẫn không biết phải sửa gì, thêm gì.
Cái dòng màu đem như dân quãng ninh kia nhột lắm Anh ... Em mò học mà cứ quăng thế tết tây quá !!!
Mạnh Phán xanh dì 1 câu trên cung trăng có đầy vàng mi cứ lên đó mà lấy ........... vãi kinh hồn nuôn !!!
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ì.
Trong VBA có hàm TypeName() để lấy tên của class hay tên của lớp khai báo control hay các object. Khi các bạn lập trình Delphi cho Excel muốn dùng hàm TypeName không thể được vì nó không cùng môi trường VBA. Giải pháp chúng ta phải biết hàm API nào trong thư viên VBAxxx xuất nó ra đồng thời phải biết tham số để sử dụng. Chúng ta thực sự khó nếu không có tài liệu cung cấp từ nhà lập trình ra vbaxxx.
Nhân chủ đề Undocument API VBA ở bài số #10 tại đây
Cái laptop hư lâu lắc, phải gởi vào thành hồ chứa mưa sữa, mới lấy về. Nên quay lại tiếp với cái gọi là "rờ chxx em" Windows và VBA. Topic này tui sẽ đăng lần lượt những gì cu anh tui phát hiện ra trong quá trình "rờ em" Windows API, DLLs và VBAxxx.dll. Các tips, tricks này sẽ bảo đảm không có...
www.giaiphapexcel.com
Code mà bác CU Anh moi ra nó là C và rất phức tạp đây:
Điều quan trọng là bác @ThangCuAnh đã giúp lấy được tên hàm API của hàm TypeName cùng prototype, tôi viết lại code để chúng ta dùng trong Delphi như sau.
1. Các bạn thao khảo cách dùng bên VB/VBA (mang tính học tập vì trong VBA hàm TypeName đã có.
Option Explicit
#If VBA7 Then
Declare PtrSafe Function rtcTypeName Lib "VBE7.DLL" (v As Variant) As String
#Else
Declare Function rtcTypeName Lib "VBE6.DLL" (v As Variant) As String
#End If
Sub TestTypeNameAPI()
Dim sName As String
sName = rtcTypeName(ActiveCell)
MsgBox StrConv(sName, vbFromUnicode)
End Sub
2. Cách khai báo API hàm rtcTypeName() để dùng trong Delphi. Nếu chúng ta tạo Add-in thì đây là tư liệu quý.
Code dưới đây tôi viết trong chương trình chính dạng Console (màn hình đen trắng). Các bạn làm trình tự như sau.
1. Từ Delphi, tạo application dạng Console (nếu ai có add-in rồi thì chỉ cần code chính của nó).
2. Paste đoạn code dưới đây.
3. Chạy Excel với quyền "Run as administrator"
4. Chạy progam trong Delphi (F9)
Mã:
program Test_VBA_API.dproj;
//This code call function API in VBAxxx "rtcTypeName()". In VBA its name is TypeName()
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
Winapi.Windows,
ComObj,
System.Variants;
type
TFuncVBAPI_rtcTypeName = function(var v: OleVariant): PWideChar; stdcall;
var sName: WideString;
h: HMODULE;
pFunc: TFuncVBAPI_rtcTypeName;
App: OleVariant;
v: OleVariant;
begin
try
App := GetActiveOleObject('Excel.Application');
Writeln('Ung dung da ma la', ': ', App.Name);
h := LoadLibrary('C:\Program Files (x86)\Common Files\Microsoft Shared\VBA\VBA7\VBE7.DLL');
try
pFunc := GetProcAddress(h, 'rtcTypeName');
v := App.ActiveCell;
sName := PWideChar(TFuncVBAPI_rtcTypeName(pFunc)(v));
Writeln('Gia tri bien la', ': ', sName);
finally
FreeLibrary(h);
App := Unassigned;
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
Tóm lại đã hết "EOleSysError: CoInitialize has not been called". Chỉ còn "EOleSysError: Operation unavailable"? Nếu bạn đã khởi động Excel mà còn lỗi này thì có nghĩa là lỗi không còn ở code nữa. Tôi không rõ lắm về các quyền vì tôi chỉ quan tâm tới XP Home của tôi thôi. Nhưng nếu nói về quyền thì theo lôgíc của tôi phải phân quyền cho Project1.exe. Tức run project1.exe với quyền "Run as administrator". Dù sao thì theo tôi lỗi không nằm trong code nữa.
Tóm lại đã hết "EOleSysError: CoInitialize has not been called". Chỉ còn "EOleSysError: Operation unavailable"? Nếu bạn đã khởi động Excel mà còn lỗi này thì có nghĩa là lỗi không còn ở code nữa. Tôi không rõ lắm về các quyền vì tôi chỉ quan tâm tới XP Home của tôi thôi. Nhưng nếu nói về quyền thì theo lôgíc của tôi phải phân quyền cho Project1.exe. Tức run project1.exe với quyền "Run as administrator". Dù sao thì theo tôi lỗi không nằm trong code nữa.
Tóm lại đã hết "EOleSysError: CoInitialize has not been called". Chỉ còn "EOleSysError: Operation unavailable"? Nếu bạn đã khởi động Excel mà còn lỗi này thì có nghĩa là lỗi không còn ở code nữa. Tôi không rõ lắm về các quyền vì tôi chỉ quan tâm tới XP Home của tôi thôi. Nhưng nếu nói về quyền thì theo lôgíc của tôi phải phân quyền cho Project1.exe. Tức run project1.exe với quyền "Run as administrator". Dù sao thì theo tôi lỗi không nằm trong code nữa.
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ế
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ì.
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ế
Đây là video hướng dẫn cách tạo DLL trên Delphi nhưng sử dụng trong VBA, Excel. Đây là phương pháp lập trình chuyên nghiệp nhưng không phải là khó. Giúp bạn bảo mật code của phần mềm tốt hơn. Loạt video hướng dẫn lập trình Delphi cơ bản của mình tại đây...
www.giaiphapexcel.com
Lỗi quá tinh vi, quá hiểm, kg phải dân "rờ chim em" thì thua
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é.
Đây là video hướng dẫn cách tạo DLL trên Delphi nhưng sử dụng trong VBA, Excel. Đây là phương pháp lập trình chuyên nghiệp nhưng không phải là khó. Giúp bạn bảo mật code của phần mềm tốt hơn. Loạt video hướng dẫn lập trình Delphi cơ bản của mình tại đây...
www.giaiphapexcel.com
Lỗi quá tinh vi, quá hiểm, kg phải dân "rờ chim em" thì thua
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é.
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
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.
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
Ẩ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ế
=========== 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 ????
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
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ó )
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?
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?
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
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
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.
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
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 đó.
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
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
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.
Ai rảnh thì vô mà dòm coi nó Sao: Delphi Tips
Mạnh nói xong quên liền mai mốt lại nhớ .. xong lại quên ... khi nhớ lại là nhớ rất chi là lâu ... Lưu vào đây cho tiện
Làm xong lâu rồi, mà nó ảnh hưởng tốc độ Group chưa tìm ra hướng giải quyết, (có thời gian em bận việc nhà bỏ bê từ đó tới giờ. Hiện tại bây giờ em chưa bắt kịp nhịp độ hhiiiii)
Làm xong lâu rồi, mà nó ảnh hưởng tốc độ Group chưa tìm ra hướng giải quyết, (có thời gian em bận việc nhà bỏ bê từ đó tới giờ. Hiện tại bây giờ em chưa bắt kịp nhịp độ hhiiiii)
Lâu nay mạnh cũng bận lắm lu xu bu đủ việc ... nhớ Code két vào GPE à ơi tẹo đó mà
mấy ngày trước lang thang trên Google tìm ra cái Help đó cho Excel đang coi thấy có đủ thứ hết ... lưu sử dụng khi cần thiết quên lại mở ra coi như cẩm nang cơ bản vậy... nhiều lúc nghĩ có 1 dòng code mò cả tháng mới ra thấy vãi kinh
Coi thấy VBA và Delphi code nó gần gủi ghê
Mã:
Sub VBA()
Range("A1:C10").Interior.PatternColor = RGB(255, 0, 0)
End Sub
Sub Delphi()
Range['A1', 'C10'].Interior.PatternColor := RGB(255,0,0);
End Sub
Sub VBA()
Range("A1:C10").Interior.PatternColor = RGB(255, 0, 0)
End Sub
Sub Delphi()
Range['A1', 'C10'].Interior.PatternColor := RGB(255,0,0);
End Sub
procedure Delphi()
begin
Range['A1:C10', EmptyParam].Interior.PatternColor := RGB(255,0,0);
end;
Class RANGE trong Excel có hai tham số, phần lớn mọi người chỉ biết đến tham số thứ nhất, trong VBA tham số thứ hai được bỏ qua nếu không khai báo. Nhưng trong Delphi nó không bỏ qua vì thế phải đưa vào EmptyParam. Vẫn có cách bỏ qua nếu dùng thông qua biến OleVariant.
Bác Tuân nói mình mới để ý tới vụ missing param này. Trước giờ cứ nghĩ thằng VBA compiler nó thông minh, với các hàm có tham số Optional hay ParamArrays thì khi gọi, tùy hàm truyền tham số thế nào nó sẽ push stack thế ấy chứ. Còn gọi xuống API của C/C++ dll thì sao ? Xem trong VBEx.dll, vd hàm InStr thôi thì lại thấy 1 mớ pVariant truyền vào.
Hì hì, xem kỹ, debug ra ngoài vào VBA thì phát hiện ra, ông ta truyền tất tần tật, optional, params array mà coder không gõ tường mình thì ông VBA cũng truyền tường minh pVariant với field vt = VT_MISSING luôn (= VBA IsMissing) hết. Nói chung là đầy đủ, chả có lợi hơn tẹo nào.
Với keyword ParamArray như của hàm Array (rtcArray in VBEx.dll) thì VBA truyền xuống pointer to 1 Variant chứa array của các Variant nhé (SAFEARRAY of VARIANT field).
Lập trình tạo XLL Add-in cho Excel bằng Delphi giúp tạo các hàm chạy tốc độ chiêu nhanh và bảo mật. C/C++, Delphi được biết đến là ngôn ngữ lập trình hay trình biên dịch ra mã máy (Native code) nên tốc độ rất nhanh (không tính đến thuật toán). Sản phẩm XLL Add-in này mình đã tạo ra từ rất nhiều...
www.giaiphapexcel.com
Mấy ngày nay khi nào rảnh Mạnh tìm tài liệu hay code mẫu trên Delphi cũng bắt trước làm theo 1 cái mà thấy quá khó luôn
Tìm trên Google thì thấy người ta toàn viết C/c++ Or DNA ... vvv còn tài liệu hay code mẫu trên Delphi rất ít
mà thấy họ hướng dẫn kiểu nữa vời vậy coi tới lui vẫn tịt toàn tập luôn ...
vậy Mạnh muốn hỏi bạn nào biết chỉ dùm mạnh chỉ cơ bản như sau:
1/ khai báo trong Delphi làm sao khi mình Build *.XLL xong thì check trên Excel nó load vào luôn và ngược lại khi Uncheck nó
2/ Viết 1 cái hàm đơn giản như GetSum() trong *.XLL khi load trên Excel Gõ =Getsum() là nó chạy ok
Với mong muốn rất cơ bản và đơn giản vậy ai biết chỉ dùm ( nếu có code mẫu trên Delphi càng tốt hay tài liệu chỉ dùm )
Xin cảm ơn
Mạnh đã viết được Add-ins trên Delphi *.XLL chạy rất tốt ........... Trân trọng thông báo với cả nhà vậy
Ai thích nghiên cứu vào link bài #869 nghiên cứu kỹ nhiều bài trong đó là viết ok ....
Nó quá đơn giản luôn .... trong đó nó chỉ cà Viết Menu Ribbon đó he ....
Google như tàng kinh các vậy .... chia sẻ link đó ai có đam mê là viết quá ngon luôn ko Phải C/c++ Or DNA làm cái chi cho mệt
Em Cảm ơn Anh ... Em ko ngờ nó dễ thế ... giờ cứ thế mà triển khai code thôi Anh
trong link đó nó chỉ cả tạo Menu Ribbon nữa đó .... Google mà nó như tàng kinh các vậy
Trong VBA có hàm TypeName() để lấy tên của class hay tên của lớp khai báo control hay các object. Khi các bạn lập trình Delphi cho Excel muốn dùng hàm TypeName không thể được vì nó không cùng môi trường VBA. Giải pháp chúng ta phải biết hàm API nào trong thư viên VBAxxx xuất nó ra đồng thời phải biết tham số để sử dụng. Chúng ta thực sự khó nếu không có tài liệu cung cấp từ nhà lập trình ra vbaxxx.
Nhân chủ đề Undocument API VBA ở bài số #10 tại đây
Cái laptop hư lâu lắc, phải gởi vào thành hồ chứa mưa sữa, mới lấy về. Nên quay lại tiếp với cái gọi là "rờ chxx em" Windows và VBA. Topic này tui sẽ đăng lần lượt những gì cu anh tui phát hiện ra trong quá trình "rờ em" Windows API, DLLs và VBAxxx.dll. Các tips, tricks này sẽ bảo đảm không có...
www.giaiphapexcel.com
Code mà bác CU Anh moi ra nó là C và rất phức tạp đây:
Điều quan trọng là bác @ThangCuAnh đã giúp lấy được tên hàm API của hàm TypeName cùng prototype, tôi viết lại code để chúng ta dùng trong Delphi như sau.
1. Các bạn thao khảo cách dùng bên VB/VBA (mang tính học tập vì trong VBA hàm TypeName đã có.
Option Explicit
#If VBA7 Then
Declare PtrSafe Function rtcTypeName Lib "VBE7.DLL" (v As Variant) As String
#Else
Declare Function rtcTypeName Lib "VBE6.DLL" (v As Variant) As String
#End If
Sub TestTypeNameAPI()
Dim sName As String
sName = rtcTypeName(ActiveCell)
MsgBox StrConv(sName, vbFromUnicode)
End Sub
2. Cách khai báo API hàm rtcTypeName() để dùng trong Delphi. Nếu chúng ta tạo Add-in thì đây là tư liệu quý.
Code dưới đây tôi viết trong chương trình chính dạng Console (màn hình đen trắng). Các bạn làm trình tự như sau.
1. Từ Delphi, tạo application dạng Console (nếu ai có add-in rồi thì chỉ cần code chính của nó).
2. Paste đoạn code dưới đây.
3. Chạy Excel với quyền "Run as administrator"
4. Chạy progam trong Delphi (F9)
Mã:
program Test_VBA_API.dproj;
//This code call function API in VBAxxx "rtcTypeName()". In VBA its name is TypeName()
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
Winapi.Windows,
ComObj,
System.Variants;
type
TFuncVBAPI_rtcTypeName = function(var v: OleVariant): PWideChar; stdcall;
var sName: WideString;
h: HMODULE;
pFunc: TFuncVBAPI_rtcTypeName;
App: OleVariant;
v: OleVariant;
begin
try
App := GetActiveOleObject('Excel.Application');
Writeln('Ung dung da ma la', ': ', App.Name);
h := LoadLibrary('C:\Program Files (x86)\Common Files\Microsoft Shared\VBA\VBA7\VBE7.DLL');
try
pFunc := GetProcAddress(h, 'rtcTypeName');
v := App.ActiveCell;
sName := PWideChar(TFuncVBAPI_rtcTypeName(pFunc)(v));
Writeln('Gia tri bien la', ': ', sName);
finally
FreeLibrary(h);
App := Unassigned;
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
Vì mình dùng hàm TypeName trong DLL nên bắt buộc phải loadlibrary mới lấy được con trỏ hàm đó. Nếu tự viết hàm này đùng như TypeName mình chưa tự viết được
Phải kiểm tra xem thằng lạ ở ngoài load nó chịu lên kg, DllMain nó return False là xong. Đồ MS nó khôn, quái lắm. Vì nó được viết riêng để dùng cho Office.
Mà load lên được chắc gì nó chạy đúng kg, vì nó có share, set chung gì với apps Office thì sao ?
khổ ghê chưa biết chi đang mò mà thằng nào cười thằng đó như con bò ... mới sinh ra có thằng nào ăn bắp ngay được ... bú sữa đã xong mới ăn cơm chứ quy luật lẻ thường vậy mà ko hiểu thì ko = con Bò
Lập trình XLL tài liệu C/C++ thì Microsoft có và update bản mới nhất. Các bạn muốn tự tay làm trên Delphi thì cần học C/C++ rồi viết lại trên Delphi. Và món này không dễ ăn như lập trình trên VCL đâu. Trong Delphi phải hiểu lập trình hàm API, kiểu dữ liệu, đặc biệt pointer,
Thế mà tui thấy cậu Kiều Mạnh đòi nhảy thẳng đi nhậu luôn đó.
Đô được 2 3 lon kg Mạnh, hôm nào đi nhậu với tui ?
Từ xưởng tui xuống nhà cậu khoảng vài cây, 5 10 phút à
Vì mình dùng hàm TypeName trong DLL nên bắt buộc phải loadlibrary mới lấy được con trỏ hàm đó. Nếu tự viết hàm này đùng như TypeName mình chưa tự viết được
Thế mà tui thấy cậu Kiều Mạnh đòi nhảy thẳng đi nhậu luôn đó.
Đô được 2 3 lon kg Mạnh, hôm nào đi nhậu với tui ?
Từ xưởng tui xuống nhà cậu khoảng vài cây, 5 10 phút à
OK đón tiếp nhiệt Tình
Mạnh ko sống vì code ... nhưng đam mê code
Mạnh ko có trí thông Minh nhưng có lòng kiên nhẫn
bất cứ ai trạm tới cái tôi của mạnh ... bất cứ giá nào phải xử nó !
Thế thôi
The solution below gets the actual type name of such an object in three steps:
Cast the object to the IDispatch type.
Get the ITypeInfo interface via IDispatch.GetTypeInfo().
Get the type name using ITypeInfo.GetDocumentation().
Mã:
using System;
using System.Runtime.InteropServices;
using ComTypes = System.Runtime.InteropServices.ComTypes;
namespace ComUtils
{
public class ComHelper
{
/// <summary>
/// Returns a string value representing the type name of the specified COM object.
/// </summary>
/// <param name="comObj">A COM object the type name of which to return.</param>
/// <returns>A string containing the type name.</returns>
public static string GetTypeName(object comObj)
{
if (comObj == null)
return String.Empty;
if (!Marshal.IsComObject(comObj))
//The specified object is not a COM object
return String.Empty;
IDispatch dispatch = comObj as IDispatch;
if (dispatch == null)
//The specified COM object doesn't support getting type information
return String.Empty;
ComTypes.ITypeInfo typeInfo = null;
try
{
try
{
// obtain the ITypeInfo interface from the object
dispatch.GetTypeInfo(0, 0, out typeInfo);
}
catch (Exception ex)
{
//Cannot get the ITypeInfo interface for the specified COM object
return String.Empty;
}
string typeName = "";
string documentation, helpFile;
int helpContext = -1;
try
{
//retrieves the documentation string for the specified type description
typeInfo.GetDocumentation(-1, out typeName, out documentation,
out helpContext, out helpFile);
}
catch (Exception ex)
{
// Cannot extract ITypeInfo information
return String.Empty;
}
return typeName;
}
catch (Exception ex)
{
// Unexpected error
return String.Empty;
}
finally
{
if (typeInfo != null) Marshal.ReleaseComObject(typeInfo);
}
}
}
/// <summary>
/// Exposes objects, methods and properties to programming tools and other
/// applications that support Automation.
/// </summary>
[ComImport()]
[Guid("00020400-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IDispatch
{
[PreserveSig]
int GetTypeInfoCount(out int Count);
[PreserveSig]
int GetTypeInfo(
[MarshalAs(UnmanagedType.U4)] int iTInfo,
[MarshalAs(UnmanagedType.U4)] int lcid,
out ComTypes.ITypeInfo typeInfo);
[PreserveSig]
int GetIDsOfNames(
ref Guid riid,
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)]
string[] rgsNames,
int cNames,
int lcid,
[MarshalAs(UnmanagedType.LPArray)] int[] rgDispId);
[PreserveSig]
int Invoke(
int dispIdMember,
ref Guid riid,
uint lcid,
ushort wFlags,
ref ComTypes.DISPPARAMS pDispParams,
out object pVarResult,
ref ComTypes.EXCEPINFO pExcepInfo,
IntPtr[] pArgErr);
}
}
Variant có cái type đó anh. String, double, inter,... Range cung co cách, tên class thi chưa anh. Giống như đợt trước em lấy field type đó anh
Hì hì, bé phát minh lại bánh xe rồi, Delphi nó có sẵn hàm VarTypeAsText trong unit Variants.pas rồi, sao không dùng mà đi viết lại.
Trong file bác @kieu manh gởi đây
Mã:
function VarTypeAsText(const AType: TVarType): string;
const
CText: array [varEmpty..varUInt64] of string = ('Empty', 'Null', 'Smallint', //Do not localize
'Integer', 'Single', 'Double', 'Currency', 'Date', 'OleStr', 'Dispatch', //Do not localize
'Error', 'Boolean', 'Variant', 'Unknown', 'Decimal', '$0F', 'ShortInt', //Do not localize
'Byte', 'Word', 'Cardinal', 'Int64', 'UInt64'); //Do not localize
var
LHandler: TCustomVariantType;
begin
if AType and varTypeMask <= varUInt64 then
Result := CText[AType and varTypeMask]
else if AType = varString then
Result := 'String' //Do not localize
else if AType = varUString then
Result := 'UnicodeString' //Do not localize
else if AType = varAny then
Result := 'Any' //Do not localize
else if FindCustomVariantType(AType, LHandler) then
Result := Copy(LHandler.ClassName, 2, High(Integer))
else
Result := HexDisplayPrefix + IntToHex(AType and varTypeMask, 4);
if AType and varArray <> 0 then
Result := 'Array ' + Result; //Do not localize
if AType and varByRef <> 0 then
Result := 'ByRef ' + Result; //Do not localize
end;
Hì hì, bé phát minh lại bánh xe rồi, Delphi nó có sẵn hàm VarTypeAsText trong unit Variants.pas rồi, sao không dùng mà đi viết lại.
Trong file bác @kieu manh gởi đây
Mã:
function VarTypeAsText(const AType: TVarType): string;
const
CText: array [varEmpty..varUInt64] of string = ('Empty', 'Null', 'Smallint', //Do not localize
'Integer', 'Single', 'Double', 'Currency', 'Date', 'OleStr', 'Dispatch', //Do not localize
'Error', 'Boolean', 'Variant', 'Unknown', 'Decimal', '$0F', 'ShortInt', //Do not localize
'Byte', 'Word', 'Cardinal', 'Int64', 'UInt64'); //Do not localize
var
LHandler: TCustomVariantType;
begin
if AType and varTypeMask <= varUInt64 then
Result := CText[AType and varTypeMask]
else if AType = varString then
Result := 'String' //Do not localize
else if AType = varUString then
Result := 'UnicodeString' //Do not localize
else if AType = varAny then
Result := 'Any' //Do not localize
else if FindCustomVariantType(AType, LHandler) then
Result := Copy(LHandler.ClassName, 2, High(Integer))
else
Result := HexDisplayPrefix + IntToHex(AType and varTypeMask, 4);
if AType and varArray <> 0 then
Result := 'Array ' + Result; //Do not localize
if AType and varByRef <> 0 then
Result := 'ByRef ' + Result; //Do not localize
end;
Bé viết theo code C# hả ? Hì hì, chưa chính xác đâu
Code của MS coder cho hàm rtcTypeName, cho VT_DISPATCH đây, bonus mọi người viết theo đúng vậy trên ngôn ngữ của mình.
Chú mới "rờ em" nó ra full, đầy đủ rồi đó.
Theo bé thì nên viết theo code C# hay nên viết theo code C/C++ này ?
Tự like cho mình 1 cái, hổng ai like hết ! Cho cái vỗ tay đê !
Bé viết theo code C# hả ? Hì hì, chưa chính xác đâu
Code của MS coder cho hàm rtcTypeName, cho VT_DISPATCH đây, bonus mọi người viết theo đúng vậy trên ngôn ngữ của mình.
Chú mới "rờ em" nó ra full, đầy đủ rồi đó.
Theo bé thì nên viết theo code C# hay nên viết theo code C/C++ này ?
Tự like cho mình 1 cái, hổng ai like hết ! Cho cái vỗ tay đê !