我在delphi中调用excel,用来打印一些东西,代码如下:
function TTAppBasicForm.ShowExcelWindow(sCaption, sFileName: string;
Cmd: array of string): boolean;
var
i,j,iNum: integer;
S: string;
begin
with OleExcel do begin
try
//CreateObjectfromfile(sFileName,false);
CreateObject('Excel.Application',False);
OleObject.Application.WorkBooks.Open(sFileName); OleObject.Application.ActiveWindow.Caption := sCaption;
OleObject.Application.Caption := Application.MainForm.Caption;
OleObject.Application.Application.WindowState := 3;
OleObject.Application.ActiveWindow.WindowState := 2;
Screen.Cursor := crHourGlass;
for i:=1 to 52 do begin
for j:=1 to 26 do begin
S := OleObject.Application.Cells[i,j].Value;
if System.Copy(S,1,2)='##' then begin
iNum := StrToInt(System.Copy(S,3,Length(S)));
if (iNum<0) or (iNum>Length(Cmd)-1) then
OleObject.Application.Cells(i,j) := ''
else
OleObject.Application.Cells(i,j) := Cmd[iNum];
end;
end;
end;
Screen.Cursor := crDefault;
OleObject.Application.Visible := true;
except
on e:exception do begin
ShowErrMessage('Open excel error!'+#13+#10+e.Message,'E');
result := false; exit;
end;
end
end;
result := True;
end;procedure TTAppBasicForm.CreateOleExcel;
begin
OleExcel := TOleContainer.Create(self);
with OleExcel do begin
Visible := false;
AllowInPlace := false;
Parent := self;
Align := alClient;
OldStreamFormat := false;
end;
end;可以运行,可是我发现程序中打开的excel进程好像在死循环,cpu占用99%,而且时间一直在涨.
请问是什么原因,怎么解决?我很少用ole,不是恨懂,望指教.
function TTAppBasicForm.ShowExcelWindow(sCaption, sFileName: string;
Cmd: array of string): boolean;
var
i,j,iNum: integer;
S: string;
begin
with OleExcel do begin
try
//CreateObjectfromfile(sFileName,false);
CreateObject('Excel.Application',False);
OleObject.Application.WorkBooks.Open(sFileName); OleObject.Application.ActiveWindow.Caption := sCaption;
OleObject.Application.Caption := Application.MainForm.Caption;
OleObject.Application.Application.WindowState := 3;
OleObject.Application.ActiveWindow.WindowState := 2;
Screen.Cursor := crHourGlass;
for i:=1 to 52 do begin
for j:=1 to 26 do begin
S := OleObject.Application.Cells[i,j].Value;
if System.Copy(S,1,2)='##' then begin
iNum := StrToInt(System.Copy(S,3,Length(S)));
if (iNum<0) or (iNum>Length(Cmd)-1) then
OleObject.Application.Cells(i,j) := ''
else
OleObject.Application.Cells(i,j) := Cmd[iNum];
end;
end;
end;
Screen.Cursor := crDefault;
OleObject.Application.Visible := true;
except
on e:exception do begin
ShowErrMessage('Open excel error!'+#13+#10+e.Message,'E');
result := false; exit;
end;
end
end;
result := True;
end;procedure TTAppBasicForm.CreateOleExcel;
begin
OleExcel := TOleContainer.Create(self);
with OleExcel do begin
Visible := false;
AllowInPlace := false;
Parent := self;
Align := alClient;
OldStreamFormat := false;
end;
end;可以运行,可是我发现程序中打开的excel进程好像在死循环,cpu占用99%,而且时间一直在涨.
请问是什么原因,怎么解决?我很少用ole,不是恨懂,望指教.
你的代码中此句:
iNum := StrToInt(System.Copy(S,3,Length(S)));
存在内存访问漏洞,copy函数将从S字符串的第3个字符开始拷贝Length(S)长度的子串,而此长度正好超过S字符串实际长度3个字节。strtoint函数有可能在对不规则文本转换时出错。
copy的问题,delphi的帮助这样讲
If Count specifies more characters or array elements than are available, only the characters or elements from S[Index] to the end of S are returned.
那个地方如果不是数字会异常,但不会内存访问越界的.
ExcelApp: OLEVariant;
begin
ExcelApp := CreateOleObject('Excel.Application');
ExcelApp.Visible := false;
ExcelApp.WorkBooks.Open('MyExcelFile.xls'); try
ExcelApp.Cells[j,i+1].Value := '...';
{...}
finally
if not VarIsEmpty(ExcelApp) then
begin
ExcelApp.Quit;
ExcelApp := Unassigned;
end;
end;
end; 説明:増加一個変量「ExcelApp: OLEVariant;」
操作完、最後释放該変量。
初始化ole执行环境是每一个使用ole对象的程序员都必须要做的事,只是当你将comobj或comsvr两个单元显示加入到你的引用单元列表中后,delphi会执行comobj单元的初始化代码如下:
procedure InitComObj;
begin
if SaveInitProc <> nil then TProcedure(SaveInitProc);
if (CoInitFlags <> -1) and Assigned(ComObj.CoInitializeEx) then
begin
NeedToUninitialize := Succeeded(ComObj.CoInitializeEx(nil, CoInitFlags));
IsMultiThread := IsMultiThread or
((CoInitFlags and COINIT_APARTMENTTHREADED) <> 0) or
(CoInitFlags = COINIT_MULTITHREADED); // this flag has value zero
end
else
NeedToUninitialize := Succeeded(CoInitialize(nil));
end;
其中,就有我所说的初始化com执行环境的关键代码CoInitializeEx/CoInitialize,对于这个函数的作用,windows sdk解释如下:
The CoInitialize function initializes the Component Object Model(COM) library. You must initialize the library before you can call its functions. Applications must call CoInitialize before they make any other COM library calls with two exceptions: the
CoGetMalloc function, and memory allocation calls.
其大意是你在使用com执行环境的任何api之间,你必须运行CoInitialize来初始化com库。而OleInitialize在内部也会调用CoInitialize来初始化ole执行环境。从你的代码来看,你并没有将delphi自带的Excel包装对象TExcelOLEObject,因此也就没有引用excel2000.pas这一单元文件。而excel2000.pas本身引用comobj单元。
function TTAppBasicForm.ShowExcelWindow(sCaption, sFileName: string;
Cmd: array of string): boolean;
var
OleExcel: Variant;
i,j,iNum: integer;
S: string;
TmpFile: string;
begin
try
OleExcel := CreateOleObject('Excel.Application');
except
ShowErrMessage('Open excel error!','E');
result := false; exit;
end; try
OleExcel.Application.WorkBooks.Open(sFileName);
OleExcel.Application.ActiveWindow.Caption := sCaption;
OleExcel.Application.Caption := Application.MainForm.Caption+'-'+sCaption;
OleExcel.Application.WindowState := 3;
OleExcel.Application.ActiveWindow.WindowState := 2; Screen.Cursor := crHourGlass;
for i:=1 to 52 do for j:=1 to 26 do begin
S := OleExcel.Application.Cells[i,j].Value;
if System.Copy(S,1,2)='##' then begin
iNum := StrToInt(System.Copy(S,3,Length(S)));
if (iNum<0) or (iNum>Length(Cmd)-1) then
OleExcel.Application.Cells(i,j) := ''
else
OleExcel.Application.Cells(i,j) := Cmd[iNum];
end;
end;
Screen.Cursor := crDefault; TmpFile := RunPath+'Temp\Invoice_'+FormatDateTime('yymmdd-hhnnss',now)+'.xls';
OleExcel.Application.ActiveWorkBook.SaveAs(TmpFile);
OleExcel.Application.Visible := true;
except
on e:exception do begin
OleExcel.Applicaton.DisplayAlerts := false;
OleExcel.Applicaton.Quit;
ShowErrMessage('Open excel error!'+#13+#10+e.Message,'E');
result := false; exit;
end;
end;
result := True;
end;