【发布时间】:2018-05-08 01:41:48
【问题描述】:
我有一个唯一标识符(A 列)及其各自的坐标集(DD 单位,例如 59、-110),用于 500 多个位置,我想编写一个创建二维数组的宏(500+ X 500 +) 并使用数据集中所有其他坐标之间的距离自动填充数组中的每个单元格。
样本数据集(从 A1 开始):
ID Lat Long
A 59 -110
B 58 -105
C 62 -103
希望我可以创建一个如下所示的数组:
A B C
A 0 X Y
B X 0 Z
C Y Z 0
计算两个坐标之间距离的公式是:
=ACOS( SIN(lat1*PI()/180)*SIN(lat2*PI()/180) + COS(lat1*PI()/180)*COS(lat2*PI()/180)*COS(long2*PI()/180-long1*PI()/180) ) * 6371000
除此之外,如果可能的话,我想在数组的末尾添加一行,计算出的最小距离不为零。
这是我目前所拥有的:
Const R2D As Double = (3.1459 / 180)
Const MagicNumber As Long = 637100
Private Function GetDistances(Lat1 As Double, Lat2 As Double, Long1 As Double, Long2 As Double) As Double
GetDistances = Acos(Sin(Lat1) * Sin(Lat2) * R2D ^ 2 + Cos(Lat1) * Cos(Lat2) * Cos(Long2) * R2D ^ 3 - Long1 * R2D) * MagicNumber
End Function
Sub MakeMatrix()
Dim Originals As Variant
Dim Distances As Variant
Dim Results As Double
Dim i As Long, j As Long, k As Long, l As Long
Dim Rws As Long
Const Lat As Long = 1
Const Lon As Long = 2
Const MinDistance = 0.01
Rws = Cells(Rows, Count, "A").End(xlUp).Row - 1
Originals = Application.Transpose(Range(Cells(2, "B"), Cells(Rws, "C"))).Value
ReDim Distances(1 To Rws1, 1 To Rws)
For i = LBound(Originals) To UBound(Originals)
For j = LBound(Originals) To UBound(Originals)
Results = GetDistance(Lat1:=Originals(i, Lat), Lat2:=Originals(j, Lat), Long1:=Originals(i, Lon), Long1:=Originals(j, Lon))
If Results > MinDistance Then Distances(i, j) = Results
Next j: Next i
Range("F1").Resize(Rws, Rws) = Distances
End Sub
对此的任何帮助将不胜感激
新的堆栈,如果需要任何其他信息,请询问
提前致谢
【问题讨论】:
-
由于地球并不是真正的球形,因此您正在引入扭曲。如果您想要或需要更准确的信息,可以考虑使用Vincenty's formula。无论如何——你的代码到底有什么问题?如果您描述出了什么问题会有所帮助。
-
什么是
Rws1?您需要在模块顶部使用Option Explicit。此外,您的Rws = Cells(Rows, Count, "A").End(xlUp).Row - 1语法已关闭 - 应该是Rows.Count。 -
另外,
Long1在您的GetDistance()等式中有两次 - 您需要逐行仔细校对,但一定要从Option Explicit开始以帮助您发现明显的错误 - 它会阻止您用它们编译的代码。 -
@dwirony 关于
Optional Explicit的观点的重要性怎么强调都不为过。与其让它碰运气 - 您可以一劳永逸地转到 VBA 编辑器中的Options选项卡并启用“需要变量声明”选项(或类似的词)。我一直觉得这不是编辑器中的默认设置很奇怪。