กระทู้เก่าบอร์ด อ.สุภาพ ไชยา
515 15
URL.หัวข้อ /
URL
Module - Funtion การปัดจุดทศนิยม
รบกวน อ.สุภาพ ครับ
คือ ผมมีปัญหากับ จุดทศนิยม ครับ ผมต้องการเพียง 2 ตำแหน่ง
แต่ Access จะสะสมมากกว่า 2 ตำแหน่ง และ ทำให้เวลา Sum จะผิด
เช่น Part จุดทศนิยม 2 ตำแหน่ง จุดทศนิยม 3 ตำแหน่ง
A 2.34 2.345
B 2.48 2.475
Sum 5.83 5.830
ซึ่งบางทีก็ปัดขึ้น บางทีก็ไม่ปัดขึ้น ไม่ทราบว่า อ.สุภาพ
มี Funtion แก้ไขไหมครับ หรือมีวิธีอื่นๆ รบกวนแนะนำด้วยครับ
( Update รูปลูกชาย/ลูกสาว ใหม่หรือครับ โตขึ้นแล้ว )
ขอบพระคุณมากๆ ครับ
Suchat
คือ ผมมีปัญหากับ จุดทศนิยม ครับ ผมต้องการเพียง 2 ตำแหน่ง
แต่ Access จะสะสมมากกว่า 2 ตำแหน่ง และ ทำให้เวลา Sum จะผิด
เช่น Part จุดทศนิยม 2 ตำแหน่ง จุดทศนิยม 3 ตำแหน่ง
A 2.34 2.345
B 2.48 2.475
Sum 5.83 5.830
ซึ่งบางทีก็ปัดขึ้น บางทีก็ไม่ปัดขึ้น ไม่ทราบว่า อ.สุภาพ
มี Funtion แก้ไขไหมครับ หรือมีวิธีอื่นๆ รบกวนแนะนำด้วยครับ
( Update รูปลูกชาย/ลูกสาว ใหม่หรือครับ โตขึ้นแล้ว )
ขอบพระคุณมากๆ ครับ
Suchat
15 Reply in this Topic. Dispaly 1 pages and you are on page number 1
1 @R00361
ถ้าใช้ Access 97 จะไม่มีฟังก์ชัน Round() มาให้ แต่จะมีตั้งแต่เวอร์ชัน 2000 ขึ้นไป
แต่จะมีบักอยู่ ผมจะใช้ฟังก์ชัน Round() ซึ่ง Ken Getz เขียนไว้ดีมาก ที่
http://www.mvps.org/access/modules/mdl0054.htm
นี่คือโค้ดที่เขาให้ไว้ครับ
Public Function Round( _
ByVal Number As Variant, NumDigits As Long, _
Optional UseBankersRounding As Boolean = False) As Double
'
' ---------------------------------------------------
' From "Visual Basic Language Developer's Handbook"
' by Ken Getz and Mike Gilbert
' Copyright 2000; Sybex, Inc. All rights reserved.
' ---------------------------------------------------
'
Dim dblPower As Double
Dim varTemp As Variant
Dim intSgn As Integer
If Not IsNumeric(Number) Then
' Raise an error indicating that
' you've supplied an invalid parameter.
Err.Raise 5
End If
dblPower = 10 ^ NumDigits
' Is this a negative number, or not?
' intSgn will contain -1, 0, or 1.
intSgn = Sgn(Number)
Number = Abs(Number)
' Do the major calculation.
varTemp = CDec(Number) * dblPower + 0.5
' Now round to nearest even, if necessary.
If UseBankersRounding Then
If Int(varTemp) = varTemp Then
' You could also use:
' varTemp = varTemp + (varTemp Mod 2 = 1)
' instead of the next If ...Then statement,
' but I hate counting on TRue == -1 in code.
If varTemp Mod 2 = 1 Then
varTemp = varTemp - 1
End If
End If
End If
' Finish the calculation.
Round = intSgn * Int(varTemp) / dblPower
End Function
วิธีการใช้
ถ้าต้องการที่จะปัด 2 ตำแหน่ง ทำได้ดังนี้
? MRound(2.345,2)
2.35
2 @R00363
ขอบพระคุณ อ.สุภาพ มากๆ ครับ
3 @R00370
เพิ่มเติม ครับ จากการที่ผมส่ง File ไปให้ อาจารย์ ตรวจสอบว่าเกิดอะไรขึ้น
เมื่อผม Add New Record แล้วจะพบ Error ใน Funtion Round
ขอเล่าเรื่องก่อนนะครับ
ผมมี Form 2 Form (Main Form และ Sub Form)
Form ทั้ง 2 Form ผม Link มาจาก Table โดยตรง (ไม่ได้ผ่านทาง Query)
ทีนี้ใน Sub Form ผมใช้การคูณระหว่าง Field เช่น ก x ย x ส = M3
ผมต้องการ ทศนิยม 2 ตำแหน่ง ก็สร้าง Field ใหม่ เช่น =Round([M3],2)
และผมทำการ Sum ในทุกๆ Field ปรากฏว่าเมื่อผม Add New Record ก็จะพบ Error
ขณะนี้ผมแก้ไขได้แล้วครับ
ก็คือ ใน Sub Form ให้ Link มาจาก Query และไปสร้าง Field จุดทศนิยมไว้ที่นั่น
เสร็จแล้ว Sub Form ก็ Link ตามปกติ เวลา Sum Total ก็ Sum([ชื่อ Field])
เมื่อ Add New Record ก็จะไม่มี Error เกิดขึ้นครับ
ก็ขอบพระคุณ อ.สุภาพ มากๆ นะครับ สำหรับความรู้ดีๆ
พอดีผมเจอ Funtion Round จากใน website อีกที่หนึ่ง คือ
Function SRound(Number As Double, num_digits As Integer) As Double
On Error GoTo Err_round
digits = 10 ^ (num_digits * -1)
Round = Int(Number / digits + 0.5) * digits
Exit_round:
Exit Function
Err_round:
MsgBox Error$
Resume Exit_round
End Function
รบกวน อ.สุภาพ ตรวจสอบดูด้วยครับว่า ผลลัพธ์ ที่ออกมาถูกต้อง
เหมือนกับ Funtion ที่ อ.สุภาพ ให้มาหรือไม่
ขอบพระคุณมากๆ ครับ
Suchat
4 @R00371
ยังมีปัญหาครับ เช่น
เช่น ถ้าต้องการ Round เลข .2405 ให้เป็นทศนิยม 3 ตำแหน่ง
ถ้าทำแบบโค้ดของฝรั่ง หรือทำใน Excel (=Round(.2405,3) จะได้ .241
? Round(.2405,3)
.241
แต่ถ้าเป็นโค้ดที่ให้ผลทดสอบ จะได้ .24 ซึ่งไม่ถูกต้อง
? SRound(.2405,3)
.24
ซึ่งจะมีบักเหมือน Round() ที่มากับ Access 2000 และ Access XP ตรงนี้เหมือนกันครับ
ผมเคยใช้สูตร Round คล้ายนี้เมื่อ 4 ปีที่แล้วในการปัดเกรดนักศึกษาวิศวะแห่งหนึ่ง ดังนี้
? sround(2.405,2)
2.4
ซึ่งเขาต้องได้ 2.41
ผมเลยถูกตรวจสอบจากทางทบวงมหาวิทยาลัย โดยไล่มาเป็นขั้นๆ จนถึงตัวโปรแกรมของผม แต่ผมก็พิสูตร์ให้เห็นว่า มันเป็นบักของฟังก์ชัน Int() ของ Access
ถ้าทำการปัดทศนิยมด้วยเครื่องคิดเลยตามสูตร จะได้ผลที่ถูกต้อง
ถ้าว่างๆ ก็ลองทดสอบกับตัวเลขต่อไปนี้อีกก็ได้
.2845
.3445
.3545
.3645
.4145
.4245
.4745
.4845
.5045
.5145
.5245
.5345
.5445
.6345
.7545
.7645
.8845
โดยทำการปัดทศนิยมแบบ GPA คือ ปัดจากหลักที่สี่เป็นต้นมา แต่เอาแค่ 2 หลัก
? sround(sround(.3545,3),2)
.35
แทนที่จะเป็น .36
ก่อนที่ผมจะได้เจอโค้ดที่ถูกต้องและสั้นของฝรั่งนั้น ผมได้แก้ปัญหาของบักโดยการเขียนโค้ดขึ้นมาเอง ซึ่งยาวเหยียด ดังนี้ครับ
Function Round3(Value As Variant, Decimals As Variant)
If Decimals >= 0 Then
If InStr(Value, ".") = 0 Then
Round3 = Value
ElseIf Value < 0 Then
Round3 = Left((Value * 10 ^ Decimals - 0.5) _
/ 10 ^ Decimals, InStr(Value, ".") + Decimals)
Else
Round3 = Left((Value * 10 ^ Decimals + 0.5) _
/ 10 ^ Decimals, InStr(Value, ".") + Decimals)
End If
Else
If InStr(Value, ".") = 0 Then
If Len(Abs(Value)) > Abs(Decimals) Then
If Value < 0 Then
If InStr((Value * 10 ^ Decimals) - 0.5, ".") = 0 Then
Round3 = ((Value * 10 ^ Decimals) - 0.5) * 10 ^ Abs(Decimals)
Else
Round3 = Left(((Value * 10 ^ Decimals) - 0.5), _
InStr(((Value * 10 ^ Decimals) - 0.5), ".") - 1) * 10 ^ Abs(Decimals)
End If
Else
If InStr((Value * 10 ^ Decimals) + 0.5, ".") = 0 Then
Round3 = ((Value * 10 ^ Decimals) + 0.5) * 10 ^ Abs(Decimals)
Else
Round3 = Left(((Value * 10 ^ Decimals) + 0.5), _
InStr(((Value * 10 ^ Decimals) + 0.5), ".") - 1) * 10 ^ Abs(Decimals)
End If
End If
ElseIf Left(Abs(Value), 1) <= 4 Or Len(Abs(Value)) < Abs(Decimals) Then
Round3 = 0
Else
If Value < 0 Then
If InStr((Value * 10 ^ Decimals) - 0.5, ".") = 0 Then
Round3 = ((Value * 10 ^ Decimals) - 0.5) * 10 ^ Abs(Decimals)
Else 'Having problems here
Round3 = Left(((Value * 10 ^ Decimals) - 0.5), _
InStr(((Value * 10 ^ Decimals) - 0.5), ".") - 1) * 10 ^ Abs(Decimals)
End If
Else
If InStr((Value * 10 ^ Decimals) + 0.5, ".") = 0 Then
Round3 = ((Value * 10 ^ Decimals) + 0.5) * 10 ^ Abs(Decimals)
Else
Round3 = Left(((Value * 10 ^ Decimals) + 0.5), _
InStr(((Value * 10 ^ Decimals) + 0.5), ".") - 1) * 10 ^ Abs(Decimals)
End If
End If
End If
Else
If Len(Left(Abs(Value), InStr(Abs(Value), ".") - 1)) > Abs(Decimals) Then
If Value < 0 Then
Round3 = Left(((Value * 10 ^ Decimals) - 0.5), _
InStr(((Value * 10 ^ Decimals) - 0.5), ".") - 1) * 10 ^ Abs(Decimals)
Else
Round3 = Left(((Value * 10 ^ Decimals) + 0.5), _
InStr(((Value * 10 ^ Decimals) + 0.5), ".") - 1) * 10 ^ Abs(Decimals)
End If
ElseIf Left(Abs(Value), 1) <= 4 Or Len(Left(Abs(Value), _
InStr(Abs(Value), ".") - 1)) < Abs(Decimals) Then
Round3 = 0
Else
If Value < 0 Then
Round3 = Left(((Value * 10 ^ Decimals) - 0.5), _
InStr(((Value * 10 ^ Decimals) - 0.5), ".") - 1) * 10 ^ Abs(Decimals)
Else
Round3 = Left(((Value * 10 ^ Decimals) + 0.5), _
InStr(((Value * 10 ^ Decimals) + 0.5), ".") - 1) * 10 ^ Abs(Decimals)
End If
End If
End If
End If
Round3 = Val(Round3)
End Function
และทดสอบแล้วว่าตั้งแต่ 0.0001 ถึง 3.9999 จะไม่มีปัญหากับการปัดแบบ GPA
5 @R00372
ขอบพระคุณ อ.สุภาพ มากๆ ครับ สำหรับผลการทดสอบ
แล้วไม่ทราบว่า ผมควรใช้ Funtion อันไหนดีครับ
ระหว่าง Funtion Round() ซึ่งเขียนโดย Ken Getz
กับ Function Round3 ของ อาจารย์
ซึ่งจะทำให้ผลการปัดจุดทศนิยม ถูกต้องครับ
ขอบพระคุณครับ
Suchat
ชลบุรี
6 @R00373
ใช้ของ Ken Getz ก็น่าจะดี เพราะโค้ดมันสั้นดี ส่วนของผมจะลองตรวจสอบตัวเลขที่มีมากกว่า 4.00 ดูก่อนครับ หรือจะช่วยทดสอบก็ยินดีมากเลขครับ
7 @R00374
ขอบพระคุณมากๆ ครับ
Suchat
ชลบุรี
8 @R00376
ผมไปลองทดสอบการใช้ฟังก์ชัน Round() ซึ่งมีมาพร้อมกับ Visual FoxPro 6.0 ไม่มีปัญหาอะไรครับ
ใช้ได้ถูกต้องดีมาก
? round(.2405,3)
.241
แต่ทำไม่โปรแกรมแต่ละตัวของ Microsoft เหมือนกัน แต่ใช้ฟังก์ชัน Round ที่ต่างกันไม่ทราบ และที่น่าสนใจคือ Round() ใน Worksheet ของ Excel จะไม่มีปัญหาเหมือน Round ใน VBA ของ Excel ทั้งๆ ที่เป็นโปรแกรมเดียวกัน
9 @R00377
อ.สุภาพ ครับ แล้วเรามีวิธีดึงเอา Funtion Round
จาก Excel หรือ Visual FoxPro 6.0 มาใช้ใน Excel
ได้หรือไม่ครับ รบกวนอีกครั้งครับ
Suchat
ชลบุรี
10 @R00378
การดึง Round ของ Excel ที่อยู่ใน Worksheet มาใช้ใน Access ทำได้ดังนี้ครับ
1. เปิด Module แล้วไปที่เมนู Tools>References> ให้คลิกเลือก Microsoft Excel X.0 Object Library เข้ามาอยู่ใน References ด้วย
2. จากนั้นก็เรียกใช้ฟังก์ชันข้างล่างนี้ได้ทันทีครับ
Function XcelRound(dbl As Double, exp As Integer) As Double
XcelRound = Excel.WorksheetFunction.Round(dbl, exp)
End Function
11 @R00379
ขอบพระคุณ อ.สุภาพ มากๆ อีกครั้งครับ
ขอบพระคุณครับ
Suchat
ชลบุรี
12 @R00380
เรียน อ.สุภาพ ครับ
ที่บริษัทฯ ที่ผมทำงาน ใช้ Windows ME + Access97 และ Office 2000 Pro (Thai)
ผมทำตามที่ vอ.สุภาพ แนะนำในข้อ 1 คือ
เปิด Module แล้วไปที่เมนู Tools>References> ให้คลิกเลือก Microsoft Excel X.0 Object Library เข้ามาอยู่ใน References ด้วย
ในนั้นจะมีอยู่ 2 ตัวคือ
1. Microsoft Excel 5.0 Object Library
2. Microsoft Excel 9.0 Object Library
ผมเลือกไม่ว่าจะเป็นรายการที่ 1 หรือ 2 ก็จะขึ้น Dialog Microsoft Visual Basic
และขึ้นข้อความว่า Name conflicts with existing module , project or library
เมื่อผมปิด Program ทั้งหมด และเปิดใหม่ ก็พบว่า library ที่ผมเลือกไว้ไม่ได้ถูก mark เลือกไว้
ก็จะมาพบ Error อีก
แต่ขณะเดียวกัน ที่บ้านของผมใช้ WindowsXP Pro + Access 97 และ Office XP Pro
กลับไม่พบปัญหานี้ รบกวน อ.สุภาพแนะนำด้วยครับ
ขอบพระคุณครับ
Suchat
ชลบุรี
13 @R00381
อ.สุภาพ ครับ
ผมได้ลองสร้าง Access 2000 ใหม่
แล้วทำตามขั้นตอนใหม่ ตามที่ อ.แนะนำ
การดึง Round ของ Excel ที่อยู่ใน Worksheet มาใช้ใน Access ทำได้ดังนี้ครับ
1. เปิด Module แล้วไปที่เมนู Tools>References> ให้คลิกเลือก Microsoft Excel X.0 Object Library เข้ามาอยู่ใน References ด้วย
2. จากนั้นก็เรียกใช้ฟังก์ชันข้างล่างนี้ได้ทันทีครับ
Function XcelRound(dbl As Double, exp As Integer) As Double
XcelRound = Excel.WorksheetFunction.Round(dbl, exp)
End Function
ผลปรากฏว่า เมื่อผม Add Library เข้ามาใหม่ ไม่พบข้อความ
Name conflicts with existing module , project or library ครับ
แต่เมื่อใช้ Funtion ปรากฏว่าไม่สามารถใช้งานได้ Debug ที่ Module
และเมื่อผม ไปที่เมนู Tools>References ปรากฏว่า Library ทั้ง 2 ตัว คือ
1. Microsoft Excel 5.0 Object Library
2. Microsoft Excel 9.0 Object Library
หายไปหมดเลยครับ
รบกวน อ.สุภาพ แนะนำวิธีการนำกลับมาด้วยครับ หรือต้องไป D/L ที่ไหนครับ
ขอบพระคุณมากๆ ครับ
Suchat
ชลบุรี
14 @R00382
ทั้ง 2 ตัว มีฟังก์ชัน Round() เหมือนกัน
Microsoft Excel 5.0 Object Library
Microsoft Excel 9.0 Object Library
แต่ตัวเวอร์ชัน 5.0 จะมีวิธีการเรียกใช้ที่ต่างไปหน่อยหนึ่ง ผมเคยเขียนบทความเกี่ยวกับเรื่องนี้ไว้อยู่ เดี๋ยวผมจะค้นแล้วนำมาโพสต์ไว้ที่นี่ให้ก็แล้วกันครับ
แนะนำให้ใช้เวอร์ชัน 9.0 ดีกว่า
ที่เกิดปัญหา Error เพราะทั้ง 2 ตัวมีชื่อเหมือนกัน ให้เลือกเอาตัวหลังก็แล้วกันครับ
หรือตัวอย่างที่ผมเคยทำไว้อยู่ที่ http://agserver.kku.ac.th/basiceng/Computer/download/BahtText.zip ลองเอาไปลองศึกษาดูครับ
15 @R00383
ขอบพระคุณ อ.สุภาพ มากๆ ครับ
ผมแก้ได้แล้วครับ เป็นอย่างที่ อ.สุภาพ บอกครับ ต้องใช้
Microsoft Excel 9.0 Object Library ถึงใช้ได้ครับ
ผมไป Copy File XL5EN32.OLB จากเครื่องอื่นๆ ที่ลง OfficeXP
มาลงทับที่ C:\Program Files\Microsoft Office\Office หรือ Office10\
แล้ว Add Library Microsoft Excel 9.0 Object Library ก็ใช้ได้ครับ
จากตัวอย่างที่ อ.สุภาพให้ไว้ ผม D/L มาแล้วครับ กำลังศึกษาอยู่
ผมขอบพระคุณ อ.สุภาพ มากๆ ครับ
ขอบพระคุณครับ
Time: 0.1091s