Приветствую!
Моя первая запись.
Написал перечень функций и процедур для работы с градусами, минутами и секундами. Данная работа является подготовкой к созданию модуля для операций с датой-временем (там похожий принцип).
Этот код подойдёт для практикующих разработчиков на VBA, как готовое решение, заточенное на высокую скорость работы.
Постарался оттестировать, но мог что-то пропустить.
Код может:
• быстро разбирать строки вида 1°1'1'', -10°11'12'', -10°1', 1°111'', 12'1'', 12°, -15', 10'' в одномерный массив (от 0 до 3): ЗначениеВСекундах, Градусы, Минуты, Секунды.
• не разбирать строку, а просто проверить её на соответствие.
• перевести в одномерный массив, как выше, значение в секундах
• создать из массива, как выше, строку
• преобразовать градусы больше 360 и меньше 0
Скрин работы UDF на листе
Код
"Модуль «UDF»"
| Visual Basic | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
| Option Explicit
'==================================================================================================
Function UDF_Degree_StringToSec(iString$) As Long
Dim aL3(0 To 3) As Long
Degrees_Str_ToArrL3 iString, aL3
UDF_Degree_StringToSec = aL3(0)
End Function
'==================================================================================================
Function UDF_Degree_SecToString(iSec&, Optional SkipZeros As Boolean) As String
Dim aL3(0 To 3) As Long
Degrees_Sec_ToArrL3 iSec, aL3
UDF_Degree_SecToString = Degrees_ArrL3_ToStr(aL3, SkipZeros)
End Function
'================================================================================================== |
|
Модуль «Тест»
| Visual Basic | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
| Option Base 1
Option Explicit
'==================================================================================================
Sub FullTest()
Dim aStr(), aArrsL3(), aStrNew() As String, aSec() As Long, aL3(0 To 3) As Long
Dim L_1(0 To 3) As Long, L_2(0 To 3) As Long, L_3(0 To 3) As Long, L_4(0 To 3) As Long, L_5(0 To 3) As Long, L_6(0 To 3) As Long, L_7(0 To 3) As Long, L_8(0 To 3) As Long
Dim tx$, t!, n&, c&
Dim sec&, a_D&, a_M&, a_S&
Const cyc& = 1000000
tx = "Get Arrays(Timer)": Debug.Print tx & String$(100 - Len(tx), "="),
t = Timer
aStr = Array("1°1'1''", "-10°11'12''", "-10°1'", "1°111''", "12'1''", "12°", "-15'", "10''") ' * cyc = 8 mln Operations
ReDim aArrsL3(UBound(aStr))
ReDim aStrNew(UBound(aStr))
ReDim aSec(UBound(aStr))
For n = 1 To UBound(aStr)
Degrees_Str_ToArrL3 aStr(n), aL3
aArrsL3(n) = aL3
aSec(n) = aL3(0)
For c = 0 To 3
Select Case n
Case 1: L_1(0) = aL3(0): L_1(1) = aL3(1): L_1(2) = aL3(2): L_1(3) = aL3(3)
Case 2: L_2(0) = aL3(0): L_2(1) = aL3(1): L_2(2) = aL3(2): L_2(3) = aL3(3)
Case 3: L_3(0) = aL3(0): L_3(1) = aL3(1): L_3(2) = aL3(2): L_3(3) = aL3(3)
Case 4: L_4(0) = aL3(0): L_4(1) = aL3(1): L_4(2) = aL3(2): L_4(3) = aL3(3)
Case 5: L_5(0) = aL3(0): L_5(1) = aL3(1): L_5(2) = aL3(2): L_5(3) = aL3(3)
Case 6: L_6(0) = aL3(0): L_6(1) = aL3(1): L_6(2) = aL3(2): L_6(3) = aL3(3)
Case 7: L_7(0) = aL3(0): L_7(1) = aL3(1): L_7(2) = aL3(2): L_7(3) = aL3(3)
Case 8: L_8(0) = aL3(0): L_8(1) = aL3(1): L_8(2) = aL3(2): L_8(3) = aL3(3)
End Select
Next c
Next n
Debug.Print Round(Timer - t, 2) ' 0.0
'================================================
tx = "String Check(Timer)": Debug.Print tx & String$(100 - Len(tx), "="),
t = Timer
For c = 1 To cyc
For n = 1 To UBound(aStr)
If Not Degrees_Str_IsCorrect(aStr(n), , True) Then Exit Sub
Next n
Next c
Debug.Print Round(Timer - t, 2) ' 4.5
'================================================
tx = "String To ArrArrL3(Timer)": Debug.Print tx & String$(100 - Len(tx), "="),
t = Timer
For c = 1 To cyc
For n = 1 To UBound(aStr)
If Not Degrees_Str_ToArrL3(aStr(n), aL3, , True) Then Exit Sub
Next n
Next c
Debug.Print Round(Timer - t, 2) ' 5.3
'------------------------------------------------
tx = "String To ArrArrL3(Check)": Debug.Print tx & String$(100 - Len(tx), "-")
For n = 1 To UBound(aStr)
Degrees_Str_ToArrL3 aStr(n), aL3
For c = 0 To UBound(aL3)
If aL3(c) <> aArrsL3(n)(c) Then Debug.Print n, c, aL3(c) & "<>" & aArrsL3(n)(c)
Next c
Next n
'================================================
tx = "Second To ArrL3(Timer)": Debug.Print tx & String$(100 - Len(tx), "="),
t = Timer
For c = 1 To cyc
For n = 1 To UBound(aSec)
Degrees_Sec_ToArrL3 aSec(n), aL3
Next n
Next c
Debug.Print Round(Timer - t, 2) ' 1.0
'------------------------------------------------
tx = "Second To ArrL3(Check)": Debug.Print tx & String$(100 - Len(tx), "-")
For n = 1 To UBound(aSec)
Degrees_Sec_ToArrL3 aSec(n), aL3
For c = 0 To UBound(aL3)
If aL3(c) <> aArrsL3(n)(c) Then Debug.Print n, c, aL3(c) & "<>" & aArrsL3(n)(c) ' 1<>0 And 51<>111 because "1°111''" = "1°0'111''" transformed to "1°1'51''"
Next c
Next n
'================================================
tx = "ArrL3 To String(Timer)": Debug.Print tx & String$(100 - Len(tx), "="),
t = Timer
For c = 1 To cyc
aStrNew(1) = Degrees_ArrL3_ToStr(L_1, True)
aStrNew(2) = Degrees_ArrL3_ToStr(L_2, True)
aStrNew(3) = Degrees_ArrL3_ToStr(L_3, True)
aStrNew(4) = Degrees_ArrL3_ToStr(L_4, True)
aStrNew(5) = Degrees_ArrL3_ToStr(L_5, True)
aStrNew(6) = Degrees_ArrL3_ToStr(L_6, True)
aStrNew(7) = Degrees_ArrL3_ToStr(L_7, True)
aStrNew(8) = Degrees_ArrL3_ToStr(L_8, True)
Next c
Debug.Print Round(Timer - t, 2) ' 4.2
'------------------------------------------------
tx = "ArrL3 To String(Check)": Debug.Print tx & String$(100 - Len(tx), "-")
For n = 1 To UBound(aStrNew)
Debug.Print n, aStr(n) & "<>" & aStrNew(n)
If aStr(n) <> aStrNew(n) Then Debug.Print n, aStr(n) & "<>" & aStrNew(n) ' 1<>0 And 51<>111 because "1°111''" = "1°0'111''" transformed to "1°1'51''"
Next n
End Sub
'================================================================================================== |
|
Модуль «Work»
| Visual Basic | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
| Option Base 1
Option Explicit
'==================================================================================================
Function Degrees_Deg_FixNeg(d&) As Long
Degrees_Deg_FixNeg = 360 + d
End Function
'==================================================================================================
Function Degrees_Deg_FixBig(d&) As Long
Degrees_Deg_FixBig = d Mod 360
End Function
'==================================================================================================
'==================================================================================================
Function Degrees_Str_IsCorrect(v, Optional fMsgTrue As Boolean, Optional fMsgFalse As Boolean) As Boolean
Dim tx$
Static st&, RE As RegExp
If st = 0 Then st = 1: Set RE = New RegExp: RE.Pattern = "^\d+°\d+'\d+''$|^\d+°\d+'$|^\d+°\d+''$|^\d+'\d+''$|^\d+°$|^\d+'$|^\d+''$"
If AscW(v) = 45 Then tx = Right$(v, Len(v) - 1) Else tx = v
Degrees_Str_IsCorrect = RE.Test(tx)
If Not Degrees_Str_IsCorrect Then GoTo no
If fMsgTrue Then MsgBox "String «" & v & "» is a Degree!", vbInformation, "Degrees_Str_IsCorrect": Exit Function Else Exit Function
no: If fMsgFalse Then MsgBox "String «" & v & "» is NOT a Degree!", vbCritical, "Degrees_Str_IsCorrect"
End Function
'==================================================================================================
' Transform String like 3°4'3'' to Array 0 To 3: LongInSec, Degreeses, Minutes, Seconds
Function Degrees_Str_ToArrL3(ByVal v$, aL3() As Long, Optional fMsgTrue As Boolean, Optional fMsgFalse As Boolean) As Boolean
Dim z&, d&, m&, s&
If AscW(v) = 45 Then
z = -1: v = Right$(v, Len(v) - 1)
Else
z = 1
End If
d = InStr(v, "°")
s = InStrRev(v, "''")
m = InStr(d + 1, v, "'"): If m = s Then m = 0
On Error GoTo ex
If d Then
If m Then
If s Then
aL3(1) = Left$(v, d - 1)
aL3(2) = Mid$(v, d + 1, m - d - 1)
aL3(3) = Mid$(v, m + 1, s - m - 1)
Else
aL3(1) = Left$(v, d - 1)
aL3(2) = Mid$(v, d + 1, m - d - 1)
aL3(3) = 0
End If
Else
If s Then
aL3(1) = Left$(v, d - 1)
aL3(2) = 0
aL3(3) = Mid$(v, d + 1, s - d - 1)
Else
aL3(1) = Left$(v, d - 1)
aL3(2) = 0
aL3(3) = 0
End If
End If
Else
If m Then
If s Then
aL3(1) = 0
aL3(2) = Left$(v, m - 1)
aL3(3) = Mid$(v, m + 1, s - m - 1)
Else
aL3(1) = 0
aL3(2) = Left$(v, m - 1)
aL3(3) = 0
End If
Else
If s Then
aL3(1) = 0
aL3(2) = 0
aL3(3) = Left$(v, s - 1)
Else
Stop: End
End If
End If
End If
aL3(0) = z * (3600 * aL3(1) + 60 * aL3(2) + aL3(3))
If fMsgTrue Then MsgBox "String «" & v & "» is a Degree!", vbInformation, "Degrees_Str_ToArrL3"
Degrees_Str_ToArrL3 = True: Exit Function
ex: If fMsgFalse Then MsgBox "String «" & v & "» is NOT a Degree!", vbCritical, "Degrees_Str_ToArrL3"
End Function
'==================================================================================================
Function Degrees_Sec_ToArrL3(ByVal sec&, aL3() As Long) As Boolean
aL3(0) = sec
sec = Abs(sec)
aL3(1) = sec \ 3600
aL3(2) = (sec - 3600 * aL3(1)) \ 60
aL3(3) = sec - 60 * aL3(2) - 3600 * aL3(1)
Degrees_Sec_ToArrL3 = True
End Function
'==================================================================================================
Function Degrees_ArrL3_ToStr(aL3() As Long, Optional fSkipZeros As Boolean) As String
If fSkipZeros Then
If aL3(1) Then
If aL3(2) Then
If aL3(3) Then
Degrees_ArrL3_ToStr = aL3(1) & "°" & aL3(2) & "'" & aL3(3) & "''"
Else
Degrees_ArrL3_ToStr = aL3(1) & "°" & aL3(2) & "'"
End If
Else
If aL3(3) Then
Degrees_ArrL3_ToStr = aL3(1) & "°" & aL3(3) & "''"
Else
Degrees_ArrL3_ToStr = aL3(1) & "°"
End If
End If
Else
If aL3(2) Then
If aL3(3) Then
Degrees_ArrL3_ToStr = aL3(2) & "'" & aL3(3) & "''"
Else
Degrees_ArrL3_ToStr = aL3(2) & "'"
End If
Else
If aL3(3) Then
Degrees_ArrL3_ToStr = aL3(3) & "''"
Else
Degrees_ArrL3_ToStr = CVErr(xlErrNA)
End If
End If
End If
Else
Degrees_ArrL3_ToStr = aL3(1) & "°" & aL3(2) & "'" & aL3(3) & "''"
End If
If aL3(0) < 0 Then Degrees_ArrL3_ToStr = "-" & Degrees_ArrL3_ToStr
End Function
'================================================================================================== |
|
|