ถึงท่านอาจารย์ สันติสุข ค่ะ
กระทู้เก่าบอร์ด อ.Yeadram

 48,413   91
URL.หัวข้อ / URL
ถึงท่านอาจารย์ สันติสุข ค่ะ

คำถามต่อเนื่องนะคะอาจารย์ พอดีที่หนูหายไปหนูแอบไปรับปริญญามาค่ะ
ข้อที่ 1 เรื่องการค้นหาข้อมูลจากกล่องComboค่ะ

หนูได้นำCodeที่อาจารย์ให้ไปวางตามนี้ค่ะ

Option Compare Database
Option Explicit


Sub SetDefaultShippingAddress()
    If IsNull(Me![Customer ID]) Then
        ClearShippingAddress
    Else
       
        Dim rsw As New RecordsetWrapper
        If rsw.OpenRecordset("Customers Extended", "[ID] = " & Me.Customer_ID) Then
        Me.[InvoiceNO] = DMax("[InvoiceNumber]", "[Orders]") + 1
            With rsw.Recordset
               Me![Ship Name] = ![Contact Name]
               Me![Ship Address] = ![Address]
               End With
        End If
    End If
End Sub


Private Sub cmdDeleteOrder_Click()
    If IsNull(Me![Order ID]) Then
        Beep
    ElseIf Me![Status ID] = Shipped_CustomerOrder Or Me![Status ID] = Closed_CustomerOrder Then
        MsgBoxOKOnly CannotCancelShippedOrder
    ElseIf MsgBoxYesNo(CancelOrderConfirmPrompt) Then
        If CustomerOrders.Delete(Me![Order ID]) Then
            MsgBoxOKOnly CancelOrderSuccess
            eh.TryToCloseObject
        Else
            MsgBoxOKOnly CancelOrderFailure
        End If
    End If
End Sub


Private Sub cmdClearAddress_Click()
    ClearShippingAddress
End Sub


Private Sub ClearShippingAddress()
    Me![Ship Name] = Null
    Me![Ship Address] = Null
    Me![Ship City] = Null
    Me![Ship State/Province] = Null
    Me![Ship ZIP/Postal Code] = Null
    Me![Ship Country/Region] = Null
End Sub


Private Sub cmdCompleteOrder_Click()
    If Me![Status ID] <> Shipped_CustomerOrder Then
        MsgBoxOKOnly OrderMustBeShippedToClose
    ElseIf ValidateOrder(Closed_CustomerOrder) Then
        Me![Status ID] = Closed_CustomerOrder
        eh.TryToSaveRecord
        MsgBoxOKOnly OrderMarkedClosed
        SetFormState
    
    End If
End Sub


Private Sub cmdCreateInvoice_Click()
    Dim OrderID As Long
    Dim InvoiceID As Long

    OrderID = Nz(Me![Order ID], 0)
    
    ' Gracefully exit if invoice already created
    If CustomerOrders.IsInvoiced(OrderID) Then
        If MsgBoxYesNo(OrderAlreadyInvoiced) Then
       
        CustomerOrders.PrintInvoice Me.Customer_ID, OrderID
       
        End If
    ElseIf ValidateOrder(Invoiced_CustomerOrder) Then
       
        ' Create Invoice Record
        If CustomerOrders.CreateInvoice(OrderID, 0, InvoiceID) Then
            
            ' Mark all Order Items Invoiced
            ' Need to change Inventory Status to SOLD from HOLD
            Dim rsw As New RecordsetWrapper
            With rsw.GetRecordsetClone(Me.sbfOrderDetails.Form.Recordset)
               While Not .EOF
                    If Not IsNull(![Inventory ID]) And ![Status ID] = OnHold_OrderItemStatus Then
                        rsw.Edit
                        ![Status ID] = Invoiced_OrderItemStatus
                        rsw.Update
                        Inventory.HoldToSold ![Inventory ID]
                    End If
                    rsw.MoveNext
               Wend
            End With
            
            ' Print the Invoice
          CustomerOrders.PrintInvoice Me.Customer_ID, OrderID

       
            SetFormState
        End If
    End If
End Sub



Private Sub cmdShipOrder_Click()
    If Not CustomerOrders.IsInvoiced(Nz(Me![Order ID], 0)) Then
        MsgBoxOKOnly CannotShipNotInvoiced
    ElseIf Not ValidateShipping() Then
        MsgBoxOKOnly ShippingNotComplete
    Else
        Me![Status ID] = Shipped_CustomerOrder
    
        If IsNull(Me![Shipped Date]) Then
            Me![Shipped Date] = Date
        End If
        eh.TryToSaveRecord
        SetFormState
    End If
End Sub


Private Sub Customer_ID_AfterUpdate()
    Me.sbfOrderDetails.Form.[Product ID].RowSource = "SELECT Inventory.[Product ID], Inventory.[Product Code], Inventory.[Qty Available] from Inventory where [Product Code] like '*" & Customer_ID & "*'"

    SetFormState False
    If Not IsNull(Me![Customer ID]) Then
        SetDefaultShippingAddress
    End If
End Sub
Private Sub Customer_ID_Current()
     If Not Me.NewRecord Then
       Me.sbfOrderDetails.Form.[Product ID].RowSource = "SELECT Inventory.[Product ID], Inventory.[Product Code], Inventory.[Qty Available] from Inventory where [Product Code] like '*" & Customer_ID & "*'"

     End If
End Sub



Private Sub Customer_ID_KeyUp(KeyCode As Integer, Shift As Integer)

    Me.Customer_ID.RowSource = "SELECT [ID], [Company], [Address For Ship], [ID] FROM [Customers Extended]where [Company], [Address For Ship], [ID] like '*" & Me.Customer_ID.Text & "*' order by [Company], [Address For Ship]"
    Me.Customer_ID.Dropdown
End Sub


Private Sub Form_Current()
    
    SetFormState
   
End Sub


Private Sub Form_Load()
    SetFormState
End Sub


Function GetDefaultSalesPersonID() As Long
    GetDefaultSalesPersonID = GetCurrentUserID()
End Function

Function ValidateShipping() As Boolean
   If Nz(Me![Shipping Fee]) = "" Then Exit Function
    ValidateShipping = True
End Function

Function ValidatePaymentInfo() As Boolean
    If IsNull(Me![Payment Type]) Then Exit Function
    If IsNull(Me![Paid Date]) Then Exit Function
    
    ValidatePaymentInfo = True
End Function


Sub SetFormState(Optional fChangeFocus As Boolean = True)
    If fChangeFocus Then Me.Customer_ID.SetFocus
    Dim Status As CustomerOrderStatusEnum
       
    Status = Nz(Me![Status ID], New_CustomerOrder)

    TabCtlOrderData.Enabled = Not IsNull(Me![Customer ID])
    Me.cmdCreateInvoice.Enabled = (Status = New_CustomerOrder)
    
    Me.cmdShipOrder.Enabled = (Status = New_CustomerOrder) Or (Status = Invoiced_CustomerOrder)
   
    Me.cmdDeleteOrder.Enabled = (Status = New_CustomerOrder) Or (Status = Invoiced_CustomerOrder)
    Me.cmdCompleteOrder.Enabled = (Status <> Closed_CustomerOrder)
    
    
    Me.[Order Details_Page].Enabled = (Status = New_CustomerOrder)
    Me.[Shipping Information_Page].Enabled = (Status = New_CustomerOrder)
    Me.[Payment Information_Page].Enabled = (Status <> Closed_CustomerOrder)
    
    Me.Customer_ID.Locked = (Status <> New_CustomerOrder)
    Me.Employee_ID.Locked = (Status <> New_CustomerOrder)
    Me.sbfOrderDetails.Locked = (Status <> New_CustomerOrder)

End Sub


Function ValidateOrder(Validation_OrderStatus As CustomerOrderStatusEnum) As Boolean
    If IsNull(Me![Customer ID]) Then
        MsgBoxOKOnly MustSpecifyCustomer
    ElseIf IsNull(Me![Employee ID]) Then
        MsgBoxOKOnly MustSpecifySalesPerson
    ElseIf Not ValidateShipping() Then
        MsgBoxOKOnly ShippingNotComplete
    Else
        If Validation_OrderStatus = Closed_CustomerOrder Then
            If Not ValidatePaymentInfo() Then
               MsgBoxOKOnly PaymentInfoNotComplete
               Exit Function
            End If
        End If

        Dim rsw As New RecordsetWrapper
        With rsw.GetRecordsetClone(Me.sbfOrderDetails.Form.Recordset)
            ' Check that we have at least one specified line items
            If .RecordCount = 0 Then
               MsgBoxOKOnly OrderDoesNotContainLineItems
            Else
               ' Check all that all line items have allocated inventory
               Dim LineItemCount As Integer
               Dim Status As OrderItemStatusEnum
               LineItemCount = 0
               While Not .EOF
                    
                    LineItemCount = LineItemCount + 1
                    Status = Nz(![Status ID], None_OrderItemStatus)
                    If Status <> OnHold_OrderItemStatus And Status <> Invoiced_OrderItemStatus Then
                        MsgBoxOKOnly MustBeAllocatedBeforeInvoicing
                        Exit Function
                    End If
                    rsw.MoveNext
               Wend
                                        
               ValidateOrder = True
            End If
        End With
    End If
End Function


ผลที่ได้คือเวลาพิมหาแล้วขึ้นกล่องว่าเปล่าค่ะ

91 Reply in this Topic. Dispaly 5 pages and you are on page number 4

61 @R14675
เย้ๆๆๆๆๆได้แล้วววววค่ะ อาจารย์เก่งมาเลยค่ะ


ปล.รอบนี้ไม่ต้องรออีก2เดือนแล้วค่ะ อิอิ ที่ปรึกษาพร้อมดอกเบี้ย 10 %
62 @R14808

อาจารย์คะ รบกวนนิดนึงค่ะ ตามFunctionนี้ ถ้าหนูต้องการจะกดปุ่ม Printinvoice แล้วให้ขึ้นPreview และprintด้วยเลย ต้องใส่ Function ตรงไหนคะ ใช่ตรงที่ต่อจาก acviewpreview หรือเปล่าคะ ต้องใส่คำว่าอะไรบ้างคะ รบกวนอาจารย์อีกแล้ว ขอบคุณค่ะ :)


Function PrintInvoice(Customer_ID As String, OrderID As Long) As Boolean
Dim Result
Result = DLookup("[Language]", "Customers", "[ID]=" & CStr(Customer_ID))

If Result = "TH" Then
DoCmd.OpenReport "InvoiceTH", acViewPreview, , "[Order ID]=" & OrderID, acDialog
Else
DoCmd.OpenReport "InvoiceEN", acViewPreview, , "[Order ID]=" & OrderID, acDialog

End If

End Function
63 @R14809
สั่งพิมพ์เลย ก็ใช้คำว่า acViewNormal แทน acViewPreview ครับ โดยจะสั่งก่อนหรือหลังบรรทัดเดิมก็ได้ครับ
64 @R14815
ขอบพระคุณมากค่ะ ;)
65 @R14858
อาจารย์คะ ส่งเมลล์ให้อาจารย์นะคะ
66 @R14863
ในเมล์ คุณส้มถามมาดังนี้นะครับ

อาจารย์คะ ตามที่หนูถามอาจารย์ไปว่าให้ขึ้น preview และ ปริ้นพร้อมกัน ถ้าหนูอยากให้ขึ้น preview และ มีmsg box ถามขึ้นมาว่าจะปริ้น หรือ ดูเฉยๆ ได้ไหมคะรบกวนขอความรู้จากอาจารย์อีกทีค่ะ

Function PrintInvoice(Customer_ID As String, OrderID As Long) As Boolean
   Dim Result
   Result = DLookup("[Language]", "Customers", "[ID]=" & CStr(Customer_ID))
   If Result = "TH" Then
      DoCmd.OpenReport "InvoiceTH", acViewNormal, , "[Order ID]=" & OrderID, acDialog
      DoCmd.OpenReport "InvoiceTH", acViewPreview, , "[Order ID]=" & OrderID, acDialog
   Else
      DoCmd.OpenReport "InvoiceEN", acViewNormal, , "[Order ID]=" & OrderID, acDialog
      DoCmd.OpenReport "InvoiceEN", acViewPreview, , "[Order ID]=" & OrderID, acDialog
   End If
End Function



ผมทำตัวอย่างให้ดูในส่วนของ Invoice ภาษาไทยนะครับ คุณส้มนำไปทำอย่างเดียวกันเลยในส่วนของ Invoice ภาษาอังกฤษได้เลย

      DoCmd.OpenReport "InvoiceTH", acViewPreview, , "[Order ID]=" & OrderID, acDialog
      If Msgbox("Do you want to print ?", vbQuestion + vbYesNo + vbDefaultButton1, Me.Caption) = vbYes then
        DoCmd.OpenReport "InvoiceTH", acViewNormal, , "[Order ID]=" & OrderID, acDialog
      End If

ในโค้ดนี้ กล่องข้อความที่ถามเพื่อให้เลือกคลิก Yes หรือ No นั้น จะกำหนดให้ปุ่ม Yes เป็นปุ่ม default ไว้    ถ้าคิดว่าต้องการเปลี่ยนให้ปุ่ม No เป็นปุ่ม default แทน ก็ให้เปลี่ยน vbDefaultButton1 ไปเป็น vbDefaultButton2 แทนครับ
67 @R14870
ขอบพระคุณค่ะอาจารย์ อีก1 เรื่องค่ะ ปุ่มdelete order ของหนูมีปัญหามากเลยค่ะ คาดว่าเวลาเปิดบิลไปแล้วอยากจะลบorder นั้นแต่ในorder มันมีความสัมพันธ์กันอยู่กับตารางอื่นๆ เช่น ตารางInventory ตารางorder detail อาจารย์แนะนำหน่อยได้ไหมค่ะ ถ้าพอหนูเปิดinvoiceไปแล้ว อยากกลับมาลบinvoice เลขนี้ เพราะเลขinvoice เป็นauto id พอเลขซ้ำก็มีปัญหา ตอนนี้หนูแก้ไขโดย ลบไปทีละตารางๆไล่ลบเอาอะค่ะ หนูอยากกดปุ่มเดียวแล้วลบได้ไหมคะ ประมาณว่าสั่งให้ปุ่มรู้ว่าถ้าเรากดลบตรงนี้่ให้ไปเทียบดูว่าต้องลบตารางไหนบ้างแล้วลบไปทั้งแผงเลยอะค่ะ ตอนนี้โค้ดของปุ่มที่อยุ่ในฟอร์ม เป็นแบบนี้นะคะ

Private Sub cmdDeleteOrder_Click()
    If IsNull(Me![Order ID]) Then
        Beep
    ElseIf Me![Status ID] = Shipped_CustomerOrder Or Me![Status ID] = Closed_CustomerOrder Then
        MsgBoxOKOnly CannotCancelShippedOrder
    ElseIf MsgBoxYesNo(CancelOrderConfirmPrompt) Then
        If CustomerOrders.Delete(Me![Order ID]) Then
            MsgBoxOKOnly CancelOrderSuccess
            eh.TryToCloseObject
        Else
            MsgBoxOKOnly CancelOrderFailure
        End If
    End If
End Sub

codeนี้มันลบได้แค่ตอนที่เรายังไม่เลือกสินค้า แต่พอเราเปิดบิลอะไรเสร็จปุ่มนี้ใช้ไม่ได้เลยค่ะ จะขึ้นmsgบอกว่า ลบไม่ได้เพราะมีข้อมูลอยู่ในตารางinventory ประมาณนั้นอะค่ะ รบกวนท่านอาจารย์ แนะนำหน่อยค่ะ

ปล.อาจารย์อ่านอีเมลล์ไม่หมด อิอิ ลืมตอบคำถามปล.ตอนท้ายนะคะ

68 @R14871
อาจารย์ค่ะ code นี้ขึ้น error ตรง me.caption :( ค่ะ



DoCmd.OpenReport "InvoiceTH", acViewPreview, , "[Order ID]=" & OrderID, acDialog
      If MsgBox("Do you want to print ?", vbQuestion + vbYesNo + vbDefaultButton1, Me.Caption) = vbYes Then
        DoCmd.OpenReport "InvoiceTH", acViewNormal, , "[Order ID]=" & OrderID, acDialog
69 @R14873
ถ้าผมเข้าใจไม่ผิดว่าสาเหตุที่ลบ Order ไม่ได้เพราะติดสถานะที่ได้กำหนดเป็น Shipped Order หรือไม่ก็ Completed Order ไปก่อนหน้านี้แล้วหล่ะก็ เราก็ไม่ต้องสนใจการตรวจสอบในบรรทัด
ElseIf Me![Status ID] = Shipped_CustomerOrder Or Me![Status ID] = Closed_CustomerOrder Then

แต่ต้องไปเพิ่มโค้ดสำหรับ
- ลบ Order Details และ Invoice ที่เกี่ยวข้องด้วย
- ทำ Transaction Control เพื่อควบคุมว่า ถ้าการลบติดขัดที่เทเบิลใดเทเบิลหนึ่ง ข้อมูลจากทุกเทเบิลต้องไม่ถูกลบเลย

ก็จะได้โค้ดเป็น
Private Sub cmdDeleteOrder_Click()
     Dim DB      As DAO.Database
    Dim InTrans As Boolean
    
On Error GoTo Err_Handling

    InTrans = False
    Set DB = CurrentDb

    If IsNull(Me![Order ID]) Then
        Beep
    ElseIf MsgBoxYesNo(CancelOrderConfirmPrompt) Then
        InTrans = True: DBEngine.BeginTrans
             DB.Execute "delete * from [Orders] where [Order ID] = " & CStr(Me![Order ID])
             DB.Execute "delete * from [Order Details] where [Order ID] = " & CStr(Me![Order ID])
             DB.Execute "delete * from [Invoices] where [Order ID] = " & CStr(Me![Order ID])
        DBEngine.CommitTrans: InTrans = False
        MsgBoxOKOnly CancelOrderSuccess
        eh.TryToCloseObject
    End If

Exit_Sub:
    Set DB = Nothing
    Exit Sub
    
Err_Handling:
    If InTrans Then DBEngine.Rollback: InTrans = False
    MsgBox "Error code " & Err.Number & ", " & Err.Description
    MsgBoxOKOnly CancelOrderFailure
    Resume Exit_Sub
End Sub


หมายเหตุ : เนื่องจากมีการลบข้อมูลออกจากฐานข้อมูล ดังนั้นก่อนการทดสอบโค้ดนี้ ให้ทำก๊อปปี้ฐานข้อมูลเก็บเอาไว้ก่อนนะครับ หากเกิดผิดพลาดอย่างไรแล้วจะได้เอาชุดก๊อปปี้มาใช้ได้ เวลาทดสอบก็ตรวจดูว่าข้อมูลจากทั้งเทเบิล [Orders], [Order Details], [Invoices] นั้นถูกลบไปจริงหรือไม่ ทดสอบจนแน่ใจแล้วถึงค่อยเอาไปใช้งานจริงๆนะครับ

---------------------------------------------

ส่วนปัญหาจาก Me.Caption เป็นเพราะผมลืมไปว่า procedure นี้ไม่ได้อยู่ในฟอร์ม แต่เป็นอีกโมดูลหนึ่งแยกต่างหาก ซึ่งจะไม่คุณสมบัติ Caption หน่ะครับ ถ้าอย่างนั้นก็ละไว้ก็ได้

จาก MsgBox("Do you want to print ?", vbQuestion + vbYesNo + vbDefaultButton1, Me.Caption)
ก็เปลี่ยนเป็น MsgBox("Do you want to print ?", vbQuestion + vbYesNo + vbDefaultButton1)

---------------------------------------------
70 @R14874
ขอบพระคุณมากค่ะ กำลังนำไปTest เลยค่ะ
71 @R14877
อาจารย์ค่ะ ลองแล้วค่ะ [Order Details], [Invoices] ถูกลบค่ะ แต่ตางราง Orders ไม่ลบเพราะ ติดตาราง Invetory Transactions ค่ะ แต่พอหนูใส่เข้าเพิ่มไปอีกแถวนึงว่า

DB.Execute "delete * from [Inventory Transactions] where [Order ID] = " & CStr(Me![Order ID]) ซึ่งในตารางนี้ก็ระบุ Order Id อยู่นะคะ

แต่มันขึ้นก็ขึ้น Error อะค่ะ

ว่า Error 3061 : Too few parameters. Expected 1   ค่ะ

ปล. อาจารย์คะ อีก 1 เรื่องค่ะ น่าจะเป็นปัญหาสุดท้ายแต่ใหญ่พอสมควร จริงๆแล้วโปรแกรมที่เสร็จก่อนหน้านี้หนูเอาไปใช้กับบริษัทลูกซึ่งมีสินค้าไม่เยอะการPurchase จากsupplier ต้องทำไปทีละรายการๆซึ่งสามารถทำได้ แต่ตอนนี้ที่หนูมาแก้ไขให้ใช้กับHead officeของหนูซึ่งมีสินค้ามากกว่า4000 item อะค่ะ ถ้าหนูมานั่งกดPurchase นั่งกดapprove กด posted to inventory คิดว่าคงต้องกดเป็นแสนๆครั้งแน่เลยค่ะ หนูขออนุญาติส่งขั้นตอนการpurchase เข้าเมลล์ให้อาจารย์นะคะ รบกวนอาจารย์แนะนำอีกทีนะคะ



72 @R14878
- [Inventory Transactions] เป็นตารางหรือคิวรี่ เราควรลบจากตารางแหล่งกำเนิดโดยตรง เพราะคิวรี่บางประเภทจะลบไม่ได้ครับ

- รู้ได้อย่างไรว่า "ตางราง Orders ไม่ลบเพราะ ติดตาราง Invetory Transactions" เพราะในโค้ดที่ให้มาไม่เห็นมีจุดไหนที่ตรวจสอบตาราง [Inventory Transactions] ก่อนการลบเรคอร์ดเลย

- บรรทัดที่เพิ่มมา ลองเช็คดูดีๆว่ามีสะกดตรงไหนผิดหรือเปล่า แล้วมีฟิลด์ [Order ID] ถูกต้องหรือไม่ สะกดถูกหรือไม่ เพราะมันไม่ควรจะขึ้น Error อย่างนั้น

- เรื่องสุดท้ายยังไม่เห็นเมล์นะครับ
73 @R14879
1.มันขึ้นมาบอกอะค่ะ ว่า ไม่สามารถลบรายการในตารางorder ได้เพราะมีข้อมูลอยู่ในตารางinventory transactions คือในตารางนี้จะแสดง status ว่า สินค้าได้sold หรือon holdหรือเป็นpurchase ประมาณนั้นอะค่ะ

2.กำลังexport data แล้วทำเป็น v.เก่าอยู่นะคะของหนูเป็นv.ใหม่หรือว่า อาจารย์ให้หนูส่งได้เลยคะ เดี๋ยวหนูรีบส่งไปค่ะ

เดี๋ยวหนูลองแก้ไขบรรทัดนั้นดูนะคะเผื่อมีอะไรผิดพลาดค่ะ
74 @R14880
เรียบร้อยค่ะในตาราง inventory มันเป็น คำว่า Customer Order ID ไม่ใช่ Order Id หนูแก้ไขเรียบร้อยลบได้100 เปอร์เซ็นแล้วค่ะ
75 @R14881
ส่งเมลล์ไปแล้วค่ะแต่ format เป็น v ใหม่ค่ะ มันsaveเป็นอันเก่าไม่ได้ค่ะ ;(
76 @R14902
อาจารย์คะ หนูคิดออกแล้วถ้าcode นี้ ทำให้รับค่าจากตางรางproduct เลยได้ไหมค่ะ โดยที่ไม่ต้องผ่านการpuchaseและpostขึ้น แต่แค่set ค่า qty avalaible ให้เป็นค่าเริ่มต้นอะค่ะ

Option Compare Database
Option Explicit




Private Sub Product_ID_AfterUpdate()

    'Initialize price and discount for each product change
     
    If Not IsNull(Me![Product ID]) Then
        Me![Quantity] = 0
        Me.Quantity.Locked = False
        Me![Unit Price] = GetListPrice(Me![Product ID])
        Me![Discount] = 0
        Me![Status ID] = None_OrderItemStatus
        Me.Discount = Nz(Me.Product_ID.Column(3), 0)

    'Empty Product records mean user wants to delete line item
    Else
        eh.TryToRunCommand acCmdDeleteRecord
    End If
End Sub


Private Sub Form_Current()
    If Nz(Me![Status ID], None_OrderItemStatus) = Invoiced_OrderItemStatus Then
        Me.AllowEdits = False
    Else
        Me.AllowEdits = True
    End If
End Sub


Private Sub Quantity_AfterUpdate()
    On Error GoTo ErrorHandler
    
    Dim IT As InventoryTransaction
    Dim PurchaseOrderID As Long
    Dim SupplierID As Long
    
    IT.ProductID = Nz(Me![Product ID], 0)
    IT.Quantity = Me![Quantity]
    IT.AllOrNothing = True
    IT.InventoryID = Nz(Me![Inventory ID], NewInventoryID)
    
    'Request Hold on specified Inventory
    If Inventory.RequestHold(Me![Order ID], IT) Then
        Me![Inventory ID] = IT.InventoryID
        Me![Status ID] = OnHold_OrderItemStatus
       
    'Insufficient Inventory
    ElseIf Me![Status ID] <> None_OrderItemStatus And Me![Status ID] <> NoStock_OrderItemStatus Then
        MsgBoxOKOnly InsufficientInventory
        Me![Quantity] = Me.Quantity.OldValue
    
    'Attempt to create purchase order for back ordered items
    ElseIf MsgBoxYesNo(NoInventoryCreatePO) Then
     
        SupplierID = Inventory.FindProductSupplier(IT.ProductID)
       
        'Create purchase order if we have supplier for this product
        If SupplierID > 0 Then
            If PurchaseOrders.Generate(SupplierID, IT.ProductID, Me![Quantity], Me![Order ID], PurchaseOrderID) Then
               PurchaseOrders.OpenOrder PurchaseOrderID
               Me![Status ID] = OnOrder_OrderItemStatus
               Me![Purchase Order ID] = PurchaseOrderID
               eh.TryToSaveRecord
            Else
               Me![Status ID] = NoStock_OrderItemStatus
            End If
            
        'Could not find a supplier for this product
        Else
            MsgBoxOKOnly CannotCreatePO_NoSupplier
            Me![Status ID] = NoStock_OrderItemStatus
        End If
       
    Else
        Me![Status ID] = NoStock_OrderItemStatus
    End If
    
Done:
    Exit Sub

ErrorHandler:
    ' Resume statement will be hit when debugging
    If eh.LogError("Quantity_AfterUpdate") Then Resume
End Sub


Private Sub Status_Name_DblClick(Cancel As Integer)
    Select Case Me![Status ID]
    Case NoStock_OrderItemStatus, None_OrderItemStatus
        Quantity_AfterUpdate
    Case OnOrder_OrderItemStatus
        Dim PurchaseOrderID As Long
        PurchaseOrderID = Nz(Me![Purchase Order ID], 0)
        If PurchaseOrderID > 0 Then
            PurchaseOrders.OpenOrder PurchaseOrderID
            Me.Requery
        End If
    Case Invoiced_OrderItemStatus
    End Select
End Sub
77 @R14903
อันนี้เป็นข้อความที่คุณส้มส่งมา

ที่หนูติดคือ ตรง ปุ่ม new purchase อะค่ะ มันหลายขั้นตอนกว่าจะเปิด invoice ได้ ขั้นตอน คือ
1 เราต้อง add product ที่เป็น standard ก่อน
2 เราต้อง add ลูกค้า+สิค้าของลูกค้า+ราคา พอเสร็จ เรายังเปิดบิลไม่ได้ เพราะ ใน stock ของเรายังเป็น 0 เราจึงต้องไปที่ new purchase เพื่อไปกด เลือก supplier + สินค้าที่เราadd ราคาแล้ว ต่อด้วยส่ง รอ approve และ approve เสร็จ ต้อง กด post to inventory เพื่อจำนวนที่เรา purchase จะได้ไปขึ้น แสดงให้เห็นว่า ใน stock เรามีจำนวนสินค้าพร้อมเปิดบิล ซึ่งในบริษัทลูกที่หนูทำลูกค้าน้อยสินค้าน้อย สามารถทำได้ แต่ตอนนี้มาทำของ head office ลูกค้าเยอะค่ะ และ สินค้าก็เยอะ หนูไม่สามรถ มานั่งกดเข้าทีละรายการได้ หนูทำอย่างไรได้บ้างคะ เราสามารถลัดขั้นตอนไปเลย เช่น เวลาที่เรา addสินค้า+ราคา แล้วให้จำนวน set auto เลยได้ไหมคะ อยู่ในformเดียวกันเลยได้หรือเปล่าคะ


พอจะมีวิธีทำได้ครับ เท่าที่ดูคร่าวๆ สิ่งที่เกิดขึ้นคือระบบจะสร้างเรคอร์ดในเทเบิล [Purchase Orders], [Purchase Order Details] และ [Inventory Transactions] โดย Purchase Order ที่เราสร้างขึ้นจะมีแค่รายการสินค้ารายการเดียวเท่านั้น และ Inventory Transactions ที่เกิดขึ้นก็จะอ้างถึง Purchase Order นี้ไปเลย แต่จะไม่ได้ทำกระบวนการ Back Order ซึ่งผมไม่ได้ดูรายละเอียดว่ามันทำอะไรบ้าง เพราะเยอะเกินไป

สิ่งที่ต้องทำก็คือ
1. สร้าง Textbox ชื่อ OrderQty ไว้บน Detail section ของฟอร์ม Product Details เพื่อไว้ป้อนจำนวนที่จะสร้างในเทเบิล [Purchase Order Details] และถือว่าเป็นจำนวนที่จะนำเข้าสู่ระบบ Inventory ด้วยเช่นกัน; กำหนด Format property เป็น Standard; Decimal Place เป็นศูนย์; Input Mask เป็น ##,### (ถ้าต้องการมากกว่าหลักหมื่น ก็เพิ่มจำนวน # ได้ครับ)

2. สร้าง Command Button ชื่อ cmdGenPOandPostInven ไว้บน FormHeader section ของฟอร์ม Product Details เพื่อให้คลิกสำหรับสร้างเรคอร์ดในเทเบิล [Purchase Orders], [Purchase Order Details] และ [Inventory Transactions]   เมื่อไหร่ก็ตามที่ปุ่มนี้กด เรคอร์ดใน 3 เทเบิลจะถูกสร้างขึ้นมาทุกครั้ง ระบบไม่มีความสามารถตรวจได้ว่ากดเบิ้ลไปหรือไม่ ถ้ากด 10 ครั้งก็จะได้ Purchase Order ของรายการเดิม 10 ใบ และนำเข้า Inventory 10 ครั้งเช่นกัน; การคลิกปุ่มนี้ ให้คลิกหลังจากได้ป้อนและบันทึก Product Details ไปแล้ว

ใส่โค้ดนี้สำหรับปุ่ม cmdGenPOandPostInven

Private Sub cmdGenPOandPostInven_Click()
    Dim DB          As DAO.Database
    Dim RS          As DAO.Recordset
    
    Dim POID        As Long
    Dim InventID    As Long
    Dim InTrans     As Boolean
    Dim NowTime     As Date
    
On Error GoTo Err_Handling

    InTrans = False
    Set DB = CurrentDb

    If Me.Dirty Then
        MsgBox "Please save editing product first.", vbExclamation, Me.Caption
        GoTo Exit_Sub
    End If
    
    If Nz(Me.ID, 0) Then
        MsgBox "ID is required", vbExclamation, Me.Caption
        Me.ID.SetFocus
        GoTo Exit_Sub
    End If
    
    If Nz(Me.Supplier_IDs, 0) Then
        MsgBox "Supplier is required", vbExclamation, Me.Caption
        Me.Supplier_IDs.SetFocus
        GoTo Exit_Sub
    End If
    
    If Nz(Me.Standard_Cost, 0) Then
        MsgBox "Standard Cost is required", vbExclamation, Me.Caption
        Me.Standard_Cost.SetFocus
        GoTo Exit_Sub
    End If
    
    If Nz(Me.OrderQty, 0) Then
        MsgBox "Order Qty is required", vbExclamation, Me.Caption
        Me.OrderQty.SetFocus
        GoTo Exit_Sub
    End If
    
    NowTime = Now()
    
    InTrans = True: DBEngine.BeginTrans
    
    Set RS = DB.OpenRecordset("Purchase Orders", dbOpenDynaset, dbAppendOnly)
    With RS
        .AddNew
        ![Supplier ID] = Me.Supplier_IDs
        ![Created By] = GetCurrentUserID
        ![Creation Date] = NowTime
        ![Approved By] = GetCurrentUserID
        ![Approved Date] = NowTime
        ![Submitted By] = GetCurrentUserID
        ![Submitted Date] = NowTime
        ![Status ID] = Approved_PurchaseOrder
        .Update
        POID = ![Purchase Order ID]
    End With
    RS.Close
             
    Set RS = DB.OpenRecordset("Inventory Transactions", dbOpenDynaset, dbAppendOnly)
    With RS
        .AddNew
        ![Transaction Type] = Purchase_TransactionType
        ![Transaction Created Date] = NowTime
        ![Product ID] = Me.ID
        ![Quantity] = Me.OrderQty
        ![Purchase Order ID] = POID
        .Update
        InventID = ![Transaction ID]
    End With
    RS.Close
             
    Set RS = DB.OpenRecordset("Purchase Order Details", dbOpenDynaset, dbAppendOnly)
    With RS
        .AddNew
        ![Purchase Order ID] = POID
        ![Product ID] = Me.ID
        ![Quantity] = Me.OrderQty
        ![Unit Cost] = Me.Standard_Cost
        ![Posted To Inventory] = True
        ![Inventory ID] = InventID
        .Update
    End With
    RS.Close
             
    DBEngine.CommitTrans: InTrans = False
    MsgBox "PO No " & CStr(POID) & " is generated and post to inventory completely", vbInformation, Me.Caption

Exit_Sub:
    On Error Resume Next
    RS.Close: Set RS = Nothing
    Set DB = Nothing
    Exit Sub
    
Err_Handling:
    If InTrans Then DBEngine.Rollback: InTrans = False
    MsgBox "Error code " & Err.Number & ", " & Err.Description
    MsgBox "Can not generate PO and post qty to inventory", vbExclamation, Me.Caption
    Resume Exit_Sub
End Sub


ผมเขียนแต่ไม่ได้ทดสอบนะครับ คุณส้มลองดูว่ามันสร้าง PO และโพสจำนวนไปสินค้าคงคลังได้ถูกต้องหรือไม่ โดยเปิดเทเบิล [Purchase Order Details] ของ PO ที่ได้สร้างไปแล้ว ดูว่าฟิลด์ [Purchase Order ID] และฟิลด์ [Inventory ID] มีค่าหรือไม่ ถ้ามีก็โอเคครับ

------------------------

อีกเรื่องคือ ใต้ Private Sub Company_KeyUp(KeyCode As Integer, Shift As Integer) มี End Sub ซ้อนกัน 2 บรรทัดหรือไม่ ถ้ามีก็ให้เอา End Sub ที่เกินมาบรรทัดนึงออกครับ

------------------------
78 @R14906
If Nz(Me.Standard_Cost, 0) Then
        MsgBox "Standard Cost is required", vbExclamation, Me.Caption
        Me.Standard_Cost.SetFocus
        GoTo Exit_Sub
    End If
     

บรรทัดนี้ error ตรงสีแดงค่ะ
79 @R14907
แก้ไขแล้ว ตอนแรกมันบอก หาข้อมูล standard cost ไม่เจอ พอดีโอไปลบออกจากฟอร์มอะค่ะ หายerror แล้ว มาขึ้น error ตรงนี้แทนค่ะ


If Nz(Me.OrderQty, 0) Then
        MsgBox "Order Qty is required", vbExclamation, Me.Caption
        Me.OrderQty.SetFocus
        GoTo Exit_Sub

    End If
     
80 @R14908
อาจารย์ค่ะerrorนั้นก็หายแล้วค่ะแต่ที่ขึ้นว่า

Please save editing product first

คืออะไรคะอาจารย์
@ ประกาศใช้งานเว็บบอร์ดใหม่ => บอร์ดเรียนรู้ Access สำหรับคนไทย
แล้วจะใส่ลิ้งอ้างอิงมาที่โพสต์เก่านี้หรือไม่ก็ตามสะดวกครับ
Time: 0.2047s