摘 要: 讲述了在建立数据库和SQL查询的基础上,使用程序方法访问数据库中的表和查询,同时引用电子表格文件作为对象,对其进行自动填写的思路和实现方法。将该方法与电子表格内嵌公式和程序的传统方法进行了对比。最后使用该方法实现了对机场气候表的自动填写。
关键词: 电子表格; 数据库访问; Excel引用; 民航气象
制作填写电子表格在今天已是一项非常常见的工作了。很多时候,都需要将手头的数据统计汇总填写成表格样式以供阅读和报告。为了完成复杂一些的功能,需要在电子表格中嵌入公式和程序代码,以减少人工的工作量,并减少错误的发生,提高工作效率[1-2]。鉴于Microsoft Excel电子表格软件的强大功能,它基本成为电子表格的代名词,因此,以下主要以Excel为例进行讨论。
然而,在Excel表格中嵌入公式和程序代码(经常也被称为宏)会带来一些其他的问题。例如运行效率不高,在代码比较多时,会使电子表格文件变得很大,不利于发布和交换等。
1 电子表格中嵌入公式和程序代码的不足
内嵌公式和程序代码的电子表格有它的好处,首先不需要安装任何软件,交换文件的同时就相当于交换了程序。然而,表数量多、代码量较大时,就会存在下面的不足:(1) 电子表格文件变大
虽然简单的代码不会造成这种情况,或者说无关紧要,但当需要完成的计算和填写代码很多(往往表格只有几百千字节的文件,加上代码后就会有几兆字节)时,对交换和保存这类表格文件显然不利。
(2) 嵌入代码不利于使用
当电子表格制作完成,就会将其文件用于发布和交换。这时大多数使用文件的人都是非专业人员,一旦打开文件时提示是否启用宏时,他们往往会不知所措;另一方面,启用内嵌代码可能被人利用,增加恶意代码,造成真正对计算机的危害;最后,内嵌的公式往往效率不高,其计算结果不易使用。
(3) 开发、调试困难
少量的程序代码不会存在这样的问题,但当代码很多时,就会发现Excel内嵌的那个VBA功能不够,调试也不方便,完全无法与Visual Studio这样的开发工具相提并论,使得效率大大下降,今后的维护也十分困难。
2 另一种填写电子表格的思路
大多数时,发布和交换电子表格只是作为一种可视化的资料保存或查阅,这时内嵌的公式和程序代码就成了负担。因此,考虑另一种思路,将电子表格只是作为模板,不使用内嵌的公式或程序代码进行统计计算,在数据库中使用SQL查询进行统计、计算,另外编写程序访问数据库中的查询,在程序中引用电子表格文件作为对象,将查询结果填写到电子表格文件中。两种方式的对比如图1所示。
3 电子表格自动填写的实现
如上所述,需要分三步实现,首先要制作最终的输出表格,之后需要建立好数据库,并在数据库中建立SQL查询以完成主要的统计计算;最后编写程序访问数据库,并引用电子表格文件进行自动填写。
3.1 模板中表格一致性的程序实现
首先设计表格的样式,如果有类似的表格只需要复制后稍加修改即可。然而,经验表明,往往在调试程序时,还需要更改表格中的样式,这时又要进行前述的重复工作,这种工作在程序开发和调试过程中还要反复进行。因此,宜使用程序来对表格的样式进行修改。
以Visual Basic 2008为例,要访问电子表格文件,需在工程中添加引用COM中的Microsoft Excel,并选中命名空间Microsoft.Office.Interop(若存在的话)。示例1过程更改电子表格文件中的全部表显示大小为100%,更改每个表第一行单元格格式为合并居中并自动缩小字体填充,显示一位小数。
示例代码1:
Sub RegSheets()
Dim a As New Excel.Application
Dim b As Excel.Workbook = a.Workbooks.Open
(“电子表格的文件名”)
For Each sht As Excel.Worksheet In b.Sheets
sht.Activate()
‘不能省略,Excel仅对活动工作表操作
a.ActiveWindow.Zoom = 100
s= "A1:" & Chr(64 + sht.UsedRange.Columns.
Count) & "1"
a.Range(s).Select()
With a.Selection
.HorizontalAlignment = xlCenter ‘水平居中
.VerticalAlignment = xlCenter ‘垂直居中
.WrapText = False ‘取消自动换行
.ShrinkToFit = True
‘设置为自动缩小字体填满
.NumberFormat = ”0.0” ‘显示一位小数
.MergeCells = True‘合并第一行使用的单元格
End With
Next sht
b.SaveCopyAs("副本文件名")
b.Close(False)
a.Quit()
End Sub
只需对以上过程稍加修改并调用一次就可以完成其他所需格式修改,当需要对大量表格更改格式时,这样比人工修改格式大大提高了效率,减少了错误。
3.2 数据库设计
原始数据不仅仅是数字,还包括文本记录,这种混合数字和文本的数据在数据库中是很难使用查询进行统计的,而且会大大降低查询的效率。因此,首先要考虑对原始数据进行合理的解析,其目的在于将文本中数字混合的原始数据转换为数据库中的数值记录了[3]。之后将统计计算以SQL命令也放在数据库中,这样可以充分利用数据库的优势,减少程序代码的开发和调试[4]。以Microsoft Access数据库为例,若统计一个简单的气温记录表(年,月,日,小时,T)可使用一个查询:
SELECT 月, Avg(T) AS 月平均, Max(T) AS 月最高气温, Min(T) AS 月最低气温
FROM 气温记录表
WHERE 年≥起始年and年≤终止年
GROUP BY 月
将这一查询命名为sMonthT,则其关系模式为:
sMonthT(月, 月平均, 月最高气温, 月最低气温)
该查询统计起始年到终止年间的月气温平均、月最大、月最小值。显然在程序中调用该查询比在程序代码中计算要简单得多。
3.3 电子表格的自动填写
前面已经设计好了表格和数据库,为在程序代码中填写表格,需要调用数据库和电子表格文件,示例2将上面数据库查询结果各月份的最高气温填写在不同表的第一行、第一列中。
示例代码2:
Sub Fill(ByVal DBFilename As String, ByVal b As Excel.Workbook, ByVal YearFrom As Long, ByVal YearTo As Long)
Dim cn As New Data.OleDb.OleDbConnection
Dim dc As New Data.OleDb.OleDbCommand
Dim m As String
Dim t As single
cn.ConnectionString = ("Provider=Microsoft.Jet.OLEDB.
4.0;Data Source=" & DBFilename)
cn.Open()
dc.CommandText = "SELECT * FROM sMonthT"
dc.Connection = cn
dc.Parameters.Add("起始年", Data.OleDb.OleDbType.
Integer, 4).Value = YearFrom
dc.Parameters.Add("终止年", Data.OleDb.OleDbType.
Integer, 4).Value = YearTo
Dim dr As OleDb.OleDbDataReader
dr = dc.ExecuteReader()
While dr.Read()
m= dr.GetValue(dr.GetOrdinal("月")).ToString
t = dr.GetValue(dr.GetOrdinal("月最高气温"))
b.Worksheets(m & "月").Cells(1, 1).value = t
‘使用表名访问不同的表
End While
dr.Close()
cn.Close()
End Sub
示例中,使用数据库OleDbConnection对象连接数据库,使用OleDbCommand对象访问数据库中的查询,使用OleDbDataReader对象读取查询结果。由于前面数据库查询中有类似“起始年”、“终止年”这样的参数,因此需要在OleDbCommand对象中添加Parameter。对于多个表,可以使用表名称来区分。
4 应用与实践
在实际中遇到了机场气候统计的问题,按照要求气候统计结果需要输出26类106张表,仅这些表形成的电子表格文件大小就约为1.2 MB,而完成数据统计填写的全部程序源代码合计约有2 MB。若将代码嵌入电子表格,得到的电子表格文件将会超过3 MB。
通过上面的思路和方式,将程序代码独立出来,另外在数据库中建立了19个表和202个查询用于统计计算。由于程序代码基于.NET Framework,经过编译后的可执行文件大小仅有1 MB左右。这样使得填写输出的电子表格文件大大减小,便于交换和使用;没有内嵌代码的文件,提高了安全性。另一方面,编译过的代码显然比内嵌公式和源代码有更高的运行效率,独立的代码也便于后期的维护工作。最后,建立在数据库内的查询非常容易使用,为今后的其他应用奠定了基础。
参考文献
[1] 张庆丰.三种Excel访问oracle数据库的方法比较[J].计算机系统应用,2004(12):64-66.
[2] 杨振宇,杨海智,杨信东.用Excel中的VBA编写卡方测算相关程序[J].微型机与应用, 2012,31(19):18-20.
[3] 韩金涛.民航气象观测数据库的建立及应用[J]. 民航科技,2011,147(5):110-112.
[4] ULLMAN J D, WIDOM J著.数据库系统基础教程[M].史嘉权,译.北京:清华大学出版社,1999.