计算机世界1999年第1期
利用OLE自动化解决ACESS97中文版
报表生成器直线不能往下顺延的缺陷
总参通信工程设计研究院外五室 王 涛
ACCESS97 是 一 个 非 常 优 秀 的 数 据
库 软 件, 它 不 仅 能 充 当 办 公 自 动 化 的 桌 面 数 据 管 理 工
具, 也 是 一 个 开 发Client/Server 产 品 的 优 秀 前 端 开 发 工 具. 它
的 特 点 是 易 学 易 用、 工 具 丰 富、 不 需 写 大 量 代 码 就 可
以 在 很 短 的 时 间 内 开 发 出 界 面 优 美 且 功 能 强 大 的 系
统, 长 期 以 来 受 到 广 大 开 发 者 的 青 睐。 但 笔 者 在 使 用
时 发 现 其 报 表 生 成 器 中 有 一 个 明 显 不 适 合 我 国 国 情
的 缺 陷, 就 是 当 设 置 报 表DETAIL 节 上 的 字 段 长 度 因 为 横
向 空 间 不 够 而 设 为 自 动 向 下 顺 延(Can Grow 属 性 为True)
时, 如 果 字 段 旁 有 竖 线( 国 内 大 部 分 公 文 报 表 都 有 竖
线, 而 国 外 则 很 少 有), 则 竖 线 不 能 和 字 段 一 起 向 下
顺 延。 使 整 个 报 表 看 起 来 不 美 观。 这 个 缺 陷 在ACCESS2.0 和ACCESS97
中 文 版 上 都 有, 而 在FoxPro2.5B/3.0/5.0 下 却 没 有。 据 微 软 技 术
服 务 部 的 工 作 人 员 说 是 由 于 本 地 化 时 测 试 不 够 原 因
所 致。 为 此, 笔 者 在ACCESS 内 采 用 了OLE 自 动 化 方 法, 将ACCESS97
查 询 生 成 的 表 送 交EXCEL97 进 行 处 理( 分 类 汇 总、 打 印、
预 演), 较 好 地 解 决 了 这 个 问 题。 由 于ACCESS97 和EXCEL97 的VBA
在97 版 本 上 几 乎 完 全 兼 容, 在EXCEL97 下 录 制 的 宏 代 码 只
需 在ACCESS 下 稍 加 修 改 就 行 了, 所 以 采 用 此 方 法 和 用 内
部 报 表 生 成 器 设 计 所 用 的 时 间 差 不 多。 整 个 工 作 需 要
下 面 几 步:
1 . 在EXCEL97 下 设 计 好 报 表 的 样 式, 包 括 表 头、 页
眉、 页 码 等, 对 需 要 自 动 翻 转 的 列, 在" 单 元 格 格 式
设 置" 下 设 为" 自 动 换 行"。
2 . 在EXCEL97 下 录 制 好 当 数 据 送 入 后 进 行 的 操 作 宏(
如 分 类 汇 总、 加 边 框 线, 加 空 行、 打 印 输 出、 预 演 等
动 作)。
3 . 在ACCESS 下 用VBA 语 句 和DAO 对 象 的 方 法 将 数 据 送 入EXCEL
表 内, 并 将EXCEL 下 宏 操 作 变 成ACCESS 下 的 语 句。
以 下 是ACCESS97 下 的 程 序 代 码, 实 际 应 用 程 序 界 面 是
一 个 对 话 框 屏 幕(FORM), 上 面 有 五 个 下 拉 框(Comb_) 和 一 个 文
字 框(Text), 由 用 户 选 择 相 应 的 信 息, 然 后 用 户 按"
确 定" 命 令 按 钮 执 行 程 序。 其 中 有 些 属 性 和 方 法 在ACCESS2.0
下 不 能 使 用, 可 采 用 相 应 的 语 句.
Private Sub确认_Click()
On Error GoTo ErrorHandler
Dim stDocName As String
Dim k As Integer
stDocName = "Pqry_YEAR"
DoCmd.OpenQuery stDocName '从原始表内根据
用户输入的信息条件运行"生成表查询",生成一个供打印用的表.
'增加空记录处理--为了保证记录数少时也打印整张表.
If Val(Me![Comb空行]) > 0 Then '
如果用户输入了大于0的数值,表示加空行
For k = 1 To Val(Me![Comb空行])
CurrentDb.Execute "INSERT INTO
Pqry_YEAR (项目类) VALUES ('空行空行空行');"
Next k
End If
Dim msgVar As Integer
'定义EXCEL对象变量
'------------------------------
Dim xlobj As Object
Dim xlsheetobj As Object
Dim xlrange As Object
'------------------------------
'定义ACESS记录集对象变量
Dim dbs As Database, rst As Recordset
Dim strSQL As String
Dim recTotal, fieldTotal As Integer ' recTotal:
表示该表内记录总数; fieldTotal表示字段总数
Dim i, j As Integer
i = 0
j = 0
' Return reference to current database.
Set dbs = CurrentDb '当前数据库
Set rst = dbs.OpenRecordset("Pqry_YEAR ") '选择记录集
recTotal = rst.RecordCount '得出记录数
fieldTotal = rst.Fields.Count '得出字段数
'----------------------------------
'建立EXCEL对象
Set xlobj = CreateObject("Excel.Application.8")
'打开设计好的EXCEL表--REPORT.XLS
xlobj.Workbooks.Open FileName:=pPathname & " REPORT.xls"
Set xlsheetobj = xlobj.ActiveWorkbook.
Worksheets("REPORT ") '指向工作表
'如果是改动过的表,不再打开
If MsgBox("当前打印表格文件中
已有数据,是否需要更新?" & Chr(13) & _
"提示:只有对数据进行改动后,才需要更新.", 68) = vbYes Then
DoCmd.Hourglass True '由于时间较长,将鼠标设为沙漏形状
xlsheetobj.Rows("5:200").Select '选定区域
xlobj.Selection.Delete Shift:=-4162 '注意!
原录制宏中-4162为xlnone,是EXCEL97的常量,但在
ACCESS下却不认,只能到EXCEL下的对象浏览器去查询对应的常数.
'开始向EXCEL传送数据
Do Until rst.EOF
For j = 1 To fieldTotal
xlsheetobj.cells(5 + i, j).Value = rst.Fields(j - 1)
Next j
rst.MoveNext
i = i + 1
Loop
rst.Close
'在EXCEL中调整,具体常数参见EXCEL下的对象浏览器
xlsheetobj.Range("A4:Q" &
Trim(Str(recTotal + 4))).Select '选定范围
'以下为设置边框线录制的宏代码,已删除了相似的语句.
xlobj.Selection.Borders(5).LineStyle = -4142
xlobj.Selection.Borders(6).LineStyle = -4142
With xlobj.Selection.Borders(7)
.LineStyle = 1
.Weight = -4138
.ColorIndex = -4105
End With
With xlobj.Selection
'确定是合计在表上还是在表尾
If Me![Fram位置] = 1 Then
.Subtotal GroupBy:=2, Function:=-4157,
TotalList:=Array(6, 9, 10, _
11, 12, 13, 14, 15, 16),
Replace:=True, PageBreaks:=False, _
SummaryBelowData:=False
Else
.Subtotal GroupBy:=2, Function:=-4157,
TotalList:=Array(6, 9, 10, _
11, 12, 13, 14, 15, 16),
Replace:=True, PageBreaks:=False, _
SummaryBelowData:=True
End If
End With
'根据用户的选择设置页眉和页尾。
With xlsheetobj.PageSetup
.LeftHeader = "" & Chr(10) & "" & Chr(10) & "
" & Mid(Me![Cmbo单位], 4)
.CenterHeader = "&""宋体,加粗""&18 " &
Me![Cmbo年度] & "年" & Mid(Me![Cmbo类别], 4) & "XXX表"
End With
xlsheetobj.Range("A1").Select
'将空行内容清掉
k = Val(Me![Comb空行])
If Val(Me![Comb空行]) > 0 Then
Dim content As String
i = 5
content = xlsheetobj.cells(i, 2).formulaR1C1
Do While InStr(1, content, "空行空行空行") = 0
i = i + 1
content = xlsheetobj.cells(i, 2).formulaR1C1
Loop
xlsheetobj.Range("B" & Trim(Str(i - k + 5))
& ":" & "Q" & Trim(Str(i + 5))).Select
xlobj.Selection.ClearContents
xlsheetobj.Range("A1").Select
End If
Else '不更新
xlsheetobj.Activate
End If
xlobj.ActiveWindow.SelectedSheets.PrintPreview '预演报表
'如为打印:xlobj.ActiveWindow.SelectedSheets.PrintOut
DoCmd.Hourglass False '恢复鼠标形状
xlobj.Visible = True '让EXCEL可见
清除对象变量空间,节省内存
Set dbs = Nothing
Set xlobj = Nothing
xlobj.quit '关闭EXCEL
Exit Sub
ErrorHandler: '出错处理
DoCmd.Hourglass False
MsgBox "Error number " & Err.Number & ": " &
Err.Description
' Resume with statement following occurrence of error.
Resume Next
End Sub
通 过 这 个 例 子 我 们 看 到 在OFFICE97 下 利 用OLE 自 动 化 扩 展 应
用 程 序 的 功 能 是 多 么 方 便 和 强 大。 用EXCEL 完 成 的 报 表
的 优 点 是 格 式 美 观, 修 改 方 便. 缺 点 是 第 一 次 生 成EXCEL 表
格 时 速 度 较 慢.
本 例 是 用EXCEL 对 数 据 进 行 报 表 操 作, 其 实 也 可 参 照
此 例 的 方 法 在EXCEL 上 建 立 图 形 统 计、 财 务 分 析、 数 据 透
视 表 分 析 等 应 用 程 序, 只 要 在EXCEL 下 录 制 相 应 的 宏, 再
加 到ACCESS 下 就 行 了。