connhangheo
Thành viên thường trực




- Tham gia
- 18/5/07
- Bài viết
- 214
- Được thích
- 225
- Nghề nghiệp
- Sinh Viên
Function noisuy1(vungtra As Range, X As Double, cot As Integer) As Double
'ham noi suy 1 chieu
Dim ktra As Boolean
Dim i As Integer
Dim x1 As Double, x2 As Double, y1 As Double, y2 As Double
For i = 1 To vungtra.Cells.Count
kiemtra = False
If vungtra.Cells(i, 1) <= X And vungtra.Cells(i + 1, 1) >= X Then
x1 = vungtra.Cells(i, 1): x2 = vungtra.Cells(i + 1, 1)
y1 = vungtra.Cells(i, cot): y2 = vungtra.Cells(i + 1, cot)
noisuy1 = (y2 - y1) * (X - x1) / (x2 - x1) + y1
ktra = True
End If
Next i
If ktra = False Then
MsgBox "gia tri can tim ko nam trong bang tra", vbInformation
Exit Function
End If
End Function
Option Explicit
Function NoiSuyGPE(VungTra As Range, xX As Double, yY As Double) As Double
'Ham Noi Suy 2 Chieu Tai GPE.COM (Sa_DQ)'
Dim iW As Integer, jI As Integer
Dim x1 As Double, x2 As Double, y1 As Double, y2 As Double
Dim a11 As Double, a12 As Double, a21 As Double, a22 As Double
Dim t1 As Double, t2 As Double
Dim RgNg As Range, RgDoc As Range
Dim Rng As Range, Clls As Range
Set RgNg = VungTra.Cells(1, 1).Resize(1, VungTra.Columns.Count - 1)
Set RgDoc = VungTra.Cells(1, 1).Resize(VungTra.Rows.Count, 1)
1 For Each Rng In RgNg
2 If Rng <= yY And Rng.Offset(, 1) >= yY Then
3 y1 = Rng: y2 = Rng.Offset(, 1)
For Each Clls In RgDoc
5 If Clls <= xX And Clls.Offset(1) >= xX Then
x1 = Clls: x2 = Clls.Offset(1)
'3*'
7 a11 = Cells(Clls.Row, Rng.Column): a12 = Cells(Clls.Row, Rng.Column + 1)
a21 = Cells(Clls.Row + 1, Rng.Column): a22 = Cells(Clls.Row + 1, Rng.Column + 1)
9 t1 = (a12 - a11) * (yY - y1) / (y2 - y1) + a11
t2 = (a22 - a21) * (yY - y1) / (y2 - y1) + a21
11 NoiSuyGPE = (t2 - t1) * (xX - x1) / (x2 - x1) + t1
Exit For
13 End If
Next Clls
15 End If
Next Rng
17 If NoiSuyGPE = 0 Then '!'
msgbox "gia tri can tim ko nam trong bang tra", vbInformation
19 End If
End Function
Mình đã thử hàm của bạn rồiconnhangheo đã viết:hàm của mình nó chưa hoàn chỉnh, trong thời gian này mình đang phải làm nhiều bài tập TKMH và chuẩn bị ôn thi nên khá bận, khi nào có thời gian nhiều hơn mình sẽ học hỏi để hoàn thiện nó tốt hơn. Ví dụ như phần bắt lỗi mình cũng chưa làm,và còn 1 số cái khác nữa. Nhưng nếu dùng tạm thì cũng vẫn ổn. Mong mọi người góp ý và cũng hoàn thiện hàm này cho anh em trong forum học hỏi. Thanks
Hàm noisuy2 bạn mắc lỗi giống hàm nội suy 1 chỗ chọn giá trị vòng lặpconnhangheo đã viết:em xin giải thích hàm của em như sau, mọi người cho ý kiến về code giúp em
t1 = (a12 ) * (yY - y1) / (y2 ) + a11
t2 = (a22 ) * (yY - y1) / (y2 ) + a21
Option Explicit
[B]Function NoiSuyGPE(VungTra As Range, xX As Double, yY As Double) As Double[/B]
[COLOR="Blue"] 'Ham Noi Suy 2 Chieu Tai GPE.COM (Sa_DQ)'[/COLOR]
[COLOR="Silver"]Dim iW As Integer, jI As Integer[/COLOR]
Dim x1 As Double, x2 As Double, y1 As Double, y2 As Double
Dim a11 As Double, a12 As Double, a21 As Double, a22 As Double
Dim t1 As Double, t2 As Double
Dim RgNg As Range, RgDoc As Range
Dim Rng As Range, Clls As Range
Set RgNg = VungTra.Cells(1, 1).Resize(1, VungTra.Columns.Count - 1)
Set RgDoc = VungTra.Cells(1, 1).Resize(VungTra.Rows.Count, 1)
1 For Each Rng In RgNg
2 If Rng <= yY And Rng.Offset(, 1) >= yY Then
3 y1 = Rng: [COLOR="Silver"] y2 = Rng.Offset(, 1)[/COLOR]
For Each Clls In RgDoc
5 If Clls <= xX And Clls.Offset(1) >= xX Then
x1 = Clls: x2 = Clls.Offset(1)
'3*'
7 a11 = Cells(Clls.Row, Rng.Column): [COLOR="silver"]a12 = Cells(Clls.Row, Rng.Column + 1)[/COLOR]
a21 = Cells(Clls.Row + 1, Rng.Column): [COLOR="silver"]a22 = Cells(Clls.Row + 1, Rng.Column + 1)[/COLOR]
9 [COLOR="silver"] t1 = (a12 - a11) * (yY - y1) / (y2 - y1) + a11
t2 = (a22 - a21) * (yY - y1) / (y2 - y1) + a21[/COLOR]
11 NoiSuyGPE = (t2 - t1) * (xX - x1) / (x2 - x1) + t1
Exit For
13 End If
Next Clls
15 End If
Next Rng
17 If NoiSuyGPE = 0 Then '!'
msgbox "gia tri can tim ko nam trong bang tra", vbInformation
19 End If
End Function
mình đã down file của ban về nhưng không dùng được, no bị lỗi #Name, chac do minh thieu cài chi đó đúng không?bạn nào help mình với, thanks alot
Mình là dân kỹ thật nên sử dụng nội suy từ rất lâu (từ năm 1998) nên cũng đã viết ra hàm nội suy để dùng riêng. Cũng phải qua thực tế sử dụng rất nhiều lần mới viết được một hàm ưng ý (vì trong lĩnh vực kỹ thuật rất cần sự chính xác và tin cậy), tiện đây xin giới thiệu để các bạn tham khảo:
' One Directions Interpolate Function
' Author : Dang Vu Tuan
'
Function NS(table_array, Lookup_value)
Dim NumRows As Integer, i As Integer
Dim Max, Min
Dim Range1 As Range, Range2 As Range
NumRows = table_array.Rows.Count
Set Range1 = table_array.Columns(1)
Set Range2 = table_array.Columns(2)
' check for case if val = last value in range1
If Lookup_value = Range1.Cells(NumRows) Then
NS = Range2.Cells(NumRows)
Exit Function
End If
' Get Max and Min
Max = Range1.Cells(1)
Min = Range1.Cells(1)
For i = 1 To NumRows
If Max <= Range1.Cells(i) Then Max = Range1.Cells(i)
If Min >= Range1.Cells(i) Then Min = Range1.Cells(i)
Next i
' Return an error if lookup_value is not within range1
If Lookup_value > Max Or Lookup_value < Min Then
NS = "Out of range" 'Evaluate("NA()")
Exit Function
End If
' Do linear interpolation
For i = 1 To NumRows - 1
If (Lookup_value >= Range1.Cells(i) And Lookup_value <= Range1.Cells(i + 1)) Or (Lookup_value <= Range1.Cells(i) And Lookup_value >= Range1.Cells(i + 1)) Then
If (Range1.Cells(i) - Range1.Cells(i + 1)) <> 0 Then
NS = (Range2.Cells(i + 1) + (Range2.Cells(i) - Range2.Cells(i + 1)) * (Lookup_value - Range1.Cells(i + 1)) / (Range1.Cells(i) - Range1.Cells(i + 1)))
Else
NS = Range2.Cells(i)
End If
Exit Function
End If
Next i
End Function
Và đây là hàm nội suy hai chiều:
' Two Directions Interpolate Function
' Author : Dang Vu Tuan
'
Function NS2(Data_Range As Range, x, y)
Dim A(), xMax, yMax, xMin, yMin
Dim Nx, Ny, i, J, k1, k2, k3, k4, k12, k34
'Get the data
Nx = Data_Range.Columns.Count
Ny = Data_Range.Rows.Count
ReDim A(Nx, Ny)
For i = 1 To Nx
For J = 1 To Ny
A(i, J) = Data_Range(J, i)
Next J
Next i
'Check data
xMax = A(2, 1)
xMin = A(2, 1)
For i = 2 To Nx
If xMax < A(i, 1) Then xMax = A(i, 1)
If xMin > A(i, 1) Then xMin = A(i, 1)
Next i
yMax = A(1, 2)
yMin = A(1, 2)
For J = 2 To Ny
If yMax < A(1, J) Then yMax = A(1, J)
If yMin > A(1, J) Then yMin = A(1, J)
Next J
If x < xMin Or x > xMax Or y < yMin Or y > yMax Then
NS2 = "Out of range"
Exit Function
End If
'Do linear interpolation
For i = 2 To Nx - 1
If (A(i, 1) <= x And x <= A(i + 1, 1)) Or (A(i, 1) >= x And x >= A(i + 1, 1)) Then
For J = 2 To Ny - 1
If (A(1, J) <= y And y <= A(1, J + 1)) Or (A(1, J) >= y And y >= A(1, J + 1)) Then
k1 = A(i, J)
k2 = A(i + 1, J)
k3 = A(i, J + 1)
k4 = A(i + 1, J + 1)
If (A(i + 1, 1) - A(i, 1)) = 0 Then
k12 = k1
k34 = k3
Else
k12 = k1 + (k2 - k1) * (x - A(i, 1)) / (A(i + 1, 1) - A(i, 1))
k34 = k3 + (k4 - k3) * (x - A(i, 1)) / (A(i + 1, 1) - A(i, 1))
End If
If (A(1, J + 1) - A(1, J)) = 0 Then
NS2 = k12
Else
NS2 = k12 + (k34 - k12) * (y - A(1, J)) / (A(1, J + 1) - A(1, J))
End If
Exit Function
End If
Next J
End If
Next i
End Function
Hai hàm trên mình viết để dễ theo dõi nên thực sự còn có thể compact được hơn nữa.
E chỉ biết đọc thôi, hông bít viết, e thấy dễ hiểu với ai cần bắt chước làm, but hơi bị dài, đặc biệt là ở ns1c
E thấy có ng viết cái code này nè, ngắn gọn đơn giản lắm
Function NSTT(xnew, xx, yy)
For i = 1 To xx.Count
If xx(i) > xnew Then
Exit For
End If
Next i
NSTT = (xnew - xx(i - 1)) / (xx(i) - xx(i - 1)) * (yy(i) - yy(i - 1)) + yy(i - 1)
End Function
Vì ns1c chỉ cần cho i chạy tới khi giá trị x(i)>xnew (là giá trị tra), là ta đã có thể nội suy đc rồi
Đấy là ý kiến của e, có gì sai sót pác thông cảm
đồng chí ơi sao ko gọp hai cái vào một đi cho rồi sao phải chia ra hai cái làm gìem mới học VBA, mọi người xem file em viết 2 hàm này rồi cho em ý kiến để em hoàn thiện hơn, Thanks
Hàm noisuyc trong công thức của bạn là hàm tự tạo. Bạn gửi file lên thử xem. Có thể dịch ngược từ hàm ra cách tính.''=noisuyc(IF(C18<3;3;IF(C18>400;400;C18));'1-P. Luc'!$A$160:$D$178;IF($D$9="A";2; IF($D$9="B";3;4)))'' ai biết hàm này là như thế nào ko. mình có file tính có hàm này mà ko biết ý nghĩa sao cả. ai biết có thể trả lời cho mình qua địa chỉ mail quythienx1.bkdn@gmail.com . Mình cảm ơn rất nhiều!!!!
Function TraBang2Chieu(ByVal Hang, ByVal Cot, VungChon As Range)
'PMXD'
Dim i As Long, j As Long
Dim TangAnPha
Dim NoiSuy1 As Double, NoiSuy2 As Double
For i = 1 To UBound(VungChon.Value, 2) ' Theo phuong ngang
If Hang = VungChon(1, i) Then
For j = 1 To UBound(VungChon.Value, 1) - 1
If (Cot - VungChon(j, 1)) * (Cot - VungChon(j + 1, 1)) <= 0 Then
TangAnPha = (VungChon(j + 1, i) - VungChon(j, i)) / (VungChon(j + 1, 1) - VungChon(j, 1))
TraBang2Chieu = VungChon(j, i) + (Cot - VungChon(j, 1)) * TangAnPha
GoTo Thoat:
End If
Next j
ElseIf (Hang - VungChon(1, i)) * (Hang - VungChon(1, i + 1)) < 0 Then
For j = 1 To UBound(VungChon.Value, 1) - 1
If (Cot - VungChon(j, 1)) * (Cot - VungChon(j + 1, 1)) < 0 Then
TangAnPha = (VungChon(j, i + 1) - VungChon(j, i)) / (VungChon(1, i + 1) - VungChon(1, i))
NoiSuy1 = VungChon(j, i) + (Hang - VungChon(1, i)) * TangAnPha
TangAnPha = (VungChon(j + 1, i + 1) - VungChon(j + 1, i)) / (VungChon(1, i + 1) - VungChon(1, i))
NoiSuy2 = VungChon(j + 1, i) + (Hang - VungChon(1, i)) * TangAnPha
TangAnPha = (NoiSuy2 - NoiSuy1) / (VungChon(j + 1, 1) - VungChon(j, 1))
TraBang2Chieu = NoiSuy1 + (Cot - VungChon(j, 1)) * TangAnPha
GoTo Thoat:
End If
Next j
End If
Next i
Thoat:
'TraBang = UBound(VungChon.Value, 2)
End Function
Function Noisuy(Hang, Cot As Double, ByVal bangns As Range) As Double
' Ham sau cho phep noi suy ca bang mot chieu va hai chieu CNPM
Dim Tg1, Tg2, Delta As Double
Dim m As Long ' so hang
Dim n As Long ' so cot
Dim i, j As Long
Dim Found As Boolean
n = bangns.Columns.Count
m = bangns.Rows.Count
Found = False
For j = 1 To n
Bangns(m + 1, j) = Bangns(m, j)
Next j
For i = 1 To m
Bangns(i, n + 1) = Bangns(i, n)
Next i
' bay gio chung ta co mot mang hai chieu kich thuoc m x n
For j = 2 To n - 1
If (bangns(1, j) <= Cot) And (bangns(1, j + 1) >= Cot) Then
Delta = (Cot - bangns(1, j)) / (bangns(1, j + 1) - bangns(1, j))
Found = True
Exit For
End If
Next j
If Not Found Then
MsgBox ("So noi suy nam ngoai Hang cua BangNS")
End
End If
For i = 2 To m - 1
If (bangns(i, 1) <= Hang) And (bangns(i + 1, 1) >= Hang) Then
Tg1 = bangns(i, j) + (bangns(i, j + 1) - bangns(i, j)) * Delta
Tg2 = bangns(i + 1, j) + (bangns(i + 1, j + 1) - bangns(i + 1, j)) * Delta
Delta = (Hang - bangns(i, 1)) / (bangns(i + 1, 1) - bangns(i, 1))
Noisuy = Tg1 + (Tg2 - Tg1) * Delta
Found = True
Exit For
End If
Next i
If Not Found Then
MsgBox ("So noi suy nam ngoai cot cua BangNS")
End
End If
End Function
Function noisuy(ByVal r As Range, ByVal hang As Double, ByVal cot As Double) As Variant
Dim i, j, h1, h2, co1, co2 As Integer
Dim ns1, ns2 As Double
If hang = r(r.Rows.Count, 1) And cot = r(1, r.Columns.Count) Then
noisuy = r(r.Rows.Count, r.Columns.Count)
Exit Function
ElseIf hang = r(r.Rows.Count, 1) Then
For j = 2 To r.Columns.Count - 1
If cot >= r(1, j) And cot < r(1, j + 1) Then
co1 = j
co2 = j + 1
Exit For
End If
Next
noisuy = ns(r(1, co1), r(1, co2), cot, r(r.Rows.Count, co1), r(r.Rows.Count, co2))
ElseIf cot = r(1, r.Columns.Count) Then
For i = 2 To r.Rows.Count - 1
If hang >= r(i, 1) And hang < r(i + 1, 1) Then
h1 = i
h2 = i + 1
Exit For
End If
Next
noisuy = ns(r(h1, 1), r(h2, 1), hang, r(h1, r.Columns.Count), r(h2, r.Columns.Count))
Else
For i = 2 To r.Rows.Count - 1
If hang >= r(i, 1) And hang < r(i + 1, 1) Then
h1 = i
h2 = i + 1
Exit For
End If
Next
For j = 2 To r.Columns.Count - 1
If cot >= r(1, j) And cot < r(1, j + 1) Then
co1 = j
co2 = j + 1
Exit For
End If
Next
ns1 = ns(r(h1, 1), r(h2, 1), hang, r(h1, co1), r(h2, co1))
ns2 = ns(r(h1, 1), r(h2, 1), hang, r(h1, co2), r(h2, co2))
noisuy = ns(r(1, co1), r(1, co2), cot, ns1, ns2)
End If
End Function
Function ns(ByVal a As Double, ByVal b As Double, ByVal c As Double, ByVal x As Double, ByVal y As Double)
''Laulemroi va toi
As Double
ns = x + (y - x) * (c - a) / (b - a)
End Function
Function finds(ByVal r As Range, ByVal hang As Double, ByVal cot As Double) As Variant
Dim h1, h2, co1, co2 As Integer
Dim ns1, ns2 As Double
Dim r1, r2 As Range
Set r1 = r.Rows(1): Set r2 = r.Columns(1)
Dim Fn As WorksheetFunction
Set Fn = Application.WorksheetFunction
On Error Resume Next
If hang < r(2, 1) Or hang > r(r.Rows.Count, 1) Or cot < r(1, 2) Or cot > r(1, r.Columns.Count) Then
finds = "Out Range": Exit Function
Else
h1 = Fn.Match(hang, r2): h2 = h1 + 1
co1 = Fn.Match(cot, r1): co2 = co1 + 1
ns1 = ns(r(h1, 1), r(h2, 1), hang, r(h1, co1), r(h2, co1))
ns2 = ns(r(h1, 1), r(h2, 1), hang, r(h1, co2), r(h2, co2))
finds = ns(r(1, co1), r(1, co2), cot, ns1, ns2)
End If
End Function
Có khi nào chương trình diệt VIRUS trong máy bạn nó xơi tái cái hạm tự tạo í rồi cũng nên! Đang đói mà!hic, sao minh down về nhưng ko thể dùng đc hàm của bạn, nó cứ báo lỗi NAME. bạn nào có thể giúp mình đc ko? Cảm ơn nhiều![]()
cảm ơn bác rất nhiều ....... em tin tưởng hoàn toàn vào bácQuan sát dòng lệnh 9 & 10 mình thấy còn có thể rút gọn thêm (về cách viết) để đỡ rườm rà. Đó là tính trước 2 biểu thức, như sau
Tính trước cho y2: tại phần sau của dòng lệnh 3 sẽ là
y2 = Rng.Offset(, 1) - y1
Tương tự như vậy, tại phần sau của dòng lệnh 7 sẽ là:
a12 = Cells(Clls.Row, Rng.Column + 1) - a11
& tại phần sau của dòng lệnh 8 là:
a22 = Cells(Clls.Row + 1, Rng.Column + 1) - a12
Bác cho hỏi nếu bảng tra mình muốn để ở Sheet khác thì phải làm như thế nào? Thanksem xin giải thích hàm của em như sau, mọi người cho ý kiến về code giúp em
bạn ơi cho mình hỏi dùng hàm này có thể ngoại suy các giá trị bên ngoài không? hay là mình phải dùng hàm khác. mình mới tìm hiểu VBA thôi, xin chỉ giáoem mới học VBA, mọi người xem file em viết 2 hàm này rồi cho em ý kiến để em hoàn thiện hơn, Thanks
bác ơi sao em copy về dùng mà giá trị trả lại hết =0 vậy bácMình là dân kỹ thật nên sử dụng nội suy từ rất lâu (từ năm 1998) nên cũng đã viết ra hàm nội suy để dùng riêng. Cũng phải qua thực tế sử dụng rất nhiều lần mới viết được một hàm ưng ý (vì trong lĩnh vực kỹ thuật rất cần sự chính xác và tin cậy), tiện đây xin giới thiệu để các bạn tham khảo:
' One Directions Interpolate Function
' Author : Dang Vu Tuan
'
Function NS(table_array, Lookup_value)
Dim NumRows As Integer, i As Integer
Dim Max, Min
Dim Range1 As Range, Range2 As Range
NumRows = table_array.Rows.Count
Set Range1 = table_array.Columns(1)
Set Range2 = table_array.Columns(2)
' check for case if val = last value in range1
If Lookup_value = Range1.Cells(NumRows) Then
NS = Range2.Cells(NumRows)
Exit Function
End If
' Get Max and Min
Max = Range1.Cells(1)
Min = Range1.Cells(1)
For i = 1 To NumRows
If Max <= Range1.Cells(i) Then Max = Range1.Cells(i)
If Min >= Range1.Cells(i) Then Min = Range1.Cells(i)
Next i
' Return an error if lookup_value is not within range1
If Lookup_value > Max Or Lookup_value < Min Then
NS = "Out of range" 'Evaluate("NA()")
Exit Function
End If
' Do linear interpolation
For i = 1 To NumRows - 1
If (Lookup_value >= Range1.Cells(i) And Lookup_value <= Range1.Cells(i + 1)) Or (Lookup_value <= Range1.Cells(i) And Lookup_value >= Range1.Cells(i + 1)) Then
If (Range1.Cells(i) - Range1.Cells(i + 1)) <> 0 Then
NS = (Range2.Cells(i + 1) + (Range2.Cells(i) - Range2.Cells(i + 1)) * (Lookup_value - Range1.Cells(i + 1)) / (Range1.Cells(i) - Range1.Cells(i + 1)))
Else
NS = Range2.Cells(i)
End If
Exit Function
End If
Next i
End Function
Và đây là hàm nội suy hai chiều:
' Two Directions Interpolate Function
' Author : Dang Vu Tuan
'
Function NS2(Data_Range As Range, x, y)
Dim A(), xMax, yMax, xMin, yMin
Dim Nx, Ny, i, J, k1, k2, k3, k4, k12, k34
'Get the data
Nx = Data_Range.Columns.Count
Ny = Data_Range.Rows.Count
ReDim A(Nx, Ny)
For i = 1 To Nx
For J = 1 To Ny
A(i, J) = Data_Range(J, i)
Next J
Next i
'Check data
xMax = A(2, 1)
xMin = A(2, 1)
For i = 2 To Nx
If xMax < A(i, 1) Then xMax = A(i, 1)
If xMin > A(i, 1) Then xMin = A(i, 1)
Next i
yMax = A(1, 2)
yMin = A(1, 2)
For J = 2 To Ny
If yMax < A(1, J) Then yMax = A(1, J)
If yMin > A(1, J) Then yMin = A(1, J)
Next J
If x < xMin Or x > xMax Or y < yMin Or y > yMax Then
NS2 = "Out of range"
Exit Function
End If
'Do linear interpolation
For i = 2 To Nx - 1
If (A(i, 1) <= x And x <= A(i + 1, 1)) Or (A(i, 1) >= x And x >= A(i + 1, 1)) Then
For J = 2 To Ny - 1
If (A(1, J) <= y And y <= A(1, J + 1)) Or (A(1, J) >= y And y >= A(1, J + 1)) Then
k1 = A(i, J)
k2 = A(i + 1, J)
k3 = A(i, J + 1)
k4 = A(i + 1, J + 1)
If (A(i + 1, 1) - A(i, 1)) = 0 Then
k12 = k1
k34 = k3
Else
k12 = k1 + (k2 - k1) * (x - A(i, 1)) / (A(i + 1, 1) - A(i, 1))
k34 = k3 + (k4 - k3) * (x - A(i, 1)) / (A(i + 1, 1) - A(i, 1))
End If
If (A(1, J + 1) - A(1, J)) = 0 Then
NS2 = k12
Else
NS2 = k12 + (k34 - k12) * (y - A(1, J)) / (A(1, J + 1) - A(1, J))
End If
Exit Function
End If
Next J
End If
Next i
End Function
Hai hàm trên mình viết để dễ theo dõi nên thực sự còn có thể compact được hơn nữa.