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,652
Được thích
10,140
Giới tính
Nam
Nghề nghiệp
Giáo viên, CEO tại Bluesofts
Lần chỉnh sửa cuối:
Code Unit
Mã:
unit UDFExcel;

interface



implementation
Uses ComObj, Classes, Variants;

Function GetSumUnit(a, b : Integer) : Integer;
begin
  Result := a + b;
end;

end.

Code Dll
Mã:
library DllATuan;

{ Important note about DLL memory management: ShareMem must be the
  first unit in your library's USES clause AND your project's (select
  Project-View Source) USES clause if your DLL exports any procedures or
  functions that pass strings as parameters or function results. This
  applies to all strings passed to and from your DLL--even those that
  are nested in records and classes. ShareMem is the interface unit to
  the BORLNDMM.DLL shared memory manager, which must be deployed along
  with your DLL. To avoid using BORLNDMM.DLL, pass string information
  using PChar or ShortString parameters. }

//uses
//  System.SysUtils,
//  System.Classes;
uses
  Winapi.Windows,
  Winapi.Messages,
  System.SysUtils,
  System.Variants,
  System.Classes,
  Vcl.Graphics,
  Vcl.Controls,
  Vcl.Forms,
  Vcl.Dialogs,
  ComObj,
  Excel2000,
  Vcl.StdCtrls,
  Math,
  Vcl.ComCtrls,
  DateUtils,
  System.StrUtils,
  ActiveX,
  Data.DB,
  Data.Win.ADODB,
  System.Generics.Collections,
  UDFExcel in 'UDFExcel.pas',
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}



Function GetSumDLL(a, b : Integer) : Integer;
begin
  Result := GetSumUnit(a,b);
end;


exports
GetSumDLL;

begin

end.

Code trong Form

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;

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

var
  Form1: TForm1;

implementation
Uses UDFExcel; //ten cua Unit
{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
ketqua,a,b:integer;
begin
a:=10;
b:=5;
ketqua:=GetSumUnit(a,b);
end;


end.
Làm y trang nó báo đỏ hàm GetSumUnitppppmmm.PNG
 
Upvote 0
có khai báo cái dòng này trong form khong đó
nó gạch đỏ như vậy là nó không hiểu cái hàm đó ở đâu
implementation
Uses UDFExcel; //ten cua Unit coi chừng cái tên của mạnh khác của mình áh
đúng mà ... ma sao thấy 2 cái Uses vậyok.PNG
 
Upvote 0
PÓ TAY MẠNH LUU FILE CHƯA
CÁI LỖI ĐÓ LÀ NO KHÔNG BIẾT HÀM ĐÓ LÀ GÌ
ĐÂY CỦA MÌNH NÓ THAM CHIẾU ĐƯỢC HÀM NÀY NẰM TRONG Unit (UDFExcel.pas)
View attachment 205374
Thì làm y trang mà ... chụp cái hình vầy mình nhìn cũng tịt Luôn
Chịu khó làm úp cho Mình 1 cái Source coi biết liền à ... có khi nói bên tây lại nghe bên đông à
Mới chụp xong nó như Hình mà Khi Buil nó lại lỗi Hàm
fffff.png
 
Lần chỉnh sửa cuối:
Upvote 0

File đính kèm

  • DLL giaiphapexcel.rar
    2.9 MB · Đọc: 24
Upvote 0
Vẫn lỗi đó ... bó tay
kkkk.PNG
 
Upvote 0
Form
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,UDFExcel;

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

var
  Form1: TForm1;
  UDF : TUDFExcel;
implementation
//Uses ; //ten cua Unit
{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
ketqua,a,b:integer;
begin
a:=10;
b:=5;
ketqua:= UDF.GetSumUnit(a,b);
ShowMessage('LowBound 2  '+IntToStr(ketqua));
end;


end.

Dlll
Mã:
library DllATuan;

{ Important note about DLL memory management: ShareMem must be the
  first unit in your library's USES clause AND your project's (select
  Project-View Source) USES clause if your DLL exports any procedures or
  functions that pass strings as parameters or function results. This
  applies to all strings passed to and from your DLL--even those that
  are nested in records and classes. ShareMem is the interface unit to
  the BORLNDMM.DLL shared memory manager, which must be deployed along
  with your DLL. To avoid using BORLNDMM.DLL, pass string information
  using PChar or ShortString parameters. }

//uses
//  System.SysUtils,
//  System.Classes;
uses
  Winapi.Windows,
  Winapi.Messages,
  System.SysUtils,
  System.Variants,
  System.Classes,
  Vcl.Graphics,
  Vcl.Controls,
  Vcl.Forms,
  Vcl.Dialogs,
  ComObj,
  Excel2000,
  Vcl.StdCtrls,
  Math,
  Vcl.ComCtrls,
  DateUtils,
  System.StrUtils,
  ActiveX,
  Data.DB,
  Data.Win.ADODB,
  System.Generics.Collections,
  UDFExcel in 'UDFExcel.pas',
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {Form2};

{$R *.res}
var
  UDF : TUDFExcel;


Function GetSumDLL(a, b : Integer) : Integer;
begin
  Result := UDF.GetSumUnit(a,b);
end;

Unit
Mã:
unit UDFExcel;

interface

  type TUDFExcel = class
    private
    public
      Function GetSumUnit(a, b : Integer) : Integer;

  end;

var
E:variant;
implementation
Uses ComObj, Classes, Variants;

Function TUDFExcel.GetSumUnit(a, b : Integer) : Integer;
begin
  Result := a + b;
end;

end.


Hồi nya4 chưa Buil, cái này Buil ok rồi nhé ma không biết có chạy hông hihihihi
 
Upvote 0
Form
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,UDFExcel;

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

var
  Form1: TForm1;
  UDF : TUDFExcel;
implementation
//Uses ; //ten cua Unit
{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
ketqua,a,b:integer;
begin
a:=10;
b:=5;
ketqua:= UDF.GetSumUnit(a,b);
ShowMessage('LowBound 2  '+IntToStr(ketqua));
end;


end.

Dlll
Mã:
library DllATuan;

{ Important note about DLL memory management: ShareMem must be the
  first unit in your library's USES clause AND your project's (select
  Project-View Source) USES clause if your DLL exports any procedures or
  functions that pass strings as parameters or function results. This
  applies to all strings passed to and from your DLL--even those that
  are nested in records and classes. ShareMem is the interface unit to
  the BORLNDMM.DLL shared memory manager, which must be deployed along
  with your DLL. To avoid using BORLNDMM.DLL, pass string information
  using PChar or ShortString parameters. }

//uses
//  System.SysUtils,
//  System.Classes;
uses
  Winapi.Windows,
  Winapi.Messages,
  System.SysUtils,
  System.Variants,
  System.Classes,
  Vcl.Graphics,
  Vcl.Controls,
  Vcl.Forms,
  Vcl.Dialogs,
  ComObj,
  Excel2000,
  Vcl.StdCtrls,
  Math,
  Vcl.ComCtrls,
  DateUtils,
  System.StrUtils,
  ActiveX,
  Data.DB,
  Data.Win.ADODB,
  System.Generics.Collections,
  UDFExcel in 'UDFExcel.pas',
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {Form2};

{$R *.res}
var
  UDF : TUDFExcel;


Function GetSumDLL(a, b : Integer) : Integer;
begin
  Result := UDF.GetSumUnit(a,b);
end;

Unit
Mã:
unit UDFExcel;

interface

  type TUDFExcel = class
    private
    public
      Function GetSumUnit(a, b : Integer) : Integer;

  end;

var
E:variant;
implementation
Uses ComObj, Classes, Variants;

Function TUDFExcel.GetSumUnit(a, b : Integer) : Integer;
begin
  Result := a + b;
end;

end.


Hồi nya4 chưa Buil, cái này Buil ok rồi nhé ma không biết có chạy hông hihihihi
Nó vẫn sai cái chi đó
eeeeeeeeeeeee.PNG
 
Upvote 0
Chạy ok rồi đó tuy nhiên thấy khai báo dài dòng quá
Có cách nào khác khai báo sử dung hàm ngắn gọn hơn 1 chút ko ???!!!
Mạnh Nghiên cứu đi.....

Mạnh đi vô tới đây mình chuẩn bị bí rồi a1h.

Mà sao đề tài này mình thấy nhiều người quan tâm lắm sao không ai vào commen hết nhỉ ??????????????
 
Lần chỉnh sửa cuối:
Upvote 0
À sẵn tiện đây cho mình hỏi khi viết hàm kết nối ADO mình đang phân vân không biết hướng nào tốt.

Hướng thứ 1:
Khi mở Chương trình lên thì cho kết nói ADO khi nào cần truy vấn tới Table nào thì mình chỉ cần connec tới Table đó. khi thoát chương trình thì mới ngắt kết nối.

Hướng thứ 2:
Khi cần truy vấn tới Table nào thì mình connec tới Table đó xong rồi thì ngắt kết nối.

Thank you
 
Upvote 0
À sẵn tiện đây cho mình hỏi khi viết hàm kết nối ADO mình đang phân vân không biết hướng nào tốt.

Hướng thứ 1:
Khi mở Chương trình lên thì cho kết nói ADO khi nào cần truy vấn tới Table nào thì mình chỉ cần connec tới Table đó. khi thoát chương trình thì mới ngắt kết nối.

Hướng thứ 2:
Khi cần truy vấn tới Table nào thì mình connec tới Table đó xong rồi thì ngắt kết nối.

Cảm ơn
bạn vào link sau đọc lại chút mấy bài Mạnh viết đó ... và HLMT trả lời đó
https://www.giaiphapexcel.com/diendan/threads/Đố-vui-về-ado-dao.80367/page-17
Mạnh mới coi link sau nó load Hàm trong DLL cho Form.exe đơn giản lắm
http://www.onlinedelphitraining.com/newsletters/dllexample.htm
 
Upvote 0
bạn vào link sau đọc lại chút mấy bài Mạnh viết đó ... và HLMT trả lời đó
https://www.giaiphapexcel.com/diendan/threads/Đố-vui-về-ado-dao.80367/page-17
Mạnh mới coi link sau nó load Hàm trong DLL cho Form.exe đơn giản lắm
http://www.onlinedelphitraining.com/newsletters/dllexample.htm
Cái đó là tùy mọi người, mỗi cái nó có mặt mạnh riêng ;);););););)
Mà cũng nhờ Mạnh nên mình cũng nghiệm ra được một chút hihihihihihihihi
 
Lần chỉnh sửa cuối:
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.
 
Lần chỉnh sửa cuối:
Upvote 0
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.
Cần nói rõ là "thông thường" là thế này thế này. Nhưng không phải thích chỗ nào cũng được. Vd. không thể có
Mã:
unit Unit1;

interface

uses
  ..., Unit2;
và
Mã:
unit Unit2;

interface

uses
  ..., Unit1;

Không thể để cả 2 unit (uses) trong phần interface (lỗi circular unit reference). Cả 2 ở phần implementation hoặc 1 ở implementation 1 ở interface thì được.

Nói rõ thế để khi bị "dính" thì hiểu vì sao.
 
Upvote 0
Cần nói rõ là "thông thường" là thế này thế này. Nhưng không phải thích chỗ nào cũng được. Vd. không thể có
Mã:
unit Unit1;

interface

uses
  ..., Unit2;

Mã:
unit Unit2;

interface

uses
  ..., Unit1;

Không thể để cả 2 unit (uses) trong phần interface (lỗi circular unit reference). Cả 2 ở phần implementation hoặc 1 ở implementation 1 ở interface thì được.

Nói rõ thế để khi bị "dính" thì hiểu vì sao.

Các bạn thêm ý của anh Batman1 vào nữa nhé. Bài trước tôi chưa nói về vấn đề lỗi tham chiếu vòng “circular unit reference”. Khai báo Unit phải có cách tổ chức code khoa học kẻo sau này khi làm nhiều unit khai bái loạn lên là dò lỗi mệt. Trước đây tôi từng bị lỗi này mặc dù đã làm khá lắm thứ trên Delphi.
 
Upvote 0
Web KT
Back
Top Bottom