DELPHI "the object invoked has disconnected from its clients"
DELPHI "the object invoked has disconnected from its clients"
excel运行时,打开我处理的数据文件。 (如果我关闭这个文件,我的程序就会停止)
unit UBImportFromExcel;
interface
uses
MainDM, Contnrs, DB, Classes, UGeneral, BSYSTMGlobals,
SysUtils, ADODB, BDataSet, NThermo, ComObj, Graphics, Forms, ShellAPI, Windows, Math, DBClient;
type
TBImportFromExcel = class
private
ExcelApp, ExcelWorkbook, ExcelWorksheet,
Unassigned : Variant;
iStartingRow : Integer;
iSheetCount : Integer;
iRowCount : Integer;
public
function ReadCell(iRow : Integer; iColumn : Integer) : string;
procedure Worksheet(iWorksheetIndex : integer = 1);
protected
published
property StartingRow : Integer read iStartingRow write iStartingRow;
property SheetCount : Integer read iSheetCount;
property RowCount : Integer read iRowCount;
constructor Create(sFile : string); virtual;
destructor Destroy; override;
end;
implementation
{ TBImportFromExcel }
constructor TBImportFromExcel.Create(sFile : string);
begin
ExcelApp := CreateOleObject('Excel.Application');
ExcelWorkbook := ExcelApp.WorkBooks.Open(sFile);
iSheetCount := ExcelWorkbook.Worksheets.Count;
iStartingRow := 2;
end;
destructor TBImportFromExcel.Destroy;
begin
ExcelWorkbook.Close(False);
ExcelWorksheet := Unassigned;
ExcelWorkbook := Unassigned;
ExcelApp := Unassigned;
inherited;
end;
function TBImportFromExcel.ReadCell(iRow, iColumn: Integer): string;
var
oCell : OleVariant;
begin
oCell := ExcelWorksheet.Cells[iRow, iColumn];
Result := oCell.Value;
end;
procedure TBImportFromExcel.Worksheet(iWorksheetIndex: integer);
begin
ExcelWorksheet := ExcelWorkbook.Worksheets.Item[iWorksheetIndex];
ExcelWorksheet.Activate;
ExcelWorksheet.Select;
iRowCount := ExcelWorksheet.UsedRange.Rows.Count;
end;
end.
如果 excel 文件自行打开,我会在 header 中收到错误,我的程序会中断。
对不起,我的英语不好。 createoleobject 无法创建独立 object。为什么?
如果我理解正确的话,我想我可能有办法解决你的问题。
除了Visible
,Excel的OLE对象还有两个相关属性:
DisplayAlerts
确定 Excel 应用程序是否生成警报
显示在屏幕上;和
Interactive
,判断是否Excel对象(使用CreateOleObject创建)
可以与用户通过 Windows gui 启动的 Excel 实例进行交互。如果设置为 False,
Excel OLE 实例与用户的桌面实例完全“隔离”。
这两个都由 MS 记录,请参阅 here
Interactive
.
的文档
所以我创建了一个简单的测试应用程序,只有两个按钮和两个复选框以及这段代码
procedure TForm1.Start;
begin
sFile := ExtractFilePath(Application.ExeName) + 'Test.Xlsx';
ExcelApplication := CreateOleObject('Excel.Application');
ExcelApplication.Interactive := cbInteractive.Checked;
ExcelApplication.Visible := cbVisible.Checked;
ExcelApplication.DisplayAlerts := ExcelApplication.Visible; // no point in displaying alerts if Excel app is not visible
ExcelWorkbook := ExcelApplication.WorkBooks.Open(sFile);
end;
procedure TForm1.Stop;
begin
ExcelWorkBook.Close; // Needed to hide Excel if it was started with Visible = True
ExcelApplication.Quit;
ExcelWorkBook := Unassigned;
ExcelApplication := Unassigned;
end;
procedure TForm1.btnStartClick(Sender: TObject);
begin
Start;
end;
procedure TForm1.btnStopClick(Sender: TObject);
begin
Stop;
end;
将 cbInteractive 复选框设置为 False 确实可以将 OLE 创建的实例与任何交互式创建的实例隔离开来。
总之,先试试看,看看能不能满足你的需求。
excel运行时,打开我处理的数据文件。 (如果我关闭这个文件,我的程序就会停止)
unit UBImportFromExcel;
interface
uses
MainDM, Contnrs, DB, Classes, UGeneral, BSYSTMGlobals,
SysUtils, ADODB, BDataSet, NThermo, ComObj, Graphics, Forms, ShellAPI, Windows, Math, DBClient;
type
TBImportFromExcel = class
private
ExcelApp, ExcelWorkbook, ExcelWorksheet,
Unassigned : Variant;
iStartingRow : Integer;
iSheetCount : Integer;
iRowCount : Integer;
public
function ReadCell(iRow : Integer; iColumn : Integer) : string;
procedure Worksheet(iWorksheetIndex : integer = 1);
protected
published
property StartingRow : Integer read iStartingRow write iStartingRow;
property SheetCount : Integer read iSheetCount;
property RowCount : Integer read iRowCount;
constructor Create(sFile : string); virtual;
destructor Destroy; override;
end;
implementation
{ TBImportFromExcel }
constructor TBImportFromExcel.Create(sFile : string);
begin
ExcelApp := CreateOleObject('Excel.Application');
ExcelWorkbook := ExcelApp.WorkBooks.Open(sFile);
iSheetCount := ExcelWorkbook.Worksheets.Count;
iStartingRow := 2;
end;
destructor TBImportFromExcel.Destroy;
begin
ExcelWorkbook.Close(False);
ExcelWorksheet := Unassigned;
ExcelWorkbook := Unassigned;
ExcelApp := Unassigned;
inherited;
end;
function TBImportFromExcel.ReadCell(iRow, iColumn: Integer): string;
var
oCell : OleVariant;
begin
oCell := ExcelWorksheet.Cells[iRow, iColumn];
Result := oCell.Value;
end;
procedure TBImportFromExcel.Worksheet(iWorksheetIndex: integer);
begin
ExcelWorksheet := ExcelWorkbook.Worksheets.Item[iWorksheetIndex];
ExcelWorksheet.Activate;
ExcelWorksheet.Select;
iRowCount := ExcelWorksheet.UsedRange.Rows.Count;
end;
end.
如果 excel 文件自行打开,我会在 header 中收到错误,我的程序会中断。 对不起,我的英语不好。 createoleobject 无法创建独立 object。为什么?
如果我理解正确的话,我想我可能有办法解决你的问题。
除了Visible
,Excel的OLE对象还有两个相关属性:
DisplayAlerts
确定 Excel 应用程序是否生成警报 显示在屏幕上;和Interactive
,判断是否Excel对象(使用CreateOleObject创建) 可以与用户通过 Windows gui 启动的 Excel 实例进行交互。如果设置为 False, Excel OLE 实例与用户的桌面实例完全“隔离”。
这两个都由 MS 记录,请参阅 here
Interactive
.
所以我创建了一个简单的测试应用程序,只有两个按钮和两个复选框以及这段代码
procedure TForm1.Start;
begin
sFile := ExtractFilePath(Application.ExeName) + 'Test.Xlsx';
ExcelApplication := CreateOleObject('Excel.Application');
ExcelApplication.Interactive := cbInteractive.Checked;
ExcelApplication.Visible := cbVisible.Checked;
ExcelApplication.DisplayAlerts := ExcelApplication.Visible; // no point in displaying alerts if Excel app is not visible
ExcelWorkbook := ExcelApplication.WorkBooks.Open(sFile);
end;
procedure TForm1.Stop;
begin
ExcelWorkBook.Close; // Needed to hide Excel if it was started with Visible = True
ExcelApplication.Quit;
ExcelWorkBook := Unassigned;
ExcelApplication := Unassigned;
end;
procedure TForm1.btnStartClick(Sender: TObject);
begin
Start;
end;
procedure TForm1.btnStopClick(Sender: TObject);
begin
Stop;
end;
将 cbInteractive 复选框设置为 False 确实可以将 OLE 创建的实例与任何交互式创建的实例隔离开来。
总之,先试试看,看看能不能满足你的需求。