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ài này nhờ mạnh xíu nữa nhé.
Cái bài lọc trùng của Mạnh rồi tính tổng đó giờ mình muốn sau khi kiếm được dòng duy nhất thì sẽ thêm 1 dòng tổng cộng dưới mỗi dòng duy nhất thì mình giải quyết làm sao :):):):). Nghĩ hòai không rao_Oo_Oo_O
 
Upvote 0
Vấn đề sử dụng hàm tham chiếu qua UNIT tôi thấy cách bạn Thuyyeu99 làm qua Class cũng được nhưng chỉ nên dùng trong những trường hợp cần phải thế. Còn khi hàm đóng vai trò như một tài nguyên dùng chung ở mọi nơi với việc gọi thuận tiện thì không làm thế.

Delphi có một cách tổ chức code rất khoa học và "gói gọn". Khi một Project có nhiều function, procedure, Class thì Delphi cho phép tách code thành các unit, mỗi unit chứa một số tài nguyên làm một số tác vụ nào đó theo người lập trình sắp xếp. Với Form lưu mỗi form một unit đi cùng với file đính kèm một cặp là *.DFM. (sẽ thấy trong unit form ở gần từ khóa "implementation".

Nguyên tắc tách code ra unit. Bạn có thể bê một cụm các hàm và thủ tục vào một file unit riêng, ví dụ là "Unit1". Trong Unit1 này bạn chú ý 2 phần code:
INTERFACE: là nơi khai báo các Class, các biến - Var; hăng số - const; các function và procedure để các unit, project khác có thể gọi những tài nguyên này. Ví dụ bạn muốn các unit khác được phép sử dụng hàm GetSum thì trong khu vực INTERFACE cần khai báo

Mã:
function GetSum(a,b: Double): Double; //stdcall;
Khai báo trên gọi là Prototype - trong ngôn ngữ C, C++ thì nó chính là khai báo trong file *.h

Khu vực viết mã nguồn cho hàm là

IMPLEMENTATION (trong nguôn ngữ C, C++ thifcode phần này nằm trong file *.C, *.CPP)
{$ *.dfm} //khai báo này Delphi tự thêm vào nếu unit này được tạo ra khi bạn tạo Form, bản chất là đính kèm file khai báo cấu trúc hiển thị của form.

Trong khu vực này bạn vẫn có thể sử dụng khai báo USES để đưa vao các unit mà nó cung cấp các tài nguyên phục vụ cho việc viết mã nguồn phía dưới, nếu các unit đã khai báo ở mục USES trong INTERFACE chưa đáp ứng được.

Tiếp theo bạn viết mã nguồn hoặc tham chiếu tới DLL ở đây:

Mã:
function GetSum(a,b: Double): Double;

begin

  Result := a + b;

end;
Bạn hãy nhớ, nếu không có khai báo prototye ở phần INTERFACE với function GetSum(a,b: Double): Double; thì hàm GetSum sẽ không gọi được ở các unit khác. Bây giờ giả sử trong một Project hoặc Unit khác muốn dùng các hàm trong "Unit1" (nói ở trên) thì cần khai báo

Mã:
USES Unit1;

Các bạn hãy chú ý có hai nơi được khai báo USES như nhau là INTERFACE và IMPLEMENTATION, thông thường khu vực INTERFACE chung ta khai báo các unit cần để sử dụng để khai báo được các prototype. Khu vực IMPLEMENTATION là phục vụ cho việc triển khai viết mã nguồn.

Sau khi bạn đã khai bảo Unit1 ở trên bạn đã có thể gọi ngay hàm GetSum một cách bình thường như nó đang nằm trong chính Unit bạn đang lập trình (mặc dù nó đang ở Unit khác).

Mã:
procedure CallSum;

var

  res: Double;

begin

   res := GetSum(10, 20);

end;
...

Tóm lại còn khá nhiều kiến thức mà nếu các bạn không đọc kỹ một chút tài liệu Object Pascal thì sẽ phải mò mẫm hơi lâu. Loạt bài trên các bạn đang đeo duổi phần ngọn mà gốc bị đuối.
Cảm ơn Bạn chỉ dẫn ... rất khoa học và ngắn gọn
Cho mình hỏi chút VD: Mình viết code sau cho Unit3 ... sử dụng tốt
Mã:
unit Unit3;

interface
{INTERFACE: là nơi khai báo các Class, các biến - Var; hăng số - const;
các function và procedure để các unit, project khác có thể gọi
những tài nguyên này. Ví dụ bạn muốn các unit khác được phép sử dụng
hàm GetSum thì trong khu vực INTERFACE cần khai báo}

function GetSum(a,b: Integer): Integer; stdcall;

implementation
{IMPLEMENTATION - Khu vực viết mã nguồn cho hàm là}

function GetSum(a,b: Integer): Integer;
begin
  Result := a + b;
end;


end.
Vậy mình muốn hỏi :
1/ trong Unit3 đó Thấy Mục : interface có viết Hàm GetSum rồi mà trong Mục: implementation lại viết lại chi tiết Hàm GetSum

2/ Vậy tại sao Mình ko viết thẳng Hàm GetSum vào luôn Mục interface luôn đi cho gọn .... tại sao ??!
Bài đã được tự động gộp:

Bài này nhờ mạnh xíu nữa nhé.
Cái bài lọc trùng của Mạnh rồi tính tổng đó giờ mình muốn sau khi kiếm được dòng duy nhất thì sẽ thêm 1 dòng tổng cộng dưới mỗi dòng duy nhất thì mình giải quyết làm sao :):):):). Nghĩ hòai không rao_Oo_Oo_O
Giờ lại bận chút mai viết trên VBA cho ... Delphi chưa viết nên chưa hiểu cách viết lắm ... Trên GPE có hết rồi mà
 
Upvote 0
Cảm ơn Bạn chỉ dẫn ... rất khoa học và ngắn gọn
Cho mình hỏi chút VD: Mình viết code sau cho Unit3 ... sử dụng tốt
Mã:
unit Unit3;

interface
{INTERFACE: là nơi khai báo các Class, các biến - Var; hăng số - const;
các function và procedure để các unit, project khác có thể gọi
những tài nguyên này. Ví dụ bạn muốn các unit khác được phép sử dụng
hàm GetSum thì trong khu vực INTERFACE cần khai báo}

function GetSum(a,b: Integer): Integer; stdcall;

implementation
{IMPLEMENTATION - Khu vực viết mã nguồn cho hàm là}

function GetSum(a,b: Integer): Integer;
begin
  Result := a + b;
end;


end.
Vậy mình muốn hỏi :
1/ trong Unit3 đó Thấy Mục : interface có viết Hàm GetSum rồi mà trong Mục: implementation lại viết lại chi tiết Hàm GetSum

2/ Vậy tại sao Mình ko viết thẳng Hàm GetSum vào luôn Mục interface luôn đi cho gọn .... tại sao ??!

Cả hai câu hỏi của bạn chung một câu trả lời: Delphi quy định như thế :). Interface là nơi khai báo cấu trúc thủ tục, hàm, class , biến và hằng số. Implementation là nơi viết mã nguồn cho nó hoặc khai vào tham chiếu tới thư viện ngoài - DLL. Mình cũng chỉ biết thừa nhận như vậy.
 
Upvote 0
Cảm ơn Bạn chỉ dẫn ... rất khoa học và ngắn gọn
Cho mình hỏi chút VD: Mình viết code sau cho Unit3 ... sử dụng tốt
Mã:
unit Unit3;

interface
{INTERFACE: là nơi khai báo các Class, các biến - Var; hăng số - const;
các function và procedure để các unit, project khác có thể gọi
những tài nguyên này. Ví dụ bạn muốn các unit khác được phép sử dụng
hàm GetSum thì trong khu vực INTERFACE cần khai báo}

function GetSum(a,b: Integer): Integer; stdcall;

implementation
{IMPLEMENTATION - Khu vực viết mã nguồn cho hàm là}

function GetSum(a,b: Integer): Integer;
begin
  Result := a + b;
end;


end.
Vậy mình muốn hỏi :
1/ trong Unit3 đó Thấy Mục : interface có viết Hàm GetSum rồi mà trong Mục: implementation lại viết lại chi tiết Hàm GetSum

2/ Vậy tại sao Mình ko viết thẳng Hàm GetSum vào luôn Mục interface luôn đi cho gọn .... tại sao ??!
Bài đã được tự động gộp:


Giờ lại bận chút mai viết trên VBA cho ... Delphi chưa viết nên chưa hiểu cách viết lắm ... Trên GPE có hết rồi mà
Khai báo ở interface là quy định đâu có viết hàm được

Mạnh thử nghiệm chút nhé
trường hợp 1
interface có khai báo GetSum (ok)
Mã:
procedure TForm1.Button1Click(Sender: TObject);
var
I,a,b:integer;
begin
a:=15;
b:=10;
I:=GetSum(a,b);
ShowMessage('Ket Qua ' + IntToStr(I));
end;

function GetSum(a,b: Integer): Integer;
begin
  Result := a + b;
end;

trường hợp 2
interface không khai báo GetSum (lỗi)
Mã:
procedure TForm1.Button1Click(Sender: TObject);
var
I,a,b:integer;
begin
a:=15;
b:=10;
I:=GetSum(a,b);
ShowMessage('Ket Qua ' + IntToStr(I));
end;

function GetSum(a,b: Integer): Integer;
begin
  Result := a + b;
end;

trường hợp 3
interface không khai báo GetSum (ok)
Mã:
function GetSum(a,b: Integer): Integer;
begin
  Result := a + b;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
I,a,b:integer;
begin
a:=15;
b:=10;
I:=GetSum(a,b);
ShowMessage('Ket Qua ' + IntToStr(I));
end;
 
Upvote 0
Khai báo ở interface là quy định đâu có viết hàm được

Mạnh thử nghiệm chút nhé
trường hợp 1
interface có khai báo GetSum (ok)
Mã:
procedure TForm1.Button1Click(Sender: TObject);
var
I,a,b:integer;
begin
a:=15;
b:=10;
I:=GetSum(a,b);
ShowMessage('Ket Qua ' + IntToStr(I));
end;

function GetSum(a,b: Integer): Integer;
begin
  Result := a + b;
end;

trường hợp 2
interface không khai báo GetSum (lỗi)
Mã:
procedure TForm1.Button1Click(Sender: TObject);
var
I,a,b:integer;
begin
a:=15;
b:=10;
I:=GetSum(a,b);
ShowMessage('Ket Qua ' + IntToStr(I));
end;

function GetSum(a,b: Integer): Integer;
begin
  Result := a + b;
end;

trường hợp 3
interface không khai báo GetSum (ok)
Mã:
function GetSum(a,b: Integer): Integer;
begin
  Result := a + b;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
I,a,b:integer;
begin
a:=15;
b:=10;
I:=GetSum(a,b);
ShowMessage('Ket Qua ' + IntToStr(I));
end;
MÌNH CHƯA HIỀU 1 VÀ 3 LẮM ... NGÓ QUA CHÚT MAI RẢNH TEST LUÔN MỘT LƯỢT :D
 
Upvote 0
Cả hai câu hỏi của bạn chung một câu trả lời: Delphi quy định như thế :). Interface là nơi khai báo cấu trúc thủ tục, hàm, class , biến và hằng số. Implementation là nơi viết mã nguồn cho nó hoặc khai vào tham chiếu tới thư viện ngoài - DLL. Mình cũng chỉ biết thừa nhận như vậy.
Trong trường hợp mình muốn gọi hàm trực tiếp từ DLL cho Form thì có được ko Bạn
Nếu được thì khai báo sử dụng sao mong Bạn hướng dẫn luôn cho mình với

Mới hỏi như trên .... xong thì làm vầy thấy OK
Mã:
Function GetSumDLL(a, b : Integer):Integer; stdcall; external 'VBLibrary.dll';
Tuy nhiên ngoài cách này còn cách nào khác ?
 
Lần chỉnh sửa cuối:
Upvote 0
Trong trường hợp mình muốn gọi hàm trực tiếp từ DLL cho Form thì có được ko Bạn
Nếu được thì khai báo sử dụng sao mong Bạn hướng dẫn luôn cho mình với

Ok. Việc tạo function trong DLL vẫn như bài đầu tiên tôi hướng dẫn. Trong video đó tôi hướng dẫn khai báo DLL trong VBA. Nếu khai báo DLL trong Delphi thì làm như sau:

Tạo một Unit mới tên là UnitImportFuncInDLL (tùy ý)
Mã:
unit UnitImportFuncInDLL;

interface
  function GetSum(a,b: Double): Double; stdcall;

implementation

  function GetSum(a,b: Double): Double; stdcall; external 'MyDLL.dll';

end.
 
Upvote 0
Có ai yêu thích ôn lại Pascal cơ bản (basic) lại... không? thì cùng bàn (rất có ích với Delphi)
 
Upvote 0
Ok. Việc tạo function trong DLL vẫn như bài đầu tiên tôi hướng dẫn. Trong video đó tôi hướng dẫn khai báo DLL trong VBA. Nếu khai báo DLL trong Delphi thì làm như sau:

Tạo một Unit mới tên là UnitImportFuncInDLL (tùy ý)
Mã:
unit UnitImportFuncInDLL;

interface
  function GetSum(a,b: Double): Double; stdcall;

implementation

  [CODE]function GetSum(a,b: Double): Double; stdcall; external 'MyDLL.dll';

end.

[/CODE]
dòng sau là khai báo sử dụng DLL bên trong và bên ngoài DLL thì phải (Mình đoán vậy)
Mã:
function GetSum(a,b: Double): Double; stdcall; external 'MyDLL.dll';
 
Upvote 0
dòng sau là khai báo sử dụng DLL bên trong và bên ngoài DLL thì phải (Mình đoán vậy)
Mã:
function GetSum(a,b: Double): Double; stdcall; external 'MyDLL.dll';

Đó là để báo cho Delphi biết là cái hàm đó phải lấy trong DLL có tên "MyDLL" chứ đừng tìm code trong dự án này :)
 
Upvote 0
Ok. Việc tạo function trong DLL vẫn như bài đầu tiên tôi hướng dẫn. Trong video đó tôi hướng dẫn khai báo DLL trong VBA. Nếu khai báo DLL trong Delphi thì làm như sau:

Tạo một Unit mới tên là UnitImportFuncInDLL (tùy ý)
Mã:
unit UnitImportFuncInDLL;

interface
  function GetSum(a,b: Double): Double; stdcall;

implementation

  function GetSum(a,b: Double): Double; stdcall; external 'MyDLL.dll';

end.
MÌnh cũng ko hiểu lắm tại sao mình cho lên interface thì nó báo lỗi như hình
Mong Bạn chỉ dẫn
Capture.PNG
 
Upvote 0
Upvote 0
Upvote 0
Bạn chụp phía dưới sau Implement tôi kiểm tra xem
Code Unit Hết như Sau
Mã:
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils,
  System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
  Unit2,Unit3;


type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    //procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
end;

//function GetSumDLL(a,b: Integer): Integer;// stdcall;

//procedure adxtShowPrintSheet;
var
  Form1: TForm1;
  f: TForm1;
  UDF : TUDFExcel;

//function GetSumDLL(a,b: Integer): Integer;// stdcall;

implementation

{$R *.dfm}

//Điều này khai báo Max là một hàm cần tìm // bên ngoài, trong dll
//Function GetSumDLL(a, b : Integer):Integer; stdcall; external 'VBLibrary.dll';

procedure adxtShowPrintSheet;
begin
    f := TForm1.Create(nil);
    try
      //f.Show; //.ShowModal;
      f.ShowModal;
      finally
      f.free
    end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  res: integer;
begin
   res := GetSum(10, 20);
   ShowMessage('CallPublic  '+IntToStr(res));
end;

procedure TForm1.Button2Click(Sender: TObject);
var //Khai bao Kieu Class
  ketqua,a,b:integer;
begin
  a:=10;
  b:=5;
  ketqua:= UDF.GetSumUnit(a,b);
  ShowMessage('CallClass  '+IntToStr(ketqua));
end;

procedure TForm1.Button3Click(Sender: TObject);
var
  res: integer;
begin
    //res := GetSumDLL(10, 20);
   ShowMessage('CallDLL  '+IntToStr(res));
end;

end.
 
Upvote 0
Code Unit Hết như Sau
Mã:
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils,
  System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
  Unit2,Unit3;


type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    //procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
end;

//function GetSumDLL(a,b: Integer): Integer;// stdcall;

//procedure adxtShowPrintSheet;
var
  Form1: TForm1;
  f: TForm1;
  UDF : TUDFExcel;

//function GetSumDLL(a,b: Integer): Integer;// stdcall;

implementation

{$R *.dfm}

//Điều này khai báo Max là một hàm cần tìm // bên ngoài, trong dll
//Function GetSumDLL(a, b : Integer):Integer; stdcall; external 'VBLibrary.dll';

procedure adxtShowPrintSheet;
begin
    f := TForm1.Create(nil);
    try
      //f.Show; //.ShowModal;
      f.ShowModal;
      finally
      f.free
    end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  res: integer;
begin
   res := GetSum(10, 20);
   ShowMessage('CallPublic  '+IntToStr(res));
end;

procedure TForm1.Button2Click(Sender: TObject);
var //Khai bao Kieu Class
  ketqua,a,b:integer;
begin
  a:=10;
  b:=5;
  ketqua:= UDF.GetSumUnit(a,b);
  ShowMessage('CallClass  '+IntToStr(ketqua));
end;

procedure TForm1.Button3Click(Sender: TObject);
var
  res: integer;
begin
    //res := GetSumDLL(10, 20);
   ShowMessage('CallDLL  '+IntToStr(res));
end;

end.
Bạn khai báo như thế nhưng trong phần implementation bạn có implement hàm đó đâu.
Nếu đã khai báo ở interface như thế thì trong phần implementation phải có
Mã:
function GetSumDLL(a,b: Integer): Integer;// stdcall;
begin
...
end;
 
Upvote 0
Bạn khai báo như thế nhưng trong phần implementation bạn có implement hàm đó đâu.
Nếu đã khai báo ở interface như thế thì trong phần implementation phải có
Mã:
function GetSumDLL(a,b: Integer): Integer;// stdcall;
begin
...
end;
ý Em là muốn sử dụng lại cái Hàm GetSumDLL đã viết trong DLL ấy cho Form chỉ khai báo sử dụng nó ko phải viết lại nữa
 
Upvote 0
ý Em là muốn sử dụng lại cái Hàm GetSumDLL đã viết trong DLL ấy cho Form chỉ khai báo sử dụng nó ko phải viết lại nữa
Tôi chỉ chỉ ra cái sai thôi. Với khai báo như thế thì trong phần implementation phải có
Mã:
function GetSumDLL(a,b: Integer): Integer;// stdcall;
begin
...
end;

Còn ý bạn thế nào tôi không biết.

Rất khó trả lời trong chủ đề này vì mỗi bài chỉ là một câu cụt lủn hoặc một mẩu code. Muốn trả lời thì phải đọc hàng chục bài trước đó, mà chưa chắc đã đủ để hiểu ý.

Nếu là gọi hàm trong DLL thì Tuân đã hướng dẫn rồi:
Mã:
function GetSum(a,b: Double): Double; stdcall; external 'MyDLL.dll';

Nếu chỉ dùng trong code ở phần implementation (vd. trong TForm1.Button3Click) thì khai báo thậm chí có thể đặt trong phần implementation sau
Mã:
implementation

{$R *.DFM}
 
Lần chỉnh sửa cuối:
Upvote 0
Web KT
Back
Top Bottom