понедельник, 25 ноября 2013 г.

Советы шеф-повара: обновление данных в таблицах

Основная ценность, при работе практически с любыми программами, это данные. У программы, занимающейся работой с данными, должны присутствовать механизмы ввода, редактирования, сохранения данных.
В Mapinfo данные хранятся в таблицах и могут содержать две составляющие: графические и семантические данные. Со стороны Mapinfo, каждая таблица представляет собой нечто целое, содержащее некоторые записи, у каждой записи обязательно есть минимум одно семантическое поле. Со стороны файловой системы, таблица Mapinfo состоит из нескольких файлов, в каждом из которых содержится какая-то информация: семантика, графика, служебная информация, индексные файлы.
Сегодня я захотел написать о редактировании данных, так как это неотъемлемая часть процесса подготовки картографического материала. Ко всем прочему, в форумах регулярно возникают вопросы, связанные с "а как...?"

Я бы разделил возможности по редактированию на три группы:
1. ручное редактирование
2. полуавтоматизированное редактирование
3. автоматизированное редактирование

1. Ручное редактирование.
Дешево, надежно и практично. Графические объекты редактируются в окне карты, семантические поля - в окне списка или в окне информации. Хотел бы обратить внимание, что при редактировании таблиц, имеющих графические объекты (Mappable), через окно списка можно создавать записи без графических объектов. Это делается простым добавлением новой записи в окне списка. В последующем, прицепить к таким записям графические объекты, проблематично для неподготовленных пользователей. Если в такой таблице нужно добавить новый графический объект, но необходимо открыть эту таблицу в окне карты и нарисовать нужный графический объект.

2. Полуавтоматизированное редактирование.
Под полуавтоматизированным методом я понимаю редактирование с использованием
окна Mapbasic, построителя запросов и прочих штатных встроенных инструментов Mapinfo.
Для полноценного использования такого метода, на мой взгляд, нужны знания языка Mapbasic. Сложности в нем нет, но есть особенности версий, есть особенности Mapinfo, есть некоторые ограничения на использование Mapbasic в одноименном окне Mapinfo. Как я уже упоминал в ранних постах, документация Mapinfo и Mapbasic на очень хорошем уровне, и даже самостоятельное изучение не вызовет проблем.
В качестве живого примера полуавтоматизированного обновления приведу простой пример. Возникла элементарная и показательная задача по замене двойных кавычек на одинарные в поле таблицы.Хоть Mapbasic и довольно развитый язык, но, в основном, он содержит базовые(элементарные) функции. И строковой функции "ЗаменитьПодстроку" в нем нет. Зато есть огромное поле для фантазий по решению задачи с использованием ограниченного набора инструментов. Решение простое :-). Пара команд:

select * from SrcTable where InStr(1, SrcField, SrcSubstring) > 0 into TmpTable noselect

update TmpTable set SrcField = Mid$(SrcField, 1, InStr(1, SrcField, SrcSubstring) - 1) + NewSubString + Mid$(SrcField, InStr(1, SrcField, SrcSubstring) +Len(SrcSubstring) , 254)

Выполняем эту пару два раза получаем решенную задачу...

Первая команда select дает нам выборку записей исходной таблицы, в исходном поле которой есть требуемая для замены подстрока (в нашем случае - символ двойной кавычки ["]). В результате мы получаем запросную таблицу TmpTable. Теперь любые изменения в записях таблицы TmpTable автоматически записываются в соответствующие записи исходной таблицы SrcTable. Кто-то может спросить: а почему нельзя сразу написать update SrcTable ...?
Использование промежуточной таблицы обусловлено тем, что прямой update может вызвать ошибку, в случае если встретится запись, в которой в просматриваемом поле не искомой подстроки. Перехватывать ошибки в окне Mapbasic невозможно, поэтому используется промежуточная таблица.
  Вторая команда (update...) производит замену нашей SrcSubstring на NewSubString.
  Просто и быстро.
  Если надо произвести изменение графического объекта, то команда может выглядеть следующим образом:

update SrcTable set obj = ConvertToPLine(obj)
эта команда превратит все графические объекты в полилинии.

update SrcTable set obj = CreatePoint(x,y)
а эта команда создаст для каждой записи точечный объект, при условии что в таблице есть поля x и y с координатами.

3. Автоматизированное редактирование.
Под автоматизированным редактированием я понимаю использование специализированной программы на языке Mapbasic.
Это, пожалуй, универсальный метод, позволяющий реализовать все что душе угодно. С опытом, каждый для себя сможет сформулировать критерии, по которым можно принимать решение о выборе подхода, для решения вопроса о редактировании данных. Зачастую, написать пару команд в окне Mapbasic позволяет выполнить задачу быстрее, нежели подготовка самой простой программы на Mapbasic.
Простейшая программа для наших целей будет содержать всего две функции : обязательную main и пользовательскую, которая производит обработку строки.

sub main
  update TmpTable set SrcField = StringReplace(SrcField, SrcSubstring, NewSubString )
end sub

function StringReplace(byval aStr as string, byval aOldSub as string, byval aNewSub as string) as string
...
  StringReplace = ...
end function

Что мы имеем?
В коде присутствует обязательная для каждой программы Mapbasic sub main, в которой происходит обновление поля таблицы.
Функция StringReplace() производит обработку значения поля SrcField: заменяет все вхождения SrcSubstring на NewSubString.
Если нужна функция для обработки графических объектов, то ее объявление может иметь следующий вид

function ModifyObject(byval aObj as object) as object
...
  ModifyObject = ...
end function

В программе можно использовать все возможности Mapbasic. Остается откомпилировать текст программы при помощи компилятора Mapbasic и запускать ее на выполнение.

Вот, пожалуй, и все. Общая тема обозначена, все остальное - дело техники и опыта. Не бойтесь изучать, экспериментировать и думать.

вторник, 12 ноября 2013 г.

Экзотический рецепт использования Mapinfo.


В стародавние времена, когда стала проблескивать перспектива публикации геоданных в на просторах интернет, появилась задача быстренько смастерить прототип некой интернет страницы, на которой можно увидеть фрагмент карты Mapino, подготовленный на основании некоего семантического запроса...
На тот момент я еще только начинал осваивать Mapinfo, а в каком состоянии был MapXtreme сейчас я уже не припомню. В любом случае, времени на освоение новых технологий не было.
Итак, начнем с условия задачи.
Дано: некоторое количество однотипных рабочих наборов. семантическая БД с объектами, имеющими свое представление в одном из рабочих наборов. семантический объект, в зависимости от своего типа, располагается в определенной таблице рабочего набора.
Требуется: на некой web-странице, предоставить возможность выбора критериев поиска объекта и показать фрагмент соответствующего рабочего набора, с выделенным объектом, найденным в результате выполнения параметризованного поиска.
Исходя из имеющихся знаний и умений, мы с коллегой сошлись на "простом", в теоретическом плане, решении и организовали сервер приложений, который отвечал на запросы пользователей и взаимодействовал с MapInfo через COM-интерфейс.
Схема взаимодействия получилась такой:
Моя задача состояла в реализации взаимодействия с Mapinfo.
Основной проблемой явились однотипные рабочие наборы, а именно: невозможно открыть в Mapinfo две таблицы с одинаковым псевдонимом (alias).
Есть ли у Вас план, мистер Фикс?
Вот чем мне нравится разработка, так это то, что нет "правильных" и "неправильных" решений. Есть "работающие" или "не работающие" решения. Задачи можно решать разными способами, а это есть творчество, приносящее чувство глубокого удовлетворения. :-)
Придумалось оригинальное решение: каждый новый рабочий набор парсить и исправлять перед открытием в Mapinfo с целью присвоения всем таблицам рабочего набора уникальных псевдонимов. После этого, открывать рабочий набор и регистрировать информацию о нем, его открытых окнах и таблицах в специальных служебных таблицах. Все эти телодвижения нужны для того, чтобы знать в какой из таблиц производить поиск, какое из окон масштабировать по найденному объекту. Кроме этого, регистрация рабочего набора делается с целью предотвращения повторных открытий одного и того же файла.
После того как рабочий набор открыт, остаются сущие пустяки: найти объект по Идентификатору в нужной таблице нужного рабочего набора, масштабировать окно рабочего набора по найденному объекту и сохранить окно в графический файл.

В общем, оно заработало!!!
Честно скажу, что нет информации о тестировании под нагрузкой, но суть не в этом.
Сам процесс увлекает!

среда, 6 ноября 2013 г.

Швейцарский нож для Mapinfo.

Mapinfo имеет в своем распоряжении полный набор средств, для манипуляций с данными. Это и штатные инструменты, это и язык MapBasic, при помощи которого можно расширять функционал практически до бесконечности. Сам язык MapBasic довольно прост. Помимо родной документации вроде "MapBasic xxx UserGuide.pdf", есть книга «Программирование для MapInfo на примерах». Книга свежая, содержит много интересного и полезного, позволяющего начать движение в сторону освоения Mapinfo и MapBasic. Ко всему прочему, в Mapinfo есть крайне полезная, с практической точки зрения, вещь - "окно MapBasic". Когда это окно активно, в нем отображаются команды MapBasic, при помощи которых Mapinfo выполняет те или иные операции, например: открытие таблиц, отображение таблиц в виде карты или списка, команды по оформлению слоев карты и многое другое... Кроме отображения команд, "окно Mapbasic" служит для ввода и выполнения команд со стороны пользователя.

И вроде все хорошо, всего вроде хватает, но в один прекрасный момент появляется необходимость обработать много таблиц или рабочих наборов, и применить к ним однотипные действия. Конечно можно много поработать руками, но иногда приятно поработать головой, и освободить руки для более полезных и интересных дел. Вот так и родилась идея "швейцарского ножа" - инструмента, который поможет выполнять однотипные действия над таблицами Mapinfo и даже рабочими наборами.

Интерфейс "ножа" содержит элемент выбора рабочей папки (Искать в) в которой, с учетом вложенных папок, производится поиск файлов, согласно указанной в поле "файлы" маске.
Для каждого из найденных файлов выполняется "действие".
В качестве выполняемого "действия" над результатами поиска можно использовать произвольный модуль программы MapBasic или набор команд MapBasic


Индикатор в статусной панели отображает количество обработанных файлов.


Как это может быть полезно?
Например:
  • преобразовать кучу таблиц в формат mif/mid
  • обновить данные в полях таблиц(цы) рабочего набора