一个关于创建excel郁闷得问题(40分)

  • 主题发起人 主题发起人 zl_cch
  • 开始时间 开始时间
Z

zl_cch

Unregistered / Unconfirmed
GUEST, unregistred user!
各位大侠,我用的是ole的方法动态创建excel,将表中得数据导入到excel,导完之后随即打开excel查看,而且自动保存了,但是如果我修改了excel,然后没有保存,这个时候再重新将表中得数据导出到excel得时候就会报错:遇到一个microsoft软件安装程序错误。如果将第一次打开得那个excel文档保存后就不会报错了,不知道为什么。我在单部跟踪时发现是再打开excel那句话报的错,小弟实在不明白为什么,各位大侠有什么好的解决办法帮帮小弟啊!!!
 
抱错提示是什么?
可能是上次你关闭excel是,ole variant变量没有释放干净(alt+ctrl+del查看内存)
excel ole 变量关闭后 变量:=unassign//加上这句
 
你的excel使用後沒有完全釋放....這時再建一個excel就會出錯了...
完成釋放不是用close, 還要使 myexcel:=unassign;
 
报的错就是:遇到一个microsoft软件安装程序错误!问题是我如果随便先打开一个excel,修改过了没有保存,这个时候我再用程序生成一个新的excel就会报上面的错误,和释放没有多大关系吧!
 
或者有哪位大侠告诉在下如何判断系统中已经打开了一个excel?
 
procedure TerminateOLE;
var
FSnapshotHandle:THandle;
FProcessEntry32:TProcessEntry32;
Ret : BOOL;
ProcessID : integer;
s:string;
begin
FSnapshotHandle:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
FProcessEntry32.dwSize:=Sizeof(FProcessEntry32);
Ret:=Process32First(FSnapshotHandle,FProcessEntry32);
while Ret do
begin
s:=ExtractFileName(FProcessEntry32.szExeFile);
if s='EXCEL.EXE' then
begin
ProcessID:=FProcessEntry32.th32ProcessID;
TerminateProcess(OpenProcess(PROCESS_TERMINATE,false,ProcessID),1);//结束
s:='';
end;
Ret:=Process32Next(FSnapshotHandle,FProcessEntry32);
end;
end;

 
出现这样的问题是因为你第一次打开已经存在的excel,并把数据导出到该文件中后并没有关闭这个文件,而第二次再打开同一个excel文件时,发生了文件打开时的共享锁错误。因此,你需要在打开excel文件前进行判断,是否该文件已打开。具体方法如下:
调用Windows API 提供的函数FindWindow,可以在应用程序启动时检查自己是否已经存在。
该函数在Delphi中的语法是:

function FindWindow(lpClassName: PChar, lpWindowName: PChar): HWND;

其中,参数lpCalssName 是要查找的窗口的类的名称,参数lpWindowName是要查找的窗口的标题(Caption)。 如果找到了相应的窗口实例,将返回一个非0 的该窗口句柄的整型值,否则返回0 。因此,只要判断应用程序的主窗口(或者伴随着应用程序存在而存在的窗口)是否存在就可以判断是否已经有实例存在了。

例如:

H := FindWindow('TForm1', nil);

if H = 0 then begin

ShowMessage('没有发现相同的应用程序实例。');

//加入加载应用程序的语句

//...

end else begin

ShowMessage('应用程序已经加载。');

SetActiveWindow(H);

end;

其中,参数lpWindowName的位置以Delphi保留字nil 代替,是因为窗口的标题可能在应用程序中是变化的。Windows API 函数SetActiveWindow 用于指定活动窗口。
 
还有一个方法是:
利用Windows API函数:OpenFile函数或CreateFile函数判断文件共享锁定状态
1. OpenFile函数使用说明
函数原型:function OpenFile(const lpFileName: LPCSTR; var lpReOpenBuff: TOFStruct;
uStyle: UINT): HFILE; stdcall;
函数功能:以不同方式打开文件的操作(为兼容16位Windows程序保留的函数)。建议
Windows下使用CreateFile函数。
参数说明:lpFileName: 要打开文件的名称
lpReOpenBuff: 变量指针,用于存储文件被首次打开时接收信息。
UStyle: 打开文件的常量类型。
常量名
意义

Of_Create
创建文件

Of_Delete
删除指定文件

Of_Exist
打开文件以验证其存在否?存在,返回一无效句柄;否则,返回负数

Of_Parse
填充lpReOpenBuff内容,但不进行任何操作

Of_Prompt
如存在不存在,则显示一有重试和取消按钮的消息框

Of_Read
只读方式打开

Of_ReadWrite
读写方式打开

Of_ReOpen
打开lpReOpenBuff内指定的文件,而不依据lpFileName

Of_Search
强迫Windows查找文件---即使指定了文件路径

Of_Share_Compat
文件可由多个程序多次打开

Of_Share_Deny_None
共享打开

Of_Share_Deny_Read
禁止其它程序读该文件

Of_Share_Deny_Write
禁止其它程序写该文件

Of_Share_Exclusive
独占方式打开文件,其它程序不得再打开该文件

Of_Write
只写方式打开

 
返回值:成功,返回值为文件句柄(但可能无效,如:Of_Exist);出错,返回HFile_Error。
2. CreateFile函数使用说明
函数原型:function CreateFile(lpFileName: PChar;
dwDesiredAccess, dwShareMode: DWORD;
lpSecurityAttributes: PSecurityAttributes;
dwCreationDisposition, dwFlagsAndAttributes: DWORD;
hTemplateFile: THandle): THandle; stdcall;
函数功能:以不同方式打开文件的操作,还可操作管道、邮槽、通信服务、设备以及控
制台等。
参数说明: lpFileName: 要打开文件的名称
dwDesiredAccess:期望存取模式
取值 0:只允许获取一个设备的相关信息。
Generic_Read:只允许读设备
Generic_Write:只允许写设备(二者可组合使用)。
dwShareMode:共享模式。
取值 0: 不共享。
File_Share_Read和/或File_Share_Write:共享读和/或写。
lpSecurityAttributes: 定义文件安全特性的指针(前提:操作系统支持)。
DwCreationDisposition: 打开和创建文件方式。
取值 Create_New: 总创建新文件,如文件已存在,则出错。
Create_Always: 总创建新文件(会覆盖旧文件)。
Open_Existing: 打开已存在的文件,若文件不存在,则出错。
Open_Always: 总打开文件,如不存在,则创建。
dwFlagsAndAttributes: 要打开文件的标志和属性(如:隐藏,系统等)。
一般用File_Attribute_Normal,默认属性。
hTemplateFile::模板文件句柄。
若非0则指定一个文件句柄;否则,新文件将从这个文件复制
扩展属性。
返回值:成功,返回值为文件句柄;出错,返回Invalid_Handle_Value。

3。程序实现
利用上述两个函数,我们可编写程序判断某文件是否正在被其它进程锁定,以下为详细代码。
//利用OpenFile Api函数判断
function FileLocked(Fn: string): Boolean;
var
I : Integer;
Struct: TOfStruct;
Style: Cardinal;
Hdl: Hfile;
Drive: String;
begin
Style := OF_Share_Exclusive; //排它方式打开
Drive := UpperCase(Fn[1]);
Struct.fFixedDisk := Ord(Drive <> 'A'); //判断是否是硬盘
Struct.cBytes := SizeOf(Struct);
For I := 1 to Length(Fn) do
Struct.szPathName[I-1] := Fn;
Struct.szPathName := Chr(0); //填充文件名
Hdl := OpenFile(Pchar(Fn), Struct, Style);
if Hdl = HFILE_ERROR then
begin
Result := True; //文件被锁定
Showmessage(SysErrorMessage(GetLastError)); //显示错误原因
end
else
Result := False;
end;

//利用CreateFile Api函数判断
function LockedFile(Fn: string): Boolean;
var
AFile: THandle;
SecAtrrs: TSecurityAttributes;
begin
FillChar(SecAtrrs, SizeOf(SecAtrrs), #0);
SecAtrrs.nLength := SizeOf(SecAtrrs); //结构体长度
SecAtrrs.lpSecurityDescriptor := nil; //安全描述
SecAtrrs.bInheritHandle := True; //继承标志
AFile := CreateFile(PChar(Fn), GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_Read, @SecAtrrs, OPEN_EXISTING,
FILE_ATTRIBUTE_Normal, 0);
if AFile = INVALID_HANDLE_VALUE then
begin
Result := True; //文件被锁定
showmessage(SysErrorMessage(GetLastError));
end
else
Result := False;
end;

4。程序的测试
在Delphi中新建一Application,在Form1的OnCreate事件中写入:
if Not FileLocked(‘c:/windows/desktop/a.txt’) then Showmessage(‘Cannot Open 1’);

if Not LockedFile (‘c:/windows/desktop/a.txt’) then Showmessage(‘Cannot Open 2’);
再新建一批处理文件保存到桌面上,内容为:
dir c:/*.*/s>c:/windows/desktop/a.txt’
运行此批处理文件,然后运行上述Delphi程序。这时候会出现消息框“其他进程正使用该文件, 因此现在无法访问。”。当批处理命令运行完毕后,再运行此程序则不会出现此信息。此时,再双击a.txt文档,记事本程序将无法打开该文档,说明加锁成功。

以上用两种方法实现了如何判断一个文件是否正被其它进程锁定。其中,方法一实现较为简单,但兼容性不好;而方法二为Windows推荐的方法,且功能强大。
利用以上实现方法,较好地解决了Windows下文件锁定状态判断的问题。为避免发生共享冲突和提高文件操作程序的健壮性提供了很好的参考依据。
 
上一楼高明,学习中。
 
后退
顶部