Mỗi tuần một chuyên đề

Tạo report hàng ngang

  • Thread starter phecvit
  • Ngày gửi
P

phecvit

Guest
26/5/06
3
0
0
42
HCM
giúp mình tạo 1 report hang ngang duoc khong?ví dụ 1 trường tiểu học có 15 lớp,từ khối 1 tới khối 5.mổi khối có 3 lớp và slhs.Làm sao để tạo 1 báo cáo hàng ngang.ví dụ :
khối 1 khối 2 khối 3 khối 4 khối 5
lớp slhs lớp slhs lớp slhs lớp slhs lớp slhs
1A1 45 2A1 48 3A1 41 4A1 42 5A1 43
1A2 43 2A2 41 3A2 40 4A2 39 5A2 40
1A3 41 2A3 45 3A3 47 4A3 45 5A3 45

TONG : 129 TONG : 134 TONG :128 TONG :126 TONG :128

TỔNG HS CỦA TRƯỜNG LÀ: 645 HS
Với cơ sơ dữ liệu gồm nhiều tỉnh,nhiều hệ và nhiều trường.1 trường nhiều lớp.Các bạn giúp mình nhé.Thanks
 
Khóa học Quản trị dòng tiền
C

Cayman

Cao cấp
26/11/03
246
4
0
43
HCM
danketoan.com
Chưa hiểu rõ câu hỏi của bạn lắm ? Bạn dùng report trong chương trình nào ? Đơn giản nhất là trong Excel thì mình nghĩ dùng Pivot Table cũng giúp bạn tạo report đó !
 
HongViet

HongViet

Cao cấp
10/11/05
286
10
18
Đà nẵng
Đây là ACCESS mà, fải không?!

Trong access thì bạn thử xài hàm =DCOUNT([F2];[Table0]) xem sao; Vô tư đi cho mọi control!:dance2:
Khi tính tổng thì =DSUM([F1];[Table0]) hay réo tên các control đó ra mà =CTr1 + CTr2 + CTr3 +. . . :dzo:
 
Sửa lần cuối:
P

phecvit

Guest
26/5/06
3
0
0
42
HCM
minh sử dụng access de viet chương trình quản ly học sinh.Nhưng khi viết báo cáo thi nó hiển thị theo hàng dọc,hết khối 1 rồi tới khối 2....Mình muốn bản báo cáo dàn theo hàng ngang nhưng không được.bạn nào chỉ minh đi.
Bạn Hồngviet đã hướng dẫn nhưng sao mình lam không rõ lắm.bạn chỉ rõ hơn dược không.
Bạn nào cho mình mail minhsẽ gởi bài chi tiết cho bạn xem.Xin chỉ giáo cho mình nhé.Cám 7n
 
paulsteigel

paulsteigel

Trung cấp
13/11/05
103
0
16
48
Hoà Bình
www.sfdp.net
Về kỹ thuật tạo báo cáo hàng ngang, dữ liệu động dùng access, tôi xin phép được trình bày vài điều căn bản nhé.
1. Đặt vấn đề
+ Tôi có một bảng dữ liệu có một số cột là Tên lớp, Số học sinh ….
+ Tôi muốn in ra báo cáo theo đó các cột về lớp sẽ hiển thị.
+ Tôi muốn lọc ra các danh sách trong đó điều kiện là số học sinh.
2. Phân tích
Do việc chúng ta chọn danh sách lớp làm số cột và có quản lý điều kiện thông qua số học sinh vì thế với các điều kiện khác nhau thì số lớp hiển thị cũng khác nhau.
Về mặt kỹ thuật, điều này có thể giải quyết tốt đối với các báo cáo có số cột cố định và lớp sẽ hiển thị theo dòng.
Trong báo cáo của access, chúng sử dụng các cột làm các nhân tố phát xuất dữ liệu để in vì thế nó đòi hỏi dữ liệu nguồn cho cột báo cáo là cố định, vì thế ta có thể tiến tới một kết luận có vẻ khá buồn bã là: Muốn hiển thị được điều bạn làm thì phải thiết kế ra tất cả các báo cáo ứng với mỗi điều kiện bạn lựa chọn… Khó quá – điều này là không khả thi.
Vâng, quả thật làm sao mà không loay hoay được cơ chứ… Nhưng thật may mắn – công cụ VBA và các dạng truy vấn lại có thể giúp chúng ta làm điều này một cách dễ dàng. Các bạn xem này.
Trong lần trả lời của ai đó trước đấy có đề cập đến Pivot table, vâng đúng vậy, Access cũng có một công cụ như vậy song nó đựơc đặt tên là Crosstab Querry.
Ta hãy xem một đoạn Query như thế này:

TRANSFORM Sum(tbl_Basic.Figures) AS SumOfFigures
SELECT tbl_Basic.Heading, tbl_Basic.UpperID
FROM tbl_Basic
WHERE (((nz([IsFeedBack],0))=0) AND ((tbl_Basic.Level)=4) AND ((tbl_Basic.UpperID)=2))
GROUP BY tbl_Basic.Heading, tbl_Basic.UpperID
PIVOT tbl_Basic.ID;

TRANSFORM Sum(tbl_Basic_His.Figures) AS SumOfFigures
SELECT tbl_Basic_His.ID, tbl_Basic_His.Heading
FROM tbl_Basic_His
WHERE (((tbl_Basic_His.Level)=3) AND ((tbl_Basic_His.ID)=2))
GROUP BY tbl_Basic_His.ID, tbl_Basic_His.Heading
ORDER BY tbl_Basic_His.Heading
PIVOT tbl_Basic_His.Year In (2005,2004,2003);
Cách tạo ra truy vấn Crosstab
Cú pháp
TRANSFORM [hàm tính tổng]
[mệnh đề select]
PIVOT [trường hiển thị dạng cột] [IN (giá trị 1[, giá trị 2[, ...]])]
..
Các phần của cú pháp
Hàm tính tổng: Là một hàm tính tổng dạng SQL sẽ thực thi tính toán đối với dữ liệu đã lựa chọn.
Mệnh đề Select: Là một mệnh đề truy vấn Select.
Trường hiển thị dạng cột: Là trường hay biểu thực bạn muốn sử dụng làm cột trong kết quả truy vấn.
Giá trị 1, giá trị 2: Giá trị cố định dùng để làm đề mục tên cột hiển thị.
Lưu ý
Khi bạn tóm tắt dữ liệu bằng truy vấn crosstab, bạn sẽ chọn các giá trị từ các trường cụ thể nào đó hay biểu thức làm cột vì thế bạn có thể xem được dữ liệu dạng gọn gàng hơn so với một truy vấn dạng Select.
Cú pháp Transform là tuỳ chọn nhưng khi được đưa vào làm mệnh đề đầu tiên trong chuỗi truy vấn, nó sẽ thực hiện truy vấn Select theo trường được đặc tả để hiển thị dòng và mệnh đề GROUP BY theo đó quy định nhóm dòng lại.
Ngoài ra, bạn có thể bổ sung các mệnh đề khác như WHERE để đặc tả điều kiện. Các giá trị trả về trong trường đã chọn làm cột theo một dãy giá trị đặc tả trong cú pháp IN().
Ví dụ bạn có thể chuyển dòng cột các số liệu bán hàng của các tháng trong năm bằng cách sử dụng một cú pháp truy vấn Crosstab để hiển thị lượng bán trong 12 tháng với việc dùng thêm cấu trúc IN (1,2,3....11,12).
Quay lại phần trên các bạn có thể thấy việc tạo ra một báo cáo chung nhất để hiển thị dữ liệu theo hàng ngang là tương đối dễ dàng bất kể số lượng cột có thể thay đổi. Tuy nhiên chúng ta cần lưu ý một số vấn đề sau:
+ Xác định số cột tối đa mà khổ giấy A4 có thể hiển thị để giới hạn kết quả in ra. Ví dụ ta có 16 lớp trong khi chỉ có thể in được 12 cột trên một trang giấy chẳng hạn.
+ Đặt sẵn ra 12 textbox có mục controlsource để dạng Unbound.
+ Thiết kế truy vấn Crosstab.
+ Sau đó bạn tiến hành viết một số thủ tục Visual Basic để gán cho textbox controlSource là các trường kết quả của Query trên (Lưu ý là tên lớp cần phải được chuẩn hoá ví dụ 11A, 12B, 11C, 9A...)
Về thủ tục này - các bạn có thể tham khảo trong phần mềm VDP tôi có đăng tại www.sfdp.net hoặc trao đổi cụ thể với tôi qua email, vì nó cũng khá dài và phức tạp do yêu cầu của phần mềm đó.
Và thế là xong ....
Tư tưởng của thủ tục này cũng không có gì khá phức tạp. Tôi mạn phép trích ra vài dòng để các bạn xem nhé:
Quy trình tiến hành như sau:
  • Tạo lập một Crosstab Query với các tham số sau:
TRANSFORM Sum(tbl_class.AverageMark) AS SumOfAverageMark
SELECT tbl_class.NumberofStudent, Sum(tbl_class.AverageMark) AS [Total Of AverageMark]
FROM tbl_class
GROUP BY tbl_class.NumberofStudent
PIVOT tbl_class.ClassName;
  • Dùng wizard để thiết kế báo cáo với querry trên (chọn tối đa 8 trường thôi) và thay đổi các đối tượng như sau:
  • Các Textbox được đặt tên là txtxx trong đó xx là số thứ tự ví dụ txt1, txt2
  • Đặt vào báo cáo các nhãn có tên cũng tương tự ví dụ lblxx
Trong phần sự kiện report_open, ta đặt các thủ tục để tiến hành gán thuộc tính controlsource cho các textbox.
Lưu ý:
Vì các cột có dữ liệu sẽ thay đổi do đó nhãn sẽ cần có thay đổi tương ứng. Chúng ta hoàn toàn có thể làm điều này thông qua việc mở một đối tượng recordset để xem tên trường là gì và thay đổi nhãn tương ứng cho phù hợp nhé


Gửi kèm theo đây là ví dụ của tôi, các bạn tải về và xem nhé - nhớ chọn điều kiện để có thể xem được báo cáo…
Chúc vui vẻ hen
Còn đây là đoạn mã nguồn của form
Option Compare Database

Private Sub Command2_Click()
' Tao ra cross tab query nay
Dim tSql As String
tSql = "TRANSFORM Sum(tbl_class.AverageMark) AS SumOfAverageMark " & _
"SELECT tbl_class.NumberofStudent, Sum(tbl_class.AverageMark) AS [Total Of AverageMark] " & _
"FROM tbl_class " & _
"WHERE Val(tbl_class.ClassName)=" & Combo0 & " " & _
"GROUP BY tbl_class.NumberofStudent " & _
"PIVOT tbl_class.ClassName;"
On Error Resume Next
DoCmd.DeleteObject acQuery, "tbl_class_Crosstab"
CurrentDb.CreateQueryDef "tbl_class_Crosstab", tSql
DoCmd.OpenReport "rpt_Test", acViewPreview
End Sub
Mã nguồn báo cáo đây
Option Compare Database

Private Sub Report_Open(Cancel As Integer)
' Xac dinh xem hien co nhung cot nao xuat hien, neu it hon 8 thi cac cot con lai se
' de nhan la trang va textbox co control source la unbound
Dim rs As Recordset, i As Long
Set rs = CurrentDb.OpenRecordset(Me.RecordSource)
Dim iFld As Field
For Each iFld In rs.Fields
'Debug.Print iFld.Name
If i > 7 Then Exit For
' chu y dieu kien de loc cho dung truong nhe
If Val(iFld.Name) <> 0 Then
' Trước khi làm việc này lưu ý - cần phải ..... không thì chúng ta không nhìn thấy các cột nữa .. hihi:pepsi:
' gan cac truong va nhan o day
Me.Controls("lbl" & i + 1).Caption = iFld.Name
Me.Controls("txt" & i + 1).ControlSource = iFld.Name
i = i + 1
End If
Next
' bay gio xoa cac nhan
While i <= 7
Me.Controls("lbl" & i + 1).Caption = ""
Me.Controls("txt" & i + 1).ControlSource = ""
i = i + 1
Wend
Set rs = Nothing
End Sub
':dance2: Ở đây tôi còn thiếu một việc - đố các bạn biêt là gì?:drummer:
Xin phép được không giải thích ở đây mà tôi sẽ giới thiệu sau nhé.
Nay xin tạm dừng.
 

Đính kèm

  • test_wkt.rar
    21 KB · Lượt xem: 318
Sửa lần cuối:
L

luckytranquan

Guest
3/5/05
31
0
0
43
HCM
Chao Paulstei...!
01. Bài bạn viết rất hay, khi nay mình không nghĩ ra cách truyền thông số cho Crostab. Nay cảm ơn bạn nhiều.
02. Bạn cho mình hỏi thêm vấn đề này nữa:
- Mình muốn biết đoạn code để mở một file (vd: .doc) được đặt sẵn trong 01 thư mục nào đó khi mình command có điều kiện để mở chúng lên. Mình muốn ứng dụng để tại cho mình một chương trình quản lý VB mình hay dùng đấy mà.

Mong giúp đệ tử!

ketoantructuyen@yahoo.com
 
T

thanhlongcom

Guest
9/6/06
6
0
0
Hà Nội
Mong các bạn giúp mình giải quyết vấn đề sau với nhé:

Yêu cầu thể hiện Crosstab
Column heading: Giới tính Là NV Chưa là NV
Row heading Nam 2 1
Nữ 2 2

Khi mình làm Crosstab thể hiện như sau:
Coumn heading: Giới tính -1 0
Vì trong table, trường Nhân viên có giá trị booland

Vậy mình phải làm thế nào?!!
 
paulsteigel

paulsteigel

Trung cấp
13/11/05
103
0
16
48
Hoà Bình
www.sfdp.net
Xin tạm nợ bạn thanhlongcom về bài trả lời chi tiết nhé – tôi không rõ ý hỏi của bạn nhưng có thể đưa ra một đề xuất đơn giản bằng cách dùng hàm người dùng cho trường hợp của bạn.
Với câu hỏi của bạn, ta có 2 cách giải quyết
  • Dùng phép tính SQL
Ví dụ select iif([gioitinh]=true,1,2) as gioitinhx from [tenbang]
đoạn iif([gioitinh]=true,1,2) là câu trả lời đấy ... bạn hãy thử xem nào
  • Hàm người dùng
Bạn hãy mở một module, viết một hàm để chuyển đổi giá trị ví dụ:
Function ConvertSex(InputText)
.... và đặt xử lý thủ tục ở đây
End function
Sau đó bạn có thể gọi SQL
Select ConvertSex([gioitinh] from [tenbang];
Cách này về cơ bản giống cách 1 nhưng đây là điểm nổi bật của Access VBA - cực mạnh
... Còn tại sao, tôi xin nợ các bạn. Bận quá!
Về câu hỏi của bạn luckytranquan, tôi chỉ xin gợi ý một cách đơn giản là dùng hàm ShellExecute (dùng cho cả VBA và VB được – nhưng phải khai báo hàm API này trước khi dùng) hoặc đơn giản là docmd ... của Access.
Cách khác là bạn dùng BoundObject ví dụ nếu muốn mở Tài liệu Word, bạn hãy tạo ra một đối tượng word và điểu khiển word theo ý bạn. Cách làm chi tiết tôi đã nói khá nhiều trong topic OFFICE VBA mỗi ngày một ví dụ trên www.ddth.com, nay xin không trích lại.
Thành thật xin lỗi các bạn vì không viết được nhiều.
Nay kính thư.
 
T

thanhlongcom

Guest
9/6/06
6
0
0
Hà Nội
Mình mới bước chân vào khám phá anh chàng Access này thôi, nên nhiều khi, trong cách hỏi mọi người cũng không rõ ràng. Chán mình thật.

Mình đưa rõ hơn mong bạn bè giúp đỡ nhé.
Trong Table:
1. Trường Mã GiaNhap
2. Trường Là NV: Data Type = Yes/No(Yes = Là nhân viên, No = Chưa là nhân viên).
3. Trường GioiTinh

Khi lập Crosstab:
GioiTinh: Row heading
La NV: Column heading
Ma GiaNhap:Value
=>Khi View sẽ như sau:
GioiTinh -1 0
Nam
Nu

Tuy nhiên, mình phải thể hiện như thành (-1 = Là Nhân viên, 0 = Chưa là nhân viên). Vậy có cách nào đơn giản không phải sử dụng đến VBA vì phần mình học chưa có nói đến VBA.
 
HongViet

HongViet

Cao cấp
10/11/05
286
10
18
Đà nẵng
Khi bạn thiết kế Report trên CrosstabQuery thì thấy 2 trường [0] & [-1]. Nhưng tên của trường (để mọi người nhìn thấy) ta có thể gán khác mà ( Khi kéo trường đó vô lưới report thì mình hay sửa lại tên cho 2 control này & chuyển nó lên phần hearter):
G_T : NoTV : TVCT
Nu : 112 : 51
Nam : 49: 99
 
paulsteigel

paulsteigel

Trung cấp
13/11/05
103
0
16
48
Hoà Bình
www.sfdp.net
thanhlongcom nói:
Mong các bạn giúp mình giải quyết vấn đề sau với nhé:

Yêu cầu thể hiện Crosstab
Column heading: Giới tính Là NV Chưa là NV
Row heading Nam 2 1
Nữ 2 2

Khi mình làm Crosstab thể hiện như sau:
Coumn heading: Giới tính -1 0
Vì trong table, trường Nhân viên có giá trị booland

Vậy mình phải làm thế nào?!!
Mình đã trả lời rồi mà
  • Dùng phép tính SQL
Ví dụ select iif([gioitinh]=true,1,2) as gioitinhx from [tenbang]
đoạn iif([gioitinh]=true,1,2) là câu trả lời đấy ... bạn hãy thử xem nào
Bạn hãy chú ý cấu trúc iif đặt trong cú pháp SQL này
select iif([GiaNhap]=-1,"Là nhân viên","Chưa là Nhân viên") as NhanvienX from [tenbang];
Đấy nhé, có gì bạn mail cho tôi ngocdd@sfdp.net
 
Secret_grasses

Secret_grasses

Guest
paulsteigel nói:
Đấy nhé, có gì bạn mail cho tôi ngocdd@sfdp.net
Vậy, cuối cùng anh đã quyết định trở lại rồi hả anh? Nếu vậy thì em mừng lắm!:inlove:
 

Xem nhiều

Webketoan Zalo OA