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:
Em mới thử viết kiểu vầy nó vẫn báo lỗi ... Anh xem Em viết sai cái gì hay thiếu cái gì viết lại dùm Em với
Với tập tin ở bài #1098 thì ví dụ:
Trong Unit1
Mã:
public
    { Public declarations }
    FExcelApp: ExcelApplication;  //TExcelApplication;
end;
...
procedure TForm1.Button2Click(Sender: TObject);
var
  sh: _WorksheetDisp;
begin
  if Assigned(FExcelApp) then
  begin
    sh := _WorksheetDisp(FExcelApp.ActiveSheet);
    sh.Cells._Default[1, 1].Value := 'Kiều Mạnh';
    ShowMessage(sh.name);
  end;
end;
Trong uDelphiAddIn1
Mã:
procedure TDelphiAddIn1.OnConnection(const Application: IDispatch;
  ConnectMode: ext_ConnectMode; const AddInInst: IDispatch;
  var custom: PSafeArray);
begin
  Form1 := TForm1.Create(nil);
  supports(Application, ExcelApplication, Form1.FExcelApp);
end;

procedure TDelphiAddIn1.OnStartupComplete(var custom: PSafeArray);
begin
  Form1.Show;
end;

Đây chỉ là ví dụ thôi.
 
Upvote 0
Với tập tin ở bài #1098 thì ví dụ:
Trong Unit1
Mã:
public
    { Public declarations }
    FExcelApp: ExcelApplication;  //TExcelApplication;
end;
...
procedure TForm1.Button2Click(Sender: TObject);
var
  sh: _WorksheetDisp;
begin
  if Assigned(FExcelApp) then
  begin
    sh := _WorksheetDisp(FExcelApp.ActiveSheet);
    sh.Cells._Default[1, 1].Value := 'Kiều Mạnh';
    ShowMessage(sh.name);
  end;
end;
Trong uDelphiAddIn1
Mã:
procedure TDelphiAddIn1.OnConnection(const Application: IDispatch;
  ConnectMode: ext_ConnectMode; const AddInInst: IDispatch;
  var custom: PSafeArray);
begin
  Form1 := TForm1.Create(nil);
  supports(Application, ExcelApplication, Form1.FExcelApp);
end;

procedure TDelphiAddIn1.OnStartupComplete(var custom: PSafeArray);
begin
  Form1.Show;
end;

Đây chỉ là ví dụ thôi.
Em mới Thử Build nó lỗi dòng đó Anh
Untitled.png
 
Upvote 0
OK Tuyệt vời Anh cảm ơn Anh @batman1 ... chạy Ngon Rồi
1592836662913.png

Nó thiếu mấy cái Uses à

Trong code sau nếu Em ko muốn chạy cái Form khi load Excel mà chỉ Load ExcelApp vào thôi thì sửa lại sao Anh nhỉ
Vì Form Em cho lên Menu Ribbon khi em bấm vào đó thì nó Show lên Rồi
Mã:
procedure TDelphiAddIn1.OnConnection(const Application: IDispatch;
  ConnectMode: ext_ConnectMode; const AddInInst: IDispatch;
  var custom: PSafeArray);
begin
  Form1 := TForm1.Create(nil);
  supports(Application, ExcelApplication, Form1.FExcelApp);
end;

và khi thoát Excel ( Add-ins ) thì có cần Giải phóng biến như trên VBA Set x = Nothing không vào Code sau
Mã:
procedure TDelphiAddIn1.OnBeginShutdown(var custom: PSafeArray);
begin

end;
 
Lần chỉnh sửa cuối:
Upvote 0
OK Tuyệt vời Anh cảm ơn Anh @batman1 ... chạy Ngon Rồi
Nó thiếu mấy cái Uses à
Tôi không hiểu.

Trong uDelphiAddIn1 ở phần implementation có uses Unit1. Trong Unit1 có
var
Form1: TForm1;

ExcelApplication có trong Excel2010.

Thiếu gì ở đây? Thiếu Excel2010 trong uses của uDelphiAddIn1?
Trong code sau nếu Em ko muốn chạy cái Form khi load Excel mà chỉ Load ExcelApp vào thôi thì sửa lại sao Anh nhỉ
Vì Form Em cho lên Menu Ribbon khi em bấm vào đó thì nó Show lên Rồi
Tôi không hiểu ý. Nếu không muốn hiện Form thì bỏ Form1 := TForm1.Create(nil) và Form1.Show

Chỉ để lại supports(Application, ExcelApplication, FExcelApp). Và FExcelApp chuyển ra chỗ mới trong Unit1:
...
var

Form1: TForm1;
FExcelApp: ExcelApplication;
-----
Thực ra trong VBA cũng không cần Set x = Nothing. Nếu x là biến cục bộ ̣(local) thì khi ra khỏi procedure "sau cánh gà" "người ta" sẽ hủy x. Nếu x là biến toàn cục thì khi kết thúc "sau cánh gà" "người ta" sẽ hủy x.
Trong Delphi nếu đối tượng là biến cục bộ thì khi ra khỏi procedure thì compilator sẽ hủy đối tượng.
 
Lần chỉnh sửa cuối:
Upvote 0
Thiếu cái Excel2010 đó em cho vào mới chạy
 
Upvote 0
Thiếu cái Excel2010 đó em cho vào mới chạy
Tôi biết ngay mà.

Có những cái mình phải tự thêm vào uses tùy vào việc cần làm. Có những cái bạn phải tự thêm vào tùy theo code hướng dẫn của tôi đòi hỏi gì. Tôi không phải ghi ra chi tiết tới Z vì vấn đề không phải của tôi. Và người có compiler trong tay là bạn chứ không phải tôi. Bạn compile lần đầu là Delphi đã gào lên là có lỗi, và chỉ rõ vị trí lỗi. Vậy tại tao bạn không sửa mà còn đăng ký cho Excel và bỏ công viết bài #1102?
 
Upvote 0
Tôi biết ngay mà.

Có những cái mình phải tự thêm vào uses tùy vào việc cần làm. Có những cái bạn phải tự thêm vào tùy theo code hướng dẫn của tôi đòi hỏi gì. Tôi không phải ghi ra chi tiết tới Z vì vấn đề không phải của tôi. Và người có compiler trong tay là bạn chứ không phải tôi. Bạn compile lần đầu là Delphi đã gào lên là có lỗi, và chỉ rõ vị trí lỗi. Vậy tại tao bạn không sửa mà còn đăng ký cho Excel và bỏ công viết bài #1102?
Không biết Em làm sai cái gì hay khai báo thiếu cái gì khi Em tạo 1 cái Form mới Em bỏ nó chạy khi Excel Load chỉ thực hiện khi bấm trên Menu mà nó không có chạy và không báo lỗi

Anh chỉ dùm Em khai báo lại , viết lại code sao mà sử dụng chung cho nhiều cái Form khi em gọi nó trên menu Excel

Code trong TDelphiAddIn1.OnConnection
Mã:
procedure TDelphiAddIn1.OnConnection(const Application: IDispatch;
  ConnectMode: ext_ConnectMode; const AddInInst: IDispatch;
  var custom: PSafeArray);
begin
  supports(Application, ExcelApplication)//Thiếu hay sai cái gì ở khúc này
end;

Code trên Form không chạy mà cũng ko báo lỗi
Mã:
procedure TForm1.GetRangeClick(Sender: TObject);
var
  sh: _WorksheetDisp;
begin
  if Assigned(FExcelApp) then
  begin
    sh := _WorksheetDisp(FExcelApp.ActiveSheet);
    sh.Cells._Default[1, 1].Value := 'Kiều Mạnh';
    ShowMessage(sh.name);
  end;
end;
Cảm ơn Anh
 
Lần chỉnh sửa cuối:
Upvote 0
(*) Lưu ý khi viết COM Add-in
Việc khởi tạo Excel không được tự tạo mới nếu không có nhu cầu tách biệt (new instance). Hãy kết nối với tham số Application truyền vào từ sự kiện OnConnection(Application,...). Có nghĩa là biến FExcelApp không khai báo trong Form mà khai báo public - không nằm trong class mà nằm trong nhánh INTERFACE.

1. Cách kết nối với ứng dụng Excel khi chạy như sau

unit AddinConnect;

Inteface
uses ...

Mã:
procedure TDelphiAddIn1.OnConnection(const Application: IDispatch;
  ConnectMode: ext_ConnectMode; const AddInInst: IDispatch;
  var custom: PSafeArray);
begin
  FExcelApp := TExcelApplication.Create(nil);
  FExcelApp.ConnectTo(_Application(Application));
end;

2. Giải phóng biến FExcelApp khi thoát Excel và add-in

Mã:
procedure TDelphiAddIn1.OnDisconnection(RemoveMode: ext_DisconnectMode;
  var custom: PSafeArray);
begin
  if Assigned(FExcelApp) then
     FExcelApp.Free;// hoặc FreeAndNil(FExcelApp);
end;

Với cách làm như trên thì biên FExcepApp là đầu mối làm việc với Excel gọi nó. Khai báo cũ mà khởi tạo Excel trong Form là ví dụ mà tôi làm trong video trên là khi viết ứng dụng chạy độc lập (EXE). Vậy nên khi viết add-in thì không được viết như thế này nữa

Mã:
procedure TForm2.FormCreate(Sender: TObject);
begin
  FExcelApp := TExcelApplication.Create(nil);
  FExcelApp.ConnectKind := ckNewInstance;
  FExcelApp.Connect;
end;

Hai Lúa, Kiều Mạnh và các bạn chú ý nhé.
 
Lần chỉnh sửa cuối:
Upvote 0
(*) Lưu ý khi viết COM Add-in
Việc khởi tạo Excel không được tự tạo mới nếu không có nhu cầu tách biệt (new instance). Hãy kết nối với tham số Application truyền vào từ sự kiện OnConnection(Application,...). Có nghĩa là biến FExcelApp không khai báo trong Form mà khai báo public - không nằm trong class mà nằm trong nhánh INTERFACE.

1. Cách kết nối với ứng dụng Excel khi chạy như sau

unit AddinConnect;

Inteface
uses ...

Mã:
procedure TDelphiAddIn1.OnConnection(const Application: IDispatch;
  ConnectMode: ext_ConnectMode; const AddInInst: IDispatch;
  var custom: PSafeArray);
begin
  FExcelApp := TExcelApplication.Create(nil);
  FExcelApp.ConnectTo(_Application(Application));
end;

2. Giải phóng biến FExcelApp khi thoát Excel và add-in

Mã:
procedure TDelphiAddIn1.OnDisconnection(RemoveMode: ext_DisconnectMode;
  var custom: PSafeArray);
begin
  if Assigned(FExcelApp) then
     FExcelApp.Free;// hoặc FreeAndNil(FExcelApp);
end;

Với cách làm như trên thì biên FExcepApp là đầu mối làm việc với Excel gọi nó. Khai báo cũ mà khởi tạo Excel trong Form là ví dụ mà tôi làm trong video trên là khi viết ứng dụng chạy độc lập (EXE). Vậy nên khi viết add-in thì không được viết như thế này nữa

Mã:
procedure TForm2.FormCreate(Sender: TObject);
begin
  FExcelApp := TExcelApplication.Create(nil);
  FExcelApp.ConnectKind := ckNewInstance;
  FExcelApp.Connect;
end;

Hai Lúa, Kiều Mạnh và các bạn chú ý nhé.
Mạnh đang kẹt code trên Form mỗi lần nó Show ra mà ko chạy code ...
Mạnh tạo 1 cái Form xong Từ Menu Ribbon Excel bấm nó Show lên mỗi lần khi có nhu cầu mà khai báo sao nó không có chạy code sau:
Mã:
procedure TForm1.GetRangeClick(Sender: TObject);
var
  sh: _WorksheetDisp;
begin
  if Assigned(FExcelApp) then
  begin
    sh := _WorksheetDisp(FExcelApp.ActiveSheet);
    sh.Cells._Default[1, 1].Value := 'Kiều Mạnh';
    ShowMessage(sh.name);
  end;
end;

Toàn bộ code trên Form
Mã:
interface

uses
  System.Win.ComObj,
  Vcl.Buttons,
  Winapi.Windows, Winapi.Messages,
  System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms,
  Vcl.Dialogs, Excel2010, Vcl.OleServer,
  Vcl.ComCtrls, Vcl.StdCtrls,
  Vcl.DBCtrls, Vcl.ExtCtrls;

type
  TForm1 = class(TForm)
    OpenDialog1: TOpenDialog;
    SpeedButton1: TSpeedButton;
    DBRadioGroup1: TDBRadioGroup;
    DBListBox1: TDBListBox;
    Edit1: TEdit;
    GetRange: TButton;
    Label1: TLabel;
    procedure SpeedButton1Click(Sender: TObject);
    procedure GetRangeClick(Sender: TObject);
  private
    { Private declarations }
    FExcelApp: TExcelApplication; // Uses Excel2010
  public
    { Public declarations }
    //FExcelApp: ExcelApplication; // TExcelApplication; khai báo sử dụng ExcelApp
  end;

  { var
    Form1: TForm1; code Delphi tao ra }
  { Khai bao cac bien su dung Cho Form }
procedure ShowForm;
var
  Form1: TForm1;
  f: TForm1; // Su dung Form

implementation

{$R *.dfm}

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

procedure TForm1.GetRangeClick(Sender: TObject);
var
  sh: _WorksheetDisp;
begin
  if Assigned(FExcelApp) then
  begin
    sh := _WorksheetDisp(FExcelApp.ActiveSheet);
    sh.Cells._Default[1, 1].Value := 'Kiều Mạnh';
    ShowMessage(sh.name);
  end;
end;

Chỉnh sửa dùm Mạnh làm sao mỗi khi bấm Form Show lên là xài code Check Sheetname Ok
 
Upvote 0
Kiều Mạnh: bạn đang viết add-in hay EXE ?
 
Upvote 0
Upvote 0
Bạn đọc kỹ bài mình viết #1109 . Đưa đoạn code full trong Unit có sự kiện "OnConnection" đã sửa của bạn lên, chụp màn hình báo lỗi nhé.
code nó như sau ... chạy ko báo lỗi chỉ dùm Mạnh
Mã:
unit CustomUI;

{$WARN SYMBOL_PLATFORM OFF}

interface

uses
  Winapi.windows,
  Winapi.Messages,
  Vcl.Graphics,
  Vcl.oleServer,
  Vcl.stdctrls,
  Vcl.controls,
  Vcl.forms,
  System.Win.ComObj,
  Winapi.ActiveX,
  VBLibrary_TLB,
  System.Win.StdVcl,
  Vcl.Dialogs,
  System.Variants,
  AddInDesignerObjects_TLB,
  System.Classes,
  System.SysUtils,
  Office2010;

type
  TXLComAddinFactory = class(TAutoObjectFactory)
    procedure UpdateRegistry(Register: Boolean); override;
  end;

  TCoMultipleUIThreadsDemo = class(TAutoObject, ICoMultipleUIThreadsDemo,
    IDTExtensibility2, IRibbonExtensibility)
  private
    procedure OnConnection(const Application: IDispatch;
      ConnectMode: ext_ConnectMode; const AddInInst: IDispatch;
      var custom: PSafeArray); safecall;
    procedure OnDisconnection(RemoveMode: ext_DisconnectMode;
      var custom: PSafeArray); safecall;
    procedure OnAddInsUpdate(var custom: PSafeArray); safecall;
    procedure OnStartupComplete(var custom: PSafeArray); safecall;
    procedure OnBeginShutdown(var custom: PSafeArray); safecall;
    { IRibbonExtensibility }
    function GetCustomUI(const RibbonID: WideString): WideString; safecall;
  protected
    procedure ShowModelessForm(const Control: IDispatch); safecall;
    procedure Server(const Control: IDispatch); safecall;
    procedure SQLServer(const Control: IDispatch); safecall;
    procedure Client(const Control: IDispatch); safecall;
    procedure Help(const Control: IDispatch); safecall;
  end;

implementation

uses
  System.Win.ComServ,
  SQLDatabaseOffice,
  ExcelXP,
  Office2010,
  System.Win.Registry;

var
  FExcelApp: TExcelApplication;
  { TCoMultipleUIThreadsDemo }

function TCoMultipleUIThreadsDemo.GetCustomUI(const RibbonID: WideString)
  : WideString;
begin
  result := '<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">'#13#10
    + '<ribbon startFromScratch="false">'#13#10 + '    <tabs>'#13#10 +
    '      <tab id="NetworkTCPIP" label="ExcelTools">'#13#10 +
    '        <group id="GROU1" label="Access And Excel">'#13#10 +
    '          <button id="GetDatabase" onAction="ShowModelessForm" size="large" imageMso="ImportMoreMenu" label="SQL String Database" screentip="T&#249;y Ch&#7885;n L&#7845;y D&#7919; Li&#7879;u" supertip="Access V&#224; Excel"/>'#13#10
    + '        </group>'#13#10 +
    '        <group id="GROU3" label="Windows">'#13#10 +
    '          <button id="SQLServer" onAction="SQLServer" size="large" imageMso="ViewsAdpDiagramSqlView" label="Server Databases&#8203;" screentip="L&#7845;y D&#7919; Li&#7879;u T&#7915; Server" supertip="SQL Server"/>'#13#10
    + '        </group>'#13#10 +
    '        <group id="GROU2" label="Network - TCPIP">'#13#10 +
    '          <button id="Server" onAction="Server" size="large" imageMso="RemoveDuplicates" label="Server" screentip="NetworkTCPIP - Server" supertip="L&#7845;y D&#7919; Li&#7879;u Ph&#432;&#417;ng Th&#7913;c TCPIP"/>'#13#10
    + '          <separator id="SEPA1"/>'#13#10 +
    '          <button id="Client" onAction="Client" size="large" imageMso="MeetingsWorkspace" label="Client" screentip="NetworkTCPIP - Client" supertip="L&#7845;y D&#7919; Li&#7879;u Ph&#432;&#417;ng Th&#7913;c TCPIP"/>'#13#10
    + '        </group>'#13#10 +
    '        <group id="GROU4" label="About Excel Tools">'#13#10 +
    '          <button id="Help" onAction="Help" size="large" imageMso="FunctionsLogicalInsertGallery" label="Help" screentip="H&#7893; Tr&#7907;" supertip="S&#7917; D&#7909;ng Tr&#432;&#417;ng Tr&#236;nh"/>'#13#10
    + '          <separator id="SEPA2"/>'#13#10 +
    '          <labelControl id="LABE2" label="Author"/>'#13#10 +
    '          <labelControl id="LABE3" label="Phone"/>'#13#10 +
    '          <labelControl id="LABE4" label="Email"/>'#13#10 +
    '          <labelControl id="LABE5" label=": Ki&#7873;u M&#7841;nh"/>'#13#10
    + '          <labelControl id="LABE6" label=": 0929 555 666 - 0922 366 377"/>'#13#10
    + '          <labelControl id="LABE1" label=": kieumanh366377@gmail com"/>'#13#10
    + '        </group>'#13#10 + '      </tab>'#13#10 + '    </tabs>'#13#10 +
    '  </ribbon>'#13#10 + '</customUI>';

end;

procedure TCoMultipleUIThreadsDemo.OnAddInsUpdate(var custom: PSafeArray);
begin

end;

procedure TCoMultipleUIThreadsDemo.OnBeginShutdown(var custom: PSafeArray);
begin

end;

procedure TCoMultipleUIThreadsDemo.OnConnection(const Application: IDispatch;
  ConnectMode: ext_ConnectMode; const AddInInst: IDispatch;
  var custom: PSafeArray);
var
  // FExcelApp: ExcelApplication;
  FExcelApp: TExcelApplication;
begin
  // Form1 := TForm1.Create(nil); // Bỏ Show From Khi Excel Load
  // supports(Application, ExcelApplication, Form1.FExcelApp);
  // tren chay Ok
  FExcelApp := TExcelApplication.Create(nil);
  FExcelApp.ConnectTo(_Application(Application));
end;

procedure TCoMultipleUIThreadsDemo.OnDisconnection
  (RemoveMode: ext_DisconnectMode; var custom: PSafeArray);
var
  // FExcelApp: ExcelApplication;
  FExcelApp: TExcelApplication;
begin
  if Assigned(FExcelApp) then
    FExcelApp.Free; // hoặc FreeAndNil(FExcelApp);
end;

procedure TCoMultipleUIThreadsDemo.OnStartupComplete(var custom: PSafeArray);
begin
  Form1.Show; // bỏ trên OnConnection  thi dòng này mất tác dụng
end;

{ TXLComAddinFactory }

procedure TXLComAddinFactory.UpdateRegistry(Register: Boolean);
var
  RootKey: HKEY;
  AddInKey: string;
  r: TRegistry;
begin
  RootKey := HKEY_CURRENT_USER;
  AddInKey := 'Software\Microsoft\Office\Excel\Addins\' + ProgID;
  r := TRegistry.Create;
  r.RootKey := RootKey;
  try
    if Register then
      if r.OpenKey(AddInKey, True) then
      begin
        r.WriteInteger('LoadBehavior', 3);
        r.WriteInteger('CommandLineSafe', 0);
        r.WriteString('FriendlyName', 'VBLibrary Excel Add-Ins');
        r.WriteString('Description', 'Code By Kieu Manh');
        r.CloseKey;
      end
      else
        raise EOleError.Create('Can''t register Add-In ' + ProgID)
    else if r.KeyExists(AddInKey) then
      r.DeleteKey(AddInKey);
  finally
    r.Free;
  end;
  inherited;
end;

procedure TCoMultipleUIThreadsDemo.ShowModelessForm(const Control: IDispatch);
begin // onAction="ShowModelessForm" //gán Sub vao dây
  // ShowMessage('SQL String ... Thực hiện sau');
  ShowForm; { gọi Form SQLDatabaseOffice }
end;

procedure TCoMultipleUIThreadsDemo.Server(const Control: IDispatch);
Var // onAction="Server" //gán Sub vao dây
  Range: OleVariant;
  ExcelApp: Variant;
  XlVersion: Integer;
begin
  try
    ExcelApp := GetActiveOleObject('Excel.Application');
  except
    try
      ShowMessage('Excel not already open create a Excel Object');
      { If no instance of Word is running, try to Create a new Word Object }
      ExcelApp := CreateOleObject('Excel.Application');
      XlVersion := Trunc(ExcelApp.Application.Version);
      ShowMessage(IntToStr(XlVersion));
    except
      ShowMessage('Cannot start Excel/Excel not installed ?');
      Exit;
    end;
    ExcelApp := Unassigned;
  end;
end;
procedure TCoMultipleUIThreadsDemo.SQLServer(const Control: IDispatch);
begin // onAction="SQLServer" //gán Sub vao dây
  ShowMessage('SQLServer ... Thực hiện sau');
end;

procedure TCoMultipleUIThreadsDemo.Client(const Control: IDispatch);
begin // onAction="Client" //gán Sub vao dây
  ShowMessage('Client ... Thực hiện sau');
end;

procedure TCoMultipleUIThreadsDemo.Help(const Control: IDispatch);

begin // onAction="Help" //gán Sub vao dây
  ShowMessage('Help ... Thực hiện sau');
end;

initialization

TXLComAddinFactory.Create(ComServer, TCoMultipleUIThreadsDemo,
  Class_CoMultipleUIThreadsDemo, ciMultiInstance, tmApartment);

end.

Muốn khai báo Unit đó với Trên Form sao Mỗi khi có nhu cầu Mở Form lên là chạy ok Check SheetName và gán dữ liệu xuống Cells
 
Upvote 0
Kiều Mạnh: Hai sự kiện dưới đây không được khai báo FExxcelApp nữa vì đã khai báo public trên Interface rồi.

Mã:
procedure TCoMultipleUIThreadsDemo.OnConnection(const Application: IDispatch;
  ConnectMode: ext_ConnectMode; const AddInInst: IDispatch;
  var custom: PSafeArray);
var
  //FExcelApp: TExcelApplication; ==>Xóa đi
begin
  FExcelApp := TExcelApplication.Create(nil);
  FExcelApp.ConnectTo(_Application(Application));
end;

procedure TCoMultipleUIThreadsDemo.OnDisconnection
  (RemoveMode: ext_DisconnectMode; var custom: PSafeArray);
var
  //FExcelApp: TExcelApplication; ==>Xóa đi
begin
  if Assigned(FExcelApp) then
    FExcelApp.Free; // hoặc FreeAndNil(FExcelApp);
end;
 
Upvote 0
Kiều Mạnh: Hai sự kiện dưới đây không được khai báo FExxcelApp nữa vì đã khai báo public trên Interface rồi.

Mã:
procedure TCoMultipleUIThreadsDemo.OnConnection(const Application: IDispatch;
  ConnectMode: ext_ConnectMode; const AddInInst: IDispatch;
  var custom: PSafeArray);
var
  //FExcelApp: TExcelApplication; ==>Xóa đi
begin
  FExcelApp := TExcelApplication.Create(nil);
  FExcelApp.ConnectTo(_Application(Application));
end;

procedure TCoMultipleUIThreadsDemo.OnDisconnection
  (RemoveMode: ext_DisconnectMode; var custom: PSafeArray);
var
  //FExcelApp: TExcelApplication; ==>Xóa đi
begin
  if Assigned(FExcelApp) then
    FExcelApp.Free; // hoặc FreeAndNil(FExcelApp);
end;
Vậy code trên Form mình viết như sau nó sai cái gì mà nó ko có chạy mỗi khi Bấm Show Form lên ... sửa dùm Mình
Mã:
interface

uses
  System.Win.ComObj,
  Vcl.Buttons,
  CustomUI,
  Winapi.Windows, Winapi.Messages,
  System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms,
  Vcl.Dialogs, Excel2010, Vcl.OleServer,
  Vcl.ComCtrls, Vcl.StdCtrls,
  Vcl.DBCtrls, Vcl.ExtCtrls;

type
  TForm1 = class(TForm)
    OpenDialog1: TOpenDialog;
    SpeedButton1: TSpeedButton;
    DBRadioGroup1: TDBRadioGroup;
    DBListBox1: TDBListBox;
    Edit1: TEdit;
    GetRange: TButton;
    Label1: TLabel;
    procedure SpeedButton1Click(Sender: TObject);
    procedure GetRangeClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    FExcelApp: TExcelApplication; // Uses Excel2010
  public
    { Public declarations }
    //FExcelApp: ExcelApplication; // TExcelApplication; khai báo sử dụng ExcelApp
  end;

  { var
    Form1: TForm1; code Delphi tao ra }
  { Khai bao cac bien su dung Cho Form }
procedure ShowForm;
var
  Form1: TForm1;
  f: TForm1; // Su dung Form

implementation

{$R *.dfm}

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

procedure TForm1.FormCreate(Sender: TObject);
begin

end;

procedure TForm1.GetRangeClick(Sender: TObject);
var
  sh: _WorksheetDisp;
begin
  if Assigned(FExcelApp) then
  begin
    sh := _WorksheetDisp(FExcelApp.ActiveSheet);
    sh.Cells._Default[1, 1].Value := 'Kiều Mạnh';
    ShowMessage(sh.name);
  end;
end;
 
Upvote 0
Vậy code trên Form mình viết như sau nó sai cái gì mà nó ko có chạy mỗi khi Bấm Show Form lên ... sửa dùm Mình
Mã:
interface

uses
  System.Win.ComObj,
  Vcl.Buttons,
  CustomUI,
  Winapi.Windows, Winapi.Messages,
  System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms,
  Vcl.Dialogs, Excel2010, Vcl.OleServer,
  Vcl.ComCtrls, Vcl.StdCtrls,
  Vcl.DBCtrls, Vcl.ExtCtrls;

type
  TForm1 = class(TForm)
    OpenDialog1: TOpenDialog;
    SpeedButton1: TSpeedButton;
    DBRadioGroup1: TDBRadioGroup;
    DBListBox1: TDBListBox;
    Edit1: TEdit;
    GetRange: TButton;
    Label1: TLabel;
    procedure SpeedButton1Click(Sender: TObject);
    procedure GetRangeClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    FExcelApp: TExcelApplication; // Uses Excel2010
  public
    { Public declarations }
    //FExcelApp: ExcelApplication; // TExcelApplication; khai báo sử dụng ExcelApp
  end;

  { var
    Form1: TForm1; code Delphi tao ra }
  { Khai bao cac bien su dung Cho Form }
procedure ShowForm;
var
  Form1: TForm1;
  f: TForm1; // Su dung Form

implementation

Lại thừa khai báo FExcelApp trong class. Cái này mình đã nói kỹ ở bài #1109 rồi mà. BỎ KHAI BÁO FEXCELAPP ở tất cả các nơi, chỉ để duy nhất một lần khai báo public trong unit nhÁnh INTERFACE. Lắm bệnh quá :)

interface

uses
System.Win.ComObj,
Vcl.Buttons,
CustomUI,
Winapi.Windows, Winapi.Messages,
System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms,
Vcl.Dialogs, Excel2010, Vcl.OleServer,
Vcl.ComCtrls, Vcl.StdCtrls,
Vcl.DBCtrls, Vcl.ExtCtrls;

type
TForm1 = class(TForm)
OpenDialog1: TOpenDialog;
SpeedButton1: TSpeedButton;
DBRadioGroup1: TDBRadioGroup;
DBListBox1: TDBListBox;
Edit1: TEdit;
GetRange: TButton;
Label1: TLabel;
procedure SpeedButton1Click(Sender: TObject);
procedure GetRangeClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
FExcelApp: TExcelApplication; // XÓA ĐI!!!!
public
{ Public declarations }
//FExcelApp: ExcelApplication; // TExcelApplication; khai báo sử dụng ExcelApp
end;

{ var
Form1: TForm1; code Delphi tao ra }
{ Khai bao cac bien su dung Cho Form }
procedure ShowForm;
var
Form1: TForm1;
f: TForm1; // Su dung Form

implementation

{$R *.dfm}


end;
 
Upvote 0
Lại thừa khai báo FExcelApp trong class. Cái này mình đã nói kỹ ở bài #1109 rồi mà. BỎ KHAI BÁO FEXCELAPP ở tất cả các nơi, chỉ để duy nhất một lần khai báo public trong unit nhÁnh INTERFACE. Lắm bệnh quá :)

interface

uses
System.Win.ComObj,
Vcl.Buttons,
CustomUI,
Winapi.Windows, Winapi.Messages,
System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms,
Vcl.Dialogs, Excel2010, Vcl.OleServer,
Vcl.ComCtrls, Vcl.StdCtrls,
Vcl.DBCtrls, Vcl.ExtCtrls;

type
TForm1 = class(TForm)
OpenDialog1: TOpenDialog;
SpeedButton1: TSpeedButton;
DBRadioGroup1: TDBRadioGroup;
DBListBox1: TDBListBox;
Edit1: TEdit;
GetRange: TButton;
Label1: TLabel;
procedure SpeedButton1Click(Sender: TObject);
procedure GetRangeClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
FExcelApp: TExcelApplication; // XÓA ĐI!!!!
public
{ Public declarations }
//FExcelApp: ExcelApplication; // TExcelApplication; khai báo sử dụng ExcelApp
end;

{ var
Form1: TForm1; code Delphi tao ra }
{ Khai bao cac bien su dung Cho Form }
procedure ShowForm;
var
Form1: TForm1;
f: TForm1; // Su dung Form

implementation

{$R *.dfm}


end;
xóa đi nó báo lỗi
1592885079032.png
thiếu khai báo ở đâu đó mà mình chưa hình dung ra
 
Upvote 0
Upvote 0
Khai báo chung vào form có được ko
Được nhưng nó tối. Moitj add-in sẽ có nhiều form làm nhiều phần việc, các form đều dùng đến FExcelApp nên biến này nên nằm ở một unit riêng chứ không khai báo trong một form nào sẽ sáng phạm vi.
 
Upvote 0
Web KT
Back
Top Bottom