วันพุธที่ ๖ มกราคม พ.ศ. ๒๕๕๓

VB.NET เขียนโค้ดควบคุม Object ของ Crystal Report

หลายๆคนที่พัฒนาซอฟท์แวร์ทางธุรกิจก็หนีไม่พ้นที่จะต้องทำรายงาน และที่นิยมมากสำหรับนักพัฒนา .NET ก็คงหนีไม่พ้น Crystal Report นั่นเองครับ ซึ่งใช้งานไม่ยาก ยืดหยุ่น และมีฟังก์ชันมากมายให้ใช้งาน และความยอดเยียมอีกอย่างก็คือ เราสามารถเขียนโค้ดเพื่อควบคุม Crystal Report ได้ด้วย

ลองมาดูตัวอย่างจากคำถามที่ greatfriends ละกันครับ

How to Return total page in crystal report to VB -- HELP ME!!
http://greatfriends.biz/?118103

ปัญหามีอยู่ว่า ผมมี crstal report ที่สร้างออกมาเป็น PDF และก็ต้องเอามก Merge กับ File Attach ที่เป็น PDF ให้เป็น ไฟล์เดียว โดย File ที่ Attach นั้นจะต้องอยู่ตรงกลางระหว่างไฟล์ PDF แรก ซึ่งเลขหน้าเวลา Count จะไม่ถูกต้อง เพราะผม แบ่งไฟล์ PDF แรกเป็นสองส่วน โดยเป็นส่วนหัวและท้าย ซึ่งเวลามัน count page ก็จะแยกกันซึ่งไม่ถูกต้อง คือสมมติ ส่วนหัวมี 10 หน้า และท้าย 5 หน้ามันแสดงเป็น 1 of 10 และ ส่วนท้ายแสดงเป็น 1 of 5 ซึ่งส่วนท้ายต้องเป็น 11 of 15

ผมจึงคิดว่าให้ ส่วนหัว ส่งค่ากลับมาที่ vb ว่ามีจำหน้าทั้งหมดเท่าไหร่ และผมจะส่ง เป็น Parameter ให้กับส่วนท้าย
นะครับ แต่วิธีส่งค่ากลับมาวีบี ทำไงอะครับ ผมรู้สึกว่ามันไม่มีทาง แต่ท่านใดมีแนวทางอื่น ช่วยผมทีครับ


ผมตอบไว้ดังนี้ครับ
สมมติว่าผมสร้าง ITextObject 1 ตัวเอาไว้ที่ Report Footer ของ Crystal Report ตั้งชื่อ txtTotalPage แล้วเอาค่าของ PageNo มาใส่ไว้


ในโค้ด VB

Dim rptDoc As New ReportDocument
rptDoc.FileName = Server.MapPath("~/Reports/Test.rpt")
rptDoc.SetDataSource(DataSet1)
rptDoc.SetParameterValue(0, CDate(Me.txtAsOfDate.Text).ToString("dd MMMM yyyy"))

Dim txtTotalPage As TextObject = TryCast(rptDoc.ReportDefinition.ReportObjects("txtTotalPage"), CrystalDecisions.CrystalReports.Engine.TextObject)

Dim TotalPage As Integer = 0
If IsNumeric(txtUSAmount.Text) Then
TotalPage = CInt(txtUsAmount.Text)
End If


เสร็จแล้วก็เอา TotalPage ไปเป็น Parameter ของ report ตัวที่สอง จากนั้นก็ Export รายงานทั้ง 2 ตัว เป็น pdf แล้วเอามา merge กัน

ทีนี้นอกจาก เราจะอ่านค่าจาก TextObject เรายังสามารถใส่ค่าเข้าไปให้ TextObject ก็ได้ หรือว่าจะกำหนด property อื่นๆ เช่น Top, Width, EnableSuppress ....

ลองดูตัวอย่างครับ


Dim pos As Integer
Dim iCurrency As Integer
Dim txtEUAmount As TextObject = rptDoc.ReportDefinition.ReportObjects("txtEUAmount")
Dim txtEUSum As ReportObject = rptDoc.ReportDefinition.ReportObjects("txtEUSum")

'เรียก function เพื่อตรวจสอบเงื่อนไขสกุลเงิน
If IsContainCurrency(ARStatementOfAccounts, "EUR") Then
iCurrency += 1
pos = CalculateObjectPosition(iCurrency) ' เรียกฟังก์ชันสำหรับคำนวณตำแหน่งของ Object ใน Detail
txtEUAmount.Left = pos
pos = CalculateSumObjectPosition(iCurrency) 'เรียกฟังก์ชันสำหรับคำนวนตำแหน่งของ Object ใน Group Footer
txtEUSum.Top = pos
Else
txtEUAmount.Text = ""
txtEUSum.ObjectFormat.EnableSuppress = True
End If

pos = 920 + (iCurrency - 1) * 280
DirectCast(rptDoc.ReportDefinition.ReportObjects("LineFV0"), LineObject).Bottom = pos


จะสังเกตุว่ามีการประกาศตัวแปร TextObject และ ReportObject ครับ ซึ่ง ReportObject นั้นเป็น Base Class ของ Object ต่างๆ เช่น LineObject, TextObject ใน Crystal นั่นเอง ดังนั้นถ้าเรารู้ Type แน่นอน เราสามารถทำการ Casting เพื่อกำหนด property เฉพาะของ Type นั้นๆได้ครับ

ก็ไม่ยากใช่ไหมครับ ตอนนี้เราสามารถเขียนโปรแกรมเพื่อทำ Dynamic Layout ของ Crystal Report ได้แล้ว

ไม่มีความคิดเห็น: