Office中国论坛/Access中国论坛

标题: access子报表难题 [打印本页]

作者: lmj9401    时间: 2012-7-2 18:39
标题: access子报表难题
在access中有表mdata、主报表mrpt和子报表srpt,表mdata有名称和颜色2个字段,如下所示:

+=====+====+
|名称 |颜色|
+=====+====+
|苹果 |红色|
+-----+----+
|香蕉 |黄色|
+-----+----+

其中,主报表mrpt的报表页眉区中有2个子报表控件Child0和Child1,它们的源对象(数据来源)都是子报表srpt;子报表srpt的报表页眉区有1个文本框控件,控件来源为“颜色”。

现需动态改变子报表srpt的记录源,使得控件Child0的子报表的记录源为查询:select 颜色 where 名称="苹果",控件Child1的子报表的记录源为查询:select 颜色 where 名称="香蕉"。这样在主报表mrpt通过控件Child0和Child1可以同时看到显示“红色”和“黄色”,应该如何实现?
作者: lmj9401    时间: 2012-7-2 18:44
查询写错了,应该是:select 颜色 from mdata where 名称="苹果"
作者: lmj9401    时间: 2012-7-4 10:53
在主报表中使用2个子报表控件来显示查询内容,其中2个子报表控件都链接到一个报表srpt上。

我的想法是希望通过更改报表srpt的记录源(SQL语句)来实现在2个子报表控件中显示不同的查询结果,或者使用筛选(filter),能达到目的就行。

我有一个初步想法,就是对报表srpt记录源的SQL语句参数化,将SQL改写为:select 颜色 from mdata where 名称=reports!mrpt!child0.tag,这样只需要更改子报表控件child0的tag属性就可以实现动态查询。

遗憾的是这样做对子报表控件child1毫无用处!因为在子报表控件child1中也是按child0.tag查询的,结果2个子报表控件显示的结果是一样的。

下面是一个错误的报表srpt记录源:
select 颜色 from mdata where 名称=parent.tag
虽然是错误的,但是却很好体现了我的想法,在child0中按child0.tag查询,在child1中按child1.tag查询,这样通过设置2个子报表控件的tag属性来实现显示不同的内容。

问题是,正确的该怎么做,求教?!
作者: lmj9401    时间: 2012-7-4 10:54
此问题的关键在于,我无法在子报表srpt中获得它的parent(child1或child0)。

经过我的测试,子报表srpt的parent居然是主报表mrpt,这是不能接受的,无益于解决问题。

不知道有什么办法能够准确知道子报表srpt的父容器(child1或child0)究竟是哪一个?


作者: Henry D. Sy    时间: 2012-7-4 11:06
传例子吧,然后说明你要达到什么样子的结果!
作者: windymeng    时间: 2012-7-4 11:18
学习学习

作者: lmj9401    时间: 2012-7-4 19:17
本帖最后由 lmj9401 于 2012-7-4 19:34 编辑

mdb文件:[attach]49571[/attach]

说明:
1. access数据库中有表mdata、主报表mrpt和子报表srpt;mrpt的报表页眉区中有2个子报表控件Child0和Child1;srpt的报表页眉区有1个文本框控件Text0。
2. Child0和Child1的源对象都是“报表.srpt”;Child0的tag属性是“苹果”,Child1的tag属性是“香蕉”。
3. srpt的记录源是“SELECT 颜色 FROM mdata WHERE 名称=Reports!mrpt!child0.Tag”。
4. Text0的控件来源是“颜色”。

目的:在主报表的同一个页面上根据不同查询条件显示多个查询结果,由于子报表的记录源(SQL)仅查询条件不同,所以不考虑使用多个子报表分别实现这些查询。

期望实现:Child0的子报表执行查询“SELECT 颜色 FROM mdata WHERE 名称=Reports!mrpt!child0.Tag”,Child1的子报表执行查询“SELECT 颜色 FROM mdata WHERE 名称=Reports!mrpt!child1.Tag”。

期望结果:
[attach]49572[/attach]

另:如果Child0和Child1的源对象指定为SQL查询,可以很容易得到正确结果,遗憾的是无法对输出的数据格式化。

作者: lmj9401    时间: 2012-7-4 19:30
本项目需要解决一个核心问题:如何在子报表中正确获得链接到该报表(即以该报表为数据源)的子报表控件的的名称。
作者: roych    时间: 2012-7-4 21:13
楼主在开玩笑吧?怎么可能循环引用呢?
作者: lmj9401    时间: 2012-7-5 07:57
怎么可能循环引用呢,只是引用包含子报表的父控件(parent)而已。

实际上,子报表的parent在access中被指定为父报表(主报表),而并非容纳该子报表的控件。
作者: lmj9401    时间: 2012-7-5 08:07
绝对不可能构成循环引用,只是引用子报表的parent控件(包含子报表的控件)而已。

access子报表的实际parent是父报表,而不是包含该报表的控件,这是一个非常奇怪的设定。
作者: roych    时间: 2012-7-5 23:19
lmj9401 发表于 2012-7-5 08:07
绝对不可能构成循环引用,只是引用子报表的parent控件(包含子报表的控件)而已。

access子报表的实际pa ...

新建一个子报表,指定数据源就好了。效果如下:
[attach]49586[/attach]
不过,恕我愚钝,我实在看不出这样的嵌套报表的实际意义在哪里。
1、记录较多的时候,得根据记录不断地创建子报表,这听起来不像是什么好事。
2、从效果上来说,普通报表稍稍格式化一下完全可以实现。
3、如果想舍近求远的话,也可以通过ADO读取记录集,逐条写入子报表的控件中。
[attach]49585[/attach]
作者: lmj9401    时间: 2012-7-6 14:54
使用多个子报表,当然可以实现,也就没有前面的问题了。我们讨论的其实是一个技术问题,并非项目本身。

如果在同一报表页面上要显示几个查询结果,就要创建几个子报表,而这些报表的仅查询条件不同,显然不是一个好方案。例如,一个页面上要根据100个不同的查询条件显示100个结果,就要定制100个子报表,这多少就有些“傻气”了。

access中未使用过ado,不敢多说,“舍近求远”这个说法我还是比较赞同。

“从效果上来说,普通报表稍稍格式化一下完全可以实现”,愿闻其详。


作者: roych    时间: 2012-7-8 05:14
lmj9401 发表于 2012-7-6 14:54
使用多个子报表,当然可以实现,也就没有前面的问题了。我们讨论的其实是一个技术问题,并非项目本身。

...

这是同一个字段的不同记录,即便按向导完成也是没问题的(ADO就显得有些绕了)。
就子报表而言,个人认为不必多层嵌套(尽管可以嵌套三~四层)。如果需要显示统计方面的,很多域函数是可以实现的,又或者在子报表页脚处设置文本框计算好然后再引用到主报表上都行得通。
作者: lmj9401    时间: 2012-7-8 11:38
感谢,按常规做法最大的问题就是难以实现自由的数据格式化。
作者: t小宝    时间: 2012-7-8 21:13
子报表是可以知道自己在主报表的哪个子报表控件中的,子窗体也一样,这个以前研究过,
你的例子中在子报表的打开事件中输入以下代码即可:
  1.     Dim ctr As Control

  2.     For Each ctr In Me.Parent.Controls
  3.         If ctr.ControlType = acSubform Then
  4.             If ctr.SourceObject = "报表." & Me.Name Then
  5.                 If Nz(ctr.Report.RecordSource) = "" Then
  6.                     Me.RecordSource = "SELECT 颜色 FROM mdata WHERE 名称='" & ctr.Tag & "'"
  7.                     Exit Sub
  8.                 End If
  9.             End If
  10.         End If
  11.     Next
复制代码

作者: lmj9401    时间: 2012-7-11 15:52
t小宝 发表于 2012-7-8 21:13
子报表是可以知道自己在主报表的哪个子报表控件中的,子窗体也一样,这个以前研究过,
你的例子中在子报表 ...

这个想法非常棒,但是我发现“Each ctr In Me.Parent.Controls”扫描控件的顺序一定要与子控件的初始化顺序一致才能成功。否则可能访问到一个还没有初始化的子报表控件,引用“ctr.Report.RecordSource”会失败,如图所示:
[attach]49642[/attach]
如果无法确定上述顺序,那么这段代码具有潜在的风险。
作者: t小宝    时间: 2012-7-11 20:35
lmj9401 发表于 2012-7-11 15:52
这个想法非常棒,但是我发现“Each ctr In Me.Parent.Controls”扫描控件的顺序一定要与子控件的初始化顺 ...

忘记复制一行错误处理的代码:
On Error Resume Next

前面加上这句就没问题了。
作者: lmj9401    时间: 2012-7-11 21:57
感谢t小宝,问题已解决!{:soso_e181:}




欢迎光临 Office中国论坛/Access中国论坛 (http://www.office-cn.net/) Powered by Discuz! X3.3