A topo can't have a point directly above a point therefore you need to filter out coincident XY values regardless of Z, this can be done with a equality comparer as below. Using Excel you'll find the following duplicate x,y points in your input file. Once these are eliminated and truncated as mentioned below then you can probably insert the file in the non-api way.

The coordinates need to be truncated as they are too large for what usually suits Revit. There is section below for deducting minimums from the coords. You then have to use shared coords to represent real world values (Revit relative coords to the real world).
I like to use text field parser from the VisualBasic.FileIO namespace as it is good with dealing with the following aspects:
Comment tokens, white spaces, fields enclosed in quotes i.e. "ObjA, ObjB","100" is treated as two fields and the quotes are automatically removed if they exist.
Also gives line numbers for dealing with errors.
private class RT_PT : IEquatable<RT_PT>
{
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
public bool Equals(RT_PT other)
{
if (this.X != other.X)
return false;
if (this.Y != other.Y)
return false;
//We don't compare Z in this case as a topo can't have a point directly above a point
return true;
}
public XYZ AsXYZ()
{
return new XYZ(X / 0.3048, Y / 0.3048, Z / 0.3048);
}
}
public Result TObj41(Autodesk.Revit.UI.ExternalCommandData commandData, ref string message, Autodesk.Revit.DB.ElementSet elements)
{
if (commandData.Application.ActiveUIDocument == null)
return Result.Cancelled;
Document D = commandData.Application.ActiveUIDocument.Document;
Microsoft.Win32.OpenFileDialog OFD = new Microsoft.Win32.OpenFileDialog
{
Filter = "Text files (*.txt)|*.txt",
Multiselect = false,
DefaultExt = ".txt"
};
OFD.ShowDialog();
if (string.IsNullOrEmpty(OFD.FileName))
return Result.Cancelled;
List<RT_PT> PointsCollected = new List<RT_PT>();
using (Microsoft.VisualBasic.FileIO.TextFieldParser TFP = new Microsoft.VisualBasic.FileIO.TextFieldParser(OFD.FileName))
{
TFP.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited;
TFP.Delimiters = new string[] { "," };
TFP.TrimWhiteSpace = true;
while (TFP.EndOfData == false)
{
string[] Fds = TFP.ReadFields();
if (Fds.Length < 3)
continue;
double xx;
double yy;
double zz;
RT_PT NP = new RT_PT();
if (double.TryParse(Fds[0], out xx) == false)
continue;
if (double.TryParse(Fds[1], out yy) == false)
continue;
if (double.TryParse(Fds[2], out zz) == false)
continue;
NP.X = xx;
NP.Y = yy;
NP.Z = zz;
if (PointsCollected.Count > 0)
{
if (PointsCollected.Contains(NP) == false)
{
PointsCollected.Add(NP);
}
}
else
{
PointsCollected.Add(NP);
}
}
TFP.Close();
}
if (PointsCollected.Count == 0)
return Result.Cancelled;
//Truncate the large coords or expect a white screen with a tiny hard to find black dot
//Use shared coord system to represent large real world values (the mins below represent offsets to the real world values)
double MinX = PointsCollected.Min(j => j.X);
double MinY = PointsCollected.Min(j => j.Y);
double MinZ = PointsCollected.Min(j => j.Z);
Int32 i;
for (i = 0; i <= PointsCollected.Count - 1; i++)
{
PointsCollected[i].X -= MinX;
PointsCollected[i].Y -= MinY;
PointsCollected[i].Z -= MinZ;
}
List<XYZ> XYZLst = new List<XYZ>();
for (i = 0; i <= PointsCollected.Count - 1; i++)
{
XYZLst.Add(PointsCollected[i].AsXYZ());
}
if (XYZLst.Count == 0)
return Result.Failed;
using (Transaction Tx = new Transaction(D, "Topo please"))
{
if (Tx.Start() == TransactionStatus.Started)
{
Autodesk.Revit.DB.Architecture.TopographySurface.Create(D, XYZLst);
Tx.Commit();
}
}
return Result.Succeeded;
}
C#
Private Class RT_PT
Implements IEquatable(Of RT_PT)
Public Property X As Double
Public Property Y As Double
Public Property Z As Double
Public Overloads Function Equals(other As RT_PT) As Boolean Implements IEquatable(Of RT_PT).Equals
If Me.X <> other.X Then Return False Else
If Me.Y <> other.Y Then Return False Else
'We don't compare Z in this case as a topo can't have a point directly above a point
Return True
End Function
Public Function AsXYZ() As XYZ
Return New XYZ(X / 0.3048, Y / 0.3048, Z / 0.3048)
End Function
End Class
Public Function TObj41(ByVal commandData As Autodesk.Revit.UI.ExternalCommandData, _
ByRef message As String, ByVal elements As Autodesk.Revit.DB.ElementSet) As Result
If commandData.Application.ActiveUIDocument Is Nothing Then Return Result.Cancelled Else
Dim D As Document = commandData.Application.ActiveUIDocument.Document
Dim OFD As New Microsoft.Win32.OpenFileDialog With {.Filter = "Text files (*.txt)|*.txt", .Multiselect = False, .DefaultExt = ".txt"}
OFD.ShowDialog()
If String.IsNullOrEmpty(OFD.FileName) Then Return Result.Cancelled Else
Dim PointsCollected As New List(Of RT_PT)
Using TFP As New Microsoft.VisualBasic.FileIO.TextFieldParser(OFD.FileName)
TFP.TextFieldType = FileIO.FieldType.Delimited
TFP.Delimiters = New String() {","}
TFP.TrimWhiteSpace = True
While TFP.EndOfData = False
Dim Fds() As String = TFP.ReadFields
If Fds.Length < 3 Then Continue While Else
Dim NP As New RT_PT
If Double.TryParse(Fds(0), NP.X) = False Then Continue While Else
If Double.TryParse(Fds(1), NP.Y) = False Then Continue While Else
If Double.TryParse(Fds(2), NP.Z) = False Then Continue While Else
If PointsCollected.Count > 0 Then
If PointsCollected.Contains(NP) = False Then
PointsCollected.Add(NP)
End If
Else
PointsCollected.Add(NP)
End If
End While
TFP.Close()
End Using
If PointsCollected.Count = 0 Then Return Result.Cancelled Else
'Truncate the large coords or expect a white screen with a tiny hard to find black dot
'Use shared coord system to represent large real world values (the mins below represent offsets to the real world values)
Dim MinX As Double = PointsCollected.Min(Function(j) j.X)
Dim MinY As Double = PointsCollected.Min(Function(j) j.Y)
Dim MinZ As Double = PointsCollected.Min(Function(j) j.Z)
For i = 0 To PointsCollected.Count - 1
PointsCollected(i).X -= MinX
PointsCollected(i).Y -= MinY
PointsCollected(i).Z -= MinZ
Next
Dim XYZLst As New List(Of XYZ)
For i = 0 To PointsCollected.Count - 1
XYZLst.Add(PointsCollected(i).AsXYZ)
Next
If XYZLst.Count = 0 Then Return Result.Failed Else
Using Tx As New Transaction(D, "Topo please")
If Tx.Start = TransactionStatus.Started Then
Autodesk.Revit.DB.Architecture.TopographySurface.Create(D, XYZLst)
Tx.Commit()
End If
End Using
Return Result.Succeeded
End Function
VB