Последние записи
- TChromium (CEF3), сохранение изображений
- Как в Delphi XE обнулить таймер?
- Изменить цвет шрифта TextBox на форме
- Ресайз PNG без потери прозрачности
- Вывод на печать графического файла
- Взаимодействие через командную строку
- Перенести программу из Delphi в Lazarus
- Определить текущую ОС
- Автоматическая смена языка (раскладки клавиатуры)
- Сравнение языков на массивах. Часть 2
Интенсив по Python: Работа с API и фреймворками 24-26 ИЮНЯ 2022. Знаете Python, но хотите расширить свои навыки?
Slurm подготовили для вас особенный продукт! Оставить заявку по ссылке - https://slurm.club/3MeqNEk
Online-курс Java с оплатой после трудоустройства. Каждый выпускник получает предложение о работе
И зарплату на 30% выше ожидаемой, подробнее на сайте академии, ссылка - ttps://clck.ru/fCrQw
25th
Фев
Близкие контакты третьего вида с Visual Foxpro
Posted by Chas under Журнал, Статьи
Многие наверняка, в свое время, задавались интересным вопросом: «А вот как бы задействовать всю силу применяемой в моем проекте СУБД? Не только стандартные SQL запросы, а и скрытые возможности». Тогда ведь можно будет получать результат наиэффективнейшими методами…
Виталий Белик
by Stilet www.programmersforum.ru
Верно. Не так уж и сложно разработать свой провайдер, по крайней мере для FoxPro. Думаю, что эта СУБД еще имеет широкое применение. А вот как – описано в статье.
Предисловная поболталовка
Ну, что ж. Вот и я дожил до того, что пишу собственную статью. Возможно потому что хочется поделиться наработками или из альтруистических побуждений, или потому что не нашел аналогичных статей (может искал плохо). Но истинный смысл в том, что многие знают и умеют интегрировать свои программы с СУБД обычными путями (непрекословными истинами, прописанными кем-то из аналогичных побуждений), а ведь на них свет клином не сошелся. Очень жаль, что не всегда то, что кажется хорошим – хорошее на самом деле.
Вот и я столкнулся с весьма нетривиальной ситуацией, в которой нужно было разработать программу, хранящую и обрабатывающую данные в какой-нить удобной локальной СУБД. Первое, что пришло в голову* – это воспользоваться стандартным набором ADO, благо Delphi его любит и уважает. А что? Неплохо, методы стандартные, хорошо задокументированные (от BDE, которого изучают в любых универах, отличающиеся мало).
Да никто и не спорит: ADO удобно, можно подключить любую СУБД, проинсталированную на локальном компьютере или подключить провайдера удаленно.
«Что ж, можно попробовать» – подумал я. Но, только я начал набирать программу и базы, как оказалось, что все это до меня уже набрано хитрыми программистами. Базы, коды-расчетчики… Все уже есть, но не в Delphi, а в достаточно популярной ранее СУБД – FoxPro.
«УРА!» – сказал я и попытался почитать «километровый» код программы… Скажу вам, что малоприятно читать чужие писульки, особенно, если они плохо закоментированны…
Основное для себя уяснил – функции, которые мне нужны были оформлялись в виде подпрограмм с четкими названиями, соответствуя своим задачам, дабы их аргументы были предельно понятны, и вызывать их не составляло труда. Но, это можно было сделать только в FoxPro… Так что пришлось мне выбирать: либо писать свои, и терять время, либо как-то заставит самого Фокса выполнять этот код.
Я выбрал второе, поскольку я ленивый и мне никак не хотелось перелопачивать заново всю методику. И вот, что из этого вышло…
Немного теории
Для начала пару слов об ADO. Говоря о компоненте Delphi, ADO позволяет обрабатывать команды классического SQL плюс SQL навороты, которые поддерживает провайдер в командах. Для этого можно использовать: либо ADOQuery, как привычный компонент, либо ADOCOmmand, позволяющий выполнять как отдельные команды, так и целый файл с таковыми.
Однако и в этой ложке меда оказалась своя бочка дегтя. И дело здесь вот в чем. Многим известно, что FoxPro – это одна из первых СУБД, являющаяся на то время весьма революционной. Помимо применения сверхбыстрых (на то время) технологий обработки данных RushMore, она еще и имела мощный язык обработки данных, который, кстати, не очень сильно изменился и по сей день. Его возможности позволяли достаточно гибко работать с данными, написав при этом кода меньше, чем скажем в Клиппере. К тому же, ядро FoxPro было сделано оверлеями – прадедушками нынешней DLL, что само по себе давало неплохую экономию ресурсов и прирост скорости даже на слабеньких машинах 8086.
С переходом под крылышко Микрософтовцев, эта СУБД приобрела полноценный модуль провайдера, и стала доступна как COM система.
«Что ж, гарно» – сказали программисты и… слегка обломались – провайдер настолько урезали, что он уже перестал понимать стандартные команды этой СУБД, кроме тех, что попадают под определение классического SQL (SELECT,DELETE,UPDATE,CREATE,ALTER…).
Но оригинальный язык Фокса был помимо этих команд наполнен массой функций, которые увы оказались запертыми в недрах ядра системы, и могли выполняться лишь программами, написанными в самом FoxPro.
Практически все функции (а их в FoxPro множество) больше не могли работать в ADO. А ведь было бы удобно, тем кто знает эту СУБД как пять своих пальцев, использовать ВСЕ ее возможности в своих программах, написанных на других языках.
Тут я сделаю отступление, ибо может кто-то скажет: «Да ради бога, пусть пишут прям на Фоксе». Однако, тут много минусов. Дело все в том, что прибрав к рукам СУБД Микрософт не особо позаботилась о ее прогрессе, оно и понятно – купил конкурента, чтоб задавить своими продуктами. Поэтому, наверняка именно такими мыслями руководствовались тамошние разработчики, подарив Фоксу весьма корявую среду разработки, совершенно неудобную в пользовании и кучу багов в ядре. Да и обьектная модель ее желает лучшего. Уж лучше бы не трогали вообще, от оконных разработок на Фоксе одни проблемы. Взять хотя бы распространенный баг с закрытием окна – не всегда срабатывает крестик закрытия окна, а иногда просто вешает программу. И смех и грех. Выходили из этой проблемы банально – ставили свою кнопку «Закрыть». Где же тут удобства?
Впрочем, ладно, разговор не об этом… Вернемся к нашим баранам. Поскольку ADO мы отбрасываем, возникает вопрос: «…а что вместо него?». Резонно. Что ж, есть возможность решения этой проблемы. Дело в том, что FoxPro была сделана во времена, когда большой славой пользовались интерпретаторы – программы, пошагово выполняющие код написанный программистом. Каждая строчка программы переводилась в код и сразу же исполнялась, потом интерпретатор повторял этот фокус на следующей строчке. Эта возможность в FoxPro осталась до сих пор, правда FoxPro не совсем интерпретатор, а скоре псевдокомпилятор, а ядро на самом деле работает со скомпилированными байт-кодами (На P-CODE Visual Basiс похоже), но это нам совершенно не важно. Главное, что все-таки источником является именно «писанина» программиста аз есьм, даже одна строчка команды, посланной интерпретатору, будет рассматриваться им как целостная программа, и будет успешно переведена в псевдокод и выполнена.
Причем, строчка эта может быть представленная такими типами как String и Pchar. Уже неплохо. Но как послать интерпретатору строку-команду? Вот мы и подошли к самому главному. Дело в том, что одна из магических возможностей FoxPro – есть инструкция, которая выполняет переданную ей строку-параметр как команду.
На Фоксе это называется макроподстановкой и звучит так:
Где: StrCommand:String, говоря языком Вирта, строка содержащая команду.
При этом интерпретатору все равно, что там будет находиться, если это правильная команда он ее выполнит. С этим можно провести примерно такую аналогию:
«Ну и что такого?» – скажут многие. Чем круче макроподстановка? А те, кто знают FoxPro на пять, ответят – макроподстановка позволяет не только выполнять ВСЕ команды, но и еще возвращать результат, если в качестве команды поступило выражение. То есть:
STORE &d TO StrCommand
return StrCommand && — вернет вычисленное выражениеSyhi-подсветка кода
А вот аналогия в SQL:
К тому же, как по мне, не этично создавать отдельный курсор (курсор в FoxPro – это набор данных, полученный каким-либо образом) ради одного значения. Можно конечно и так, но что будет, если в выражении повстречаются команды, которые заложены в ядре, но неизвестные провайдеру?
Например, команду замены в поле, где содержится имя файла расширения с TIF на JPG в таблице А1:
Query подавится ею. Впрочем, для любителей классики есть менее эффективная команда – UPDATE. Но, если поздороваться так с интерпретатором тет-а-тет, то команда будет выполнена немедля.
А значит, таким образом, можно легко взять старые программы и построчно (или прям целиком программу из файла, указав его имя в SET PROCEDURE TO… после чего, пустив на выполнение процедуру командой DO или, если это функция просто выполнить ее) скармливать их интерпретатору напрямую обходя, или вообще не имея установленного провайдера.
Вот эту идею я взял за основу
Первоначально пришлось почитать литературу по FoxPro. Смысл связи оказался простым: дело все в том, что на FoxPro можно писать компоненты, которые потом с легкостью применять в Delphi, поскольку Микросовтовцы все таки пошли навстречу и снабдили СУБД возможностью компиляции (на сей раз, полноценной) кода в COM Server в виде DLL.. Опа! Собственный интерфейс – вот то, что нужно. И там же можно навертеть все чего пожелаем.
Стратегия
Ну что ж, приступим к разработке стратегии. Нам нужно написать на FoxPro DLL с функциями, которые бы общались напрямую с интерпретатором, передавая ему строку команды, и возвращали бы результат выполнения этой команды. Для передачи строки без возвращения результата напишем процедуру, ибо может понадобиться выполнять такие команды как, скажем: Use или Replace (подобной вышеописанной, из тех, что не возвращают результат или генерируют курсоры). Для получения результата выполненного выражения системой напишем функцию. Потом все это скомпилируем как DLL с COM сервером и зарегистрировав на машине (командой Regsvr32 <Имя DLL> в консоли) вставим в Delphi через команду меню Project->Import type library, где выберем эту DLL. После чего можно будет распоряжаться этими функциями, как методами компонента.
Тактика
Начнем с написания библиотеки. Для этого понадобится Visual Foxpro. Я делал на 8-й версии, но и более ранние тоже подходят.
Запустим Foxpro и в меню File выберем пункт New. В появившемся окошке File Type выберем Project, и нажмем на кнопку New File. Нас попросят написать имя проекта. Имя, допустим, будет TFoxPro. Ок. Появилось окошко с описанием проекта – это шаблон компонента (см. рисунок 1):
Рис. 1. Шаблон компонента
Создадим новый класс, для чего, став на ветку Class Library, кликнем по кнопке New. Появившееся окошко попросит нас написать имя класса и его наследование (см. рисунок 2):
Рис. 2. Создание нового класса
Допустим, имя будет TFoxPro (назвать можно как угодно). Наследовать мы будем пользовательский «чистый» класс, поскольку нам визуальные и контейнерные классы никак не нужны, поэтому в поле Based On выбираем Custom. В поле Store In укажем путь куда сохранится класс. Жмем Ок.
Теперь добавим в него методы. Тем кто знает, как в Delphi писать ActiveX, будет не сложно понять следующие действия, поскольку они схожи. В главном меню Class выбираем New Method. Чтобы меню Class появилось, нужно стать в окно Class Designer созданного класса. В появившемся окошке создаем ему метод. Допустим, назовем его MyProc с видимостью Public. Жмем Add. И так же добавим еще один метод MyFunc (см. рисунок 3):
Рис. 3. Добавляем метод классу
Если на экране есть окно Properties, то можно в нем увидеть как появляются новые методы. Если окошка этого нет, нужно его открыть либо с тулбара, либо контекстным меню по формочке класса (который у нас называется tFoxPro в окне Class Designer) выбрать элемент Properties. Добавив методы, впишем в них код. Сначала в MyProc, для чего в окне Properties найдем строчку с его названием и откроем ее, кликнув дважды. Открывшееся окно редактора всем своим видом пригласит нас писать программку, чем и займемся (см. рисунок 4):
Рис. 4. Создаем наш проект
Текст программы будет весьма простой: подобный тому, что приведен выше. Добавим только команду описания параметра, ибо нам же нужно в метод передавать команду в виде строки, вот и опишем его как строка:
lcrun as String &&- Это указание, что метод примет параметр типа String
&&- Далее на всякий случай, дабы задобрить интерпретатор обрезаем
&&ведущие и закрывающие пробелы. Можно и без этой команды обойтись,
&&но лишняя предусмотрительность не помеха.
lcrun=ALLTRIM(lcrun)
&lcrun &&- И наконец Выполним команду из строкиSyhi-подсветка кода
Здесь: && — означают комментарии (как // в Делфи или Си), так что можно копипастить эти строки полностью.
«Всего-то?» – удивится кто-то. А что тут такого? Все проще простого.Принимаемая строка будет расценена как команда.
Займемся теперь функцией: «…те же яйца, только в профиль». Так же открываем ее код и вписываем вышеприведенный пример, не забыв прикрутить параметр, в который будет передана команда:
LPARAMETERS lcrun as String (см. рисунок 5):
&&в переменную
RETURN mret &&- которую потом возвращаем.Syhi-подсветка кода
Рис. 5. Набор кода
Das Ist Alles – сохраним проект. Теперь дело за малым: скомпилировать библиотеку, но сначала укажем, что методы класса являются OLE видимыми. Для чего в меню Class откроем окно Class Info. Здесь поставим галочку на OLE Public. Если этого не сделать, компилятор не впишет класс в сервер заругавшись строчкой «Cannot build a DLL without OLE Public Class». Непонятно, зачем создатели сделали эту опцию, могли бы сделать так, чтобы компилятор сам проверял необходимость публикации класса, если компилируется COM Server (см. рисунок 6):
Рис. 6. Свойства и публикация класса
После перепрыгиваем в окно Project Manager и кликаем по кнопке Build. В появившемся окне Выберем Multi-threaded COM server DLL и выставим все птички в Options, чтобы перекомпилирование прошло над всеми фалами (Recomile All Files). Если всплывут ошибки, мы их захотим увидеть (Display errors) и пусть перестраивает ID компонента (см. рисунок 7):
Рис. 7. Входим в настройки
Жмем ОК. Итак, как говорил Слепой Пью: «Дело сделано…». Заглянув в папку с проектом можно увидеть, что в нем лежит библиотека <tfoxpro.dll> (учитывая, что я все файлы называл одинаковым именем и сложил в одну папку). Компилятор также любезно предоставил нам библиотеку типов <tfoxpro.tlb>. Остальные файлы принадлежат самому проекту FoxPro. Например: VCX – это тот самый класс, VCT – описание его методов (можно посмотреть в блокноте), тот код, что мы написали. Остальные файлы: версия проекта и описания проектов.
Интеграция
Вот и наступил второй этап. Своего провайлера мы написали. Теперь его нужно зарегистрировать (я рекомендую сделать это программой RegSVR32, расположенной, как правило, в папке “C:\WINDOWS\system32\.”. Далее нужно импортировать библиотеку типов, «превратив» ее в компонент Delphi и кинуть на форму, чтобы пользоваться им как родным.
Приступим
Поместив DLL в какой-нибудь каталог, где она будет жить, зарегистрируем ее (можно даже в System32, но я не рекомендую загаживать его). Если вы используете Total Commander или подобные проводники, то вам проще – стали на тот файл и в командной строке набрали RegSvr32 TFoxPro.DLL. Энтер и Ок. На самом деле это можно сделать и в Delphi при импорте, но я лично сталкивался с непонятными для меня глюками, когда импорт в «компонент» проходит успешно, а регистрации его в реестре нет. Поэтому «чтоб уж наверняка не было ни одного упырька» зарегим дедовским способом. Если библиотека правильно сделана, сообщение об успешной регистрации вылезет на экран. Кстати, если у вас нет regsvr32, не нужно отчаиваться, его аналог можно написать и на Delphi. Эта возможность имеется благодаря наличию в такого рода библиотеках функций DLLRegisterServer, которая регистрирует в реестре Windows свои классы. И соответственно DLLUnregisterServe, которая отменяет регистрацию. Эти функции regsvr32 и вызывает. Для регистрации или ее отмены достаточно просто вызвать эти функции из библы.
В Delphi это выглядит так:
…
begin
DllRegisterServer;
end;
…Syhi-подсветка кода
Соответственно предполагается, что эта программа-регистратор лежит возле DLL. В реестр библиотеку с классом мы поселили, теперь получим компонентик. Для этого откроем окно Import Type Library из меню Project. По крайней мере, так делается в Delphi 6. Если у вас другая версия, то нужно найти соответствующую возможность импорта библиотеки. Предположим нашли. Найдем в списке нашу библиотеку и проинсталлируем ее класс в какой-нибудь package. Выберите сами ему название (см. рисунок 8):
Рис. 8. Интеграция библиотеки
После всего, если вы правильно проинсталлировали пакет, компонент должен появиться на соответствующей вкладке палитры. Теперь можно им пользоваться.
Применение
Для начала создадим таблицу в FoxPro. Да не важно, что там будет. Предположим, список файлов в строковом поле. Назовем таблицу «а1». Допустим, в ней будет поле Filename, где прописаны пути к файлам.
Кинем на форму наш компонент. Дадим ему имя FoxPro. Теперь мы хотим отобразить содержимое этого поля в таблице. «Долой тяжелые и неповоротливые DB компоненты» – скажу я и растяну на форме обычный StringGrid. Его и будем наполнять данными. Программно нам нужно проделать следующее:
- открыть базу;
- получить количество записей функцией RECNO();
- в цикле вписать записи в таблицу.
Все, приступаем. Предположим код этот будет выполняться при создании формы. А можно его описать*** в отдельную функцию:
begin
// Откроем таблицу командой USE
foxpro.MyProc(‘USE "’+ExtractFilePath(paramstr(0))+‘a1.dbf"’);
// Получим количество записей и выставим количество строк в таблице
StringGrid1.RowCount:=foxpro.MyFunc(‘reccount()’)+1;
StringGrid1.ColCount:=2;
// Для красоты можно масштабировать размер колонки
по максимально длинной строке
m:=0;
// Пока не конец текущей таблицы
while foxpro.MyFunc(‘.NOT. EOF()’) do begin
// в соответствующую ячейку записываем из текущей записи поле FILENAME
// обрезая ненужные ведущие и замыкающие пробелы функцией ALLTRIM
StringGrid1.Cells[1,k]:=foxpro.MyFunc(‘alltrim(filename)’);
// Получаем ее порядковый номер
StringGrid1.Cells[0,k]:=foxpro.MyFunc(‘recno()’);
// Переходим на следующую запись
foxpro.MyProc(‘SKIP’);
// Маштабируем колонку авторазмером
if StringGrid1.Canvas.TextWidth(StringGrid1.Cells[1,k])>m then
m:=StringGrid1.Canvas.TextWidth(StringGrid1.Cells[1,k]);
StringGrid1.ColWidths[1]:=m;
end;
end;Syhi-подсветка кода
А в событии OnClose() формы закроем все курсоры командой foxpro.MyProc(‘close all’), дабы не оставлять мусора.
Не очень много кода. Кто-то скажет «А зачем все это, если можно применить DBGrid не написав ни одной строчки кода?». Можно, но работать с DB компонентами в Delphi – сущий мазохизм.
К тому же, в качестве еще одного довода, приведу еще один аргумент:
Растяните на чистой форме DBGrid и ADOQuery. Скомпилируйте и посмотрите размер файла. У меня он равен 758 с копейками килобайт. А теперь скомпильте проект с TFoxPro. 453 с копейками. И это при том, что я в первом проекте ни строчки кода не написал. Убедил? Если нет, попробуйте написать тяжеловесный проект с кучей DB компонентов и посмотрите, что разница будет в десятки раз.
Ну, да ладно. Продолжим. Теперь наша задача – редактирование. Редактировать будем прямо в Гриде, благо тот позволяет это сделать, выставив в свойстве Options флажок goEditing и к нему goAlwaysShowEditor, чтоб не выходить из режима редактирования.
Писать сам код можно в событии OnSetEditText. Тактика будет такова:
- становимся на запись, индекс которой передается в OnSetEditText (здесь очень важно, чтобы количество строк в гриде совпадало с количеством строк в курсоре базы);
- заменяем значение в поле.
Все это делается примерно так:
ARow: Integer; const Value: String);
begin
// Становимся на запись
foxpro.MyProc(‘GO ‘+inttostr(aRow));
// Заменяем значение ее поля новым значением
foxpro.MyProc(‘REPLACE fullname WITH "’+value+‘"’);
end;Syhi-подсветка кода
Как видим, тоже ничего мудренного. И это притом, что DBGrid в паре с Query так просто не позволит провернуть такую операцию – обязательно повыбрыкивается чем-нибудь вроде «DataSet not in edit or insert mode». FoxPro такого не скажет, потому как запись-то открыта по умолчанию и для чтения и для записи, если конечно на этой записи не стоит какой-нибудь другой клиент при многопользовательской работе. Тогда запись блокируется. Но речь сейчас не о многопользовательском сеансе. Плюс к этому (опять я похвалю FoxPro), это правило действует в любых курсорах даже тех, которые были получены классическими SELECT * FROM… или подобными. TQuery без шаманских танцев с бубном над ним подавится такими запросами. Как ни странно, это касается очень многих СУБД с которыми взаимодействует этот компонент, не потому что это плохие СУБД, а потому что сам компонент не рассчитан на такую гибкость. Впрочем, и с ним можно решить такую задачу, но чего это будет стоить… Мигрени точно.
А теперь представим, что проект ведет человек хорошо знающий FoxPro, но хуже знающий Delphi. Естественно ему выгоднее будет основную работу с БД написать командами FoxPro, а на Delphi сделать только интерфейс и выполнение таких команд. Есть два выхода из этой ситуации:
- Написать или взять командные файлы FoxPro (.PRG) и просто в Delphi считывая построчно скармливать их интерпретатору.
- FoxPro имеет возможность выполнять целые файлы, которые содержат код, самостоятельно их читая.
Первый способ неплох, но только в случае линейной программы, без процедур и функций, так как, если бы оператор ручками вводил команды в консоль FoxPro. К тому же механизм выражений теряет свою силу. Поэтому мы возьмемся за второй способ – пакетное выполнение программ и модулей. Для этого в FoxPro предусмотрена команда SET PROCEDURE TO, которая действует примерно по аналогии с Include некоторых языков, ну или, скажем, отдаленно напоминает uses в паскале. В параметрах этой инструкции указывается либо линейная программа, либо модуль с процедурами или функциями.
Выглядит это так
Для начала напишем простенький модуль с расширением PRG. Для этого подойдет обычный блокнот, либо можно писать в среде FoxPro. Допустим, в нем будет две функции. Одна будет глобально менять разрешения файлов в записи, а другая просто искать введенную строку. Вот как он будет выглядеть:
LPARAMETERS s as String
&& Найдем расширение и заменим его на новое во всех записях
&& Тут же можно написать тучу кода чего-то рассчитывающего
replace filename WITH LEFT(filename,RAT(".",filename)-1)+"."+s all
&& Вернем True
RETURN .t.
ENDFUNC
FUNCTION FindName
LPARAMETERS s as String
&& Поищем введенную подстроку в записях и станем на нее если нашли
LOCATE for AT(s,filename)<>0
&& вернем номер найденной строки
RETURN RECNO()
ENDFUNCSyhi-подсветка кода
Теперь откроем этот файлик в FoxPro и скомпилируем его*****. Полученный в результате компиляции FXP псевдокод ложем в папку с программой. В Delphi пишем следующий код. В OnCreate() инициализируем модуль:
foxpro.aproc(‘COMPILE "’+ExtractFilePath(paramstr(0))+‘File1.prg"’);
{Скомпилиный модуль инициализируем}
foxpro.MyProc(‘set procedure to "’+ExtractFilePath(paramstr(0))+‘file1"’);Syhi-подсветка кода
Предполагается, что он называется <File1.prg>. На самом-же деле выполняться будет лежащий рядом FXP. Теперь поместим на форму две кнопки. Одна будет скармливать функцию ReplExtension, другая FindName.
begin
s:=InputBox(‘Введите новое раcширение’,»,»);
foxpro.MyFunc(‘ReplExtension("’+s+‘")’);
FillGrid(StringGrid1);
end;Syhi-подсветка кода
Код второй:
var s:string;
begin
s:=InputBox(‘Введите что искать’,»,»);
StringGrid1.Row:=foxpro.MyFunc(‘findname("’+s+‘")’);
caption:=IntToStr(StringGrid1.Row);
StringGrid1.SetFocus;
end;Syhi-подсветка кода
В первом случае – возвращаемое значение мы не обрабатываем, во втором случае – присваиваем его свойству Грида, отвечающему за позиционирование курсора в Гриде. Опять таки ничего сложного, зато весь управляющий код мы спихнули на совесть FoxPro. А ведь это только пример… Мне довелось повидать расчеты в бухгалтерии, в частности – калькулирование себестоимости, где модули такие насчитывали около 100 строк. Там очень много деталей учитывалось. Удобная схема – не нужно менять EXE-шник. По аналогии с этим есть компонент TStoredProc. Но его возможностей гораздо меньше.
Послевкусие
Вот так вот, други мои. Против лома – нет приема, если нет другого лома. Я не настаиваю на том, что FoxPro круче всех и вся, но умелое применение возможностей этой СУБД извне позволит достичь весьма эффектных результатов достаточно простыми путями. Кто-то скажет: «Да ну… Это нужно ставить на каждую машину FoxPro полностью». Необязательно. Например, достаточно поставить ее на сервер, а в Delphi в свойстве компонента RemoteMachineName указать сервер. Плюс на сервере правильно настроить достут к нему удаленно. Это обычная практика для хорошего администратора. Или есть еще возможность (если ее уже не отменили разработчики), просто проинсталлировать одно ядро (это около 10 DLL’ок) на машину. Подобное мне показывал один фан этой СУБД, и ничего – заработало нормально. Опять таки повторюсь – данная статья описывает однопользовательскую систему. В многопользовательских нужно покрупнее пошаманить, например запретить клиенту вызовы компиляции, чтобы не повесить сервер.
В общем, главное, что нам предоставили выбор: либо править бал заученными до дыр возможностям, либо писать креативы, что тоже не так уж и плохо. Самое главное – учесть требования задачи, ибо может оказаться, что креатив даст большую выгоду, благодаря своей неформальности.
Статья из девятого выпуска журнала «ПРОграммист».
Обсудить на форуме — Близкие контакты третьего вида с Visual Foxpro
Похожие статьи
Купить рекламу на сайте за 1000 руб
пишите сюда - alarforum@yandex.ru
Да и по любым другим вопросам пишите на почту
пеллетные котлы
Пеллетный котел Emtas
Наши форумы по программированию:
- Форум Web программирование (веб)
- Delphi форумы
- Форумы C (Си)
- Форум .NET Frameworks (точка нет фреймворки)
- Форум Java (джава)
- Форум низкоуровневое программирование
- Форум VBA (вба)
- Форум OpenGL
- Форум DirectX
- Форум CAD проектирование
- Форум по операционным системам
- Форум Software (Софт)
- Форум Hardware (Компьютерное железо)