VC 操作XLS文件

本人在软件开发过程中遇到了标题所指的问题,在两篇相关讨论(见参考资料【1】【2】)的帮助下,想到了一个不错的解决方法。
 

当我们在程序中使用Excel.Application对象打开xls文件时,通常会使用如下的代码:(以VB为例)

  1. Private xlApp As Excel.Application 声明 Excel 程序对象  
  2. Private xlBook As Excel.Workbook 声明 Excel 工作簿对象  
  3.   
  4. '''''''''''''''''''''''''  
  5. 打开Excel 工作簿  
  6. '''''''''''''''''''''''''  
  7. Private Sub OpenXls()  
  8.     Set xlApp New Excel.Application 创建 Excel 程序对象  
  9.     Set xlBook xlApp.Workbooks.Open("A.xls"打开 Excel 工作簿  
  10.     xlApp.Visible False 设置 Excel 程序不可见(即不出现在任务栏)  
  11. End Sub   
  12.       
  13. '''''''''''''''''''''''''          
  14. '操作Excel 工作簿  
  15. '''''''''''''''''''''''''  
  16. Private Sub OperateXls()  
  17.     xlBook.Worksheets(0).Cells(1, 1) "示例文字"  
  18.     xlBook.Worksheets(0).Cells(1, 1).Font.Color RGB(255, 0, 0)  
  19.    更多其他操作......  
  20. End Sub  
  21.   
  22. '''''''''''''''''''''''''  
  23. '关闭Excel 工作簿  
  24. '''''''''''''''''''''''''  
  25. Private Sub CloseXls()  
  26.     xlBook.Close 关闭 Excel 工作簿  
  27.     xlApp.Quit 退出 Excel 程序  
  28.     Set xlApp Nothing 释放 Excel 程序对象  
  29. End Sub  

在以上程序运行期间,如果没有手动从外部打开xls文件,就不会出现任何问题。但当程序已经打开A.xls时,如果手动打开B.xls文件(跟A.xls没有任何关系),这时A.xls就会出现在任务栏(即使已经设置为不可见)。

 

这时,如果继续运行程序,调用CloseXls(),那么A.xls和B.xls都会被关掉;

         如果手动关闭A.xls,程序就会报错。

 

出现上述问题的原因是,当程序新建一个Excel.Application对象时,实际上在进程中新建了一个系统已经安装的Excel程序的实例(此时进程中会有一个EXCEL.EXE),这其实与手动启动Excel程序(注意,是启动Excel程序,不是打开xls文件)是没有分别的。只不过在程序中可以将Excel 对象设置为不可见。


运行了一个EXCEL.EXE之后,就可以打开xls文件了。在程序中,可以使用xlApp.Workbooks.Open来指定使用哪一个Excel 对象来打开xls文件;而在手动打开xls文件时,系统总是自动查找现有的EXCEL.EXE进程中最后建立的那个,并用它来打开xls文件。如果当前还没有EXCEL.EXE进程运行,系统就会新建一个EXCEL.EXE进程,这就是我们一般双击打开xls文件时的情况。

 

这里需要提到EXCEL.EXE程序的一个特性:一个EXCEL.EXE可以打开多个xls文件。(不信你可以手动打开很多xls文件,然后看看任务管理器里是不是只有一个EXCEL.EXE进程。)有意思的是,当一个EXCEL.EXE打开多个xls文件时,这些xls文件会各自独立出现在任务栏,好像它们源自不同的进程似的,容易给人错觉。

 

知道了这个特性,就可以将问题分为以下两种情况:
(1)先手动打开B.xls文件(系统会自动新建一个EXCEL.EXE进程打开B.xls),再用程序打开A.xls(程序会强制新建一个EXCEL.EXE进程打开A.xls),这两个文件的关闭就不会互相影响(不同的EXCEL.EXE进程)。
(2)先用程序打开A.xls(程序会强制一个EXCEL.EXE进程打开A.xls),再手动打开B.xls(系统会自动使用刚才那个EXCEL.EXE进程打开B.xls),两个文件的关闭就会互相影响(同一EXCEL.EXE进程)

 

问题进一步明晰了,程序打开xls文件之前,手动打开xls文件,不会造成影响;在程序打开xls文件之后,手动打开的xls文件,就会有影响。下一步就是在情况(2)下解决问题了。


现在,我们已经完全了解了这个问题的原理,要彻底解决它,就要加上一点点小聪明了。

上文中有一句话是一个突破口,“在手动打开xls文件时,系统总是自动查找现有的EXCEL.EXE进程中最后建立的那个,并用它来打开xls文件。”
既然系统总是查找现有EXCEL.EXE进程中最后打开的那一个,也就是说只有最后打开的那个EXCEL.EXE进程才会受影响,那么我们能不能在程序中,建立了用来打开xls文件的EXCEL.EXE之后,专门再用程序新建一个EXCEL.EXE,用来屏蔽手动打开xls文件时对前一个EXCEL.EXE的干扰呢?当然能,实现它并不难。

  1. Private xlApp As Excel.Application 声明用来打开xls文件的 Excel 程序对象  
  2. Private xlAppFake As Excel.Application 声明用来屏蔽外部干扰的 Excel 程序对象  
  3. Private xlBook As Excel.Workbook 声明 Excel 工作簿对象  
  4.   
  5. '''''''''''''''''''''''''  
  6. 打开Excel 工作簿  
  7. '''''''''''''''''''''''''  
  8. Private Sub OpenXls()  
  9.     Set xlApp New Excel.Application 创建用来打开xls文件的 Excel 程序对象  
  10.     Set xlAppFake New Excel.Application 创建用来屏蔽外部干扰的 Excel 程序对象  
  11.     Set xlBook xlApp.Workbooks.Open("A.xls"打开 Excel 工作簿  
  12.     xlApp.Visible False 设置 Excel 对象不可见  
  13. End Sub   
  14.       
  15. '''''''''''''''''''''''''     
  16. 操作Excel 工作簿  
  17. '''''''''''''''''''''''''  
  18. Private Sub OperateXls()  
  19.     xlBook.Worksheets(0).Cells(1, 1) "示例文字"  
  20.     xlBook.Worksheets(0).Cells(1, 1).Font.Color RGB(255, 0, 0)  
  21.     更多其他操作......  
  22. End Sub  
  23.   
  24. '''''''''''''''''''''''''  
  25. 关闭Excel 工作簿  
  26. '''''''''''''''''''''''''  
  27. Private Sub CloseXls()  
  28.     xlBook.Close 关闭 Excel 工作簿  
  29.     xlApp.Quit 退出 Excel 程序  
  30.     Set xlApp Nothing 释放 Excel 程序对象  
  31.     If xlAppFake.Workbooks.Count Then  
  32.         xlAppFake.Quit 退出 Excel 程序  
  33.         Set xlAppFake Nothing 释放 Excel 程序对象  
  34.     End If  
  35. End Sub  

程序打开A.xls之后,正在对其进行读写操作时,如果双击打开B.xls,系统就用使用xlAppFake所指的EXCEL.EXE打开B.xls,这样两个文件的关闭就互不影响了。
程序运行在最后,也要关闭和回收xlAppFake,否则进程中会留下一个EXCEL.EXE,而且没运行一次程序,进程中便会多一个EXCEL.EXE。
但是,如果直接将xlAppFake关闭的话,也是不妥的,因为外部某个xls文件是用xlAppFake所指的EXCEL.EXE打开的。
因此,需要判断xlAppFake此时是否还有文件打开,如果没有,再关闭。

 

 

参考资料:

【1】http://topic.youkuaiyun.com/u/20080506/18/1e995e5e-eb61-483f-ab64-9138403a5836.html?seed=1604491313


【2】http://topic.youkuaiyun.com/t/20040814/13/3274124.html



   转自:http://blog.sina.com.cn/s/blog_80b4f5d10100v2h8.html


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值