水晶报表 批量预览与打印(续)

Rommen 2009-09-25 04:14:27
批量预览与打印(原帖)
http://topic.csdn.net/u/20090924/12/cb2f6a94-fa0f-40b3-ab6f-dfe101c0579a.html

本来按照阿泰的思路通过子报表做好,结果领导说这个太麻烦,要直接点下一页就显示下个病人的信息,
也就是每页显示一条信息,包括图片
存在的问题:
1.按照领导的要求,我的思路是做个循环,将dataset推给报表
不过发现并没有出现想要的结果,而是后面的数据覆盖掉了前面的,比如两个病人的信息
要求第一页是第一个病人的,第二页是第二病人的,结果只出现了第二个病人的信息,也就是
循环只是不断覆盖前面的,永远只有一条信息

2.尝试了只显示一条数据
通过仔细和反复的修改字段资源管理器里的表联结,详细资料里面还是有多余的一条数据,
,如果用公式控制重复信息的话,那么有多少个字段就得写多少个公式?
其报表样式如下
----(详细资料)-----
姓名:张三 性别:男 出生日期:`1975-08-18
pic1(无图片) pic2(无图片) pic3(无图片)
姓名:张三 性别:男 出生日期:`1975-08-18
pic1(有图片) pic2(有图片) pic3(有图片)
----(详细资料)-----
这里第一条数据重复了,并且图片都不显示了,第2条数据倒是完整的

附:为了显示图片,我手动建立了一个dataSet来映射本地图片,并将其在字段资源管理器与数据库三张表关联,
关系都手动添加好了, 怀疑是否是手动添加里面的table引起的重复
参考了阿泰的图片添加一文

接触报表时间较段,大家不要见笑,阿泰,向您及各位大大寻求帮助.
...全文
634 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
Rommen 2009-09-27
  • 打赏
  • 举报
回复
13楼第一个图说明这两个表是在一个dataset里的
13楼第二个图的数据库专家里说明这两个表用是在两个dataset里。

我觉得出现一条空白信息就是这里引起的, 因为作了一次映射,所以如果将字段拖入详细资料里面
无论如何都会出现两条数据,只能这么理解了,我尝试了10来中链接都是这样的结果,
去掉dataTalbe1就问题了,不过图片就实现不了这功能了

只有一种笨办法,就是数据库单独写张存放图片的表,每当需要打印的时候将本地图片存入数据库中,
打印后再清空数据库,这样就不会出现多数据源

Rommen 2009-09-27
  • 打赏
  • 举报
回复
嗯,13楼里面两张表,其中UriResult表里面的字段是从数据库里面将图片以及ID字段拖出来的,
dataTable1是作图片映射的容器,也就是说数据库本身不存储图片.
代码能够实现单条数据的显示,关键是不能将显示的字段和图片拖入详细资料里面,否则有一条重复数据

测试代码实现如下:(比较乱)

private void frmAveCrystalReport_Load(object sender, EventArgs e)
{
string[] uriSampleID = new string[2];
uriSampleID[0] = "20090911010001";
uriSampleID[1] = "20090911010002";

for (int j = 0; j < 2; j++)
{
//连接数据库
string myConn = "Data Source=(local);Initial Catalog=AVE661;Integrated Security=True;Initial Catalog=AVE661";
string mySQL = "SELECT * FROM UriResult WHERE UriSampleID='" + uriSampleID[j] + "'";
SqlConnection myConnection = new SqlConnection(myConn);
SqlDataAdapter myDataAdapter = new SqlDataAdapter(mySQL, myConnection);
myConnection.Open();

//将数据放入DataSet中
AveDataSet ds = new AveDataSet();
DataSet allDataSet = new DataSet();
myDataAdapter.Fill(ds, "UriResult");
myDataAdapter.Fill(allDataSet, "UriResult");

//从数据集得到镜检ID
string bt1 = ds.Tables[0].Rows[0][0].ToString();

//从数据集得到镜检日期
DateTime bt2 = Convert.ToDateTime(ds.Tables[0].Rows[0][1]);

//从数据集得到图片路径
string btPicRoute = allDataSet.Tables[0].Rows[0]["PrintImage"].ToString();
//去掉最后的","号
btPicRoute = btPicRoute.Substring(0, btPicRoute.Length - 1);
string[] getPath = btPicRoute.Split(',');
for (int i = 0; i < getPath.Length; i++)
{
if (getPath[i] != "")
{
getPath[i] += ".jpg";
}
}

//初始化ArrayList
ArrayList btList = new ArrayList();
for (int i = 0; i < 6; i++)
{
btList.Add(i);
}
//根据数据库图片路径将本地图片转换成二进制
for (int i = 0; i < getPath.Length; i++)
{
if (getPath[i] != "")
{
FileStream fs = new FileStream(getPath[i], FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
byte[] bt = br.ReadBytes((int)fs.Length);
btList.Insert(i, bt);
fs.Close();
}
}
//将6副二进制图片放入DataSet数据集中
if (getPath.Length == 6)
{
ds.UriResult.AddUriResultRow(bt1, bt2, (byte[])btList[0], (byte[])btList[1], (byte[])btList[2], (byte[])btList[3], (byte[])btList[4], (byte[])btList[5]);
AveRptUri5 oRpt = new AveRptUri5();
//使用Report Engine对象模型,将此数据集传递给报表
oRpt.SetDataSource(ds.Tables[0]);
//将带有数据的报表对象绑定到水晶报表查看器
crystalReportViewer1.ReportSource = oRpt;
//设置默认打印纸张大小
oRpt.PrintOptions.PaperSize = CrystalDecisions.Shared.PaperSize.PaperA4;
}
myConnection.Close();
}
}
阿泰 2009-09-27
  • 打赏
  • 举报
回复
这对于报表来说是一个多数据源的操作。我倒还真没这么做过,呵呵。
一般我都会把数据Fill到一个dataset里去。

从12楼的关系上看没什么问题
但是13楼我就看不明白了。

上面的一个图说明这两个表是在一个dataset里的
而下面的数据库专家里说明这两个表用是在两个dataset里。

其实你的表都可以放到一个dataset里的,这样可能更清晰些。

不过按你现在的做法,你的代码上是怎么写的呢
Rommen 2009-09-27
  • 打赏
  • 举报
回复

映射数据库,因为数据库没有图片,图片是本地的


数据库专家里的表链接
Rommen 2009-09-27
  • 打赏
  • 举报
回复
嗯,好的

DataTable1->UriResult->SickInfo->ChemResult
两个字段确定一条数据

http://pd.images22.51img1.com/6000/rommen406/d3f01fe94834eabb97835daa5e915f29.jpg
DateSet 映射数据库,因为数据库没有图片,图片是本地的

http://pa.images22.51img1.com/6000/rommen406/a3db3e3df06767bf69dd62bb73bcf7a8.jpg
数据库专家里

阿泰 2009-09-27
  • 打赏
  • 举报
回复
你能把这个dataset里的表和表关系抓个图看看吗,带结构的
Rommen 2009-09-27
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 babyt 的回复:]
这个你在数据库专家里设置两个表的关联关系就可以了

你这两个应该是一个dataset里的两个datatable吧

注意,关系是在水晶报表里设,不是在dataset里设。
[/Quote]

不是,阿泰,我的dataset里面只放了一个datatable,就是存本地图片的二进制形式,
然后在在水晶报表里设定与该图片datatable的关系,
Rommen 2009-09-27
  • 打赏
  • 举报
回复
说几句心里话~~
感谢您的孜孜不倦的帮助,也感谢关注的朋友们~~
阿泰 2009-09-27
  • 打赏
  • 举报
回复
把最外面一层的for循环拿掉

string mySQL = "SELECT * FROM UriResult WHERE UriSampleID='" + uriSampleID[j] + "'";
改成
string mySQL = "SELECT * FROM UriResult WHERE UriSampleID in (" + 把id组合成一个字串 + ")";

在 myDataAdapter.Fill(allDataSet, "UriResult"); 后面一个循环,遍历这个UriResult,进行图片填充动作

然后把
AveRptUri5 oRpt = new AveRptUri5();
//使用Report Engine对象模型,将此数据集传递给报表
oRpt.SetDataSource(ds.Tables[0]);
//将带有数据的报表对象绑定到水晶报表查看器
crystalReportViewer1.ReportSource = oRpt;
//设置默认打印纸张大小
oRpt.PrintOptions.PaperSize = CrystalDecisions.Shared.PaperSize.PaperA4;

这几行拿出来,放到循环体外,myConnection.Close();这一行的后面
Rommen 2009-09-27
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 babyt 的回复:]
首先肯定一点,不用多数据源肯定是可以实现的
我仔细看了下代码,比较怪。
主要是最外面一个for循环。

uriSampleID[1] = "20090911010002";
覆盖掉
uriSampleID[0] = "20090911010001";
的结果
[/Quote]

阿泰,最后一个问题,就是这个循环,这里我用了两条数据测试,发现会覆盖掉原来的,
水晶报表并不会自动在第2页添加
阿泰 2009-09-27
  • 打赏
  • 举报
回复
其实。。你这个多数据源根本没用上,呵呵。

你用的只是最初的那个uriResult。其余的表根本没用到。

这样的话,其实你的模板上似乎应该只需要这一个独立的表就可以了。
当然,因为我看不到报表,可能你报表上还有很多其他元素。

不过,解决了问题就是最好了 :)
Rommen 2009-09-27
  • 打赏
  • 举报
回复
阿泰,搞定了!多数据源可以实现.
出现空白行的原因是:
ds.UriResult.AddUriResultRow(bt1, bt2, (byte[])btList[0], (byte[])btList[1], (byte[])btList[2], (byte[])btList[3], (byte[])btList[4], (byte[])btList[5]);

1.UriResult是手动添加的,所以在实现上面代码的时候,该table一共有两个ROW,第一个ROW和第二个ROW的区别是前者的PIC字段为空,而后面是不为空的
2.这里UriResult为母表,dataTable1为映射的表(两者字段必须一一对应,只取需要的)
两个表会分别在报表的数据库专家里面会对应一条数据,也就是前面提到的那条空数据
所以直接删除UriResult里面的第一个ROW就可以了
阿泰 2009-09-27
  • 打赏
  • 举报
回复
首先肯定一点,不用多数据源肯定是可以实现的
我仔细看了下代码,比较怪。
主要是最外面一个for循环。


string[] uriSampleID = new string[2];
uriSampleID[0] = "20090911010001";
uriSampleID[1] = "20090911010002";

for (int j = 0; j < 2; j++)
{
//..
//将6副二进制图片放入DataSet数据集中
if (getPath.Length == 6)
{
ds.UriResult.AddUriResultRow(bt1, bt2, (byte[])btList[0], (byte[])btList[1], (byte[])btList[2], (byte[])btList[3], (byte[])btList[4], (byte[])btList[5]);
AveRptUri5 oRpt = new AveRptUri5();
//使用Report Engine对象模型,将此数据集传递给报表
oRpt.SetDataSource(ds.Tables[0]);
//将带有数据的报表对象绑定到水晶报表查看器
crystalReportViewer1.ReportSource = oRpt;
//..
}
myConnection.Close();
}
这样势必会造成
uriSampleID[1] = "20090911010002";
覆盖掉
uriSampleID[0] = "20090911010001";
的结果

另外单纯从代码上看,这个报表里应该只涉及到uriResult和datatable1,另外两个表根本不需要。
(可能你的数据库设计上是有这些关系的,但是在报表上根本用不到)

报表上只要uriResult和datatable1和一个1:1的关系就可以了。
Rommen 2009-09-27
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 babyt 的回复:]
这对于报表来说是一个多数据源的操作。我倒还真没这么做过,呵呵。
一般我都会把数据Fill到一个dataset里去。

从12楼的关系上看没什么问题
但是13楼我就看不明白了。

上面的一个图说明这两个表是在一个dataset里的
而下面的数据库专家里说明这两个表用是在两个dataset里。

其实你的表都可以放到一个dataset里的,这样可能更清晰些

不过按你现在的做法,你的代码上是怎么写的呢
[/Quote]

我尝试了将表全放入一个dataset中,结果是图片显示不出来了,所以
初步推断是由于图片和数据如在同一个数据集里,只要使用容器映射就不会显示图片,
可能只能分开数据源
阿泰 2009-09-25
  • 打赏
  • 举报
回复
这个你在数据库专家里设置两个表的关联关系就可以了

你这两个应该是一个dataset里的两个datatable吧

注意,关系是在水晶报表里设,不是在dataset里设。
Rommen 2009-09-25
  • 打赏
  • 举报
回复
不过这样又导致新问题的存在,就是手动建立的dataset里面,为了图片所映射的dataTable也得
有这么多的字段,而且是多张表的,这样可能会很麻烦
Rommen 2009-09-25
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 llsen 的回复:]
你可以将所有数据(不是特别多)一起塞给报表
然后只用在报表模板上面

分组里面-组页脚上-在后面新建页即可。
[/Quote]

我隐约知道问题的所在了:
因为塞给报表的dataSet里面只有图片的字段,但是报表上除了图片字段,其它字段都是
直接从数据库专家里面托出来的,这样可能造成一条数据的图片对应多条其它数据,
不知我这样理解是否正确
Rommen 2009-09-25
  • 打赏
  • 举报
回复
DataSet是手动添加的,里面映射的dataTable在数据库专家
里面的位置如果是在末尾,也就是联结的终点而不是起点,那么数据不再重复,
然后数据也为空了,就变成了:
----(详细资料)-----
姓名:空 性别:空 出生日期:空
pic1(无图片) pic2(无图片) pic3(无图片)
----(详细资料)-----
llsen 2009-09-25
  • 打赏
  • 举报
回复
你可以将所有数据(不是特别多)一起塞给报表
然后只用在报表模板上面

分组里面-组页脚上-在后面新建页即可。
Rommen 2009-09-25
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 llsen 的回复:]
如果单单是一页一条数据的话,可以分组,每组放在一个页上。
[/Quote]

嗯,这是上面第一个问题,我觉得我只做了个循环,将数据放入dataSet中,再推入报表里,
这样就不断覆盖掉了前面的数据

我最开始做出的就是分组法,可领导说不行,要求点下一页就显示一个病人的信息
加载更多回复(3)

4,818

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 图表区
社区管理员
  • 图表区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧