Crystal Report กับการสร้าง Report รายงานแบบ JOIN ข้อมูลหลายตาราง Table (.NET) |
|
|
|
Crystal Report กับการสร้าง Report รายงานแบบ JOIN ข้อมูลหลายตาราง Table (.NET) บทความนี้เป็นการออกรายงานที่มีความซับซ้อนยิ่งขึ้น โดยดึงข้อมูลจากลาย ๆ ตารางของลูกค้ามาแสดงบนรายงานเดียวกัน เช่นข้อมูลการสั่งซื้อ ซึ่งอาจจะประกอบด้วย ชื่อที่อยู่ของ ลูกค้าและรายละเอียดอื่น ๆ เช่นรายละเอียดการสั่งซื้อ ซึ่งปกติแล้วข้อมูลเหล่านี้จะถูกจัดเก็บไว้คนล่ะตาราง ซึ่งปกตินิยมใช้ Sub Report เพื่อจัดการในแต่ล่ะส่วนของ Report ให้ออกมาตรงกับความต้องการ แต่วิธีนี้ผมจะใช้การเขียน Query เพื่อ JOIN จากตารางต่าง ๆ สร้างข้อมูลที่ ต้องการออกมา 1 ชุด จากนั้นค่อยกำหนดชื่อ Column ผ่าน DataSet และ DataTable พร้อมกับ Set DataSouce ใหักับ Crystal Report และบน Crystal Report ก็ใช้การจัดการ วางตำแหน่งของ Data ให้ถูกต้องทั้งในส่วนของ header / detail / footer ก็จะได้รายงานตามความต้องการ ถ้ายังไม่เข้าใจ ให้ลองทำความเข้าใจอย่างละเอียดจากบทความนี้ ซึ่งอธิบายการสร้างอย่างละเอียดแบบ Step by Step
Screenshot

จาก Screenshot จะเห็นว่ามีการดึงข้อมูล ของลูกค้า มาแสดงไว้สาวนบนของ Report และ ในส่วนของ detail จะแสดงรายละเอียดการใช้ยอดเงินของลูกค้า
โครงสร้างตาราง
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,
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);
INSERT INTO customer VALUES ('C002', 'John Smith', '[email protected]', 'EN', 2000000);
INSERT INTO customer VALUES ('C003', 'Jame Born', '[email protected]', 'US', 3000000);
INSERT INTO customer VALUES ('C004', 'Chalee Angel', '[email protected]', 'US', 4000000);
GO
SET ANSI_PADDING OFF
country
USE [mydatabase]
GO
/****** Object: Table [dbo].[country] 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].[country](
[CountryCode] [varchar](2) NOT NULL,
[CountryName] [varchar](50) NULL,
CONSTRAINT [PK_country] PRIMARY KEY CLUSTERED
(
[CountryCode] 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 country VALUES ('TH', 'Thailand');
INSERT INTO country VALUES ('EN', 'English');
INSERT INTO country VALUES ('US', 'United States');
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', '2011-08-01', 100000);
INSERT INTO audit VALUES (2, 'C001', '2011-08-05', 200000);
INSERT INTO audit VALUES (3, 'C001', '2011-08-10', 300000);
INSERT INTO audit VALUES (4, 'C002', '2011-08-02', 400000);
INSERT INTO audit VALUES (5, 'C002', '2011-08-07', 100000);
INSERT INTO audit VALUES (6, 'C002', '2011-08-15', 300000);
INSERT INTO audit VALUES (7, 'C003', '2011-08-20', 400000);
INSERT INTO audit VALUES (8, 'C003', '2011-08-25', 200000);
INSERT INTO audit VALUES (9, 'C004', '2011-07-04', 100000);
INSERT INTO audit VALUES (10, 'C005', '2011-07-04', 200000);
GO
SET ANSI_PADDING OFF
นำ ตารางเหล่านี้ไปรันบน Query เพื่อสร้าง Table
ความสัมพันธ์

จากรูปภาพจะแสดง 3 ตาราง customer , country , audit ที่มีความสัมพันธ์กัน เราต้องการ แค่บางส่วนของตาราง ประกอบด้วย Column
- CustomerID
- Name
- Email
- Budget
- CountryName
- Date
- Used
โดยคอลัมบ์เหล่านี้จะนำไปแสดงบน Report ทดสอบการเขียน Query JOIN บน Query

เขียน Query เพื่อทำการ JOIN ข้อมูลจาก 3 ตาราง ได้ข้อมูลดังรูป โดยสมมุติเลือกลูกค้าที่รหัส CustomerID = 'C001'
เริ่มต้นด้วยการสร้าง Project เป็น ASP.NET Application หรือ ASP.NET WebSite

เลือกหน้าจอดังรูป
ขั้นตอนแรกให้สร้าง DataSet และ DataTable เพื่อสร้าง Column ที่จะแสดงบน Report

กลับมาที่ Project ให้คลิกขวาที่ Project -> Add -> New Item เพื่อสร้างรายการใหม่

เลือกสร้าง DataSet ดังรูป

คลิกขวาที่ DataSet เลือก Add -> DataTable

เมื่อได้ DataTable ขึ้นมาแล้วให้เปลี่ยนชื่อ DataTable ให้เป็น myDataReport

คลิกขวาที่ DataTable เลือก Add -> Column

สร้าง Column ให้ครบทุกตัว อันแรกชื่อ CustomerID กำหนด Type เป็น System.String
ส่วน Column อื่น ๆ ให้สร้างให้ครบทุกตัว โดยกำหนดเป็นดังนี้
- CustomerID -> System.String
- Name -> System.String
- Email -> System.String
- Budget -> System.Decimal
- CountryName -> System.String
- Date -> System.Date
- Used -> System.Decimal

หลังจากเสร็จทุกตัวแล้วให้ Save และปิดหน้าจอการสร้าง DataSet และ DataTable ไปได้เลย
สร้าง Report

กลับมาที่ Project ให้คลิกขวาที่ Project -> Add -> New Item เพื่อสร้างรายการใหม่

เลือก Crystal Report และกำหนดชื่อให้เรียบร้อย

จะมีหน้าต่าง Pop ให้เลือกแบบ Wizard ของ Crystal Report และให้เลือก Using the Report Wizard และ OK เพื่อข้ามไปขั้นตอนถัดไป

ในส่วนนี้ให้เลือกที่ Project Data -> .NET DataSet จะมี DataSet และตามด้วนชื่อ myDataReport ตามที่ได้สร้างไว้ในขั้นตอนการสร้าง DataSet และ DataTable ให้เลือกและคลิก Next เพื่อไปขั้นตอนถัดไป

จะเห็นว่าจะมีชื่อ Column ที่เราได้สร้างรองรับจากการสร้าง DataTable ให้เลือกทั้งหมด หรือจะเลือกเฉพาะ Column ที่ต้องการก็ได้ และคลิกที่ Finish เพื่อเสร็จสิ้นการออกแบบ แต่ถ้าหากต้องการกำหนดค่าอื่น ๆ ของ Report ลองคลิกที่ Next เพื่อปรับแต่ง Report ในรูปแบบต่าง ๆ ในมุมมองของ Wizard

หน้าตา Design Report ที่สามารถปรับแต่งรายละเอียดอื่น ๆ ได้ตามความต้องการ
สร้าง Web Form เพื่อออกรายงาน

กลับมาที่ Web Form ให้สร้าง Control ของ Textbox และ Button พร้อมทั้งลาก Control ชื่อ CrystalReportViewer เหมือนในภาพ จากนั้นให้สร้าง Event ของ Button Load Report ใส่ code ดังต่อไปนี้
Code VB.NET
Imports CrystalDecisions.CrystalReports.Engine
Imports System.Data
Imports System.Data.SqlClient
Partial Public Class _Default
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub
Protected Sub btnShowReport_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnShowReport.Click
Dim objConn As New SqlConnection
Dim objCmd As New SqlCommand
Dim dtAdapter As New SqlDataAdapter
Dim ds As New DataSet
Dim dt As DataTable
Dim strConnString As String
Dim strSQL As New StringBuilder
strConnString = "Server=localhost;UID=sa;PASSWORD=;database=mydatabase;Max Pool Size=400;Connect Timeout=600;"
strSQL.Append(" SELECT a.CustomerID,a.Name,a.Email,a.Budget, ")
strSQL.Append(" b.CountryName,c.Date,c.Used ")
strSQL.Append(" FROM customer a ")
strSQL.Append(" LEFT JOIN country b ON a.CountryCode = b.CountryCode ")
strSQL.Append(" LEFT JOIN audit c ON a.CustomerID = c.CustomerID ")
strSQL.Append(" WHERE a.CustomerID = '" & Me.txtCustomerID.Text & "' ")
objConn.ConnectionString = strConnString
With objCmd
.Connection = objConn
.CommandText = strSQL.ToString()
.CommandType = CommandType.Text
End With
dtAdapter.SelectCommand = objCmd
dtAdapter.Fill(ds, "myDataReport")
dt = ds.Tables(0)
dtAdapter = Nothing
objConn.Close()
objConn = Nothing
Dim rpt As New ReportDocument()
rpt.Load(Server.MapPath("CrystalReport1.rpt"))
rpt.SetDataSource(dt)
Me.CrystalReportViewer1.ReportSource = rpt
End Sub
End Class
Code C#
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using CrystalDecisions.CrystalReports.Engine;
using System.Data.SqlClient;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, System.EventArgs e)
{
}
protected void btnShowReport_Click(object sender, EventArgs e)
{
SqlConnection objConn = new SqlConnection();
SqlCommand objCmd = new SqlCommand();
SqlDataAdapter dtAdapter = new SqlDataAdapter();
DataSet ds = new DataSet();
DataTable dt = null;
string strConnString = null;
StringBuilder strSQL = new StringBuilder();
strConnString = "Server=localhost;UID=sa;PASSWORD=;database=mydatabase;Max Pool Size=400;Connect Timeout=600;";
strSQL.Append(" SELECT a.CustomerID,a.Name,a.Email,a.Budget, ");
strSQL.Append(" b.CountryName,c.Date,c.Used ");
strSQL.Append(" FROM customer a ");
strSQL.Append(" LEFT JOIN country b ON a.CountryCode = b.CountryCode ");
strSQL.Append(" LEFT JOIN audit c ON a.CustomerID = c.CustomerID ");
strSQL.Append(" WHERE a.CustomerID = '" + this.txtCustomerID.Text + "' ");
objConn.ConnectionString = strConnString;
var _with1 = objCmd;
_with1.Connection = objConn;
_with1.CommandText = strSQL.ToString();
_with1.CommandType = CommandType.Text;
dtAdapter.SelectCommand = objCmd;
dtAdapter.Fill(ds, "myDataReport");
dt = ds.Tables[0];
dtAdapter = null;
objConn.Close();
objConn = null;
ReportDocument rpt = new ReportDocument();
rpt.Load(Server.MapPath("CrystalReport1.rpt"));
rpt.SetDataSource(dt);
this.CrystalReportViewer1.ReportSource = rpt;
}
}
หลังจากวาง Code เรียบร้อยแล้ว ลองกดที่ Run เพื่อดูผลลัพธ์ของ Report

ทดสอบการรัน Report ผ่านหน้า Web จะได้ผลเหมือนในรูป แต่จะเห็นว่ามีการแสดงข้อมูลชื่อลูกค้าที่ซ้ำ ๆ ซึ่งเราสามารถทำการย้ายข้อมูลบางส่วนไปไว้ใน header และทำการจัดรุปแบบอื่น ๆ ให้ตรงกับความต้องการ
การปรับแต่ง Report

กลับมาที่ Crystal Report ให้ปรับแต่ง Report โดยย้ายชื่อและข้อมูลของลูกค้าไปไว้ใน header และในส่วนของ detail ไว้ตำแหน่งเดิม เมื่อเสร็จแล้วให้ save และดูผลลัพธ์

ได้ผลลัพธ์ดังรูป สามารถปรับแต่งใส่ Label หรือข้อความอื่น ๆ
ตัวอย่างการสร้าง Total Amount

คลิกขวาในพื้นที่ว่าง ๆ ของ Footer Report เลือก Insert -> Text Object

สร้าง Label ชื่อ Total Amount

คลิกขวาในพื้นที่ว่าง ๆ ของ Footer Report เลือก Insert -> Summary

คลิกวางในตำแหน่งของ Footer และกำหนด Property ดังภาพ โดยเราจะ Summary คอลัมบ์ชื่อ Used

วางตำแหน่งให้พอดีกับ Report จากนั้นก็ Save และปิดหน้าจอไปได้เลย

ทดสอบการรัน Report ใหม่ ก็จะได้ผลลัพธ์ดังรูป
จากตัวอย่างจะเห็นว่ามีการเลือกข้อมูลจาก table ชื่อ customer ใช้ ADO.NET อ่านข้อมูลในรูปแบบของ DataSet และการกำหนดค่าให้กับ dtAdapter.Fill(ds, "myDataReport") ซึ่งเป็นชื่อเดียวกับ DataTable ที่อยู่ใน DataSet ที่ใช้กำหนด Column ของข้อมูลใน Crystal Report สำหรับวิธี นี้มีประโยชน์ที่ไม่ต้องเขียน Query หรือสร้าง DataSource บน Crystal Report แต่เราสามารถจัดการกับข้อมูลต่าง ๆ ที่อยู่ในโปรแกรมให้เสร็จเรียบร้อย ผ่านการ JOIN หลาย ๆ Table และนำค่าที่ได้โยนให้กับ DataSource ของ Crystal Report ทีเดียว ซึ่ง จะช่วยให้การเขียนรายงานนั้นมีความง่าย และ ได้ผลลัพธ์ตามต้องการ แทนการใช้ Formula หรือจัดการ Data บน Crystal Report
สำหรับตัวย่างนี้ใช้ได้ทั้ง Windows Application และ Web Application (ASP.NET) ซึ่งการใช้งานแทบจะไม่ต่างกันเลย หรือลองอ่านบทความที่เกี่ยวข้อง ซึ่งมีตัวอย่างทั้ง Win App และ Web App และตัรอวย่างในบทความเลือกใช้ทั้งภาษา VB.NET และ C#
Download Code!!
สำหรับบทความอื่น ๆ อยากให้ลองอ่านดูเพราะมีประโยชน์มาก ๆ
Go to : สุดยอดบทความ Crystal Report กับ .NET Framework (VB.NET , C#)
Go to : สร้าง Parameter และ Formula Fields บน Crystal Reports (VB.NET,C#)
Go to : สร้าง Crystal Report บน Visual Studio (VB.NET , C#) Step by Step
Go to : การสร้าง Crystal Report กับ DataSet หรือ DataTable (VB.NET,C#)
Go to : ASP.NET ReportViewer - rsweb:ReportViewer
Go to : ASP.NET and CrystalReportViewer
Go to : ASP.NET แสดงรูปภาพ Image บน Crystal Report แบบ Step by Step (VB.NET / C#)
Go to : การสร้าง Sub Report (Subreport) บน Crystal Report แบบ Step by Step (VB.NET /C#)
|
|
|
|
 |
|
|
|
|
|
|
|
|
|
|
|
By : |
TC Admin
|
|
Score Rating : |
- |
|
Create Date : |
2012-03-30 12:00:13 |
|
Download : |
No files |
|
|
|
|
|
|
|