Đâ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.
phải nói thật là em cũng chưa biết xài help trong Delphi sao nữa ... bấm cái gì nó ra help ... Em xài bản XE6
tiện đây Anh chỉ Em luôn với
Cảm ơn Anh View attachment 205123
Em mới thử F1 nó báo lỗi View attachment 205125
Anh úp cho Em xin cái File help trên máy Anh với
hay đó là sách của trang sau http://www.delphibasics.co.uk/index.html
trong đó rất cơ bản có hết và list Function .... mình coi trang đó thấy bài nào hay toàn lưu lại nay có hết trong 1 Ebook rồi cảm ơn bạn
Cho mình hỏi chút trên VBA mình có thể kiểm tra Type của 1 biến bằng cách sau ...
Còn trong Delphi mình kiểm tra sao Bạn nhỉ ...?!
Tại vì biết 1 chút code két nên khai báo chứ trong Delphi ko biết chi luôn
Mã:
Sub CheckTypeName()
Dim i&, str$, j#, k!, n@, b%
MsgBox TypeName(i): Rem Dim i& <===> Dim i As long
MsgBox TypeName(str): Rem Dim str$ <===> Dim str As String
MsgBox TypeName(j): Rem Dim j# <===> Dim j As Double_'La mot kieu bien la so(co nhieu kieu bien so)
MsgBox TypeName(k): Rem Dim k! <===> Dim k As Single
MsgBox TypeName(n): Rem Dim n@ <===> Dim n As Currency
MsgBox TypeName(b): Rem Dim b% <===> Dim b As Integer
End Sub
Cho mình hỏi chút trên VBA mình có thể kiểm tra Type của 1 biến bằng cách sau ...
Còn trong Delphi mình kiểm tra sao Bạn nhỉ ...?!
Tại vì biết 1 chút code két nên khai báo chứ trong Delphi ko biết chi luôn
Mã:
Sub CheckTypeName()
Dim i&, str$, j#, k!, n@, b%
MsgBox TypeName(i): Rem Dim i& <===> Dim i As long
MsgBox TypeName(str): Rem Dim str$ <===> Dim str As String
MsgBox TypeName(j): Rem Dim j# <===> Dim j As Double_'La mot kieu bien la so(co nhieu kieu bien so)
MsgBox TypeName(k): Rem Dim k! <===> Dim k As Single
MsgBox TypeName(n): Rem Dim n@ <===> Dim n As Currency
MsgBox TypeName(b): Rem Dim b% <===> Dim b As Integer
End Sub
Niếu cột mình chưa biết trước và định dạng chưa biết trước thì có dùng được không, nếu được bạn cho mình 1 cái ví dụ với.
Ví dụ Range chạy lần đầu minh có 3 cột
Cột 1 integer
cột 2 String
Cột 3 Date
Range chạy lần thứ minh có 8 cột
Cột 1 String
cột 2 Date
Cột 3 String
Cột 4 integer
Cột 5 String
Cột 6 integer
Cột 7 integer
Cột 8 Double
Úp cho Mình cái File dữ liệu đủ thứ đó mình thử xem cái đã (ít dữ liệu thôi )
tại mới biết cách viết ngày hôm qua lang thang kiến tài liệu tìm cái này nó lại ra cái khác ... tiện thấy thử luôn nó chạy ... mừng thấy bà hihihihi
Code tây nó viết như sau Bạn có thể tham khảo thêm ... sau khi có file bạn úp mình test xong úp code luôn cho ... nó đơn giản thay mấy từ à
Mã:
var
Dic : TDictionary<Integer,TPerson>;
p : TPerson;
i : integer;
begin
//Create dictionary
Dic := TDictionary<Integer,TPerson>.Create;
Dic.Add(1, TPerson.Create('Delphi', 'Mr'));
Dic.Add(2, TPerson.Create('Generic', 'Bill'));
Dic.Add(3, TPerson.Create('nonymous', 'An'));
try
//Travel the strings
for p in Dic.Values do begin
ShowMessage(p.FullName);
end;
//Travel the keys
for i in Dic.Keys do begin
ShowMessage(IntToStr(i) + ': ' +
Dic.Items[i].FullName);
end;
//Find some key
if Dic.TryGetValue(3, p) then begin
ShowMessage('Found it!: ' + p.FullName);
end;
finally
for p in Dic.Values do
p.Free;
//Also free Values and KeyCollection
//other wise you have a memoryleak
//Is this a bug?
Dic.Values.Free;
Dic.Keys.Free;
//Free the dictionary
Dic.Free;
end;
Bạn tham khảo code trên cách duyệt dic của nó trước nha
Úp cho Mình cái File dữ liệu đủ thứ đó mình thử xem cái đã (ít dữ liệu thôi )
tại mới biết cách viết ngày hôm qua lang thang kiến tài liệu tìm cái này nó lại ra cái khác ... tiện thấy thử luôn nó chạy ... mừng thấy bà hihihihi
Code tây nó viết như sau Bạn có thể tham khảo thêm ... sau khi có file bạn úp mình test xong úp code luôn cho ... nó đơn giản thay mấy từ à
Mã:
var
Dic : TDictionary<Integer,TPerson>;
p : TPerson;
i : integer;
begin
//Create dictionary
Dic := TDictionary<Integer,TPerson>.Create;
Dic.Add(1, TPerson.Create('Delphi', 'Mr'));
Dic.Add(2, TPerson.Create('Generic', 'Bill'));
Dic.Add(3, TPerson.Create('nonymous', 'An'));
try
//Travel the strings
for p in Dic.Values do begin
ShowMessage(p.FullName);
end;
//Travel the keys
for i in Dic.Keys do begin
ShowMessage(IntToStr(i) + ': ' +
Dic.Items[i].FullName);
end;
//Find some key
if Dic.TryGetValue(3, p) then begin
ShowMessage('Found it!: ' + p.FullName);
end;
finally
for p in Dic.Values do
p.Free;
//Also free Values and KeyCollection
//other wise you have a memoryleak
//Is this a bug?
Dic.Values.Free;
Dic.Keys.Free;
//Free the dictionary
Dic.Free;
end;
Bạn tham khảo code trên cách duyệt dic của nó trước nha
Mình đang bí cái chỗ này chưa nghĩ ra cách làm bằng dictionary
Theo mình nghĩ cái dictionary ban khai báo cái
TPerson
trong đó
Delphi: String;
Generic: String;
nonymous: String;
Tự vì Code này dùng cho nhiều trường hợp. ví dụ mình chạy Code với trường hợp có 5 cột có cách nào không viết lại code mà vẫn dùng Code đó để chạy rồi Add vào Range
TPerson
trong đó
Day: Tdate;
SL: Doubler;
Dongia: Integer;
ThanhTien: Doubler;
Note: String;
Mình đang bí cái chỗ này chưa nghĩ ra cách làm bằng dictionary
Theo mình nghĩ cái dictionary ban khai báo cái
TPerson
trong đó
Delphi: String;
Generic: String;
nonymous: String;
Tự vì Code này dùng cho nhiều trường hợp. ví dụ mình chạy Code với trường hợp có 5 cột có cách nào không viết lại code mà vẫn dùng Code đó để chạy rồi Add vào Range
TPerson
trong đó
Day: Tdate;
SL: Doubler;
Dongia: Integer;
ThanhTien: Doubler;
Note: String;
1/ Tại [B1] bạn gõ 1 xong chạy code ... 2,3,4,+n xong chạy code
2/ có 1 sai sót là khi Cols loc duy nhất có 1 dòng mà nó cứ lấy thêm 1 dòng là 2 .... chưa xủ lý được
Bạn gõ 9 = cột Ghi Chú là thấy
3/ xong bài này ta làm 1 cái Dic thật phúc tạp hơn nữa xem sao ha
Mã:
function GetDictionaryKeys(sArr: OleVariant; const ColDic : longint):OleVariant; stdcall;
var
Tmp,Arr : OleVariant;
i, j,k : Longint;
lcols,lRows : Longint;
dic: TDictionary<string, Integer>;
begin
dic := TDictionary<string, Integer>.create;
try
k := 0;
lRows := VarArrayHighBound(sArr, 1);
lCols := VarArrayHighBound(sArr, 2);
Arr := VarArrayCreate([1, lRows , 1, lcols],varVariant);
if ColDic <= lCols then begin
for i := 1 to lRows do begin
Tmp := trim(sArr[i, ColDic]);
if not dic.ContainsKey(Tmp) then begin
k := k + 1;
Dic.Add(Tmp, k);
For j := 1 To lcols do begin
Arr[k, j] := sArr[i, j];
End;
end;
end;
Result := Arr;
end;
finally
dic.free;
end;
end;
Sử dụng code
Mã:
Sub Test_GetDictionaryKeys()
On Error Resume Next ''xu ly loi khi gan ket qua Mang Arr = Empty
Dim Arr As Variant
Arr = Sheet4.Range("A2:I1000").Value
Range("G4:P1000").ClearContents
Rem Range("B1") la Tham so cot can loc duy nhat(Go 1,2,3,...Run Code)
Arr = GetDictionaryKeys(Arr, Range("B1"))
Range("G4").Resize(UBound(Arr), UBound(Arr, 2)) = Arr
End Sub
Bạn xem cần chỉnh sửa gì bổ sung gì thêm xong chỉ dùm mình nhé ... Học tập tương tác qua lại mà he
ý mình là có cách nào khai báo cái Class
type
TMyData = class
a: string;
b: string;
c: Integer;
end;
mà mình chưa biết định dạng trước ý.
Mà chắc không được quá, chắc phải đưa vào mãng.
ý mình là có cách nào khai báo cái Class
type
TMyData = class
a: string;
b: string;
c: Integer;
end;
mà mình chưa biết định dạng trước ý.
Mà chắc không được quá, chắc phải đưa vào mãng.
bạn chỉ cho Mình cách tạo 1 cái Form cho File DLL đi có nghĩa như sau:
1/ tao 1 Form ko phải là Form.exe đâu nha
2/ cách khai báo gọi form Show từ DLL
3/ cách sử dụng hàm trong DLL khai báo trên Form
4/ xong Mình làm thủ tục gọi Form từ Excel ... to DLL cái Form đó nó Show
Xong bài này vài ngày nữa ta chuyển qua ADO cho Access he ... Mạnh viết cho vài hàm Mẫu ... đơn giản thôi mà ... Mạnh nhìn code họ viết vọc một hồi là ok à
chịu khó giúp Mạnh bước qua cái ngưỡng khai báo và sử dụng thì coi như là ok ròi đó
bạn chỉ cho Mình cách tạo 1 cái Form cho File DLL đi có nghĩa như sau:
1/ tao 1 Form ko phải là Form.exe đâu nha
2/ cách khai báo gọi form Show từ DLL
3/ cách sử dụng hàm trong DLL khai báo trên Form
4/ xong Mình làm thủ tục gọi Form từ Excel ... to DLL cái Form đó nó Show
Xong bài này vài ngày nữa ta chuyển qua ADO cho Access he ... Mạnh viết cho vài hàm Mẫu ... đơn giản thôi mà ... Mạnh nhìn code họ viết vọc một hồi là ok à
chịu khó giúp Mạnh bước qua cái ngưỡng khai báo và sử dụng thì coi như là ok ròi đó
Code Form
Cảm ơn nhiều
thì cái Unit của mạnh tên gì thì mạnh khai báo Uses "tên của Unit" trong form roi goi hàm
Ví dụ:
mạnh nhấp chuột phải vào CT tạo AddNew - Chọn Unit
Cái Unit của Mạnh tên là UDFExcel có hàm CheckTypeName
thì trong Form mạnh khai báo Uses giống như system.Varita mà mạnh gọi hàm ý
Uses UDFExcel;
rồi code Form chỉ việc đánh tên hàm
CheckTypeName;
thì cái Unit của mạnh tên gì thì mạnh khai báo Uses "tên của Unit" trong form roi goi hàm
Ví dụ:
mạnh nhấp chuột phải vào CT tạo AddNew - Chọn Unit
Cái Unit của Mạnh tên là UDFExcel có hàm CheckTypeName
thì trong Form mạnh khai báo Uses giống như system.Varita mà mạnh gọi hàm ý
Uses UDFExcel;
No dau phải là form, nó giống như Modul trong vba để mạnh viết code trong đó rồi muốn gọi ở đâu thì gọi.
Viết code trong đó rồi vào Form mà gọi code
1. mạnh viết cái hàm trong đó
2. vào Form gọi hàm trong đó bằng cách khai báo
Mã:
implementation
Uses UDFExcel;// day la ten của Unit2
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
WriteFormula // day là hàm trong Unit2
end;
No dau phải là form, nó giống như Modul trong vba để mạnh viết code trong đó rồi muốn gọi ở đâu thì gọi.
Viết code trong đó rồi vào Form mà gọi code
1. mạnh viết cái hàm trong đó
2. vào Form gọi hàm trong đó bằng cách khai báo
Mã:
implementation
Uses UDFExcel;// day la ten của Unit2
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
WriteFormula // day là hàm trong Unit2
end;
trời cái đó mình chưa thử nên cũng không biết (Thay vì bạn viết hàm dùng chung trong Dll sao không viết ra cái Unit), mình thường viết hàm dùng chung ra 1 Unit1, rồi từ Dll hay Form gọi hàm từ Unit
trời cái đó mình chưa thử nên cũng không biết (Thay vì bạn viết hàm dùng chung trong Dll sao không viết ra cái Unit), mình thường viết hàm dùng chung ra 1 Unit1, rồi từ Dll hay Form gọi hàm từ Unit
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.
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.
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
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
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
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 View attachment 205375
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
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
Chạy ok rồi đó tuy nhiên thấy khai báo dài dòng quá ... Ít hàm thì ko sao ... Nhiều Hàm chết chắc
Có cách nào khác khai báo sử dung hàm ngắn gọn hơn 1 chút ko ???!!!
À 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.
À 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.
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á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.
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.
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 ra
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 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 ra
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.
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;
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;
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.
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.
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';
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.
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 ra
Cảm ơn chưa đọc kỹ mà vội hỏi ... thấy có mấy dòng sau:
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).
có nói khi nào đâu
tại mới nhập môn Delphi quen vba rồi qua đó mấy cái biến khác chưa học kịp đó thui
khai báo và sử dụng cũng khác nhiều lúc thấy ngáo ngơ à ... vậy nên mới hỏi chi tiết là thế đó he
không hiểu ý Mạnh. nếu muốn lọc 10 cột thì mạnh giải rồi mà
Mã:
function GetDictionaryKeys(sArr: OleVariant; const ColDic : longint):OleVariant; stdcall;
var
Tmp,Arr : OleVariant;
i, j,k,col : Longint;
lcols,lRows : Longint;
dic: TDictionary<string, Integer>;
begin
dic := TDictionary<string, Integer>.create;
try
k := 0;
lRows := VarArrayHighBound(sArr, 1);
lCols := VarArrayHighBound(sArr, 2);
Arr := VarArrayCreate([1, lRows , 1, lcols],varVariant);
for i := 1 to lRows do begin
For col := 1 To lcols do begin
Tmp := Tmp + trim(vartostr(sArr[i, col]));
End;
ShowMessage(tmp);
if not dic.ContainsKey(Tmp) then begin
k := k + 1;
Dic.Add(Tmp, k);
For j := 1 To lcols do begin
Arr[k, j] := sArr[i, j];
End;
end;
end;
Result := Arr;
finally
dic.free;
end;
end;
Mò được cái này nó lại lòi ra cái khác .... nhờ các Bạn chỉ dùm
1/ Trên VBA khi mình duyệt Sheet tạo một Array như sau để chạy For next
Mã:
Sub DuyetSheet()
Dim MySheet As Variant
Dim i As Long, j As Long
MySheet = Array("Data_Nhap", "Data_Ban") ''tên SheetName
For j = 0 To UBound(MySheet)
MsgBox MySheet(j)
Next
End Sub
2/ Vậy code trên Delphi viết sao khi mình khai báo List Sheet là Array xong chạy For duyệt Nó
Xin cảm ơn
Mò được cái này nó lại lòi ra cái khác .... nhờ các Bạn chỉ dùm
1/ Trên VBA khi mình duyệt Sheet tạo một Array như sau để chạy For next
Mã:
Sub DuyetSheet()
Dim MySheet As Variant
Dim i As Long, j As Long
MySheet = Array("Data_Nhap", "Data_Ban") ''tên SheetName
For j = 0 To UBound(MySheet)
MsgBox MySheet(j)
Next
End Sub
2/ Vậy code trên Delphi viết sao khi mình khai báo List Sheet là Array xong chạy For duyệt Nó
Xin cảm ơn
Duyệt mảng thì bạn biết mà.
Còn nếu nói về hàm Array của VBA thì tôi không biết trong các phiên bản Delphi mới có hàm giống hoặc gần giống thế hay không. Tôi linh cảm là có cái gì đó gần giống Array của VBA.
Còn trong Delphi 5 thì nếu tôi không lầm thì không có. Nhưng với trường hợp như bạn nêu thì dùng CONST thôi.
Mã:
procedure TForm1.Button2Click(Sender: TObject);
const
b: array[1..2] of string = ('Data_Nhap', 'Data_Ban');
d: array[1..2, 1..3] of string = (('hic hic', 'hi hi', 'he he'),
('bla bla', 'ble ble', 'bli blu'));
var
r, c: Integer;
begin
for r := low(b) to high(b) do
showmessage(b[r]);
for r := low(d) to high(d) do
for c := low(d[r]) to high(d[r]) do
showmessage(d[r, c]);
end;