สร้าง Sub Report (Subreport) บน Crystal Report แบบ Step by Step (VB.NET /C#) |
|
|
|
การสร้าง Sub Report (Subreport) บน Crystal Report แบบ Step by Step (VB.NET /C#) ในการสร้างหรือออกแบบ Report บน Crystal Report นั้นถ้า Report ที่มีความซับซ้อนหรือประกอบด้วยหลาย ๆ ส่วนก็จะให้ทำการสร้าง Report มีความซับซ้อนยิ่งขึ้น และจะยากขึ้นต่อการนำข้อมูลที่อยู่ใน Database ไปแสดงผลบน Report แต่ข้อดีของ Crystal Report ได้ลดความยากนี้และช่วยให้การเขียนง่ายขึ้นด้วยการแบ่ง Report ออกเป็นส่วน ๆ หรือ Subreport (Sub Report) โดยในแต่ล่ะ Subreport จะแบ่งแสดงผล รวมทั้งใช้ DataSource คนล่ะตัวกันด้วย เพราะฉะนั้นวิธีนี้จะช่วยให้เราออกแบบ Subreport ได้อย่างอีสระ และสามารถสร้าง DataSet จาก .NET Framework ในการที่จะส่งค่าให้กับ Sub Report แต่ล่ะตัวได้แยกกันอีกด้วย
Crystal Report and Subreport
ในตัวอย่างนี้จะเน้นการใช้ DataSet บน .NET Framework แทนการเรียกใช้ Database โดยตรงจาก Crystal Report เหตุผลหนึ่งก็คือ การใช้ DataSet บน .NET Framework จะยึดหยุ่นช่วยให้สามารถจัดการกับข้อมูลที่ต้องการ แล้วค่อยนำข้อมูลที่ได้แสดงผลบน Crystal Report และช่วยลดปัญหาเรื่องการ Connection เชื่อมต่อระหว่าง Crystal Report กับ Database ด้วย
การใช้ DataSet บน .NET Framework นั้นเราไม่ต้องทำการเชื่อม Crystal Report กับ Database แต่จะใช้ .NET ในการอ่านข้อมูลทุก ๆ อย่างที่ต้องการ และค่อยนำ DataSet ที่ได้โยนค่าให้กับ Crystal Report เพระาฉะนั้นปัญหาเรื่องเมื่อทำการปรับแต่ง Database เช่น Username หรือ Password หรือย้าย Database ต่าง ๆ จะไม่ต้องไปตามแก้ไขใน Crystal Report
คำอธิบายเกี่ยวกับตัวอย่างนี้
ในตัวอย่างนี้จะประกอบด้วยตาราง 2 ตาราง คือ customer และ audit ข้อมูลทั้ง 2 ตารางเชื่อมกันด้วย CustomerID โดยข้อมูลในตาราง audit จะจัดเก็บรายละเอียดการใช้ยอดเงินของลุกค้าแต่ล่ะคน วัตถุประสงค์คือ เราจะแสดงรายงาน ออกเป็น 3 ส่วนด้วยกันคือ
- ส่วน Logo หรือส่วนหัวของ Report ซึ่งจะแสดงรูปภาพที่อยู่ในโฟเดอร์ (Logo Sub Report)
- ส่วน ชื่อและรายละเอียดของลูกค้า (Main Report)
- ส่วนที่เป็น Audit รายละเอียดการใช้ยอดเงินของแต่ล่ะคน (Audit Sub Report)
โดยเราจะให้รายละเอียดชื่อลูกค้าเป็น Main Report และส่วนของ Logo , Audit เป็น Sub Report
โครงสร้างตาราง
ตาราง customer

USE [mydatabase]
GO
/****** Object: Table [dbo].[customer] Script Date: 03/13/2012 13:42:18 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[customer](
[CustomerID] [varchar](4) NOT NULL,
[Name] [varchar](50) NULL,
[Email] [varchar](50) NULL,
[CountryCode] [varchar](2) NULL,
[Budget] [float] NULL,
[Used] [float] NULL,
CONSTRAINT [PK_customer] PRIMARY KEY CLUSTERED
(
[CustomerID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
INSERT INTO customer VALUES ('C001', 'Win Weerachai', '[email protected]', 'TH', 1000000, 600000);
INSERT INTO customer VALUES ('C002', 'John Smith', '[email protected]', 'EN', 2000000, 800000);
INSERT INTO customer VALUES ('C003', 'Jame Born', '[email protected]', 'US', 3000000, 600000);
INSERT INTO customer VALUES ('C004', 'Chalee Angel', '[email protected]', 'US', 4000000, 100000);
GO
SET ANSI_PADDING OFF
ตาราง audit

USE [mydatabase]
GO
/****** Object: Table [dbo].[audit] Script Date: 03/13/2012 13:45:08 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[audit](
[AuditID] [varchar](4) NOT NULL,
[CustomerID] [varchar](4) NULL,
[Date] [datetime] NULL,
[Used] [float] NULL,
CONSTRAINT [PK_audit] PRIMARY KEY CLUSTERED
(
[AuditID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
INSERT INTO audit VALUES (1, 'C001', '2008-08-01', 100000);
INSERT INTO audit VALUES (2, 'C001', '2008-08-05', 200000);
INSERT INTO audit VALUES (3, 'C001', '2008-08-10', 300000);
INSERT INTO audit VALUES (4, 'C002', '2008-08-02', 400000);
INSERT INTO audit VALUES (5, 'C002', '2008-08-07', 100000);
INSERT INTO audit VALUES (6, 'C002', '2008-08-15', 300000);
INSERT INTO audit VALUES (7, 'C003', '2008-08-20', 400000);
INSERT INTO audit VALUES (8, 'C003', '2008-08-25', 200000);
INSERT INTO audit VALUES (9, 'C004', '2008-07-04', 100000);
INSERT INTO audit VALUES (10, 'C005', '2008-07-04', 200000);
GO
SET ANSI_PADDING OFF
สำหรับตัวอย่างนี้จะใช้ได้ทั้ง ASP.NET และ Windows Application หรือ Application อื่น ๆ บน Visual Studio โดยจะมี Code อยู่ 2 ภาษาคือ VB.NET และ C#

เริ่มต้นด้วยการคลิกขวาที่ Project เลือก Add New Item

เลือกสร้าง DataSet ชื่อว่า myDataSet.xsd

ในกรณีที่โปรแกรมต้องการให้จัดเก็บไว้ในโฟเดอร์ App_Code

DataSet เข้ามาใน Project

ทำการสร้าง DataSet และ DataTable ขึ้นมาใหม่

สร้าง DataTable ขึ้นมา 3 รายการคือ customer , audit และ logo ซึ่ง DataType กำหนดตามชนิดเหมือนกับใน Database หรือสามารถกำหนดเป็น System.String เป็นค่า Default ได้เลย

แต่สิ่งที่ต่างไปก็คือใน DataTable ของ logo จะมี Column ที่มีชื่อว่า Logo ซึ่งจะต้องกำหนด DataType เป็น System.Byte[] ดูรุปภาพประกอบ
ถ้าสร้างเสร็จทั้ง 3 รายการแล้ว ก็เป็นเสร็จสิ้นขั้นตอนการสร้าง DataSet
ขั้นตอนถัดไป เป็นการสร้างและออกแบบ Crystal Report

คลิกขวาที่ Project เลือก Add New Item

เลือกสร้าง Crystal Report โดยกำหนดชื่อเป็น myCrystalReport.rpt

เลือก OK

เลือก DataSet ที่ได้สร้างไว้ ในกรณีที่ไม่พบรายการนี้ให้เลือกที่ .NET Object เพื่อ Browse ไฟล์ myDataSet.xsd
ในขั้นตอนนี้เราจะสร้าง Main Report โดยให้เลือก DataTable ชื่อว่า customer ดังรูป

เลือก Column ที่ต้องการ

ทำตามขั้นตอนเรื่อย ๆ จนถึงขั้นตอนเสร็จสิ้น

เราจะได้ Main Report ดังรูป ที่จะแสดงข้อมูลรายละเอียดชื่อของลูกค้า
ขั้นตอนถัดไป สร้าง Logo ของ Report

คลิกขวาที่ Section 1 (Report Header) -> Insert Section Below

จะได้ Section ใหม่ขึ้นมาดังรูป ให้คลิกขวาพื้นที่ว่าง ๆ เลือก Insert -> Subreport

วางตำแหน่งของ Subreport ให้วางใว้ใน Section ที่เราได้สร้างขึ้นมาใหม่

จะแสดง Dialog สำหรับสร้าง Subreport ให้เรากำหนดชื่อเป็น Logo_Sub_Report (ชื่อนี้จะนำไปใช้ส่วนอื่นด้วย) จากนั้นให้เลือก Report Wizard

เลือก DataTable ที่ต้องการ ในที่นี้ให้เลือก DataTable ที่ชื่อว่า logo

เลือก Column ที่จะแสดงใน Report

ทำตามขั้นตอนเรื่อย ๆ จนเสร็จสิ้น

เลือก OK เพื่อเสร็จสิ้นการสร้าง Logo_Sub_Report

ในกรณีที่ต้องการปรับแต่ง Sub Report ให้คลิกขวาที่ตำแหน่งของ Sub Report นั้น ๆ แล้วเลือก Edit Subreport

ปรับแต่งตำแหน่งของ Logo_Sub_Report

ในกรณีที่ต้องการออกจาก Subreport ให้คลิกขวาเลือก Close Subreport
ขั้นตอนถัดไป สร้าง Subreport สำหรับ Audit หรือรายละเอียดการใช้ยอดเงิน

คลิกขวาที่ Section 3 -> Insert Section Below

จะได้พื้นที่ใหม่ที่ต้องการ ให้คลิกขวาเลือก Insert -> Subreport

วางตำแหน่งของ Subreport ที่ต้องการ

จะมี Dialog สำหรับสร้าง Subreport ให้กำหนดชื่อเป็น Audit_Sub_Report และเลือก Report Wizard

เลือก DataTable ที่มีชื่อว่า audit

เลือก Column ที่จะแสดงผล

ทำตามขั้นตอนเรื่อย ๆ จนกว่าจะเสร็จสิ้นขั้นตอน ให้เลือก Finish

ขั้นอตอนนี้จะเป็นการ Link ข้อมูลระหว่าง Main Report กับ Subreport อันเนื่องจากข้อมูล customer กับ audit มี Key ชื่อว่า CustomerID เชื่อมกัน และในแต่ล่ะ Loop ของการแสดงรายงาน เราต้องการเฉพาะข้อมูลของแต่ล่ะคนมาแสดงเท่านั้น ให้เชื่อมข้อมูลเหมือนในตัวอย่าง

เมื่อเสร็จสิ้นขั้นตอนการสร้าง Report แล้ว เราจะได้โครงสร้างของ Crystal Report ซึ่งประกอบด้วย 3 Report หลัก ๆ
จากนั้นกลับมาที่หน้า Webpage ของ ASP.NET เพื่อจะแสดงผล Report

ลาก Control ที่มีชื่อว่า CrystalReportViewer มาวางไว้ในหน้า WebPage ดังรูป โดยขั้นตอนนี้ไม่ต้องทำอะไรเพิ่มเติม เพราะเราจะสร้าง DataSet สำหรับ Map กับ Sub Report ต่าง ๆ ด้วย Code ของ .NET
โดยตัวอย่างนี้มีทั้งของ VB.NET และ C#
VB.NET
Imports CrystalDecisions.CrystalReports.Engine
Imports System.Data
Imports System.Data.SqlClient
Imports System.IO
Imports System.Text
Partial Class _Default
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim objConn As New SqlConnection
Dim objCmd As New SqlCommand
Dim dtAdapter As New SqlDataAdapter
Dim ds As New DataSet
Dim strConnString, strSQL As String
strConnString = "Server=localhost;UID=sa;PASSWORD=;database=mydatabase;Max Pool Size=400;Connect Timeout=600;"
'*** for Main Report (Start) ***'
Dim dtMain As DataTable
strSQL = "SELECT * FROM customer ORDER BY CustomerID ASC "
objConn.ConnectionString = strConnString
With objCmd
.Connection = objConn
.CommandText = strSQL
.CommandType = CommandType.Text
End With
dtAdapter.SelectCommand = objCmd
dtAdapter.Fill(ds)
dtMain = ds.Tables(0)
'*** for Main Report (End) ***'
'*** for Audit Sub Report (Start) ***'
Dim dtAudit As DataTable
strSQL = "SELECT * FROM audit ORDER BY AuditID ASC "
objConn.ConnectionString = strConnString
With objCmd
.Connection = objConn
.CommandText = strSQL
.CommandType = CommandType.Text
End With
dtAdapter.SelectCommand = objCmd
dtAdapter.Fill(ds)
dtAudit = ds.Tables(0)
'*** for Audit Sub Report (End) ***'
'*** for Logo Sub Report (Start) ***'
Dim dtLogo As New DataTable("logo")
Dim dr As DataRow
dtLogo.Columns.Add(New DataColumn("Logo", GetType(System.Byte())))
dtLogo.Columns.Add(New DataColumn("Company", GetType(String)))
Dim fiStream As New FileStream(Server.MapPath("Images/thaicreate.jpg"), FileMode.Open)
Dim binReader As New BinaryReader(fiStream)
Dim pic() As Byte = {}
pic = binReader.ReadBytes(fiStream.Length)
dr = dtLogo.NewRow
dr("Logo") = pic
dr("Company") = "ThaiCreate.Com Co,. LTD"
dtLogo.Rows.Add(dr)
fiStream.Close()
binReader.Close()
'*** for Logo Sub Report (End) ***'
Dim rpt As New ReportDocument()
rpt.Load(Server.MapPath("myCrystalReport.rpt"))
'** for Main Report **'
rpt.SetDataSource(dtMain)
'** for Logo Sub Report **'
rpt.Subreports("Logo_Sub_Report").Database.Tables(0).SetDataSource(dtLogo)
'** for Audit Sub Report **'
rpt.Subreports("Audit_Sub_Report").Database.Tables(0).SetDataSource(dtAudit)
Me.CrystalReportViewer1.ReportSource = rpt
dtAdapter = Nothing
objConn.Close()
objConn = Nothing
End Sub
End Class
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using CrystalDecisions.CrystalReports.Engine;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
SqlConnection objConn = new SqlConnection();
SqlCommand objCmd = new SqlCommand();
SqlDataAdapter dtAdapter = new SqlDataAdapter();
DataSet ds = new DataSet();
string strConnString = null;
string strSQL = null;
strConnString = "Server=localhost;UID=sa;PASSWORD=;database=mydatabase;Max Pool Size=400;Connect Timeout=600;";
//*** for Main Report (Start) ***'
DataTable dtMain = null;
strSQL = "SELECT * FROM customer ORDER BY CustomerID ASC ";
objConn.ConnectionString = strConnString;
var _with1 = objCmd;
_with1.Connection = objConn;
_with1.CommandText = strSQL;
_with1.CommandType = CommandType.Text;
dtAdapter.SelectCommand = objCmd;
dtAdapter.Fill(ds);
dtMain = ds.Tables[0];
//*** for Main Report (End) ***'
//*** for Audit Sub Report (Start) ***'
DataTable dtAudit = null;
strSQL = "SELECT * FROM audit ORDER BY AuditID ASC ";
objConn.ConnectionString = strConnString;
var _with2 = objCmd;
_with2.Connection = objConn;
_with2.CommandText = strSQL;
_with2.CommandType = CommandType.Text;
dtAdapter.SelectCommand = objCmd;
dtAdapter.Fill(ds);
dtAudit = ds.Tables[0];
//*** for Audit Sub Report (End) ***'
//*** for Logo Sub Report (Start) ***'
DataTable dtLogo = new DataTable("logo");
DataRow dr = null;
dtLogo.Columns.Add(new DataColumn("Logo", typeof(System.Byte[])));
dtLogo.Columns.Add(new DataColumn("Company", typeof(string)));
FileStream fiStream = new FileStream(Server.MapPath("Images/thaicreate.jpg"), FileMode.Open);
BinaryReader binReader = new BinaryReader(fiStream);
byte[] pic = {};
pic = binReader.ReadBytes((int)fiStream.Length);
dr = dtLogo.NewRow();
dr["Logo"] = pic;
dr["Company"] = "ThaiCreate.Com Co,. LTD";
dtLogo.Rows.Add(dr);
fiStream.Close();
binReader.Close();
//*** for Logo Sub Report (End) ***'
ReportDocument rpt = new ReportDocument();
rpt.Load(Server.MapPath("myCrystalReport.rpt"));
//** for Main Report **'
rpt.SetDataSource(dtMain);
//** for Logo Sub Report **'
rpt.Subreports["Logo_Sub_Report"].Database.Tables[0].SetDataSource(dtLogo);
//** for Audit Sub Report **'
rpt.Subreports["Audit_Sub_Report"].Database.Tables[0].SetDataSource(dtAudit);
this.CrystalReportViewer1.ReportSource = rpt;
dtAdapter = null;
objConn.Close();
objConn = null;
}
}
คำอธิบาย
'** for Main Report **'
rpt.SetDataSource(dtMain)
'** for Logo Sub Report **'
rpt.Subreports("Logo_Sub_Report").Database.Tables(0).SetDataSource(dtLogo)
'** for Audit Sub Report **'
rpt.Subreports("Audit_Sub_Report").Database.Tables(0).SetDataSource(dtAudit)
เป็นการ Map ตัว Data DataSource กับ Report และ Sub Report
Screenshot

แสดง Report และ Sub Report ในตำแหน่งต่าง ๆ ที่ได้ออกแบบไว้ สามารถปรับแต่งตำแหน่งต่าง ๆ เพื่อให้ได้รูปแบบหน้าตาที่ต้องการ
สามารถดาวน์โหลด Code ทั้งหมดได้ที่นี่ Download !!
บทความอื่นที่เกี่ยวข้อง
Go to : สร้าง Crystal Report บน Visual Studio (VB.NET , C#) Step by Step
Go to : สร้าง Parameter และ Formula Fields บน Crystal Reports (VB.NET,C#)
Go to : การสร้าง Crystal Report กับ DataSet หรือ DataTable (VB.NET,C#)
Go to : สร้าง Parameter และ Formula Fields บน Crystal Reports (VB.NET,C#)
Go to : ASP.NET ReportViewer - rsweb:ReportViewer
Go to : ASP.NET and CrystalReportViewer
Go to : การสร้าง Sub Report (Subreport) บน Crystal Report แบบ Step by Step (VB.NET /C#)
|
|
|
|
 |
|
|
|
|
|
|
|
|
|
|
|
By : |
TC Admin
|
|
Score Rating : |
- |
|
Create Date : |
2012-10-11 08:16:11 |
|
Download : |
No files |
|
|
|
|
|
|
|