Dim picture1 As CrystalDecisions.CrystalReports.Engine.PictureObject
picture1 = reportDoc.ReportDefinition.ReportObjects("Picture1")
picture1.ObjectFormat.EnableSuppress = True
แสดงบทความที่มีป้ายกำกับ Crystal Report แสดงบทความทั้งหมด
แสดงบทความที่มีป้ายกำกับ Crystal Report แสดงบทความทั้งหมด
วันศุกร์ที่ ๓๐ กันยายน พ.ศ. ๒๕๕๔
โค้ดสั่ง Suppress Picture ใน Crystal Report
ป้ายกำกับ:
Crystal Report,
VB.NET
วันอังคารที่ ๙ กุมภาพันธ์ พ.ศ. ๒๕๕๓
Crystal Report - สร้างรายงานให้ user กำหนดเงื่อนไข Group ได้เอง (Dynamic Group By)
วันนี้เรามาดูเทคนิคของ Crystal Report อีกครั้งครับ (เนื่องจากดูใน Google Analytics เห็นคนชอบบทความเกี่ยวกับ Crystal Report เป็นพิเศษ) คราวนี้เราจะมาสร้างรายงานที่สามารถให้ user กำหนด Group By ได้เองตามใจ Blog นี้จะทำแค่ Group by 1 ระดับให้ดู แต่เราสามารถประยุกต์ใช้ให้ user เลือก group ได้มากกว่า 1 ระดับ รวมถึงสามารถกำหนดเงื่อนไข sort by ได้ด้วย
ก่อนอื่นเลยสิ่งที่จำเป็นก็คือ เราต้องสร้าง Parameter Field ขึ้นมาก่อน เพื่อรับค่า parameter จาก user ว่าต้องการให้ group by column ไหนของข้อมูลครับ จากตัวอย่างผมสร้าง Parameter Field ชื่อ pGroupBy

จากนั้นก็สร้าง Formula Field เพื่อนำค่าที่ได้จาก Parameter Field มาคำนวนหา column ที่ต้องการ group ครับ
ในตัวอย่างผมสร้าง Formula Field ชื่อ GroupBy

จากโค้ดใน Formula Editor ผมใช้ IF THEN ELSE ซ้อนกัน (ที่จริงน่าใช้ Switch Case แต่ผมขี้เกียจแก้แล้ว) สังเกตุว่าถ้า user ส่ง parameter มาเป็น Dept ผมจะให้ Group By Formula Field อีกที นอกนั้นก็จะ Group By Database Field ตามปกติครับ
คราวนี้มาดูหน้าเวบกันบ้างครับ ผมก็สร้าง Drop-down List มา 1 ตัว ชื่อ ddlGroupBy และใส่ List ที่ต้องการไว้
ตอนสร้างรายงานก็อย่าลืม SetParameterValue ด้วยครับ
เท่านี้ก็เรียบร้อยแล้วครับ ทีนี้ user ก็สามารถเลือก column ที่ต้องการ Group By ได้ตามใจครับ
ก่อนอื่นเลยสิ่งที่จำเป็นก็คือ เราต้องสร้าง Parameter Field ขึ้นมาก่อน เพื่อรับค่า parameter จาก user ว่าต้องการให้ group by column ไหนของข้อมูลครับ จากตัวอย่างผมสร้าง Parameter Field ชื่อ pGroupBy
จากนั้นก็สร้าง Formula Field เพื่อนำค่าที่ได้จาก Parameter Field มาคำนวนหา column ที่ต้องการ group ครับ
ในตัวอย่างผมสร้าง Formula Field ชื่อ GroupBy
จากโค้ดใน Formula Editor ผมใช้ IF THEN ELSE ซ้อนกัน (ที่จริงน่าใช้ Switch Case แต่ผมขี้เกียจแก้แล้ว) สังเกตุว่าถ้า user ส่ง parameter มาเป็น Dept ผมจะให้ Group By Formula Field อีกที นอกนั้นก็จะ Group By Database Field ตามปกติครับ
คราวนี้มาดูหน้าเวบกันบ้างครับ ผมก็สร้าง Drop-down List มา 1 ตัว ชื่อ ddlGroupBy และใส่ List ที่ต้องการไว้
</asp:DropDownList ID="ddlGroupBy" runat="server" style="position:absolute;left:100px;top:10px" CssClass="txtOptional" Width="110px" EnableTheming="False" EnableViewState="False" >
</asp:ListItem Text="Client" Value="Client" Selected="True"></asp:ListItem>
</asp:ListItem Text="Most Work Lawyer" Value="MostWorkLawyer"></asp:ListItem>
</asp:ListItem Text="Resp. Lawyer" Value = "RespStaff"></asp:ListItem>
</asp:ListItem Text="Department" Value="Dept" ></asp:ListItem>
</asp:DropDownList>
ตอนสร้างรายงานก็อย่าลืม SetParameterValue ด้วยครับ
Dim reportDoc As New ReportDocument
reportDoc.FileName = Server.MapPath("~/Reports/AR/rptAgingReport.rpt")
reportDoc.SetDataSource(ARReportResults)
reportDoc.SetParameterValue("pGroupBy", ddlGroupBy.SelectedValue)
reportDoc.SetParameterValue("AsOfDate", asOfDate)
เท่านี้ก็เรียบร้อยแล้วครับ ทีนี้ user ก็สามารถเลือก column ที่ต้องการ Group By ได้ตามใจครับ
ป้ายกำกับ:
Crystal Report,
Tips
วันศุกร์ที่ ๒๙ มกราคม พ.ศ. ๒๕๕๓
Crystal Report - แสดงข้อความหลายคอลัมภ์ด้วย RTF Text Interpretation
วันก่อนได้รับ requirement ว่าในรายงานตัวหนึ่ง ต้องการให้แสดง Report Footer เพื่อแสดงข้อมูลตามเงื่อนไข โดยข้อมูลดังกล่าวต้องสามารถ ทำตัวหนา ตัวเอียง สำหรับข้อมูลที่ต้องการเน้น และจัดรูปแบบเป็น 2 คอลัมภ์ ซึ่งใน Report Footer มีทั้งหมด 5 ส่วน ส่วนดังกล่าวเป็นส่วนที่ 4
เริ่มแรกผมสร้าง Parameter Field มา 1 ตัว ชื่อ PaymentAccount และสร้าง Text Object มา 1ตัว และลาก Payment Account มาใส่ใน Text Object เพื่อให้เป็น Embedded Field เราจะได้สามารถกำหนด Text Interpretation ได้ครับ (จากรูปสังเกตุว่าเป็น Report Footer d)

เสร็จแล้วคลิ๊กเมาส์ขวาที่ Text Object ที่สร้างขึ้น เลือก Property แล้วคลิ๊กเครื่องหมายถูกที่ Can Grow ใส่ตัวเลข 0 คือไม่จำกัดบรรทัดลงไป เพื่อให้ Object นี้มันยืดได้
ต่อไปก็กำหนด Text Interpretation โดยการ double click ที่ Text Object แล้วเลือก Embedded field คลิ๊กเมาส์ขวา เลือก Format Embedded Field

เสร็จแล้วก็เลือก Paragraph Tab เลือก Text Interpretation เป็น RTF Interpretation

เสร็จขั้นตอนของรายงานแล้ว ทีนี้ก็มาเขียนโค้ดสำหรับสร้างข้อมูล RTF ครับ
มาดูรายละเอียดกันครับ
{\rtf1\ansi\ansicpg1252\deff0\deflang1033\deflangfe1033{\fonttbl{\f0\fswiss\fprq2\fcharset0 Arial;}}
บรรทัดนี้เรากำหนด RTF Format และกำหนดให้ใช้ ANSI PAGE 1252 และ font คือ Arial
\viewkind4\uc1\pard\nowidctlpar\sa200\sl276\slmult1\tx720\tx3600\f0\fs20
บรรทัดนี้เรากำหนดให้เอกสารเรามี tab 2 อัน อันแรกคือ tx720 แปลว่าอยู่ที่ 720 twips หรือ 0.5 นิ้ว (โดยปกติ 1นิ้ว จะเท่ากับ 1440 twips) และอันที่สองคือ tx3600 คือ 3600 twips หรือ 2.5นิ้ว ส่วน fs20 คือขนาดของ font เท่ากับ 10 pt ครับ
\tab Account Name \tab Nithi Juabsami \par
แปลว่าพิมพ์ tab 1 ครั้ง (คือเลื่อนไปตำแหน่งที่ 0.5 นิ้วที่กำหนด) พิมพ์คำว่า Account Name แล้วพิมพ์ tab (เลื่อนไปยังตำแหน่ง 2.5 นิ้ว พิมพ์ Nithi Juabsamai แล้วขึ้นบรรทัดใหม่ (\par)
ตอนเขียนโค้ดสั่ง Report ก็เรียกฟังก์ชันนี้เพื่อส่ง parameter ให้ Crystal Report
คราวนี้ลองรันดูผลลัพธ์ครับ

เรียบร้อยครับ ตอนนี้ข้อมูล Payment Account ของเราก็แสดงเป็น 2 column (ซึ่งเราแบ่งด้วย Tab) ถ้าต้องการเพิ่ม Column เราก็สามารถกำหนด tab ที่ตำแหน่งที่ต้องการเพิ่มได้ครับ
ที่จริงเราสามารถกำหนด HTML Interpretation ได้ครับ แต่ว่า Cystal Report รองรับแค่ subset ของ HTML ครับ คือรองรับได้แค่บาง tag ซึ่ง tag อย่าง table ไม่รองรับครับ ผมเลยเปลี่ยนมาใช้ RTF Interpretation แทน
หมายเหตุ
จริงๆแล้วเราสามารถใช้ Word Pad ที่มาพร้อม Windows ในการจัดเอกสารตามต้องการ สามารถกำหนดตัวหนา ตัวเอียงได้ตามสะดวก แล้ว save เป็น rtf ไฟล์ จากนั้นก็ใช้ Note Pad เปิดมา copy ใส่ได้เลยครับ แต่อย่าใช้ Microsoft Word นะครับ เพราะมันจะใส่ tag เพิ่มเติมมาเยอะแยะจนน่าเวียนหัว
เริ่มแรกผมสร้าง Parameter Field มา 1 ตัว ชื่อ PaymentAccount และสร้าง Text Object มา 1ตัว และลาก Payment Account มาใส่ใน Text Object เพื่อให้เป็น Embedded Field เราจะได้สามารถกำหนด Text Interpretation ได้ครับ (จากรูปสังเกตุว่าเป็น Report Footer d)
เสร็จแล้วคลิ๊กเมาส์ขวาที่ Text Object ที่สร้างขึ้น เลือก Property แล้วคลิ๊กเครื่องหมายถูกที่ Can Grow ใส่ตัวเลข 0 คือไม่จำกัดบรรทัดลงไป เพื่อให้ Object นี้มันยืดได้
ต่อไปก็กำหนด Text Interpretation โดยการ double click ที่ Text Object แล้วเลือก Embedded field คลิ๊กเมาส์ขวา เลือก Format Embedded Field
เสร็จแล้วก็เลือก Paragraph Tab เลือก Text Interpretation เป็น RTF Interpretation
เสร็จขั้นตอนของรายงานแล้ว ทีนี้ก็มาเขียนโค้ดสำหรับสร้างข้อมูล RTF ครับ
Public Shared Function GetAccount(ByVal coCode As String) As String
Dim sb As New Text.StringBuilder
'Set RTF1, ANSI Page and Font-family
sb.AppendLine("{\rtf1\ansi\ansicpg1252\deff0\deflang1033\deflangfe1033{\fonttbl{\f0\fswiss\fprq2\fcharset0 Arial;}}")
'Set Tab (at 0.5 in and 2.5 in) and Font-size
sb.AppendLine("\viewkind4\uc1\pard\nowidctlpar\sa200\sl276\slmult1\tx720\tx3600\f0\fs20")
'Insert first blank line
sb.AppendLine("\tab \par ")
Select Case coCode
Case "Nithi"
sb.AppendLine("\tab Account Name \tab Nithi Juabsami \par ")
sb.AppendLine("\tab Savings Account No.: \tab 1-1111-1111, USD account. \par")
sb.AppendLine("\tab Bank Name: \tab Citibank, N.A. \par ")
sb.AppendLine("\tab Bank Address: \tab 82 North Sathorn Road \par ")
sb.AppendLine("\tab \tab Silom, Bangrak, \par ")
sb.AppendLine("\tab \tab Bangkok 10500, Thailand \par ")
sb.AppendLine("\tab -or- \par ")
sb.AppendLine("\tab Account Name: \tab Nithi Juabsamai \par ")
sb.AppendLine("\tab Savings Account No.: \tab x-xxxx-xxxx \par ")
sb.AppendLine("\tab Bank Name: \tab The Siam Commercial Bank Plc., Thanon Witthayu Branch \par ")
sb.AppendLine("\tab Bank Address: \tab 132 Wireless Road, Lumpini, Bangkok 10330 \par ")
Case "jNithi"
sb.AppendLine("\tab Account Name: \tab jNithi O.P. \par ")
sb.AppendLine("\tab Bank Account No.: \tab xxx-xxxxxx-xxx (USD), Current Account \par ")
sb.AppendLine("\tab Name of Bank: \tab The Siam Commercial Bank Plc., Thanon Witthayu Branch. \par ")
sb.AppendLine("\tab Bank Address: \tab 132 Wireless Road, Lumpini, Bangkok 10330 \par ")
Case Else
End Select
' Insert bottom blank line
sb.AppendLine("\tab \par ")
' SET end of RTF
sb.AppendLine("}")
Return sb.ToString
End Function
มาดูรายละเอียดกันครับ
{\rtf1\ansi\ansicpg1252\deff0\deflang1033\deflangfe1033{\fonttbl{\f0\fswiss\fprq2\fcharset0 Arial;}}
บรรทัดนี้เรากำหนด RTF Format และกำหนดให้ใช้ ANSI PAGE 1252 และ font คือ Arial
\viewkind4\uc1\pard\nowidctlpar\sa200\sl276\slmult1\tx720\tx3600\f0\fs20
บรรทัดนี้เรากำหนดให้เอกสารเรามี tab 2 อัน อันแรกคือ tx720 แปลว่าอยู่ที่ 720 twips หรือ 0.5 นิ้ว (โดยปกติ 1นิ้ว จะเท่ากับ 1440 twips) และอันที่สองคือ tx3600 คือ 3600 twips หรือ 2.5นิ้ว ส่วน fs20 คือขนาดของ font เท่ากับ 10 pt ครับ
\tab Account Name \tab Nithi Juabsami \par
แปลว่าพิมพ์ tab 1 ครั้ง (คือเลื่อนไปตำแหน่งที่ 0.5 นิ้วที่กำหนด) พิมพ์คำว่า Account Name แล้วพิมพ์ tab (เลื่อนไปยังตำแหน่ง 2.5 นิ้ว พิมพ์ Nithi Juabsamai แล้วขึ้นบรรทัดใหม่ (\par)
ตอนเขียนโค้ดสั่ง Report ก็เรียกฟังก์ชันนี้เพื่อส่ง parameter ให้ Crystal Report
rpt = New rptTestReceipt
rpt.SetDataSource(_receipt)
rpt.SetParameterValue("AsOfDate", AsOfDate.ToString("dd MMM yyyy"))
rpt.SetParameterValue("PaymentAccount", PaymentAccount.GetAccount(_receipt(0).CoCode))
คราวนี้ลองรันดูผลลัพธ์ครับ
เรียบร้อยครับ ตอนนี้ข้อมูล Payment Account ของเราก็แสดงเป็น 2 column (ซึ่งเราแบ่งด้วย Tab) ถ้าต้องการเพิ่ม Column เราก็สามารถกำหนด tab ที่ตำแหน่งที่ต้องการเพิ่มได้ครับ
ที่จริงเราสามารถกำหนด HTML Interpretation ได้ครับ แต่ว่า Cystal Report รองรับแค่ subset ของ HTML ครับ คือรองรับได้แค่บาง tag ซึ่ง tag อย่าง table ไม่รองรับครับ ผมเลยเปลี่ยนมาใช้ RTF Interpretation แทน
หมายเหตุ
จริงๆแล้วเราสามารถใช้ Word Pad ที่มาพร้อม Windows ในการจัดเอกสารตามต้องการ สามารถกำหนดตัวหนา ตัวเอียงได้ตามสะดวก แล้ว save เป็น rtf ไฟล์ จากนั้นก็ใช้ Note Pad เปิดมา copy ใส่ได้เลยครับ แต่อย่าใช้ Microsoft Word นะครับ เพราะมันจะใส่ tag เพิ่มเติมมาเยอะแยะจนน่าเวียนหัว
ป้ายกำกับ:
Crystal Report,
Tips,
VB.NET
วันพุธที่ ๖ มกราคม พ.ศ. ๒๕๕๓
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
เสร็จแล้วก็เอา TotalPage ไปเป็น Parameter ของ report ตัวที่สอง จากนั้นก็ Export รายงานทั้ง 2 ตัว เป็น pdf แล้วเอามา merge กัน
ทีนี้นอกจาก เราจะอ่านค่าจาก TextObject เรายังสามารถใส่ค่าเข้าไปให้ TextObject ก็ได้ หรือว่าจะกำหนด property อื่นๆ เช่น Top, Width, EnableSuppress ....
ลองดูตัวอย่างครับ
จะสังเกตุว่ามีการประกาศตัวแปร TextObject และ ReportObject ครับ ซึ่ง ReportObject นั้นเป็น Base Class ของ Object ต่างๆ เช่น LineObject, TextObject ใน Crystal นั่นเอง ดังนั้นถ้าเรารู้ Type แน่นอน เราสามารถทำการ Casting เพื่อกำหนด property เฉพาะของ Type นั้นๆได้ครับ
ก็ไม่ยากใช่ไหมครับ ตอนนี้เราสามารถเขียนโปรแกรมเพื่อทำ Dynamic Layout ของ 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 ได้แล้ว
ป้ายกำกับ:
Crystal Report,
Tips,
VB.NET
สมัครสมาชิก:
บทความ (Atom)