(не показано 15 промежуточных версий этого же участника)
Строка 8:
Строка 8:
==Решение==
==Решение==
# Структура БД
# '''Структура БД'''
:Gpx полученные из MapSource, обладают рядом особенностей:
:Gpx полученные из MapSource, обладают рядом особенностей:
:*заполняются не все «поля»
:*заполняются не все «поля»
:*собственное расширение (<extensions>)
:*собственное расширение (<extensions>)
:*дата и время для waypoints пишется как текст в элементы <cmt> и <desc>
:*дата и время для waypoints пишется как текст в элементы <cmt> и <desc>
Дамп БД:[[Файл:Gpx db 20130407 2315.zip|Дамп БД]]
:Пример точки:
{{Скрытый
|Рамка = 1px dashed #aa0000
|Ссылка = left
|Выравнивание_заголовка = left
|Заголовок = Пример точки
|Фон_заголовка = #ccccff
|Содержание =
<syntaxhighlight lang="XML">
<syntaxhighlight lang="XML">
<wpt lat="56.8854080" lon="62.2301917">
<wpt lat="56.8854080" lon="62.2301917">
Строка 28:
Строка 34:
</extensions>
</extensions>
</wpt>
</wpt>
</syntaxhighlight>
</syntaxhighlight>}}
В данном случае меня интересовали: геометрия (lat, lon), имя (name), высота (ele), дата/время (cmt), символ(sym). Содержание <desc> дублирует <cmt>, с точки зрения MapSource: <cmt> - время, <desc> - комментарий к точке, <extensions> влияет только на отображение точки в MapSource. Символ <sym> записывается как string, лучше вынести в отдельную таблицу.
:В данном случае меня интересовали: геометрия (lat, lon), имя (name), высота (ele), дата/время (cmt), символ(sym). Содержание <desc> дублирует <cmt>, с точки зрения MapSource: <cmt> - время, <desc> - комментарий к точке, <extensions> влияет только на отображение точки в MapSource. Символ <sym> записывается как string, лучше вынести в отдельную таблицу.
{{Скрытый
|Рамка = 1px dashed #aa0000
:Структура таблиц wpt (waypoints) и symtbl (<sym>)
|Ссылка = left
|Выравнивание_заголовка = left
|Заголовок = Структура таблиц wpt (waypoints) и symtbl (<sym>)
|Фон_заголовка = #ccccff
|Содержание =
<syntaxhighlight lang="SQL">
<syntaxhighlight lang="SQL">
CREATE TABLE `wpt` (
CREATE TABLE `wpt` (
Строка 43:
Строка 53:
PRIMARY KEY (`id`))
PRIMARY KEY (`id`))
</syntaxhighlight>
</syntaxhighlight>
<br />
<syntaxhighlight lang="SQL">
<syntaxhighlight lang="SQL">
CREATE TABLE `symtbl` (
CREATE TABLE `symtbl` (
Строка 49:
Строка 58:
`desc` varchar(45) NOT NULL,
`desc` varchar(45) NOT NULL,
PRIMARY KEY (`id`))
PRIMARY KEY (`id`))
</syntaxhighlight>
</syntaxhighlight>}}
<br />
{{Скрытый
:Пример трека:
|Рамка = 1px dashed #aa0000
|Ссылка = left
|Выравнивание_заголовка = left
|Заголовок = Пример трека
|Фон_заголовка = #ccccff
|Содержание =
<syntaxhighlight lang="XML">
<syntaxhighlight lang="XML">
<trk>
<trk>
Строка 67:
Строка 81:
</trkseg>
</trkseg>
</trk>
</trk>
</syntaxhighlight>
</syntaxhighlight>}}
<br />
Трек имеет только имя и множество точек, тип которых – wptType, но с более аскетичным содержанием. Здесь надо заметить, что элемент <time> содержит время в Univeral Coordinated Time (UTC), в отличии от локального в <cmt>, следует выбрать единое время для БД и привести к нему все значения. Для удобства следует получить linestring, для отображения трэка, но желательно сохранить время для каждой точки трэка. Также удобно знать время трэка, по первой точке. Для трэков с одной точкой поле trk_line=null. Также надо учитывать, что трэк может содержать несколько сегментов (Track Segment), хотя MapSource кажется, так не делает, вместо этого создавая новый трэк. Создадим таблицы, для треков и точек треков, у последних получится два внешних ключа trk_id и nseg, хотя nseg получается «висячим» - так как никуда не указывает…
:Трек имеет только имя и множество точек, тип которых – wptType, но с более аскетичным содержанием. Здесь надо заметить, что элемент <time> содержит время в Univeral Coordinated Time (UTC), в отличии от локального в <cmt>, следует выбрать единое время для БД и привести к нему все значения. Для удобства следует получить linestring, для отображения трэка, но желательно сохранить время для каждой точки трэка. Также удобно знать время трэка, по первой точке. Для трэков с одной точкой поле trk_line=null. Также надо учитывать, что трэк может содержать несколько сегментов (Track Segment), хотя MapSource кажется, так не делает, вместо этого создавая новый трэк. Создадим таблицы, для треков и точек треков, у последних получится два внешних ключа trk_id и nseg, хотя nseg получается «висячим» - так как никуда не указывает…
{{Скрытый
|Рамка = 1px dashed #aa0000
:Структура таблиц trk(tracklogs) и trkpt (Track Point)
|Ссылка = left
|Выравнивание_заголовка = left
|Заголовок = Структура таблиц trk(tracklogs) и trkpt (Track Point)
|Фон_заголовка = #ccccff
|Содержание =
<syntaxhighlight lang="SQL">
<syntaxhighlight lang="SQL">
CREATE TABLE `trk` (
CREATE TABLE `trk` (
Строка 90:
Строка 108:
`ele` double default NULL,
`ele` double default NULL,
PRIMARY KEY (`id`))
PRIMARY KEY (`id`))
</syntaxhighlight>
</syntaxhighlight>}}
<br />
:Функция для заполнения `trk_line`
:Функция для заполнения `trk_line`
Я это называю - "собирать бисер". В SFA нет функций для редактирования геометрии (в PostGIS и Oracle Spatila - есть). По хорошему надо использовать WKB - но как сделать это на SQL - я не знаю. Поэтому использую WKT и колдую с текстом (longText, по началу использовал text - как то не хватило...). У MySQL есть пара неприятных моментов связанных с геометрией: при попытке создать в хранимке определённую геометрию (например LINESTRING) - MySQL меняет функцию на создание просто геометрии (и внезапно получаем MULTIPOINT, хотя может это косяк моей версии), поэтому я использовал geomfromtext и в строке явно указывал тип геометрии. При объявлении "Declare p1, p2 point;" p1, p2 - это указатели, а значит при set p1=p2 мы получаем два указателя на '''один''' объект. Что бы скопировать точку приходится городить такое : Set p1 = geomfromtext(concat('Point(', X(CrP), ' ', Y(CrP), ')'));
{{Скрытый
|Рамка = 1px dashed #aa0000
|Ссылка = left
|Выравнивание_заголовка = left
|Заголовок = CreateTrkLine
|Фон_заголовка = #ccccff
|Содержание =
<syntaxhighlight lang="SQL">
<syntaxhighlight lang="SQL">
PROCEDURE `CreateTrkLine`(nid int)
PROCEDURE `CreateTrkLine`(nid int)
Строка 123:
Строка 148:
update trk set `trk_line`=CrLn where id=nid;
update trk set `trk_line`=CrLn where id=nid;
END $$
END $$
</syntaxhighlight>
</syntaxhighlight>}}
:Функция для добавления Point к LineString
{{Скрытый
|Рамка = 1px dashed #aa0000
|Ссылка = left
|Выравнивание_заголовка = left
|Заголовок = Функция для добавления Point к LineString
|Фон_заголовка = #ccccff
|Содержание =
<syntaxhighlight lang="SQL">
<syntaxhighlight lang="SQL">
FUNCTION `LS_AddPoint`(Ls LineString, np point) RETURNS linestring
FUNCTION `LS_AddPoint`(Ls LineString, np point) RETURNS linestring
Строка 141:
Строка 172:
Return LineFromText(nStr);
Return LineFromText(nStr);
END $$
END $$
</syntaxhighlight>
</syntaxhighlight>}}
# Импорт данных
<br />
:Для разработки модуля импорта данных, я выбрал VBA, по двум причинам: наиболее удобный IDE из доступных у меня на рабочей машине; наличие опыта и наработок. Перед началом работы, необходимо подключить Microsoft XML v6.0 (работа с XML) и Microsoft ActiveX Data Objects 2.8 Library (подключение БД). Также я использовал WinAPI, а именно GetOpenFileNameA из comdlg32.dll.
# '''Импорт данных'''
Для разработки модуля импорта данных, я выбрал VBA, по двум причинам: наиболее удобный IDE из доступных у меня на рабочей машине; наличие опыта и наработок. Перед началом работы, необходимо подключить Microsoft XML v6.0 (работа с XML) и Microsoft ActiveX Data Objects 2.8 Library (подключение БД). Также я использовал WinAPI, а именно GetOpenFileNameA из comdlg32.dll.
Изначально, было решено, разделить чтение и запись, что бы передать данные используются структуры: wpt_rec и trk_rec. В начале разработки, в отладочных целях, данные записывались на Лист в Excel'е - данный код приведён в листингах, но закомментирован. Некрасиво получилось то, что фильтрация исходных данных происходить в разных местах: для точек - при чтении XML'я (If cWPT.cmt <> "" Then 'У "ненужных" точек cWPT.cmt=""), для треков в начале записи в БД (If nTRK.s(0).p(0).time <> "" Then). Так же разделено преобразование даты/время, но здесь это оправданно - как было сказано выше, в точках и трэках время записано по разному.
:Запуск импорта - test1.
<br />
Файл с макросами (xlsm):[[Файл:Imp_gpx.zip|файл с макросами (xlsm)]]
<br />
<br />
:Обработка XML'я
{{Скрытый
|Рамка = 1px dashed #aa0000
|Ссылка = left
|Выравнивание_заголовка = left
|Заголовок = Обработка XML'я
|Фон_заголовка = #ccccff
|Содержание =
<syntaxhighlight lang="VB">
<syntaxhighlight lang="VB">
'Переменные для записи данных на Лист
'Переменные для записи данных на Лист
Строка 328:
Строка 370:
'InsTRK cTRK
'InsTRK cTRK
End Sub
End Sub
</syntaxhighlight>
</syntaxhighlight>}}
<br />
{{Скрытый
:Загрузка в БД
|Рамка = 1px dashed #aa0000
|Ссылка = left
|Выравнивание_заголовка = left
|Заголовок = Загрузка в БД
|Фон_заголовка = #ccccff
|Содержание =
<syntaxhighlight lang="VB">
<syntaxhighlight lang="VB">
Dim MyConnect As ADODB.Connection
Dim MyConnect As ADODB.Connection
Строка 448:
Строка 495:
Next i
Next i
End Sub
End Sub
</syntaxhighlight>
</syntaxhighlight>}}
<br />
{{Скрытый
:OpenFile
|Рамка = 1px dashed #aa0000
|Ссылка = left
|Выравнивание_заголовка = left
|Заголовок = OpenFile
|Фон_заголовка = #ccccff
|Содержание =
<syntaxhighlight lang="VB">
<syntaxhighlight lang="VB">
Private Const OFN_ALLOWMULTISELECT As Long = &H200
Private Const OFN_ALLOWMULTISELECT As Long = &H200
В данном случае меня интересовали: геометрия (lat, lon), имя (name), высота (ele), дата/время (cmt), символ(sym). Содержание <desc> дублирует <cmt>, с точки зрения MapSource: <cmt> - время, <desc> - комментарий к точке, <extensions> влияет только на отображение точки в MapSource. Символ <sym> записывается как string, лучше вынести в отдельную таблицу.
Я это называю - "собирать бисер". В SFA нет функций для редактирования геометрии (в PostGIS и Oracle Spatila - есть). По хорошему надо использовать WKB - но как сделать это на SQL - я не знаю. Поэтому использую WKT и колдую с текстом (longText, по началу использовал text - как то не хватило...). У MySQL есть пара неприятных моментов связанных с геометрией: при попытке создать в хранимке определённую геометрию (например LINESTRING) - MySQL меняет функцию на создание просто геометрии (и внезапно получаем MULTIPOINT, хотя может это косяк моей версии), поэтому я использовал geomfromtext и в строке явно указывал тип геометрии. При объявлении "Declare p1, p2 point;" p1, p2 - это указатели, а значит при set p1=p2 мы получаем два указателя на один объект. Что бы скопировать точку приходится городить такое : Set p1 = geomfromtext(concat('Point(', X(CrP), ' ', Y(CrP), ')'));
Для разработки модуля импорта данных, я выбрал VBA, по двум причинам: наиболее удобный IDE из доступных у меня на рабочей машине; наличие опыта и наработок. Перед началом работы, необходимо подключить Microsoft XML v6.0 (работа с XML) и Microsoft ActiveX Data Objects 2.8 Library (подключение БД). Также я использовал WinAPI, а именно GetOpenFileNameA из comdlg32.dll.
Изначально, было решено, разделить чтение и запись, что бы передать данные используются структуры: wpt_rec и trk_rec. В начале разработки, в отладочных целях, данные записывались на Лист в Excel'е - данный код приведён в листингах, но закомментирован. Некрасиво получилось то, что фильтрация исходных данных происходить в разных местах: для точек - при чтении XML'я (If cWPT.cmt <> "" Then 'У "ненужных" точек cWPT.cmt=""), для треков в начале записи в БД (If nTRK.s(0).p(0).time <> "" Then). Так же разделено преобразование даты/время, но здесь это оправданно - как было сказано выше, в точках и трэках время записано по разному.
'Переменные для записи данных на ЛистDimgIAsInteger,gJAsIntegerDimcRangeAsRangePublicTypewpt_rec'waypointslatAsDoublelonAsDoublenameAsStringeleAsDoublecmtAsString'select str_to_date('15-AUG-12 9:38:50', '%d-%M-%Y %H:%i:%s')symAsIntegerEndTypePublicTypetrk_pt_rec'Track PointlatAsDoublelonAsDoubleeleAsDoubletimeAsStringEndTypePublicTypetrk_seg'Track Segmentp()Astrk_pt_recEndTypePublicTypetrk_rec'tracklogsnameAsStrings()Astrk_segEndTypePublicSubOpenGPX(crFileAsString)'Обрабока gpxDimiAsIntegerDimObjDocAsMSXML2.DOMDocument60DimnNodeAsIXMLDOMNode'SetObjDoc=NewMSXML2.DOMDocument60ObjDoc.LoadcrFile'ОткрываемObjDoc.setProperty"SelectionNamespaces","xmlns=""http://www.topografix.com/GPX/1/1"""Fori=0ToObjDoc.DocumentElement.ChildNodes.Length-1'получаем узел и назначаем метод обработки, в зависемости от типаSetnNode=ObjDoc.DocumentElement.ChildNodes.Item(i)IfnNode.BaseName="wpt"ThenWork_wpt1nNodeIfnNode.BaseName="trk"ThenWork_trk1nNodeNextiEndSubPublicSubtest1()'Открываем gpx'ыDimiAsIntegerDimarr'StartWorksheet 'Получаем ЛистStart1'Подключаемся к БДarr=Split(OpenFile(0),Chr(0))'Проверяем количество файловIfUBound(arr)=1ThenOpenGPX(arr(0))ElseFori=1ToUBound(arr)-1OpenGPX(arr(0)&"\"&arr(i))NextiEndIf'MsgBox "Good"EndSubPublicSubWork_wpt1(nWPTAsIXMLDOMNode)'Обработка waypointsDimiAsInteger,symidAsIntegerDimcWPTAswpt_recDimnNodeAsIXMLDOMNode'nwptcWPT.lat=nWPT.Attributes.Item(0).TextcWPT.lon=nWPT.Attributes.Item(1).Text'cRange.Cells(gI, 3).Value = nwpt.ChildNodes.Item(1).TextFori=0TonWPT.ChildNodes.Length-1SetnNode=nWPT.ChildNodes.Item(i)SelectCasenNode.BaseName'Обрабатываем потомковCase"name":cWPT.name=nNode.TextCase"ele":cWPT.ele=nNode.TextCase"cmt":cWPT.cmt=nNode.TextCase"sym":cWPT.sym=GetSymId(nNode.Text)'cRange.Cells(gI, 6).Value = symid'cRange.Cells(gI, 7).Value = nNode.TextEndSelectNextiIfcWPT.cmt<>""Then'У "ненужных" точек cWPT.cmt=""'cRange.Cells(gI, 1).Value = cWPT.lat'cRange.Cells(gI, 2).Value = cWPT.lon'cRange.Cells(gI, 3).Value = cWPT.name'cRange.Cells(gI, 4).Value = cWPT.ele'cRange.Cells(gI, 5).Value = cWPT.cmt'cRange.Cells(gI, 6).Value = cWPT.sym'cRange.Cells(gI, 8).Value = SearchWPT(cWPT)InsWPTcWPT'Отправляем waypoints в БДEndIf'gI = gI + 1EndSubPublicSubStartWorksheet()' Получаем ЛистDiml1AsWorksheetSetWorksheet=Worksheets.Item("Лист1")SetcRange=Worksheet.CellsgI=1:gJ=1'cRange.Cells(1, 1).Value = "good"EndSubPublicFunctionWork_trkseg1(nTRKsegAsIXMLDOMNode)Astrk_seg'Обработка Track SegmentDimi,J,npAsIntegerDimWorkStrAsString'Dim cP As trk_pt_recDimnNodeAsIXMLDOMNodeDimnNode2AsIXMLDOMNode'nTRKnp=0Fori=0TonTRKseg.ChildNodes.Length-1SetnNode=nTRKseg.ChildNodes.Item(i)SelectCasenNode.BaseName'Обрабатываем потомковCase"trkpt"ReDimPreserveWork_trkseg1.p(np)Work_trkseg1.p(np).lat=nNode.Attributes.Item(0).TextWork_trkseg1.p(np).lon=nNode.Attributes.Item(1).TextForJ=0TonNode.ChildNodes.Length-1SetnNode2=nNode.ChildNodes.Item(J)SelectCasenNode2.BaseName'Обрабатываем потомковCase"ele":Work_trkseg1.p(np).ele=nNode2.TextCase"time"'Форматируем времяWorkStr=nNode2.TextWorkStr=Replace(WorkStr,"T"," ")WorkStr=Replace(WorkStr,"Z","")Work_trkseg1.p(np).time=WorkStrEndSelectNextJ'Work_trkseg1.p(np) = cPnp=np+1EndSelectNextiEndFunctionPublicSubWork_trk1(nTRKAsIXMLDOMNode)'Обработка tracklogsDimi,trksegAsIntegerDimcTRKAstrk_recDimnNodeAsIXMLDOMNode'nTRKtrkseg=0Fori=0TonTRK.ChildNodes.Length-1SetnNode=nTRK.ChildNodes.Item(i)SelectCasenNode.BaseName'Обрабатываем потомковCase"name":cTRK.name=nNode.TextCase"trkseg"ReDimPreservecTRK.s(trkseg)cTRK.s(trkseg)=Work_trkseg1(nNode)trkseg=trkseg+1EndSelectNexti'WrTrk cTRKInsTRKcTRK'Отправляем tracklogs в БДEndSubPublicSubWrTrk(cTRKAstrk_rec)'Обработка Track для записи на ЛистDimi,JAsIntegerFori=0ToUBound(cTRK.s)ForJ=0ToUBound(cTRK.s(i).p)'cRange.Cells(gI, 1).Value = cTRK.name'cRange.Cells(gI, 2).Value = I + 1'cRange.Cells(gI, 3).Value = cTRK.s(I).p(J).lat'cRange.Cells(gI, 4).Value = cTRK.s(I).p(J).lon'cRange.Cells(gI, 5).Value = cTRK.s(I).p(J).ele'cRange.Cells(gI, 6).Value = cTRK.s(I).p(J).timegI=gI+1NextJNexti'InsTRK cTRKEndSub
Загрузка в БД
DimMyConnectAsADODB.ConnectionPublicFunctionConnectToMySQL()AsADODB.Connection'Подключаемся к БДSetConnectToMySQL=NewADODB.ConnectionConnectToMySQL.ConnectionString="Driver={MySQL ODBC 5.1 Driver};Server=localhost;Database=gpx_DB;User=guest;Password=guest;Option=3;"ConnectToMySQL.OpenEndFunctionPublicSubStart1()'Подключаемся к БДSetMyConnect=ConnectToMySQLEndSub'"SELECT id FROM `gpx_db`.`symtbl` where `desc`="PublicFunctionGetSymId(SymDescAsString)AsInteger' Обрабатываем <sym>, получаем ключ из symtblDimStrSQLAsStringDimMyRSAsADODB.Recordset'SetMyRS=NewADODB.RecordsetSetMyRS.ActiveConnection=MyConnectMyRS.Source="SELECT id FROM `gpx_db`.`symtbl` where `desc`="""&SymDesc&""";"MyRS.OpenIfMyRS.BOFAndMyRS.EOFThenInsSymDesc(SymDesc)GetSymId=GetSymId(SymDesc)ElseGetSymId=MyRS.fields(0).ValueEndIfEndFunction'insert into `gpx_db`.`symtbl` values (null,'Restaurant')PublicSubInsSymDesc(SymDescAsString)'Добавляем новое значение <sym>MyConnect.Execute"insert into `gpx_db`.`symtbl` values (null,"""&SymDesc&""");"EndSub'SELECT * FROM wpt w where p=geomfromtext('POINT(60.5513457 59.5433567)') and cmt=str_to_date('15-AUG-12 9:38:50', '%d-%M-%Y %H:%i:%s');PublicFunctionSearchWPT(nWPTAswpt_rec)AsInteger'Ищем waypoints в БДDimStrSQLAsStringDimMyRSAsADODB.Recordset'SetMyRS=NewADODB.RecordsetSetMyRS.ActiveConnection=MyConnectMyRS.Source="SELECT id FROM wpt w where p=geomfromtext(""POINT("&nWPT.lon&" "&nWPT.lat&")"") and cmt="&_
"str_to_date("""&nWPT.cmt&""", ""%d-%M-%Y %H:%i:%s"");"MyRS.OpenIfMyRS.BOFAndMyRS.EOFThenSearchWPT=0ElseSearchWPT=MyRS.fields(0).ValueEndIfEndFunction'select str_to_date('15-AUG-12 9:38:50', '%d-%M-%Y %H:%i:%s')PublicSubInsWPT(nWPTAswpt_rec)'Добавляем waypoints в БДIfSearchWPT(nWPT)=0Then'Проверяем наличие'geomfromtext('Point(0 0)')MyConnect.Execute"insert into `gpx_db`.`wpt` values (null,geomfromtext(""Point("&nWPT.lon&" "&nWPT.lat&")""), """&nWPT.name&_
""", "&nWPT.ele&", str_to_date("""&nWPT.cmt&""", '%d-%M-%Y %H:%i:%s'), "&nWPT.sym&");"EndIfEndSub'SELECT id FROM trk t where name='ACTIVE LOG' and dt='2012-08-15 09:51:32';PublicFunctionSearchTRK(nTRKAstrk_rec)AsInteger'Ищем tracklogs в БДDimStrSQLAsStringDimMyRSAsADODB.Recordset'SetMyRS=NewADODB.RecordsetSetMyRS.ActiveConnection=MyConnectMyRS.Source="SELECT id FROM trk where name="""&nTRK.name&""" and dt=CONVERT_TZ(str_to_date("""&nTRK.s(0).p(0).time&_
""", '%Y-%m-%d %H:%i:%s'),'+00:00','+6:00');"'MyRS.Source = "select SearchTrk(" & nTRK.s(0).p(0).lon & ", " & nTRK.s(0).p(0).lat & ", CONVERT_TZ(str_to_date(""" & nTRK.s(0).p(0).time & _' """, '%Y-%m-%d %H:%i:%s'),'+00:00','+6:00'))"MyRS.OpenIfMyRS.BOFAndMyRS.EOFThenSearchTRK=0ElseSearchTRK=MyRS.fields(0).ValueEndIfEndFunctionPublicFunctionInsTRK(nTRKAstrk_rec)AsInteger'Добавляем tracklogs в БДDimresAsInteger'IfnTRK.s(0).p(0).time<>""Thenres=SearchTRK(nTRK)Ifres=0ThenMyConnect.Execute"insert into `gpx_db`.`trk` values (null, """&nTRK.name&""", 0, null, CONVERT_TZ(str_to_date("""&_
nTRK.s(0).p(0).time&""", '%Y-%m-%d %H:%i:%s'),'+00:00','+6:00'));"res=SearchTRK(nTRK)InsTRKptsnTRK,resMyConnect.Execute"call CreateTrkLine("&res&");"EndIfInsTRK=resEndIfEndFunctionPublicSubInsTRKpts(nTRKAstrk_rec,TRK_idAsInteger)'Добавляем Track Point в БДDimi,JAsInteger'Fori=0ToUBound(nTRK.s)ForJ=0ToUBound(nTRK.s(i).p)MyConnect.Execute"insert into `gpx_db`.`trkpt` values (null, "&TRK_id&", "&i+1&_
", geomfromtext(""Point("&nTRK.s(i).p(J).lon&" "&nTRK.s(i).p(J).lat&")""), "&_
"CONVERT_TZ(str_to_date("""&nTRK.s(i).p(J).time&""", '%Y-%m-%d %H:%i:%s'),'+00:00','+6:00'), "&_
nTRK.s(i).p(J).ele&");"NextJNextiEndSub