Xin trợ giúp tính số lượng hàng nhập theo ngày (1 người xem)

  • Thread starter Thread starter ntquantn
  • Ngày gửi Ngày gửi
Liên hệ QC

Người dùng đang xem chủ đề này

ntquantn

Thành viên chính thức
Tham gia
13/4/12
Bài viết
72
Được thích
12
Chào các bạn,

Mình có 1 file theo dõi hàng nhập và xuất tại các sheets tương ứng.
Mình muốn xem nhanh số lượng từng mã hàng đã nhập theo thời gian (dùng code VBA) mà không biết cách làm thế nào.

Mong các bạn xem file đính kèm và giúp mình đoạn code nhé.

Chân thành cảm ơn.
 

File đính kèm


Cảm ơn befaint,

Tuy nhiên mình muốn sử dụng code vba (vì còn liên quan tới một số yếu tố khác). trong file mình up thì đã xử lý được phần hàng xuất. Còn phần hàng nhập thì mình chưa nắm rõ về mảng hai chiều nên chịu ngắc. Mong bạn xem và giúp mình đoạn code đó nhé.

P/s: Trong file mình up, ở sheet Nhapkhoxuong, cả phần mã hàng (dòng), và ngày (cột) vẫn còn sẽ tiếp tục nhập mở rộng.
 
Upvote 0
Bạn xem file với DSUM() có trợ giúp bỡi VBA
Cảm ơn bạn,

Nhưng bạn xử lý nhầm phần xuất, mình đang gặp rắc rối ở phần nhập kho (sheets("nhapkhoxuong"). Cụ thể là khai báo, xử lý mảng động hai chiều khi Mã hàng (theo dòng) và ngày nhập kho (theo cột) đều có biến động hàng ngày
Bạn xem lại giúp mình userform trong file mình đã up nhé
 
Upvote 0
Bạn gặp rối ở fần nhập kho do thiết chế CSDL không tốt;
& mình gặp loại CSDL đó thì bỏ qua, không dám đụng tới.

Như mình thì fần nhập của bạn nên có các trường sau:
STT, Ngày, Mã HH, ĐVT, Lượng nhập

Nếu bạn chịu thiết chế này mình sẽ tham gia tiếp; Tạm biệt!
 
Upvote 0
Bạn gặp rối ở fần nhập kho do thiết chế CSDL không tốt;
& mình gặp loại CSDL đó thì bỏ qua, không dám đụng tới.

Như mình thì fần nhập của bạn nên có các trường sau:
STT, Ngày, Mã HH, ĐVT, Lượng nhập

Nếu bạn chịu thiết chế này mình sẽ tham gia tiếp; Tạm biệt!

Hic, thế thì hơi nan giải nhỉ. Vì phần này vẫn còn liên quan tới một số phần khác mình đã làm nên giờ bỏ thì lại phải làm lại hết.

Với phần nhập kho này thì mình đã làm theo kiểu đơn giản dùng 2 vòng lặp for thì xử lý được nhưng mà khi dữ liệu lớn lớn chút là chạy chậm quá. Nên mình định nghiên cứu dùng phương pháp mảng 2 chiều để cải thiện tốc độ. Nhưng mình gặp rắc rối phần khai báo mảng động quá.
 
Upvote 0
Vậy, ngắn gọn là tìm đọc đâu đó cách mà người ta tạo ra 1 CSDL chuẩn đi

Mình sẽ tiếp tục giúp bạn là hại bạn thêm đó!

Vĩnh biệt!
 
Upvote 0
Mình xin fát biểu vài nét về cách viết các câu lệnh trong macro của bạn như sau:

a). Khi đã chuye3n sang xài VBA thì tên trang tính như của bạn là hơi dài;
Bạn thấy mã chứng khoán của các đơn vị SX & KD trên sàn giao dịch không, chỉ có ba hay 4 từ thôi;
Tên "Nhapkhoxuong" theo mình là dài, nên chăng "NhapKX";
Nếu bắt buột f ải dài như vậy, sao không là "NhapKhoXuong" cho dễ đọc hay liếc thoáng qua là nhận ra ngay
Điều này cũng nên áp dụng cho các tên tham biến của bạn;
Sao không là "TuNgay" & "DenNgay", mà là "tungay" & "denngay"?
Tên cho macro cũng vậy; Nên là 'NapMa' thay vì 'Napma'

b). Nói thêm về tên tham biến & cách xài:
Ở Sub BaoCao bạn có 2 dòng lệnh như sau:
PHP:
Dim ArrXuat(), ArrNhap(), j As Long, i As Long, tungay As Date, denngay As Date, EndR As Long, EndRN As Long, EndCN As Long, hangxuat As String, hangnhap As String
Dim soluongxuat As Double, soluongnhap As Double
Nếu là mình thì mỉnh sẽ tách ra làm 3 dòng lệnh (không nhằm mục đích nào khác là dễ quản các tham biến mà thôi):
Mã:
 Dim ArrXuat(), ArrNhap()
 Dim  J As Long, I As Long, TuNgay As Date, DenNgay As Date, EndR As Long, EndRN As Long, EndCN As Long, SLgXuat As Double, SLgNhap As Double
 Dim  HangXuat As String, HangNhap As String
b).1 Bạn nên khai báo tường minh, như
(trích các mệnh đề của bạn:)
Mã:
Dim ma
' . . . . .'
LastRow = ThisWorkbook.Worksheets("Nhapkhoxuong").Range("B" & ThisWorkbook.Worksheets("Nhapkhoxuong").Rows.Count).End(xlUp).Row
ma = ThisWorkbook.Worksheets("Nhapkhoxuong").Range("B4:B" & LastRow)
Rõ ràng ở đâu tham biến 'Ma' sẽ chứa mảng số liệu trong 1 vùng
Nếu là mình thì sẽ khai báo tường minh
PHP:
 Dim Ma(), Sh As WorkSheet
 Set Sh= ThisWorkbook.Worksheets("NhapKhoXuong")
 LastRow = Sh.Range("B" & Sh.Rows.Count).End(xlUp).Row
 Ma = Sh.Range("B4:B" & LastRow) .Value
 
Upvote 0
Mình xin fát biểu vài nét về cách viết các câu lệnh trong macro của bạn như sau:

a). Khi đã chuye3n sang xài VBA thì tên trang tính như của bạn là hơi dài;
Bạn thấy mã chứng khoán của các đơn vị SX & KD trên sàn giao dịch không, chỉ có ba hay 4 từ thôi;
Tên "Nhapkhoxuong" theo mình là dài, nên chăng "NhapKX";
Nếu bắt buột f ải dài như vậy, sao không là "NhapKhoXuong" cho dễ đọc hay liếc thoáng qua là nhận ra ngay
Điều này cũng nên áp dụng cho các tên tham biến của bạn;
Sao không là "TuNgay" & "DenNgay", mà là "tungay" & "denngay"?
Tên cho macro cũng vậy; Nên là 'NapMa' thay vì 'Napma'

b). Nói thêm về tên tham biến & cách xài:
Ở Sub BaoCao bạn có 2 dòng lệnh như sau:
PHP:
Dim ArrXuat(), ArrNhap(), j As Long, i As Long, tungay As Date, denngay As Date, EndR As Long, EndRN As Long, EndCN As Long, hangxuat As String, hangnhap As String
Dim soluongxuat As Double, soluongnhap As Double
Nếu là mình thì mỉnh sẽ tách ra làm 3 dòng lệnh (không nhằm mục đích nào khác là dễ quản các tham biến mà thôi):
Mã:
 Dim ArrXuat(), ArrNhap()
 Dim  J As Long, I As Long, TuNgay As Date, DenNgay As Date, EndR As Long, EndRN As Long, EndCN As Long, SLgXuat As Double, SLgNhap As Double
 Dim  HangXuat As String, HangNhap As String
b).1 Bạn nên khai báo tường minh, như
(trích các mệnh đề của bạn:)
Mã:
Dim ma
' . . . . .'
LastRow = ThisWorkbook.Worksheets("Nhapkhoxuong").Range("B" & ThisWorkbook.Worksheets("Nhapkhoxuong").Rows.Count).End(xlUp).Row
ma = ThisWorkbook.Worksheets("Nhapkhoxuong").Range("B4:B" & LastRow)
Rõ ràng ở đâu tham biến 'Ma' sẽ chứa mảng số liệu trong 1 vùng
Nếu là mình thì sẽ khai báo tường minh
PHP:
 Dim Ma(), Sh As WorkSheet
 Set Sh= ThisWorkbook.Worksheets("NhapKhoXuong")
 LastRow = Sh.Range("B" & Sh.Rows.Count).End(xlUp).Row
 Ma = Sh.Range("B4:B" & LastRow) .Value

Rất cảm ơn góp ý của bạn.
Mình hay đặt tên dài vì để mục đích gơi, dễ nhỡ và tiện theo dõi.

P/s: Bạn có thể code giúp mình phần hàng nhập được không?
 
Upvote 0
Chào các bạn,

Mình có 1 file theo dõi hàng nhập và xuất tại các sheets tương ứng.
Mình muốn xem nhanh số lượng từng mã hàng đã nhập theo thời gian (dùng code VBA) mà không biết cách làm thế nào.

Mong các bạn xem file đính kèm và giúp mình đoạn code nhé.

Chân thành cảm ơn.
Cái này cũng đơn giản thôi, muốn thống kê được bên nhập kho thì phải viết 1 macro để chuẩn hóa lại dữ liệu thành 1 sheet nhập kho mới, sau đó dùng sheet nhập kho mới để xử lý.
 
Upvote 0
Rất cảm ơn góp ý của bạn.
Mình hay đặt tên dài vì để mục đích gơi, dễ nhỡ và tiện theo dõi.

P/s: Bạn có thể code giúp mình phần hàng nhập được không?
Tôi "yếu trong mình" chuyện Form, chỉ biết làm thẳng trên sheet thôi được không?
Muốn tìm nhanh bao nhiêu mã hàng tùy ý.
 

File đính kèm

Upvote 0
Cái này cũng đơn giản thôi, muốn thống kê được bên nhập kho thì phải viết 1 macro để chuẩn hóa lại dữ liệu thành 1 sheet nhập kho mới, sau đó dùng sheet nhập kho mới để xử lý.
Theo hướng này cũng có lí à nha!
Nhưng theo mình, tác giả bài đăng nên có trang tính làm fụ trợ; Trên nới chứa danh mục hàng hóa;
Gồm các trường: [STT], [Mã HH], [Tên hàng], [ĐVT], [Lượng tồn theo đợt kiểm kê]
Chúng ta không thể tạo ra trang tính mà có nhiều dòng & cột trống hơ như vậy.
Với bảng 'DM HH' ta hoàn toàn khắc fục được chuyện này

Chuyện macro để chuyển từ trang tính 'Nhap. . . ' gì đó sang trang số liệu chuẩn cũng chả khó là bao:
Lấy 1 trang tính trắng
Tạo vòng lặp duyệt tại trang 'Nhap . .' những dòng có số lượng thì chép sang thành dòng mới ở trang mới này

Ví dụ:
PHP:
Sub TaoTrangNhapSanLuongHH()
 Dim Rws As Long, J As Long, W As Long, Col As Byte, Cot As Integer
 Dim Arr()

 With Sheets("NhapKhoXuong").[b3]
    Rws = .CurrentRegion.Rows.Count
    Col = .End(xlToRight).Column
    Arr() = .Offset(1).Resize(Rws, Col).Value
    ReDim dArr(1 To Rws, 1 To 5)
 End With
 For Cot = 4 To Col
    For J = 1 To UBound(Arr())
        If Arr(J, Cot) <> 0 Then
            W = W + 1:                      dArr(W, 1) = W
            dArr(W, 2) = Cells(3, Cot).Value
            dArr(W, 3) = Arr(J, 1):         dArr(W, 4) = Arr(J, 2)
            dArr(W, 5) = Arr(J, Cot)
        End If
    Next J
 Next Cot
 If W Then
    Sheets("NhapKhoXuong").[cb4].Resize(W, 5).Value = dArr()
 End If
End Sub
 
Lần chỉnh sửa cuối:
Upvote 0
Hic, thế thì hơi nan giải nhỉ. Vì phần này vẫn còn liên quan tới một số phần khác mình đã làm nên giờ bỏ thì lại phải làm lại hết.
....

Đã khong chuẩn thì tất cả những cái liên quan đến nó đều lệch lạc. Làm lại hết là đúng rồi, còn gì phải luyến tiếc.

Đừng có nói với tôi là đồ án lớn nhé. Tôi là dân chuyên quản lý đồ án phần mềm. Đồ án lớn thì mọi liên liacj với CSDL đều ua giao diện. Nếu cơ cấu CSDL bị thay đổi thì chỉ cần thay đổi cái giao diện.
 
Upvote 0
Chào các bạn,

Mình có 1 file theo dõi hàng nhập và xuất tại các sheets tương ứng.
Mình muốn xem nhanh số lượng từng mã hàng đã nhập theo thời gian (dùng code VBA) mà không biết cách làm thế nào.

Mong các bạn xem file đính kèm và giúp mình đoạn code nhé.

Chân thành cảm ơn.
Mã:
Private Sub Baocao()
  Dim Arr(), ArrNhap(), j As Long, i As Long, EndR As Long, FistC As Long, EndC As Long
  Dim Tungay As Date, Denngay As Date, Hangxuat As String, Hangnhap As String
  Dim SoluongXuat As Double, SoluongNhap As Double
  On Error Resume Next
  If Me.txtTungay.Value = "" Then
    MsgBox ("Hay nhap ngay bat dau")
    Exit Sub
  Else
    Tungay = Format(Me.txtTungay.Value, "dd/mm/yyyy")
  End If
  If Me.txtDenngay.Value = "" Then
    MsgBox ("Hay nhap ngay ket thuc")
    Exit Sub
  Else
    Denngay = Format(Me.txtDenngay.Value, "dd/mm/yyyy")
  End If
  If Me.cobHangxuat.Value <> "" Then Hangxuat = Me.cobHangxuat.Value
  If Me.cobHangnhap.Value <> "" Then Hangnhap = Me.cobHangnhap.Value
  With ThisWorkbook.Sheets("Xuatxuong")
    EndR = .Range("A" & Rows.Count).End(xlUp).Row
    Arr = .Range("A4:N" & EndR).Value
  End With
  For i = LBound(Arr) To UBound(Arr)
    If Arr(i, 3) >= Tungay And Arr(i, 3) <= Denngay Then
      If Arr(i, 9) = Hangxuat And IsNumeric(Arr(i, 12)) Then
        SoluongXuat = SoluongXuat + Arr(i, 12)
      End If
    End If
  Next i
  With ThisWorkbook.Sheets("Nhapkhoxuong")
    EndC = .Cells(3, 16000).End(xlToLeft).Column
    EndR = .Range("B" & Rows.Count).End(xlUp).Row
    Arr = .Range("B3", .Cells(EndR, EndC)).Value
  End With
 
  For j = 4 To UBound(Arr, 2)
    If Arr(1, j) >= Tungay Then FistC = j: Exit For
  Next j
  If FistC = 0 Then GoTo Thoat
  EndC = UBound(Arr, 2)
  For n = j To UBound(Arr, 2)
    If Arr(1, n) >= Denngay Then
      If Arr(1, n) = Denngay Then EndC = n Else EndC = n - 1
      Exit For
    End If
  Next n
 
  For i = 2 To UBound(Arr)
    If Arr(i, 1) = Hangnhap Then
      For j = FistC To EndC
        If Arr(i, j) <> Empty Then SoluongNhap = SoluongNhap + Arr(i, j)
      Next j
    End If
  Next i
Thoat:
  Me.lbHangxuat.Caption = SoluongXuat
  Me.lbHangnhap.Caption = SoluongNhap
End Sub
 
Upvote 0
Mã:
Private Sub Baocao()
  Dim Arr(), ArrNhap(), j As Long, i As Long, EndR As Long, FistC As Long, EndC As Long
  Dim Tungay As Date, Denngay As Date, Hangxuat As String, Hangnhap As String
  Dim SoluongXuat As Double, SoluongNhap As Double
  On Error Resume Next
  If Me.txtTungay.Value = "" Then
    MsgBox ("Hay nhap ngay bat dau")
    Exit Sub
  Else
    Tungay = Format(Me.txtTungay.Value, "dd/mm/yyyy")
  End If
  If Me.txtDenngay.Value = "" Then
    MsgBox ("Hay nhap ngay ket thuc")
    Exit Sub
  Else
    Denngay = Format(Me.txtDenngay.Value, "dd/mm/yyyy")
  End If
  If Me.cobHangxuat.Value <> "" Then Hangxuat = Me.cobHangxuat.Value
  If Me.cobHangnhap.Value <> "" Then Hangnhap = Me.cobHangnhap.Value
  With ThisWorkbook.Sheets("Xuatxuong")
    EndR = .Range("A" & Rows.Count).End(xlUp).Row
    Arr = .Range("A4:N" & EndR).Value
  End With
  For i = LBound(Arr) To UBound(Arr)
    If Arr(i, 3) >= Tungay And Arr(i, 3) <= Denngay Then
      If Arr(i, 9) = Hangxuat And IsNumeric(Arr(i, 12)) Then
        SoluongXuat = SoluongXuat + Arr(i, 12)
      End If
    End If
  Next i
  With ThisWorkbook.Sheets("Nhapkhoxuong")
    EndC = .Cells(3, 16000).End(xlToLeft).Column
    EndR = .Range("B" & Rows.Count).End(xlUp).Row
    Arr = .Range("B3", .Cells(EndR, EndC)).Value
  End With
 
  For j = 4 To UBound(Arr, 2)
    If Arr(1, j) >= Tungay Then FistC = j: Exit For
  Next j
  If FistC = 0 Then GoTo Thoat
  EndC = UBound(Arr, 2)
  For n = j To UBound(Arr, 2)
    If Arr(1, n) >= Denngay Then
      If Arr(1, n) = Denngay Then EndC = n Else EndC = n - 1
      Exit For
    End If
  Next n
 
  For i = 2 To UBound(Arr)
    If Arr(i, 1) = Hangnhap Then
      For j = FistC To EndC
        If Arr(i, j) <> Empty Then SoluongNhap = SoluongNhap + Arr(i, j)
      Next j
    End If
  Next i
Thoat:
  Me.lbHangxuat.Caption = SoluongXuat
  Me.lbHangnhap.Caption = SoluongNhap
End Sub

Ui, cảm ơn bạn rất rất nhiều. Để mình thử luôn.

Mình cũng vừa hì hục cả buổi xong. Nhờ bạn và mọi người xem giúp đoạn code của mình liệu có vấn đề gì không nhé
Mã:
With ThisWorkbook.Worksheets("Nhapkhoxuong")
  Set sht = ThisWorkbook.Sheets("Nhapkhoxuong")
  EndCN = .Cells(3, .Columns.Count).End(xlToLeft).Column
 
  EndRN = .Range("B" & Rows.Count).End(xlUp).Row
  ArrNhap = .Range("B3:B" & EndRN).Resize(, EndCN).Value

    For j = 1 To UBound(ArrNhap, 1)
                If ArrNhap(j, 1) = hangnhap Then
                    For k = 4 To UBound(ArrNhap, 2)
                       If ArrNhap(1, k) >= tungay And ArrNhap(1, k) <= denngay And IsNumeric(ArrNhap(j, k)) Then
                            soluongnhap = soluongnhap + ArrNhap(j, k)
                        End If
                    Next k
                    Exit For
                End If
    Next j
End With
Me.lbHangxuat.Caption = soluongxuat
Me.lbHangnhap.Caption = soluongnhap
End Sub
 
Upvote 0
Theo hướng này cũng có lí à nha!
Nhưng theo mình, tác giả bài đăng nên có trang tính làm fụ trợ; Trên nới chứa danh mục hàng hóa;
Gồm các trường: [STT], [Mã HH], [Tên hàng], [ĐVT], [Lượng tồn theo đợt kiểm kê]
Chúng ta không thể tạo ra trang tính mà có nhiều dòng & cột trống hơ như vậy.
Với bảng 'DM HH' ta hoàn toàn khắc fục được chuyện này

Chuyện macro để chuyển từ trang tính 'Nhap. . . ' gì đó sang trang số liệu chuẩn cũng chả khó là bao:
Lấy 1 trang tính trắng
Tạo vòng lặp duyệt tại trang 'Nhap . .' những dòng có số lượng thì chép sang thành dòng mới ở trang mới này

Ví dụ:
PHP:
Sub TaoTrangNhapSanLuongHH()
 Dim Rws As Long, J As Long, W As Long, Col As Byte, Cot As Integer
 Dim Arr()

 With Sheets("NhapKhoXuong").[b3]
    Rws = .CurrentRegion.Rows.Count
    Col = .End(xlToRight).Column
    Arr() = .Offset(1).Resize(Rws, Col).Value
    ReDim dArr(1 To Rws, 1 To 5)
 End With
 For Cot = 4 To Col
    For J = 1 To UBound(Arr())
        If Arr(J, Cot) <> 0 Then
            W = W + 1:                      dArr(W, 1) = W
            dArr(W, 2) = Cells(3, Cot).Value
            dArr(W, 3) = Arr(J, 1):         dArr(W, 4) = Arr(J, 2)
            dArr(W, 5) = Arr(J, Cot)
        End If
    Next J
 Next Cot
 If W Then
    Sheets("NhapKhoXuong").[cb4].Resize(W, 5).Value = dArr()
 End If
End Sub

Cái này cũng đơn giản thôi, muốn thống kê được bên nhập kho thì phải viết 1 macro để chuẩn hóa lại dữ liệu thành 1 sheet nhập kho mới, sau đó dùng sheet nhập kho mới để xử lý.
Đã khong chuẩn thì tất cả những cái liên quan đến nó đều lệch lạc. Làm lại hết là đúng rồi, còn gì phải luyến tiếc.

Đừng có nói với tôi là đồ án lớn nhé. Tôi là dân chuyên quản lý đồ án phần mềm. Đồ án lớn thì mọi liên liacj với CSDL đều ua giao diện. Nếu cơ cấu CSDL bị thay đổi thì chỉ cần thay đổi cái giao diện.

Rất cảm ơn mọi người đã nhiệt tình góp ý. Căn bản mọi thứ mình đã hoàn làm xong theo nhu cầu của mình nên giờ lại phải làm lại thì :(( đành phải cố tìm cách để xử lý vấn đề này.
Mình sẽ rút kinh nghiệm về việc "chuẩn hóa" CSDL trong các lần sau. Toàn tự mò cóp nhặt nên mệt thật.
 
Upvote 0
Trong Form của chủ bài đăng có 2 nhãn để thể hiện 2 sản lượng nhập hay xuất hàng hóa.
trong cùng 1 thời kỳ (Ngày đàu & ngày cuối) cho 2 loại mặt hàng khác nhau.

Có thể xài các ListBox để hiện 2 danh sách hàng đã xuất hay nhập trong kỳ hay không?

:inv:
 

File đính kèm

Lần chỉnh sửa cuối:
Upvote 0
Ui, cảm ơn bạn rất rất nhiều. Để mình thử luôn.

Mình cũng vừa hì hục cả buổi xong. Nhờ bạn và mọi người xem giúp đoạn code của mình liệu có vấn đề gì không nhé
Mã:
With ThisWorkbook.Worksheets("Nhapkhoxuong")
  Set sht = ThisWorkbook.Sheets("Nhapkhoxuong")
  EndCN = .Cells(3, .Columns.Count).End(xlToLeft).Column
 
  EndRN = .Range("B" & Rows.Count).End(xlUp).Row
  ArrNhap = .Range("B3:B" & EndRN).Resize(, EndCN).Value

    For j = 1 To UBound(ArrNhap, 1)
                If ArrNhap(j, 1) = hangnhap Then
                    For k = 4 To UBound(ArrNhap, 2)
                       If ArrNhap(1, k) >= tungay And ArrNhap(1, k) <= denngay And IsNumeric(ArrNhap(j, k)) Then
                            soluongnhap = soluongnhap + ArrNhap(j, k)
                        End If
                    Next k
                    Exit For
                End If
    Next j
End With
Me.lbHangxuat.Caption = soluongxuat
Me.lbHangnhap.Caption = soluongnhap
End Sub
ArrNhap = .Range("B3:B" & EndRN).Resize(, EndCN).Value: lấy dư 1 cột, chỉnh lại
ArrNhap = .Range("B3:B" & EndRN).Resize(, EndCN-1).Value
Code chạy chậm 1 chút nếu dữ liệu lớn vì phải xử lý những ArrNhap(j, k) không cần thiết
 
Upvote 0
Trong Form của chủ bài đăng có 2 nhãn để thể hiện 2 sản lượng nhập hay xuất hàng hóa.
trong cùng 1 thời kỳ (Ngày đàu & ngày cuối) cho 2 loại mặt hàng khác nhau.

Có thể xài các ListBox để hiện 2 danh sách hàng đã xuất hay nhập trong kỳ hay không?

:inv:
Trong form của mình có 2 combo dành cho theo dõi xuất và nhập.
Vì lúc xây dựng csdl thì phần xuất có tách theo số lượng từng lần xuất nhưng phần nhập thì lại chỉ làm theo dõi tổng trong 1 ngày (cái này là sai lầm) thành ra ko làm listbox theo dõi (do phần nữa là mình chưa thạo). Chứ nếu có thêm listbox chi tiết thì tốt quá.
 
Upvote 0
ArrNhap = .Range("B3:B" & EndRN).Resize(, EndCN).Value: lấy dư 1 cột, chỉnh lại
ArrNhap = .Range("B3:B" & EndRN).Resize(, EndCN-1).Value
Code chạy chậm 1 chút nếu dữ liệu lớn vì phải xử lý những ArrNhap(j, k) không cần thiết
Phần lấy dư 1 cột mình ko rõ lắm, mình tưởng EndCN là cột cuối thì mình tính từ cột mã hàng (B) là vừa khớp chứ nhỉ?
Còn xử lý các ArrNhap(j, k) thừa thì mình tưởng là đã có các đk trước đó rồi thì sẽ loại được việc xử lý thừa?
 
Upvote 0
Phần lấy dư 1 cột mình ko rõ lắm, mình tưởng EndCN là cột cuối thì mình tính từ cột mã hàng (B) là vừa khớp chứ nhỉ?
Còn xử lý các ArrNhap(j, k) thừa thì mình tưởng là đã có các đk trước đó rồi thì sẽ loại được việc xử lý thừa?
Ví dụ dữ liệu từ cột B đến cột G
EndCN=7 là thứ tự cột cuối
ArrNhap = .Range("B3:B" & EndRN).Resize(, EndCN).Value
Resize(, EndCN) là lấy 7 cột từ cột B, sẽ lấy tới cột G
Mã:
   For j = 1 To UBound(ArrNhap, 1)
               If ArrNhap(j, 1) = hangnhap Then
                   For k = 4 To UBound(ArrNhap, 2)
                      If ArrNhap(1, k) >= tungay And ArrNhap(1, k) <= denngay And IsNumeric(ArrNhap(j, k)) Then                            
                                   soluongnhap = soluongnhap + ArrNhap(j, k)
                       End If
                   Next k
                   Exit For
               End If
   Next j

For k = 4 To UBound(ArrNhap, 2) duyệt qua tất cả các cột, thật ra chỉ cần duyệt các cột từ ngày tới ngày
soluongnhap = soluongnhap + ArrNhap(j, k) : Có số liệu hoặc không có cũng cộng, thêm điều kiện có dữ liệu mới cộng
Code của bạn khá ổn, chạy ra kết quả chuẩn, chỉ cần chỉnh cột ArrNhap sẽ hợp lý hơn
Chỉ cần dùng 1 mảng Arr, tiết kiệm bộ nhớ, tăng tốc khi dữ liệu nhiều
 
Upvote 0
:close_tema:
. . . Vì lúc xây dựng csdl thì phần xuất có tách theo số lượng từng lần xuất nhưng phần nhập thì lại chỉ làm theo dõi tổng trong 1 ngày (cái này là sai lầm) thành ra ko làm listbox theo dõi (do phần nữa là mình chưa thạo). Chứ nếu có thêm listbox chi tiết thì tốt quá.

Hình như đến giờ bạn đã có cảm nhận rằng cấu trúc CSDL của mình đã chệch hướng.

Đã vậy bạn nên dừng ngay & mô tả từ đầu CSDL của bạn để cộng đồng GPE.COM giúp bạn xây mới CSDL cho chuẩn hơn.
Cộng đồng này có thể giúp bạn tất tần tật, kể cả việc giúp bạn lấn càng ngày càng sâu vô sai lầm.
:close_tema:
Dũng cảm lên bạn!
 
Upvote 0
:close_tema:

Hình như đến giờ bạn đã có cảm nhận rằng cấu trúc CSDL của mình đã chệch hướng.

Đã vậy bạn nên dừng ngay & mô tả từ đầu CSDL của bạn để cộng đồng GPE.COM giúp bạn xây mới CSDL cho chuẩn hơn.
Cộng đồng này có thể giúp bạn tất tần tật, kể cả việc giúp bạn lấn càng ngày càng sâu vô sai lầm.
:close_tema:
Dũng cảm lên bạn!

Mình cũng biết việc xây dựng csdl chuẩn là rất quan trọng. Nhưng như ở trên mình đã lỡ làm đến phút cuối rồi nên đành giải quyết theo kiểu xử lý sự cố.
Vốn là mình rất mù về khoản này. Trước khi làm mình cũng làm csdl (rất đơn giản) để phục vụ công việc. Nhưng đến khi bắt tay vào làm xong mục này, cộng với học hỏi hiểu biết thêm một chút, lại muốn thêm mục kia, được tính năng này lại muốn thêm tính năng kia (theo kiểu được Voi rồi thì muốn thêm cả Hai bà Trưng. Thành ra cuối cùng lổn nhổn. Cộng với điều kiện thời gian và công việc nên đành tạm chấp nhận để sử dụng trước mắt.
Còn Mình cũng đã lên kế hoạch để làm lại bản hoàn thiện mới tinh từ đầu để phục vụ công việc.
Rất cảm ơn bạn và các thành viên khác đã nhiệt tình góp ý một cách thiện chí.
Nói sơ qua về nhu cầu của mình:
Bên mình sản xuất hàng đông lạnh có 1 cơ sở sản xuất, 1 điểm giới thiệu bán lẻ và bán buôn, và 1 số đại lý.
Mình đã làm được (khá lổn nhổn, tính năng chưa thật ưng ý do khả năng có hạn) phần bán hàng, xuất nhập tồn của cửa hàng, xuất nhập tồn của xưởng sản xuất.
Phần quản lý kho nguyên liệu, vật tư sản xuất (xuất nhập tồn) thì chưa được do chưa nghĩ được cách giải quyết sai số, sai khác đơn vị tính, vật tư tiêu hao. Và các báo cáo tổng hợp tự động. Công nợ. Làm việc online.. ..
 
Upvote 0
Còn đây là file chỉ xài 1 listBox, nhưng có tách riêng cột số lượng nhập hay số lượng xuất & thêm cột lũy kế để dễ theo dõi.
 

File đính kèm

Upvote 0
Còn đây là file chỉ xài 1 listBox, nhưng có tách riêng cột số lượng nhập hay số lượng xuất & thêm cột lũy kế để dễ theo dõi.

Híc, bài toán của mình đưa ra, các bác đã mất công giải hộ mà mình nhìn như nhìn bức vách. Xấu hổ quá nhưng mãi vẫn chưa hiểu rõ code của bác , mong bác giải thích rõ thêm giúp mình về lý do sử dụng function TxTToDate, tính SoNgay, và cách hoạt động của dArr() được không?
Mã:
Private Sub NutBaocao_Click()

 Dim fDat As Date, lDat As Date, SoNgay As Integer, J As Long, W As Long, SN As Integer
 Dim DongN As Long
 Dim RgN As Range, ShN As Worksheet, ArrN(), ShX As Worksheet, ArrX()
 ReDim dArr(1 To 356, 1 To 5)
 
 fDat = TxtToDate(Me!txtTuNgay.Text):           lDat = TxtToDate(Me!txtDenNgay.Text)
 If fDat < 999 Then Exit Sub
 SoNgay = lDat - fDat
 Set ShN = ThisWorkbook.Worksheets("Nhap"):     Set ShX = ThisWorkbook.Worksheets("Xuat")
 ArrN() = ShN.Range(ShN.[b1], ShN.[b1].End(xlDown)).Value
 For J = 2 To UBound(ArrN())                    'Xác Dinh Dòng Có Mã Hàng Nhâp: '
    If ArrN(J, 1) = Me.cobHangXuat.Text Then
        DongN = J:                              Exit For
    End If
 Next J
 ArrN() = ShN.Range(ShN.[e1], ShN.[e1].End(xlToRight))
 ArrX() = ShX.[c2].Resize(ShX.[c2].CurrentRegion.Rows.Count, 10).Value
 For SN = 0 To SoNgay
1 'Nhâp Hàng '
    For J = 1 To UBound(ArrN(), 2)
        If ArrN(1, J) = SN + fDat Then
            If ShN.Cells(DongN, J + 4).Value > 0 Then
                W = W + 1:                      dArr(W, 1) = W
                dArr(W, 2) = SN + fDat
                dArr(W, 3) = ShN.Cells(DongN, J + 4).Value
                If W = 1 Then
                    dArr(W, 5) = dArr(W, 3)
                ElseIf W > 1 Then
                    dArr(W, 5) = dArr(W - 1, 5) + dArr(W, 3)
                End If
                Exit For
            End If
        End If
    Next J
2 ' Xuát Hàng  '
    For J = 1 To UBound(ArrX())
        If ArrX(J, 1) = SN + fDat And ArrX(J, 7) = Me!cobHangXuat.Text Then
            W = W + 1:                          dArr(W, 1) = W
            dArr(W, 2) = SN + fDat:             dArr(W, 4) = ArrX(J, 10)
            If W = 1 Then
                dArr(W, 5) = -1 * dArr(W, 4)
            ElseIf W > 1 Then
                dArr(W, 5) = dArr(W - 1, 5) - dArr(W, 4)
            End If
        End If
    Next J
 Next SN
 If W Then
    Me!lbXuat.List = dArr()
 End If
End Sub

Function TxtToDate(StrC As String) As Date
 Dim Nm As Long, Th As Byte, Ng As Byte, VTr As Byte

 If Len(StrC) < 8 Then Exit Function
 Nm = CLng(Right(StrC, 4))
 VTr = InStr(StrC, "/")
 If VTr Then
    Ng = CByte(Left(StrC, VTr - 1)):        StrC = Mid(StrC, VTr + 1, 4)
 End If
 VTr = InStr(StrC, "/")
 If VTr Then Th = CByte(Left(StrC, VTr - 1))
 TxtToDate = DateSerial(Nm, Th, Ng)
End Function
 
Upvote 0
Trước tiên là hàm tự tạo chuyển chuỗi sang kiểu dữ liệu ngày:
PHP:
Function TxtToDate(StrC As String) As Date
 Dim Nm As Long, Th As Byte, Ng As Byte, VTr As Byte

2 If Len(StrC) < 8 Then Exit Function
 Nm = CLng(Right(StrC, 4))
4 VTr = InStr(StrC, "/")
 If VTr Then
 6  Ng = CByte(Left(StrC, VTr - 1)):        StrC = Mid(StrC, VTr + 1, 4)
 End If
8 VTr = InStr(StrC, "/")
 If VTr Then Th = CByte(Left(StrC, VTr - 1))
10 TxtToDate = DateSerial(Nm, Th, Ng)
End Function
Dg1: Khai báo các tham biến cẩn cho chương trình
Dg2: (Ta biết rằng hàm cần được cung cấp 1 tham biến kiểu chuỗi; Nó đã được hướng dẫn nhập theo dạng 'DD/MM/yyyy')
Nếu nhập chuỗi ngắn hơn thì sẽ không nhận được kết quả hàm trả về.
Dg3: Cắt 4 kí tự số cuối trong chuỗi & biến nó thành kí số chỉ năm
Dg4: Xác định vị trí chứa "/" trong chuỗi. (Chuỗi được nhập vô được khuyến cáo fân cách giữa các kí số là "/"; Cần tuân thủ)
Dg5: Điều kiện xác định được vị trí, thì thực hiện câu lệnh dưới liền kề
Dg6: Mệnh đề thứ nhất:Cắt lấy các kí số trước vị trí & biến nó thành số & gán vô tham biến đã khai báo. (Đó sẽ là số chỉ ngày của chuỗi cung cấp cho hàm)
Mệnh đề sau: Cắt bỏ kí số chỉ ngày & dấu fân cách thứ nhất trong chuỗi
Dg7: Kết thúc điều kiện
Dg8: Xác định vị trí fân cách thứ 2 trong chuỗi.
Dg9: Tương tự trên, cắt lấy kí số chỉ tháng & biến chúng thành số & ấn định vô tham biến Th đã khai báo
Dg10: Ấn định kết quả hàm trả về là dạng ngày-tháng-năm (theo dạng MM/dd/yyyy)

Ích lợi của hàm là chuyển dạng chuỗi chứa ngày-tháng-năm sang kiểu dữ liệu đúng cho các loại máy tính (DD/MM/yyyy hay MM/DD/yyyy)

Mong rằng đã giúp bạn í nhiều & chúc vui!
 
Upvote 0
File này có thêm fần tồn đầu kì trong TextBox luôn nè; Xin mời tham khảo tiếp:
PHP:
Private Sub NutBaocao_Click()
 Dim fDat As Date, lDat As Date, SoNgay As Integer, J As Long, W As Long, SN As Integer
 Dim DongN As Long, Col As Integer, TDKy As Double
 Dim RgN As Range, ShN As Worksheet, ArrN(), ShX As Worksheet, ArrX()
 ReDim dArr(1 To 356, 1 To 5)
 fDat = TxtToDate(Me!txtTuNgay.Text):           lDat = TxtToDate(Me!txtDenNgay.Text)
 If fDat < 999 Then Exit Sub
 SoNgay = lDat - fDat
 Set ShN = ThisWorkbook.Worksheets("Nhap"):     Set ShX = ThisWorkbook.Worksheets("Xuat")
 ArrN() = ShN.Range(ShN.[b1], ShN.[b1].End(xlDown)).Value
 For J = 2 To UBound(ArrN())                    'Xác Dinh Dòng Có Mã Hàng Nhâp: '
    If ArrN(J, 1) = Me.cobHangXuat.Text Then
        DongN = J:                              Exit For
    End If
 Next J
 ArrN() = ShN.Range(ShN.[e1], ShN.[e1].End(xlToRight))
 For J = 1 To UBound(ArrN(), 2)                 'Xác Dinh Luong Hàng Nhâp Dàu Kì    '
    If ArrN(1, J) = fDat Then
        Col = J - 1
        TDKy = Application.WorksheetFunction.Sum(ShN.Cells(DongN, "E").Resize(, Col))
        Exit For
    End If
 Next J
 ArrX() = ShX.[c2].Resize(ShX.[c2].CurrentRegion.Rows.Count, 10).Value
 For SN = 0 To SoNgay
1 'Nhâp Hàng '
    For J = Col To UBound(ArrN(), 2)
        If ArrN(1, J) = SN + fDat Then
            If ShN.Cells(DongN, J + 4).Value > 0 Then
                W = W + 1:                      dArr(W, 1) = W
                dArr(W, 2) = SN + fDat
                dArr(W, 3) = ShN.Cells(DongN, J + 4).Value
                If W = 1 Then
                    dArr(W, 5) = dArr(W, 3)
                ElseIf W > 1 Then
                    dArr(W, 5) = dArr(W - 1, 5) + dArr(W, 3)
                End If
                Exit For
            End If
        End If
    Next J
2 ' Xuát Hàng  '
    For J = 1 To UBound(ArrX())
        If ArrX(J, 7) = Me!cobHangXuat.Text Then
            If ArrX(J, 1) = SN + fDat Then
                W = W + 1:                      dArr(W, 1) = W
                dArr(W, 2) = SN + fDat:         dArr(W, 4) = ArrX(J, 10)
                If W = 1 Then
                    dArr(W, 5) = -1 * dArr(W, 4)
                ElseIf W > 1 Then
                    dArr(W, 5) = dArr(W - 1, 5) - dArr(W, 4)
                End If
            End If
            If SN = 0 And ArrX(J, 1) < fDat Then
                TDKy = TDKy - ArrX(J, 10)       'Trù Luong Hàng Xuát Truóc Kì       '
            End If
        End If
    Next J
 Next SN
 If W Then
    Me!lbXuat.List = dArr():                    Me!tbTDK.Value = TDKy
 End If
End Sub
 

File đính kèm

Upvote 0
Trước tiên là hàm tự tạo chuyển chuỗi sang kiểu dữ liệu ngày:
PHP:
Function TxtToDate(StrC As String) As Date
 Dim Nm As Long, Th As Byte, Ng As Byte, VTr As Byte

2 If Len(StrC) < 8 Then Exit Function
 Nm = CLng(Right(StrC, 4))
4 VTr = InStr(StrC, "/")
 If VTr Then
 6  Ng = CByte(Left(StrC, VTr - 1)):        StrC = Mid(StrC, VTr + 1, 4)
 End If
8 VTr = InStr(StrC, "/")
 If VTr Then Th = CByte(Left(StrC, VTr - 1))
10 TxtToDate = DateSerial(Nm, Th, Ng)
End Function
Dg1: Khai báo các tham biến cẩn cho chương trình
Dg2: (Ta biết rằng hàm cần được cung cấp 1 tham biến kiểu chuỗi; Nó đã được hướng dẫn nhập theo dạng 'DD/MM/yyyy')
Nếu nhập chuỗi ngắn hơn thì sẽ không nhận được kết quả hàm trả về.
Dg3: Cắt 4 kí tự số cuối trong chuỗi & biến nó thành kí số chỉ năm
Dg4: Xác định vị trí chứa "/" trong chuỗi. (Chuỗi được nhập vô được khuyến cáo fân cách giữa các kí số là "/"; Cần tuân thủ)
Dg5: Điều kiện xác định được vị trí, thì thực hiện câu lệnh dưới liền kề
Dg6: Mệnh đề thứ nhất:Cắt lấy các kí số trước vị trí & biến nó thành số & gán vô tham biến đã khai báo. (Đó sẽ là số chỉ ngày của chuỗi cung cấp cho hàm)
Mệnh đề sau: Cắt bỏ kí số chỉ ngày & dấu fân cách thứ nhất trong chuỗi
Dg7: Kết thúc điều kiện
Dg8: Xác định vị trí fân cách thứ 2 trong chuỗi.
Dg9: Tương tự trên, cắt lấy kí số chỉ tháng & biến chúng thành số & ấn định vô tham biến Th đã khai báo
Dg10: Ấn định kết quả hàm trả về là dạng ngày-tháng-năm (theo dạng MM/dd/yyyy)

Ích lợi của hàm là chuyển dạng chuỗi chứa ngày-tháng-năm sang kiểu dữ liệu đúng cho các loại máy tính (DD/MM/yyyy hay MM/DD/yyyy)

Mong rằng đã giúp bạn í nhiều & chúc vui!

Cảm ơn bạn,

Việc ReDim dArr(1 To 356, 1 To 5) thì có làm mất dữ liệu không khi dArr(1 to 356...) và có thể thay dArr(1 to (cột cuối nhập + dòng cuối xuất) , 1 to 5) ?

Mong bạn giải thích thêm Thế còn việc tính số ngày, và hoạt động của dArr() thì như thế nào hả bạn?
 
Upvote 0
(1) Việc ReDim dArr(1 To 356, 1 To 5) thì có làm mất dữ liệu không khi dArr(1 to 356...) và có thể thay dArr(1 to (cột cuối nhập + dòng cuối xuất) , 1 to 5) ?

(3) Thế còn việc tính số ngày, và (2) hoạt động của dArr() thì như thế nào hả bạn?

(1) Con số 356 là con số bâng quơ í mà!
Nên thay là ReDim dArr( 1 To 2* [Dòng cuối trang 'Xuát'], 1 to 5)
Vì lẽ dĩ nhiện là dòng xuất thường nhiều hơn số dòng nhập.

(2) Thì trong quá trình duyệt dữ liệu của 2 trang tính, nêu dòng nào thỏa thì ta ghi vô mãng mà thôi.

(3) Tính số ngày thì thường lấy hiệu của chúng đem cọng với đơn vị
Nhưng trong chương trình thì duyệt theo tham biến từ trị 0 cho đến trị chứa trong tham biến 'SoNgay'; ta không cần thêm 1 f ép cọng nữa, tốn năng lượng cho bạn & cho xã hội.
 
Upvote 0
Cảm ơn bạn và mọi người đã rất nhiệt tình ><></

File này có thêm fần tồn đầu kì trong TextBox luôn nè; Xin mời tham khảo tiếp:
PHP:
Private Sub NutBaocao_Click()
 Dim fDat As Date, lDat As Date, SoNgay As Integer, J As Long, W As Long, SN As Integer
 Dim DongN As Long, Col As Integer, TDKy As Double
 Dim RgN As Range, ShN As Worksheet, ArrN(), ShX As Worksheet, ArrX()
 ReDim dArr(1 To 356, 1 To 5)
 fDat = TxtToDate(Me!txtTuNgay.Text):           lDat = TxtToDate(Me!txtDenNgay.Text)
 If fDat < 999 Then Exit Sub
 SoNgay = lDat - fDat
 Set ShN = ThisWorkbook.Worksheets("Nhap"):     Set ShX = ThisWorkbook.Worksheets("Xuat")
 ArrN() = ShN.Range(ShN.[b1], ShN.[b1].End(xlDown)).Value
 For J = 2 To UBound(ArrN())                    'Xác Dinh Dòng Có Mã Hàng Nhâp: '
    If ArrN(J, 1) = Me.cobHangXuat.Text Then
        DongN = J:                              Exit For
    End If
 Next J
 ArrN() = ShN.Range(ShN.[e1], ShN.[e1].End(xlToRight))
 For J = 1 To UBound(ArrN(), 2)                 'Xác Dinh Luong Hàng Nhâp Dàu Kì    '
    If ArrN(1, J) = fDat Then
        Col = J - 1
        TDKy = Application.WorksheetFunction.Sum(ShN.Cells(DongN, "E").Resize(, Col))
        Exit For
    End If
 Next J
 ArrX() = ShX.[c2].Resize(ShX.[c2].CurrentRegion.Rows.Count, 10).Value
 For SN = 0 To SoNgay
1 'Nhâp Hàng '
    For J = Col To UBound(ArrN(), 2)
        If ArrN(1, J) = SN + fDat Then
            If ShN.Cells(DongN, J + 4).Value > 0 Then
                W = W + 1:                      dArr(W, 1) = W
                dArr(W, 2) = SN + fDat
                dArr(W, 3) = ShN.Cells(DongN, J + 4).Value
                If W = 1 Then
                    dArr(W, 5) = dArr(W, 3)
                ElseIf W > 1 Then
                    dArr(W, 5) = dArr(W - 1, 5) + dArr(W, 3)
                End If
                Exit For
            End If
        End If
    Next J
2 ' Xuát Hàng  '
    For J = 1 To UBound(ArrX())
        If ArrX(J, 7) = Me!cobHangXuat.Text Then
            If ArrX(J, 1) = SN + fDat Then
                W = W + 1:                      dArr(W, 1) = W
                dArr(W, 2) = SN + fDat:         dArr(W, 4) = ArrX(J, 10)
                If W = 1 Then
                    dArr(W, 5) = -1 * dArr(W, 4)
                ElseIf W > 1 Then
                    dArr(W, 5) = dArr(W - 1, 5) - dArr(W, 4)
                End If
            End If
            If SN = 0 And ArrX(J, 1) < fDat Then
                TDKy = TDKy - ArrX(J, 10)       'Trù Luong Hàng Xuát Truóc Kì       '
            End If
        End If
    Next J
 Next SN
 If W Then
    Me!lbXuat.List = dArr():                    Me!tbTDK.Value = TDKy
 End If
End Sub

Cảm ơn bạn rất nhiều ><></
 
Chỉnh sửa lần cuối bởi điều hành viên:
Upvote 0

Bài viết mới nhất

Back
Top Bottom