แสดงกระทู้

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Tonwrp

หน้า: [1] 2
1
ถ้าผิดยังไงก็ขอโทษด้วย เพรายังไม่เคยใช้ Office 64  แต่เท่าที่อ่านความหมายของ VBA7, ประเภทข้อมูล LongLong, LongPtr และ PtrSafe Keyword https://codekabinett.com/rdumps.php?Lang=2&targetDoc=windows-api-declaration-vba-64-bit link ถ้า Office 32 bit นั้นเป็นเวอร์ชั่นตั้งแต่ 2010 ขึ้นไป เชื่อว่าไม่น่าจะรันได้ครับ เพราะ Compiler Directive VBA7 จะเป็นจริงตั้งแต่ Access 2010 ดังนั้นโค้ดจะรันแล้วเจอะข้อมูลประเภท LongLong ที่มีเฉพาะในเวอร์ชั่น 64 bit เท่านั้น ส่วนต้องโค้ดยังไงถึงจะถูก อันนี้ผมไม่รู้ ต้องคนที่ดู API เป็นครับ

แต่ถ้า Office 32 bit นั้นเป็นเวอร์ชั่นตำกว่า 2010 น่าจะแน่นอนว่าโค้ดนี้จะรันได้

แต่ Compiler Directive มีผลเฉพาะตอนที่ยังเป็นไฟล์ .accdb  ถ้าคอมไพล์เป็นไฟล์ .accde แล้ว  คอมไพล์ด้วย Office กี่ bit ก็ต้องไปใช้ที่เครื่อง Office แค่นั้น bit เท่านั้นครับ

โพสต์นี้ได้รับคำขอบคุณจาก: Tonwrp

2
Dim TSDYYMM As String
Dim MaxRunNo As Integer

TSDYYMM = "TSD-" & Format([txt_LoanDate], "yymm")
MaxRunNo = Val( Right( Nz(DMax("[Loan_No]", "[Tb_Loan]", "[Loan_No] Like '" & TSDYYMM & "*'"),"0"),3 )  )
txt_LoanNo = TSDYYMM  & Format(MaxRunNo + 1, "000")
โพสต์นี้ได้รับคำขอบคุณจาก: Tonwrp

3
อ้างถึง
txt_LoanNo = "TSD" & Format([txt_LoanDate], "yymm") & Right("000" & DCount("[Loan_No]", "[Tb_Loan]", "Left([Loan_No],4) = Format([txt_LoanDate],'yymm')") + 1, 3)

ใช่ครับ โค้ดข้างบนนี้จะเริ่มให้ค่า 1 เมื่อเป็นเดือนใหม่ ถ้าต้องการให้ +1 ในปีนั้นไปเรื่อยๆจนกว่าจะเป็นปีใหม่ ก็ต้องเป็น
อ้างถึง
txt_LoanNo = "TSD" & Format([txt_LoanDate], "yymm") & Right("000" & DCount("[Loan_No]", "[Tb_Loan]", "Left([Loan_No],2) = Format([txt_LoanDate],'yy')") + 1, 3)
แต่ผมว่าดูแปลกๆไม่สัมพันธ์กับเลขหลัง TSD หรือเปล่า เพราะพอเดือนใหม่ เลขหลัง TSD ก็เป็น ปีและเดือน ถัดไป แต่เลขรันนิ่งยังเป็นเลขต่อจากเดือนที่แล้ว เช่น ในเดือน 8 มีเลขรันจาก TSD1908001 ถึง TSD1908123 แต่เลขแรกของเดือน 9 เป็นเลข TSD1909124  แต่ไม่ว่ายังไงก็ตาม การใช้ DCount ค่อนข้างไม่ถูกต้อง เพราะมันเป็นการนับจำนวน อย่างเดือน 8 มีเลขที่สมมุติข้างบน  ถ้าเรายังอยู่ในเดือน 8 และมี 1 เรคอร์ดที่ถูกลบไป   พอสร้างเลขต่อไป  Dcount ก็จะนับได้ทั้งหมดเหลือ 122 เลข พอบวก 1 ก็จะได้เลขถัดไปเป็น TSD1908123 ซึ่งซ้ำกับเลขเดิมแน่ๆ

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

4
ผมนำไฟล์อ.OddyWriter จากกระทู้ > อยากได้ตัวอย่าง access การทำ running number แบบ ปี เดือน รันเลข 3 ตำแหน่ง มาแก้ให้เป็น yymm-00000 เป็นที่เรียบร้อย ลองไปเปลี่ยนตัวแปรเพื่อใช้ใน Qeury ของท่านดูครับ

โค๊ด: [Select]
Private Sub Data_AfterUpdate()
    txtRunningNum = Format([txtDate], "yymm") & "-" & Right("00000" & DCount("[RunningNum]", "[tblRunningNumber]", "Left([RunningNum],4) = Format([txtDate],'yymm')") + 1, 5)
End Sub

ปล.รูปที่นำไปฝากตามเว็บเมื่อจะนำมาโพสกระทู้เว็บบอร์ดให้ใช้หรือ Copy BBCode มาครับ
โพสต์นี้ได้รับคำขอบคุณจาก: Tonwrp

5
ไม่ทราบโค้ดนี้เขียนใน event ไหนของฟอร์ม ปกติผมก็จะเขียนใน Form_BeforeUpdate event พอได้เลขก็เอากลับไปเช็คในเทเบิลทันทีเลยว่า มีเรคอร์ดของเลขนั้นอยู่ในเทเบิลแล้วหรือเปล่า ถ้ามีก็จะหาเลขถัดไปใหม่อีกครั้งแล้วก็เช็คเทเบิลอีกที วนอย่างนี้ไปเรื่อยๆจนครบกี่ครั้งตามที่เรากำหนด จึงแจ้งข้อความว่าซ้ำ ให้ผู้ใช้ลองทำใหม่อีกทีเท่านั้นเองครับ โอกาสที่จะต้องเตือนผู้ใช้ให้ทำอีกครั้ง ก็เป็นไปได้ แต่น่าจะน้อยมากๆครับ
โพสต์นี้ได้รับคำขอบคุณจาก: Tonwrp

6
auto run ของคุณคือฟิลด์ที่มีข้อมูลเป็นประเภท Autonumber หรือว่าคุณเขียนโค้ดเพื่อสร้างเลข Loan No. เอาเองครับ
โพสต์นี้ได้รับคำขอบคุณจาก: Tonwrp

7
สร้างเป็น Relationship ด้วยครับ เพราะจะได้ประโยชน์โดยอัตโนมัติคือ จะป้อนเลขที่ใบยืมลงในใบคืนได้ เลขยืมนั้นต้องมีอยู่จริงแล้ว และจะไม่สามารถลบใบยืมได้ถ้าเลขที่ใบยืมยังปรากฏอยู่ในใบคืนด้วย
โพสต์นี้ได้รับคำขอบคุณจาก: Tonwrp

8
โพสต์นี้ได้รับคำขอบคุณจาก: Tonwrp

9
ผมแนะนำว่าควรมีการบันทึกในใบคืนของ ว่าเป็นการคืนมาจากการยืมเลขที่อะไรด้วย (สมมุติชื่อฟิลด์คือ Loan_no) ถ้าเพิ่มได้ คิวรี่นี้ก็เปลี่ยนเงื่อนไขที่ WHERE เป็น (Asset ถูกยืมไปแล้ว) และ (ไม่พบใบคืนที่มีเลขที่ยืมอันเดียวกันนี้ปรากฏอยู่)

WHERE ((Tb_Assets.Asset_Status=False)
     AND NOT EXISTS (SELECT Tb_Return.Loan_No FROM Tb_Return WHERE Tb_Return.Loan_No = Tb_Loan.Loan_No);



หรือไม่ต้องเช็คสถานะของ Asset เลยก็ได้ เป็น

WHERE NOT EXISTS (SELECT Tb_Return.Loan_No FROM Tb_Return WHERE Tb_Return.Loan_No = Tb_Loan.Loan_No);

เพราะตามตรรกะของระบบแล้ว แน่นอนว่าของที่มีใบยืม แต่ไม่มีเลขที่ใบยืมอยู่ในใบคืนใดๆเลย ก็คือของที่ Asset_Status เป็น False นั่นเอง แต่มัน **อาจจะ** ทำให้การค้นหาช้าลงเมื่อมีข้อมูลการยืม/คืนอยู่เป็นจำนวนมาก (ที่บอกว่า อาจจะ เพราะถ้าอยากทราบจริงๆ ต้องขุดลึกลงไปว่าตัวจัดการคิวรี่ (Query Optimizer) มันฉลาดหรือทื่อๆแค่ไหนกับคำสั่งคิวรี่นั้นๆ)
โพสต์นี้ได้รับคำขอบคุณจาก: Tonwrp

10
เอา code ไปวางไว้ที่ไหน ของผมใช้ 32 บิต พนไปเจอ 64 บิต จะต้องถอนลงใหม่ตลอด
โพสต์นี้ได้รับคำขอบคุณจาก: Tonwrp

11
ผมเขียนด้วย 2003 32บิต รันใน 2013 64บิต
โค๊ดจะเพิ่มมาอีก เท่าตัวสำหรับการประกาศค่าตัวแปรที่จะให้เข้ากันได้
ไม่รู้ว่า 2010 32บิต จะเหมือน 2003 32บิต หรือป่าวนะครับ เช่น

#If VBA7 Then
    Private Declare PtrSafe Function GetKeyboardLayout Lib "User32" (ByVal dwLayout As LongLong) As LongLong
    Private Declare PtrSafe Function ActivateKeyboardLayout Lib "User32" (ByVal HKL As LongLong, ByVal Flags As LongLong) As LongLong
    Private Declare PtrSafe Function LoadKeyboardLayout Lib "User32" Alias "LoadKeyboardLayoutA" (ByVal pwszKLID As String, ByVal Flags As LongLong) As LongLong
    Dim res As LongLong
#Else
    Private Declare Function GetKeyboardLayout Lib "User32" (ByVal dwLayout As Long) As Long
    Private Declare Function ActivateKeyboardLayout Lib "User32" (ByVal HKL As Long, ByVal Flags As Long) As Long
    Private Declare Function LoadKeyboardLayout Lib "User32" Alias "LoadKeyboardLayoutA" (ByVal pwszKLID As String, ByVal Flags As Long) As Long
    Dim res As Long
#End If
โพสต์นี้ได้รับคำขอบคุณจาก: Tonwrp

12
สั่งคำสั่ง  DoCmd.OpenReport "ชื่อรายงาน",,,"เงื่อนไขเรคอร์ดที่ต้องการในรายงาน"

เงื่อนไขที่ว่าก็เขียนเหมือนกับ WHERE clause ใน SQL statement โดยที่ถ้ามีชื่อฟิลด์ ก็ต้องเป็นชื่อฟิลด์ที่ได้จาก Query ที่เป็น Record Source ของรายงานด้วย กรณีนี้ก็คือ

DoCmd.OpenReport "ชื่อรายงาน",,,""Loan_No = '" & Me.txt_LoanNo & "'"

ดังนั้นเราก็จะเลือกพิมพ์เฉพาะการยืมที่ปรากฏบนหน้าฟอร์มรายการเดียวเท่านั้น

หรืออีกวิธีก็คือ บรรทัดเงื่อนไข (Criteria) ภายใน Query เองสำหรับคอลัมน์ Loan_No ก็ให้เขียนเป็น Forms![Frm_Loan]![txt_LoanNo] แต่ก็หมายความว่า เมื่อไหร่ที่คิวรี่ตัวนี้ทำงาน ฟอร์มที่ว่านั้นก็ต้องเปิดอยู่และมีค่า Loan_No ไว้ด้วย ไม่งั้นก็จะเกิด error ได้ และวิธีนี้ก็สั่งเปิดรายงานด้วยคำสั่งสั้นๆว่า DoCmd.OpenReport "ชื่อรายงาน" เท่านั้นเอง
โพสต์นี้ได้รับคำขอบคุณจาก: Tonwrp

13
เมื่อเก็บเป็น Path และไฟล์ภาพก็อยู่ที่เซิร์ฟเวอร์ แต่เนื่องจากโปรแกรมที่ทำงานจะอยู่ที่แต่ละเครื่อง  การเขียน Path จึงมีรูปแบบเป็น Path ที่แต่ละเครื่องอ้างไปยังไฟล์ภาพบนเซิร์ฟเวอร์ ไม่ใช่ Path ที่อ้างจากฐานข้อมูลบนเซิร์ฟเวอร์ไปยังไฟล์ภาพบนเซิร์ฟเวอร์เอง ดังนั้น Path ที่ถูกต้องก็จะเป็นรูปแบบ

\\ชื่อเซิร์ฟเวอร์\ชื่อซับโฟลเดอร์(ถ้ามี)\......\ชื่อไฟล์  เช่น \\ServEngineer\Data\Assets\Pic\NutBt0500.jpg
โพสต์นี้ได้รับคำขอบคุณจาก: Tonwrp

14
คุณจะดึงฟิลด์ Attachment มาจากคิวรี่แล้วมากำหนดให้ Attachment Control โดยตรงอย่างนี้ไม่ได้  แต่เราสามารถเอามาเป็น Control Source ของ  Attachment Control ได้ ดังนั้นเราจะสร้าง Attachment Control ตัวนึง (ชื่อว่า A) ใส่ลงฟอร์มเปล่า (ชื่อว่าฟอร์ม F) แล้วเอา F มาใส่เป็น Sub Form control (ชื่อ SF) ใน ฟอร์มการยืมอีกที ทีนี้เมื่อใดที่มีการเลือก Asset เราก็จะสร้าง Record Source ของ SF เป็น SQL SELECT statement ที่ดึงเอาเฉพาะฟิลด์ Attachment ที่เก็บรูปภาพตาม Asset_ID ที่เลือก  ดังนั้นภาพก็จะแสดงออกมา เท่านี้เองครับ

โค้ดให้ใส่ไว้ใน Private Sub cbo_Loanasset_AfterUpdate() , ใน Private Sub Form_Current() และใน Private Sub Form_Undo(Cancel As Integer) ด้วย
โค๊ด: [Select]
    If IsNull(Me.cbo_Loanasset) Then
        Me.SF.Form.RecordSource = ""
    Else
        Me.SF.Form.RecordSource = "select Asset_Photo from tb_Asset where Asset_ID = " & Cstr(Me.cbo_Loanasset)
    End If

นอกจากนี้ให้กำหนด property เหล่านี้เอาไว้ด้วย

สำหรับ A
Control Source เป็น Asset_Photo
Enabled   No

สำหรับ F
Record Selectors   No
Naviagtion Buttons   No
Dividing Lines      No
Scroll Bars         Neither
Recordset Type      Snapshot

ที่เหลือก็ปรับขนาดกรอบรูปเท่านั้นครับ
โพสต์นี้ได้รับคำขอบคุณจาก: Tonwrp

15
เลือก Data Entry property ของฟอร์มเป็น Yes เท่านี้เองครับ
โพสต์นี้ได้รับคำขอบคุณจาก: Tonwrp

16
แย่แล้วผม ทำไมผิดอย่างนี้    DoCmd.SetWarnings False หรือ True ไม่ต้องมีเครื่องหมาย = ครับ
โพสต์นี้ได้รับคำขอบคุณจาก: Tonwrp

หน้า: [1] 2