General
Данный тип предназначен для хранения OLE-объектов. Ну, например, в нем можно хранить файл Excel или результат работы MS Graph
Для работы с данными полями есть всего 2 команды
APPEND GENERAL MODIFY GENERAL |
Чтобы очистить поле General от содержимого надо просто дать команду APPEND GENERAL, не указав имени файла.
Причем описание опции LINK в команде APPEND GENERAL вводит в заблуждение в том смысле, что исходный файл будет скопирован в поле General в любом случае. Какие бы опции Вы не использовали.
Т. е. если Вы подумали, что при использовании опции LINK файл не копируется в General-поле, то Вы ошиблись. Вам ни в коем случае не удастся сэкономить дисковое пространство и уменьшить размер файл FPT (в нем хранится содержимое поля General)
А опция LINK в данном случае используется для того, чтобы синхронизировать изменения в оставшейся внешней копии файла и в той его копии, которая находится внутри поля General. Синхронизация происходит в момент открытия поля.
Можете провести простой эксперимент. Создайте в WinWord любой файл, например, test. doc. Теперь сделайте следующее:
CREATE CURSOR test (testGen G) APPEND BLANK APPEND GENERAL testGen FROM "C:\Мои документы\test. doc" LINK MODIFY GENERAL testGen |
Как видите, я задал опцию LINK, чтобы связать содержимое поля General и OLE-объект. Если Вы сделаете теперь изменения в файле "test. doc" открыв его в WinWord, то при очередном открытии этого поля General все изменения тут же в нем и отобразятся. Соответственно, верно и обратное. Изменения сделанные через вызов OLE-объекта в поле General попадут в исходный файл. Без опции LINK эти взаимные изменения не работают.
А теперь удалите файл "test. doc". Просто переместить его или переименовать недостаточно. Каким-то образом поле General найдет его под новым именем и на новом месте. Нужно именно удалить файл.
Открываем поле General и видим наш не существующий файл! Т. е. он таки записан в поле General несмотря на опцию LINK. Хотя модифицировать его уже не получится. При попытке сделать модификацию Вы получите сообщение об ошибке OLE.
Впрочем, в том, что файл OLE-объекта будет записан в поле General, можно убедиться, просто посмотрев размер файла FPT до вставки и после (для этого надо создать не курсор, а именно таблицу). Он увеличится примерно на размер вставляемого файла.
Другая особенность заключается в том, что поле General не предназначена для программной манипуляции с ее содержимым. Предполагается, что всю нужную обработку должен выполнять OLE-объект, а назначение поля General - это просто принять результаты изменения.
Частично проблему манипуляции содержимым решает опция DATA команды APPEND GENERAL, но это опять же не прямое, а опосредованное редактирование. Изменения DATA должен обработать OLE-объект, если он это умеет. Например с ними может работать такое OLE-объект, как MS Graph (для отображения графиков). Пример его использования можете посмотреть в стандартном проекте примеров Solution. pjx, который поставляется вместе с FoxPro (формы OleGraph. scx и Sctock. scx)
Поэтому, если Вы захотите, например, программно сохранить содержимое поля General как отдельный файл, то у Вас просто нет для этого никаких инструментов!
Таким образом, при использовании полей General Вы непомерно "раздуваете" базу данных (очень быстро растет размер файла FPT) данными, которыми Вы практически не можете манипулировать. Можно сказать, "архивом".
В связи с этими особенностями полей типа General я не рекомендовал бы использовать данный тип поля на постоянной основе. Т. е. как поле каких-либо основных таблиц базы данных
Собственно файлы OLE-объектов лучше хранить именно как файлы. В отдельной директории. А если их надо "прокачать" через поле типа General, то лучше создавать временную табличку или курсор непосредственно на момент исполнения приложения. В большинстве случаев хватает курсора, содержащего одну запись и одно единственное поле типа General.
Если Вы, тем не менее, твердо желаете сохранить файлы в базе данных, чтобы их не было на диске, то используйте для их хранения поля типа Memo(binary) примерно так:
CREATE CURSOR test (testMemo M NOCPTRANS) APPEND BLANK APPEND MEMO testMemo FROM "C:\Мои документы\test. doc" OVERWRITE |
А чтобы извлечь файл обратно:
COPY MEMO testMemo TO "C:\Мои документы\test. doc" |
Преимущества хранения файлов в поле типа Memo(binary) именно в том, что ими можно программно манипулировать. Чего нельзя сказать о поле General.
Кроме всего перечисленного не следует забывать, что, по сути, поле General - это особый вид Memo-поля. Соответственно на него распространяются те же особенности модификации, что и на Memo-поле описанные в разделе посвященному Memo. Т. е. требуется периодически давать команду PACK или PACK MEMO для очистки файла FPT от пустого пространства
Поиск дублирующихся записей в таблице
Чтобы показать дублирующиеся записи, можно использовать SQL-запрос показанный ниже. В результате получится курсор содержащий каждую группу дублирующихся записей, показанную один раз и количество повторений в таблице этой записи.
SELECT field1,field2, ;
COUNT(*) AS dups ;
FROM table ;
GROUP BY field1,field2,;
HAVING COUNT(*)>1 ;
INTO CURSOR whatever
Вопрос-ответ: Не работает ехе-шник. При построении ехешника все идет нормально, и если поставить галочку запустить - он работает. Но при запуске приложения из Windows оно мелькает на экране и тут же закрывается, в чем тут дело?
Вопрос
Пока я отлаживал приложение в среде FoxPro - все было нормально, но как только создал EXE (или APP) и запустил его, то:
Окно FoxPro мелькает на экране и тут же закрывается
Ошибка связана с тем, что не была организована точка останова приложения. Т. е. FoxPro пребывает в недоумении в какой момент необходимо остановиться, чтобы подождать реакции пользователя. На этапе отладки такой точкой останова была сама среда FoxPro, но в готовом EXE ее нет.
Стандартным способом организации точки останова является использование команды READ EVENTS.
Как правило, в качестве главного запускающего объекта используется файл PRG и в нем пишется примерно следующий код:
...
* Предварительные настройки среды FoxPro
...
DO MainMenu. mpr
DO FORM MainForm. SCX
READ EVENTS
...
* Операции по завершению приложения FoxPro и возврату среды в исходное состояние
...
В данном случае использовано одновременная загрузка и главного меню в основном окне FoxPro и запуск некой стартовой формы. При этом предполагается, что форма НЕ модальная (WindowType=0-Modeless).
Выполнение данной процедуры будет остановлено на команде READ EVENTS. Что и позволит работать пользователям в готовом EXE.
При подаче в любом месте программы команды CLEAR EVENTS FoxPro автоматически перейдет к выполнению команд, следующих за READ EVENTS, выполнение главной стартовой программы завершится и приложение FoxPro будет закрыто.
Таким образом, для закрытия приложения необходимо:
-) При использовании главного окна FoxPro с главным управляющим меню предусмотреть в этом меню пункт "Выход", в котором и дать команду CLEAR EVENTS
-) Если главное окно FoxPro не используется (например, при работе с формами ShowWindow=2 - As Top-Level Form), то команду CLEAR EVENTS следует дать при закрытии формы. Лучше всего в событии UNLOAD-формы
Вопрос-ответ: У меня вопрос по grid. Мне необходимо выполнить подсветку строк разным цветом для заданных условий. Как это реализовать. И если возможно даже ячеек. Если можно пример.
Динамическое изменение цветов в Grid осуществляется с помощью изменения свойств колонки - DynamicBackColor, DynamicForeColor. Эти свойства задают цвет фона и основной цвет символов объекта Column. Причем цвета на этапе выполнения заново вычисляются при каждом обновлении элемента управления Grid.
Column. DynamicBackColor = cExpression Column. DynamicForeColor = cExpression |
cExpression задает выражение, заключаемое в кавычки, которое на этапе выполнения заново вычисляется при каждом обновлении элемента управления Grid. Результатом такого вычисления должно быть одиночное значение цвета.
Иными словами, если нужно выделить все строки объекта Grid согласно некоторым условиям (назовём его MyCondition), поступаем следующим образом:
Grid. SetAll("DynamicBackColor", "IIF(MyCondition, RGB(255,0,0), RGB(0,0,0))", "Column") |
Для изменения цвета ячейки в конкретной колонке Grid (переменная i задаёт номер колонки):
Grid. Columns(i).dynamicbackcolor = "IIF(MyCondition, RGB(255,0,0), RGB(0,0,0))" |
Условия динамического изменения цвета колонки можно задать как программно, так и непосредствено в дизайнере Grid.
2 других комментария
Если в DynamicBackColor необходимо использовать много различных цветов, то из-за ограницения длины строки в свойство не поместишь вложения "IIF(усл, Rgb(), IIF(усл, Rgb(), ...))". В конце концов строка кончится. Поэтому проще задавать цвет через процедуру, например GRID1.SETALL("DynamicBackColor", "RetColor(NumColor)", "Column"), где RetColor - фунция возращающая цвет, а NumColor - поле таблицы. Сама функция, ну, приблизительно так:<br /> LPARAMETERS tnNumColor<br /> IF VARTYPE(tnNumColor) = "N"<br /> IF tnNumColor > 0<br /> RETURN tnNumColor<br /> ENDIF<br /> ENDIF<br /> RETURN RGB(255,255,255)
Ну и как следующий логический шаг - делать не функцию, а метод объекта грид (для чего создать подкласс грида и везде в формах использовать его или его наследников). А обращаться из свойств Dynamic* к этому методу как This. RetBackColor()
Кроме того стоит отметить, что в контексте вычисления выражения Dynamic* или соответствующего метода, вызываемого из этого выражения, мы можем свободно обращаться к полям теблицы - источника данных грида, и всегда будем получать те значения, которые соответствуют записи, для которой производится определение цвета - т. е. фокс сам "прозрачно" для программиста делает временное перемещение указателя записи на текущую "отрисовываемую" запись.
И ещё - не следует злоупотреблять этим приёмом, ибо он естесвенно замедляет работу интерфейса (скорость перерисовки элементов управления).
Вопрос-ответ: Как прочитать email из программы (outlook) и обработать атачмент.
Надо использовать MAPI
msess=Createobject("MSMAPI. MAPISession")
mmess=Createobject("MSMAPI. MAPIMessages")
msess. DownLoadMail = 0 && Не получать новую почту в начале этой сессии
msess. username="yurez" && Имя и пароль учетной записи
msess. Password="222"
msess. LogonUI=.F. && Не показывать диалог входа. Если имя и пароль
неправильные появиться сам
msess. signon
mmess. sessionid=msess. sessionid
mmess. FetchMsgType=`2`
mmess. MsgIndex=-1
mmess. Fetch && Создается кеш всех сообщений на диске. Уничтожается по окончании сессии
path_rec="полный_путь" && Папка для хранения аттачей
If! Directory(path_rec)
Mkdir (path_rec)
Endif
For x=0 To mmess. msgcount-1 && Общее число писем в inbox
mmess. MsgIndex=x
If! Empty(mmess. AttachmentPathName) And mmess. MsgSubject="transaction" && если есть вложения и тема совпадает - сохраняем все вложения
For Y=0 To mmess. AttachmentCount-1
mmess. AttachmentIndex=Y
Copy File (mmess. AttachmentPathName) To path_rec+"*.*"
Endfor
Endif
Endfor
*!* mmess. send
msess. signoff && заканчивм сессию
RELEASE msess, mmess
Вопрос-ответ: В программе (prg) проекта открываю необходимую базу данных, с указанием пути и имени. После открываю таблицу из этой базы данных. (USE ….) Делаю выборку данных с помощью инструкции (SELECT …) А результат выборки хочу направить в таблицу, находящуюся в данной базе данных (уже открытую) либо в новую таблицу, но обязательно В этой базе данных (DBC). Отсюда вопрос? Как использую инструкцию (SELECT … INTO…), добиться желаемого результата?
Для сохранения результата выборки в новую таблицу в базе данных конструкция запроса должна иметь вид
SELECT... INTO TABLE TableName DATABASE DatabaseName NAME LongTableName |
Если результат запроса необходимо направить в уже существующую таблицу, то выборку нужно осуществить в курсор с последующим добавлением его содержимого в эту таблицу (при этом новые записи будут добавлены к уже существующим в таблице)
SELECT... INTO CURSOR CursorName SELECT ExistTable APPEND FROM DBF('CursorName') |
Вопрос-ответ: Какие библиотеки нужно скопировать в папку с ехе - шником чтобы не запрашивало библиотек fox-са???
Для функционирования скомпилированной программы необходимы следующие библиотеки (звёздочкой заменена цифра - номер версии VFP):
для исполняемого (.exe) файла - vfp*r. dll и vfp*rrus. dll (или англоязычная vfp*renu. dll)
для COM сервера (.dll или. exe) - Vfp*t. dll
библиотека поддержки C++ - msvcr70.dll
начиная с версии VFP8 в системе должен присутствовать файл gdiplus. dll - для поддержки графики
Вопрос-ответ: В контейнере создаю единый Грид, в который прописываю разные базы (до 20 шт, разное количество полей от 1 до 21). Подцепляется хорошо, могу просмотреть. Теперь хочу навесит на "колонку. текст. двойной_клик" процедурку отбора данного поля базы, но не могу сообразить, каким образом это проще сделать. Подскажите. пожалуйста!
Задача может быть решена следующим образом.
Необходимо создать класс объекта textbox с желаемой реакцией на двойное нажатие. Это можно сделать как визуально в собственной библиотеке классов, так и программно, поместив код в общий программный модуль:
DEFINE CLASS myTextBox AS TextBox PROCEDURE DblClick && Определяем реакцию на двойное нажатие ... ENDPROC ENDDEFINE |
При программном определение свойств объекта grid заменяем textbox на определённый выше:
LOCAL i FOR i=1 TO ThisForm. GridObj. ColumnCount ThisForm. GridObj. Columns(i).RemoveObject('Text1') ThisForm. GridObj. Columns(i).AddObject('Text1', 'myTextBox') ThisForm. GridObj. Columns(i).Text1.Visible=.T. ENDFOR |
Другой комментарий.
Однако такой подход ограничивает возможности по определению разных действий для обработчика события.
Преодолеть это можно несколькими способами:
1) создание не одного а множества классов текстбоксов, и соответственно замена стандартного текстбокса на один из этого множества.
2) прописывание в обработчике события DblClick (а в идеале - вообще во всех обработчиках событий) кода наподобие This. Parent. Parent. MyEventHandler(This, "DblClick") - таким образом реальные действия будут делегированы методу самого грида, и этот метод будет иметь всю необходимую информацию для полноценной обработки любого события.
3) Аналогично п.2 (делегировать обработку события методу грида, или контейнера или вообще формы), но используя возможности "позднего связывания" добавленные в VFP8 см. функции BINDEVENT(), AEVENTS()
Вопрос-ответ: Не запускается ехешник. В гл. модуле есть read events в каталоге необходимые dll, но при запуске ничего не происходит. Даже фоксовское окно не мелькает. Программа просто сидит в памяти.
Вероятно приложение построено на главном окне VFP, а в файле config. fpw есть строка
screen=off |
Таким образом приложение запускается и выполняется (об этом свидетельствует наличие его в памяти), но не
отображается на экране.
Для устранения проблемы необходимо исключить эту строку из файла config. fpw
Вопрос-ответ: Помогите пожалуйста начинающему программисту!!! Имеется Excel-файл с заданной структурой. Задача: Из VFP открыть этот файл записать в нужные ячейки информацию, показать заполненный Excel-файл пользователю.
Самый общий пример :
LOCAL lcNameFile, oExcel
lcNameFile=GETFILE('XLS','Открыть файл :')
IF! EMPTY(lcNameFile)
oExcel=CREATEOBJECT('Excel. application')
oExcel. Workbooks. Open(lcNameFile)
oExcel. Range("A1").value='Моё значение'
oExcel. Range("A2").value=777
oExcel. Range("A:A").NumberFormat = "0.000"
oExcel. ActiveWorkbook. Save()
ENDIF
IF TYPE('oExcel')="O"
oExcel. Application. Visible=.t.
ENDIF
Вопрос-ответ: Помогите пожалуйсто в таком вопросе, можно ли и как в объекте Grid полю назначить свойство combo? Спасибо!
Пусть имеется адресный реестр
address = (addressid i, streetid i, house c(10), block(10))
street = (streetid i, name c(50))
Необходимо отобразить Grid с улицей, домом и корпусом, причем для выбора улицы использовать ComboBox, учитывая известный баг.
Для этого необходимо:
1) Создать Grid с тремя колонками, назначив каждой соответствующий ControlSource: streetid, house, block. Как правило это делается путем перетаскивания таблицы address из среды данных на поле формы - в этом случае grid будет отображать все столбцы, лишние можно удалить. Другой способ, выделить в таблице address только требуемые столбы и начать перетаскивать нажав предварительно правую кнопку мыши, тогда при отпускании мыши на поле формы VFP уточнит Ваши намерения и Вы ответите ему, что хотите создать Grid. Третий способ - можно все это сделать в ручную, но об этом в другой раз.
2) Поместить в первую колонку ComboBox (выделить столбец grid-a, на панели Form Controls нажмите ComboBox, подведите курсор к столбу и нажмите левую кнопку мыши) настроив его в редакторе свойств следующим образом
.RecordSource = 'select name, str(streetid) from street order by 1 into cursor tstreet nofilter'
.RecordSourceType = 3 && SQL Statement.
.BoundColumn = 2
.Style = 2 && Drop-down List
.BoundTo = .t.
3) Далее в колонке с только что добавленным ComboBox выбираем в качестве CurrentControl - Combo1 (если не меняли умолчания) и требуем отображать ComboBox на каждой строке - Sparse = .f.
На этом создание нашего Grid-a окончено
Вопрос-ответ: Как визуализировать древовидную структуру в фоксе?
Используй для этого стандартный объект Microsoft TreeView Control. В дизайнере форм выбери ActveX Control (OleControl) [следующая кнопка за Page Frame в панели Form Controls] ... в появившемся списке найди Microsoft TreeView Control и выбери его. Для того, чтобы ты мог использовать пиктограммы, для листьев дерева (папки, значки...) в эту форму вставь таким же способом объект Microsoft ImageList Control - он в себе будет содержать твои bmp или ico-файлы.
Вопрос-ответ: Какими командами организовать переход при нажатии кнопки на одной вкладке на другую вклаку в форме? Подскажите пожалуйста.
Thisform. PageFrame1.Activepage=[номер вкладки
Вопрос-ответ: Возникла проблема поиска по маске, например в поле фамилия произвести поиск что-нить типа 'си***ов', в ответ должен получить - 'Сидоров', 'Сикоров' и т. д. Каким образом лучше решить эту проблему?
Такой поиск можно выполнить используя функцию LIKE()
и маску "?".
LOCATE FOR LIKE('си???ов',ALLTRIM(second_name))
Вопрос-ответ: В программе на Delphi форма содержит окно (типа нашего editbox) в котором показывается html текст как в internet browser. Как это сделать в vfp6 ? (именно не в окне IE, а в форме, как например rich текст показывается через ActivX)
Вчера задал этот вопрос, сегодня сам нашел ответ, может еще кому-то пригодится. Поставил Delphi5, после этого в списке ActiveX vfp6 меню Tools/Options/Control появился Microsoft Web Browser, создал класс на базе контейнера, вставил туда этот ActiveX, в его метод Refresh:
LPARAMETERS url
IF. NOT. EMPTY(url)
this. Navigate(url) (чисто методом втыка)
ENDIF
и еще в медот Error записал RETURN (иначе выдается какая-то неопознанная ошибка. В init - установка размеров по размерам контейнера на форме. В форме с этим классом делаю
thisform. Web. Refresh("путь к файлу html или url") и все.
(Web - имя класса с activeX oleweb). Работает и на компьютерах без Delphi. *****@***diit.
Вопрос-ответ: Как сделать круглую кнопку!!!
В VFP все элементы управления рисуются самим VFP в окне формы. В связи с этим управлять ими при помощи API нет ни какой возможности. Добиться желаемого можно либо при помощи ActiveX или нарисовав элемент управления самостоятельно
Вопрос-ответ: Подскажите пожалуйста как можно сохранить в файл рисунок хранящийся в поле General? Спасибо.
Есть в решениях
http://www. *****/sol/index. php? act=view&id=359
Однако по возможности, следует избегать использованть поля типа General для хранения информации. Недостатков больше, чем достоинств. Лучше хранить картинки именно как отдельные файлы.
Вопрос-ответ: Подскажите пожалуйста, Как в запросе программно отправить отобранные данные в отчёт. Заранее спасибо.
Я делаю так:
select... into cursor
select
REPORT FORM NOEJECT NOCONSOLE [TO PRINTER PREVIEW]
А в отчете в качестве источника данных указываю
А уж откуда это все запускать - кнопкой, там, или еще как, это уж дело хозяйское.
Вопрос-ответ: Вопрос начинающего программиста на FoxPro. Как одновременно открыть одну и ту же таблицу в разных формах (одна форма вызывается из другой)? В вызываемой форме Private Data Session.
В разных формах с private data session открытие одной и той же таблицы не приводит к каким либо ошибкам или конфликтам, если конечно таблица не открывается в режиме exclusive. Private data session для того и призваны служить, чтобы облегчить работу, создавая независимсоть рабочих областей в формах.
Вопрос-ответ: Как управлять системным окном в приложении?
Системное окно имеет теже свойства, что и форма. Обращение к нему производиться через сиcтемную переменную памяти _SCREEN.
Например,
_SCREEN. Width = 300 && Ширина окна
_SCREEN. Height = 300 && Высота окна
_SCREEN. BackColor = RGB(255,255,255) && Цвет фона окна
и т. д.
Используя в качестве RowSourceType = 6 - Fields я делаю SET FILTER для этой таблицы, когда в других ComboBox делаю уточнения типа: факультет, курс, группа.
Если в качестве источника выбрать SELECT..., то как на него наложить SET FILTER при выборе в других ComboBox-ах? Возникает ошибка.
Вроде простая идея, а не работает. Может есть другое решение?
Обычно я делаю так:
RowSource='select.... into cursor mRes'
RowSourceType=3
ColumnCount=1
Не могу выйти из FoxPro. Закрыть приложение. Либо появляется сообщение "Cann't quit Visual FoxPro", либо приложение продолжает висеть в окне задач, хотя на экране ничего не видно
Необходимо чтобы программист и пользователь все делали "как положено".
Если приложение FoxPro было закрыто, но тем не менее осталось висеть в списке задач (Task Manager открывающийся по Ctrl+Alt+Del), то это значит, что программист не дал команды CLEAR EVENTS.
Сообщение же "Cann't quit Visual FoxPro" появляется при попытке закрыть приложение нажав на крестик в правом верхнем углу основного окна FoxPro или нажав кнопку "End Task" в Task Manager.
Для перехвата этого события в FoxPro предусмотрена настройка ON SHUTDOWN. Т. е. в главной стартовой программе получается примерно такой код:
...
* Предварительные настройки среды FoxPro
* И настройка не штатного выхода из программы
ON SHUTDOWN Do ExitProg
...
DO MainMenu. mpr
DO FORM MainForm. SCX
READ EVENTS
...
* Операции по завершению приложения FoxPro и возврату среды в исходное состояние
* И сброс настройки по не штатному выходу из программы
ON SHUTDOWN
...
PROCEDURE ExitProg
IF MessageBox('Вы действительно хотите закрыть приложение?',4+32+256,'Закрытие приложения')=7
RETURN
ENDIF
...
* Действия по корректному закрытию всех открытых форм
* и откату незавершенных изменений в базе данных
...
CLEAR EVENTS
RETURN
При попытке изменить данные в рабочих таблицах появляется сообщение "Cursor is read-only"
Этот вопрос напрямую не связан с первыми двумя. Причин данной ошибки может быть несколько.
а) Наиболее вероятная причина этой ошибки заключается в том, что Вы включили таблицу DBF внутрь EXE.
Чтобы убедится в этом откройте окно вашего проекта и найдите нужную таблицу. Слева от имени таблицы должен стоять значек перечеркнутого кружочка. Если это не так, то щелкните правой кнопкой мыши по имени таблицы и в появившемся меню выберите пункт "Exclude". После этого перекомпилите проект (заново постройте EXE).
Включение какого-либо файла внутрь EXE осущетсвляется аналогично. Правой кнопкой мыши по имени и в открывшемся меню выбрать пункт "Include".
Надо понимать, что включение какого-либо файла внутрь EXE означает, что этот файл становится частью EXE и его модификация недопустима. Это можно использовать как примитивный способ защиты своих данных, если эти данные предоставляются только на чтение.
Соотсветсвенно, файл включенный внутрь EXE не надо поставлять клиенту (он и так находится внутри EXE).
б) Еще одной причиной подобной ошибки может являтся перенос базы данных клиенту на лазерном диске. Дело в том, что в момент записи на лазерный диск всем файлам автоматически устанавливают признак Read-Only. Соответсвенно после копирования на жесткий диск к клиенту этот признак необходимо снять.
Правой кнопкой мыши в "Проводнике" (Explorer-Windows) на имени файла, в появившемся меню выбрать пункт "Свойства" (Properties) и снять птичку "Только чтение" ("Read-Only"). Если предварительно выделить несколько файлов, то свойства будут распространены на все выделенные файлы.
в) Более экзотическая причина - это настройка прав доступа пользователей. Возможно папка в которой расположены файлы DBF администратором была выдана в общее пользование со статусом Read-Only. В этом случае необходимо обратится к администратору с просьбой изменить права доступа.
Получение первого дня недели месяца:
Используется функция DoW...
first_day=DoW(PDInputDate + 1 - Day(PDInputDate))
PDInputDate - передаваемая дата ( например date() или ctod('01.01.2000') )
Возвращаемое значение first_day может принимать следующие значения:
1- воскресенье
2- понедельник
3-вторник
4-среда
5-четверг
6-пятница
7-суббота
Такая неделя принята в США и отличается от нашей.
Получение количества дней в месяце:
num_days=Day(GoMonth(PDInput, 1) - Day(GoMonth(PDInput, 1)))
PDInput - передаваемая дата ( например date() или ctod('01.01.2000') )
num_days - количество дней в месяце
Получение количества дней в году:
PDInput_tmp = GoMonth(PDInput, 2 - Month(PDInput))
num_days=337 + Day(GoMonth(PDInput_tmp, 1) - Day(GoMonth(PDInput_tmp, 1)))
PDInput - передаваемая дата ( например date() или ctod('01.01.2000') )
num_days - количество дней в месяце
*****
client/server technologies
Перезагрузка данных из разных каталогов
Если Вам приходится часто перегружать в программе данные из разных каталогов и Вы еще не решили как это сделать то данный код для Вас. Для работы необходимо вставить код, в DataEnvironment. BeforeOpenTable и перед этим создать глобальную переменную "Рабочий_каталог", со слешем на конце в которой прописать путь к данным, например:
C:\MyProga\Data\1999\
После этого при открытии таблиц в DataEnvironment данные будут браться из указанного выше каталога. Для перезагрузки данных не надо закрывать форму. Достаточно сделать следующие действия.
ThisForm. DataEnvironment. CloseTables
Рабочий_Каталог= 'C:\MyProga\Data\2000\'
ThisForm. DataEnvironment. OpenTables
**** Код процедуры перезагрузки
AMEMBERS(la_Cursors, ThisForm. DataEnvironment,2)
WITH ThisForm. DataEnvironment
FOR ln_Cot=1 TO ALEN(la_Cursors,1)
lc_Cursor=la_Cursors(ln_Cot)
IF.&lc_Cursor..BaseClass = 'Cursor'
IF NOT '\' $ .&lc_Cursor..CursorSource lc_Table=SUBSTR(.&lc_Cursor..DataBase, RAT('\',.&lc_Cursor..DataBase)+1,;
LEN(.&lc_Cursor..DataBase)-RAT('\',.&lc_Cursor..DataBase)) .&lc_Cursor..DataBase=РАБОЧИЙ_КАТАЛОГ+lc_Table
ELSE
lc_Table=SUBSTR(.&lc_Cursor..CursorSource, RAT('\',.&lc_Cursor..CursorSource)+1,; LEN(.&lc_Cursor..CursorSource)-RAT('\',.&lc_Cursor..CursorSource)) .&lc_Cursor..CursorSource=РАБОЧИЙ_КАТАЛОГ+lc_Table
ENDIF
ENDIF
ENDFOR
ENDWITH
Советы и рекомендации
FoxPro - это язык, который очень снисходительно относится к ошибкам программиста: не дали определения переменной - ничего, я сам определю; забыли указать рабочую область - ничего, я сам попытаюсь ее найти. И так во многих случаях, если Вы забыли что-то указать FoxPro самостоятельно попытается это что-то найти.
С одной стороны, это конечно хорошо и облегчает жизнь програмисту, но вот с другой при создании достаточно крупных проектов в результате такой "самодеятельности" со стороны FoxPro могут возникать ошибки, которые очень трудно отловить.
Самая распространенная ошибка - это самоопределение переменных. Если Вы не дали определение переменной в процедуре, то сначала FoxPro попытается найти одноименную переменную определенную в другой процедуре и доступную в данной и если такая переменная существует, то она и будет использована к полному недоумению программиста вовсе не ожидающего такой "подлости"
Со стороны разработчиков FoxPro уже явно наметилась тенденция к ужесточению синтаксиса. Оно и понятно, такие языки программирования и создавать легче, да и библиотеки поддержки будут иметь меньший объем. Но пока это только тенденция, посмотрим, что будет дальше.
С другой стороны, конечно просто замечательно, что FoxPro предоставляет возможность решить одну и ту же проблему несколькими способами, но если в каждом конкретном случае размышлять на тему "что лучше использовать", то Вы никогда не закончите ни одного приложения.
В результате, появились некоторые правила и рекомендации по программированию, которые ни в коем случае не являются абсолютно необходимыми по принципу "делай так и ника иначе". Вы можете нарушить их абсолютно все и тем не менее написать работоспособное приложение. Цель этих рекомендаций - это уменьшить вероятность появления ошибок и облегчить как собственно написание, так и последующее исправление программ
Расположение файлов проекта
По большому счету, проект - это набор файлов. Возникает вопрос - где и как их расположить? Если у Вас он не возникает, то Вы или очень опытны (это же очевидно!), или наоборот очень неопытны (а разве это важно?).
Главным правилом в данном случае выступает разделение рабочих (модифицируемых) файлов и исполняемых (не модифицируемых). Имеется в виду прежде всего их физическое (по разным директориям) разделение.
Причина такого "неравноправия" прежде всего в том, что есть серьезные опасения в порче исполняемых файлов. Пусть случайное и непреднамеренное. Но если рабочие и исполняемые файлы лежат в одной директории, то очень легко ошибиться с выбором и модифицировать не тот файл. В результате - FoxPro или начнет работать с ошибками или вообще перестанет работать.
Другой причиной является возможность быстрого копирования рабочих файлов. Если они расположены компактно в одной директории, то Вы не задумываясь просто копируете эту директорию со всем содержимым и не надо мучительно выискивать, что надо копировать, а что лишнее.
Необходимость копирования объясняется как минимум необходимостью создания резервных копий всех рабочих файлов (есть и другие причины). По самой своей сути программирование - это модификация файлов. А файл можно "модифицировать" так, что мало не покажется. После чего остается только полностью удалить эту "модификацию" и начать все заново. Хорошо, если у Вас есть резервная копия, тогда Вы начнете не с нуля. А если нет?
Еще одной немаловажной причиной хранения файлов проекта отдельно от файлов FoxPro является удобство поиска нужных рабочих файлов. Если они свалены в одну "кучу" с рабочими файлами FoxPro, то становится очень тяжело найти нужный файл.
Итак, файлы Вашего проекта не следует хранить в той директории, где установлен собственно FoxPro. Следовательно, необходимо создать отдельную директорию для Ваших проектов.
Нежелательно в именах директорий, где расположен Ваш проект использовать пробелы и русские буквы. Пробелы приведут к некторому усложнению программирования (необходимы будут дополнительные кавычки во всех путях доступа). А русские буквы нежелательны потому, что FoxPro разрабатывалось прежде всего для англоязычных пользователей и все прочие языки - это уже "надстройка". Причем зачастую эта "надстройка" весьма кривовата. Никогда не знаешь где тебе аукнутся русские буквы.
В идеале, хорошо бы давать имена директорий в DOS-формате (т. е. до 8 символов), но это уже перестраховка. Уместитесь в 8 символов - хорошо, нет - ничего страшного.
Расположение файлов внутри проекта
Следующий вопрос - это вопрос расположения уже файлов самого проекта. Опять же крайне нежелательно сваливать все файлы в одну директорию. Причины здесь те же - риск порчи, необходимость резервного копирования, сложность поиска. Но уже внутри Вашего проекта.
Прежде всего, обязательно следует выделить отдельную директорию для хранения базы данных. Как правило, эту поддиректорию так и называют "DATA". В этой директории хранится как файл контейнера базы данных (DBC, DCT, DCX), так и файлы собственно таблиц (DBF, FPT, CDX)
Прочие файлы также следует "раскидать" по поддиректориям, но тут уже возможны варианты.
В примерах от MicroSoft рекомендуется хранить файлы по их типам: формы в директории Forms, классы в директории Class и т. п. Однако я предпочитаю хранить файлы по их логическому назначению: главные файлы программы в директории Main, файлы для работы со справочниками в директории SPR, файлы для работы с документами в директории Document и т. п. Какой вариант примете Вы - не так важно. Главное, чтобы у Вас файлы были "раскиданы" по нескольким директориям
Итак, в результате у Вас получится примерно следующая структура каталога Вашего проекта
C:\ProjVFP C:\ProjVFP\MainProj C:\ProjVFP\MainProj\Class C:\ProjVFP\MainProj\Data C:\ProjVFP\MainProj\Forms C:\ProjVFP\MainProj\Prg |
Здесь каталог C:\ProjVFP - предназначен для хранения многих проектов, которые Вы без сомнения еще напишите. А собственно уже конкретно Ваш проект расположен в директории C:\ProjVFP\MainProj
Содержимое главной директории проекта
Ну хорошо, раскидали мы файлы по разным поддиректориям, а что же остается внутри главной директории проекта?
А вот внутри главной директории остается, во-первых, собственно файл проекта (файлы с расширением PJX, PJT), во-вторых, обязательно файл конфигурации CONFIG. FPW (это обычный текстовый файл, о нем чуть ниже) и в-третьх, файлы ресурсов FoxUser. DBF и FoxUser. FPT Прочие файлы уже по мере необходимости в конкретном проекте, но как правило, больше ничего здесь храниться не должно.
Вполне естесственное желание, назвать файл проекта тем же имененем, что и директория в которой он расположен, поскольку собственно ради него все это и затевается. Именно так и следует поступить - назвать файл проекта MainProj. pjx (и MainProj. pjt)
Файл ресурсов FoxUser. dbf и FoxUser. fpt можно и не создавать специально, а только сделать специальную запись в файле конфигурации (в этом случае он будет создан автоматически).
Зачем вообще надо тащить этот файл ресурсов в директорию проекта? Дело в том, что файл ресурсов хранит в себе координаты и положения всех когда-либо открываемых окон в среде FoxPro. Это значит, что в случае использования одного и того же файла ресурсов для всех проектов это файл "раздуется" до неимоверных размеров. А ведь в случае копирования проекта домой, желательно захватить с собой и файл ресурсов, чтобы "картинка не сбилась". Удобнее это сделать, если файл ресурсов физически расположен в той же директории, где и сам проект, а не искать его в директории FoxPro.
Определить какой именно файл ресурсов используется и где он находится можно с помощью функции SYS(2005)
Файл конфигурации CONFIG. FPW
Теперь важнейший вопрос о файле конфигурации CONFIG. FPW. Это обычный текстовый файл и о нем почему-то крайне редко упоминается в книгах о FoxPro. Этот файл необходимо создать самостоятельно. Автоматически он не создается.
Как правило, используют 2 файла конфигурации - один на этапе создания и отладки проекта и другой - на этапе исполнения собственно готового EXE у клиента. Тот файл конфигурации, который поставляется клиенту можно включить внутрь EXE, но лучше этого не делать. В этом случае он позволяет производить некоторую внешнюю настройку среды FoxPro даже в готовом EXE.
Итак, что же должно быть в том файле конфигурации, который используется на этапе создания и изменения проекта. Вот его примерное содержание
CODEPAGE=1251 RESOURCE=FoxUser. dbf TITLE=Мой новый проект PATH=Data, Forms, Class, Prg COMMAND=MODIFY PROJECT MainProj. pjx |
CODEPAGE - эта строка должна быть обязательно, если Вы работаете с данными на русском языке. Если этой строки не указать, то может не произойти автоматическая трансляция символов русского языка и вместо них будут отображены какие-то закорючки.
RESOURCE - эта опция говорит о том, что в качестве ресурсного файла выступает файл FoxUser. dbf расположенный в директории по умолчанию. Если такого файла там нет, то он будет создан автоматически. В принципе, Вы можете указать абсолютно любое имя для ресурсного файла, но лучше придерживаться принятого стандарта, чтобы не запутаться.
TITLE - эта опция задает текст заголовка главного окна FoxPro вместо стандартного "Microsoft Visual FoxPro". Заключать текст заголовка в кавычки не надо.
PATH - еще одна очень важная настройка. Она говорит FoxPro о том, где следует искать файлы (в каких директориях) относительно текущей директории. В качестве разделителя можно указывать как просто запятую, так и символ точки с запятой. Подробнее о путях доступа чуть ниже.
COMMAND - эта опция задает команду, которую необходимо выполнить в момент открытия среды FoxPro. К сожалению, нельзя указать несколько опций COMMAND. Из них будет выполнена только одна. Но если Вам необходимо выполнить несколько команд при открытии среды FoxPro, то напишите их все в специальном файле PRG и опция будет выглядеть например так:
COMMAND=DO Start. prg |
По умолчанию, FoxPro "запоминает" последний открытый проект и пытается его открыть при каждом открытии среды FoxPro. Это удобно, когда Вы работает с одим проектом, но при работе с несколькими проектами это раздражает. Отключить режим автоматического открытия последнего открытого проекта можно в среде FoxPro: Пункт главного меню Tools -> Options -> закладка View -> Снять "птичку" в пункте "Open last project on startup" и сохранить настройки по кнопке "Set As Default". А для открытия "нужного" проекта при открытии FoxPro как раз и используется опция COMMAND в файле конфигурации.
В файле конфигурации можно сделать еще много различных настроек, но в большинстве случаев это не нужно. Например, большинство команд SET по умолчанию настроены как раз таким образом, который помогает отлаживать проект. Т. е. делать их перенастройку в файле конфигурации просто не имеет смысла.
Следует иметь в виду, что файл конфигурации используется только один раз при запуске среды FoxPro. Поэтому, если Вы внесли изменения в файл конфигурации, то они вступят в силу только после перезагрузки среды FoxPro.
Как открыть проект
Обратите внимание, что я не указал в файле конфигурации директории по умолчанию. В принципе, это можно сделать используя опцию DEFAULT примерно так:
DEFAULT=C:\ProjVFP\MainProj |
Однако есть способ лучше. Для открытия проекта создайте ярлык на рабочем столе со следующими реквизитами (у меня VFP6, поэтому пути соответствующие)
Командная строка
"C:\Program Files\Microsoft Visual Studio\Vfp98\VFP6.EXE" - T -C"C:\ProjVFP\MainProj\config. fpw"
Директория по умолчанию "C:\ProjVFP\MainProj"
Ключи запуска можно записать вместе как "-TC". Ключ "-T" говорит о том, что при запуске среды FoxPro не надо отображать заставку-логотип, а ключ "-C" говорит о том, что следом за ним указан полный путь доступа вместе с именем файла конфигурации, который следует использовать при запуске среды FoxPro. Строго говоря здесь можно указать абсолютно любое имя файла конфигурации, но лучше придерживаться принятого стандарта, чтобы не запутаться. В следующей строке Вы указываете и собственно директорию по умолчанию, которой и является та директория в которой расположен Ваш файл проекта.
Если Вы работаете с несколькими проектами, то создайте отдельные ярлыки для каждого проекта и отдельные файлы конфигурации. А сами ярлыки поместите в отдельную папочку на рабочем столе.
Пути доступа к файлам проекта
Итак, если Вы последовали всем приведенным выше рекомендациям, то у Вас должно получится следующее: При запуске среды FoxPro в качестве директории по умолчанию устанавливается директория, где расположен сам файл проекта, а все прочие файлы проекта располагаются в поддиректориях.
Как же в этом случае обратится к рабочим файлам проекта?
Если Вы указали опцию PATH в файле конфигурации, то обращаетесь так, как-будто все файлы проекта лежат в текущей директории, например:
USE MyTable. dbf DO FORM MyForm. scx |
Несмотря на то, что физически таблица MyTable. dbf находится в папке "DATA", а файл формы MyForm. scx в папке "Forms" FoxPro тем не менее найдет и запустит нужные файлы, поскольку путь доступа к ним был прописан в опции PATH в файле конфигурации.
Использование путей доступа в настройках файла конфигурации (или же программно в стартовом файле проекта) позволяет в простых случаях легко переносить проект из одной директории в другую. То же самое можно сказать и о данных. Вы спокойно включаете таблицы в DataEnvironment форм и отчетов не заботясь о том, что у клиента эти таблицы физически будут расположены в других директориях. Они все-равно будут найдены, если задан путь доступа к ним.
Разумеется, есть ситуации, когда простого указания путей доступа оказывается недостаточно. Например, когда Вы одновременно работаете с несколькими одноименными таблицами принадлежащими разным базам данных. В таких случаях используются различные приемы принудительного указания абсолютных путей доступа (здесь я их рассматривать не буду). Но в большинстве случаев использование настройки PATH оказывается вполне достаточным.
Следование изложенным здесь рекомендациям позволит облегчить процесс поиска и использования отдельных файлов проекта не только на этапе создания и изменения проекта, но и при распростарнении готовых проектов клиентам.
Кроме того, облегчается процесс создания резервных копий (да и просто копирования) файлов Вашего проекта. А также снижается вероятность порчи рабочих файлов собственно FoxPro.
База данных
По большому счету, под термином "база данных" понимают совокупность всех данных, а также наложенных на них правил и ограничений, обеспечивающих целостность и непротиворечивость этих даных. Иногда его действительно употребляют именно в этом смысле, однако чаще всего в FoxPro этот термин понимается в более узком смысле
База данных - это файл с расширением DBC, а также связанные с ним файлы с тем же именем, но с расширениями DCX и DCT
Более правильно было бы применять термин "контейнер базы данных". Подозреваю, что от него и произошло название расширения (первые буквы в английском DataBase Container). Однако в связи с привычкой американцев все сокращать слово "контейнер" как-то затерялось.
В версиях FoxPro 2.x под термином "база данных" понимали то, что сейчас понимают под термином "таблица", просто потому, что в этих версих еще не было файла DBC. Из-за чего часто возникают недоразумения и недопонимания.
По своей сути, файл DBC - это обычный файл DBF, только с измененным расширением (как и большинство других файлов используемых в FoxPro). Соответсвенно DCT - это файл мемо-полей (переименованный FPT), а DCX - это структурный индексный файл (переименованный CDX). Отличие от простого файла DBF заключается только в содержимом 28 байта заголовка (считая что первый байт имеет порядковый номер 0). В файле базы данных в этом байте заполнен 3 бит (чего нет в DBF-файлах). Т. е. ASCII код записанного там символа не менее 4 (обычно 7), в то время, как у DBF-файлов его содержимое наоборот не превышает 3.
Поскольку файл базы данных - это обычный файл DBF, то Вы можете открыть его как таблицу и просмотреть содержимое.
USE MyBase. dbc AGAIN |
Указывать расширение файла, как и опцию AGAIN в этом случае обязательно. Без указания расширения FoxPro посчитает, что его расширение DBF и ошибется. А опция AGAIN нужна потому, что файл базы данных может быть уже открыт командой OPEN DATABASE и без этой опции Вы также получите сообщение об ошибке
Зачастую, открытие файла базы данных как таблицы в более ранних версих FoxPro был единственной возможностью быстро получить нужную информацию. Например, какие таблицы базы данных имеют поле с заранее известным именем "MyField"? Для ответа на этот вопрос строим SQL запрос примерно следующего содержания
SELECT a. ObjectName ; FROM MyBase. dbc a ; INNER JOIN MyBase. dbc b ON a. ObjectID=b. ParentID ; WHERE a. ObjectType='Table' and b. ObjectType='Field' and ; b. ObjectName=PADR(LOWER('MyField'),128) |
Но я бы не рекомендовал пользоваться такими "хакерскими" трюками и использовать штатные функции для работы с файлом базы данных INDBC(), DBGetProp(), ADBObjects() и тому подобное, поскольку в этом случае слишком велик риск непреднамеренной порчи файла базы данных.
Название файла базы данных
Файл базы данных, как и любой другой файл в системе Windows может содержать до 128 символов, содержать пробелы, русские символы, цифры и некоторые спец. символы. Однако для упрощения работы в FoxPro я бы порекомендовал следующие ограничения в наименовании файла базы данных
· Не использовать в названии русские символы - причина этой рекомендации в том, что FoxPro разрабатывался прежде всего для англоязычных пользователей и использование в нем символов другого языка - это уже последующее дополнение. Как следствие, велик риск, что чего-то, где-то недосмотрели и при определенных ситуациях русские буквы в имени вызовут неожиданные глюки
· Не использовать в названии пробелы - в принципе, ошибок использование пробелов не вызовет, но несколько усложнит сам процесс программирования, поскольку имена и пути доступа, содержащие пробелы необходимо заключать в кавычки. Просто добавит лишней заботы - не забывать кавычки. А зачем усложнять себе жизнь, когда без этого легко можно обойтись.
· По возможности, ограничивайте длину названия 8 символами и не используйте в названии цифр и спец. символов - на самом деле я не вижу разумных объяснений этому ограничению. Но дело в том, что подавляющее большинство системных файлов и файлов примеров в FoxPro (да и собственно системы Windows) ограничены как раз-таки именно 8 символами и не используют ни цифры ни спец. символы. Зачастую в ущерб информативности названия. Почему разработчики идут на такое ограничение не понятно, но имеет смысл последовать их примеру. Видимо на это есть какие-то причины, кроме привычки к DOS-нотации
· Не называйте файл базы данных также как и один из содержащихся в ней объектов - не обязательно речь идет о таблицах, это может быть совпадение с названием Local View, или индексного тега, или поля таблицы, да мало ли чего еще... Разумеется ошибки это не вызовет, но усложнит понимание написанного кода самим программистом. Не всегда с ходу можно однозначно определить, что речь идет именно о файле базы данных, а не о каком-либо другом объекте. А если еще и их названия совпадают, то совсем тяжело становится.
· Не используйте для названия одно из зарезервированных в FoxPro слов - опять же, ошибки это не вызовет, но резко снизит "читабельность" кода. Ведь зарезервированные слова автоматически подсвечиваются опеределенным цветом (если Вы используете стандартный текстовый редактор FoxPro) и с ходу становится проблематично отличить опцию или команду от имени файла базы данных
Расположение файла базы данных
· Как для файла базы данных, так и вообще для всех рабочих таблиц использующихся в проекте следует выделять специальную папку (директорию). Эта рекомендация относится как к этапу разработки проекта, так и к поставке готового приложения клиентам.
Причины этой рекомендации подробно изложены в разделе "Расположение файлов проекта"
. Вкратце, суть сводится к тому, что в противном случае возрастает риск непреднамеренной порчи файлов данных и соответственно потере данных. А также облегчается поиск нужных файлов и создание резервной копии.
· Желательно файл базы данных располагать в той же папке, где и включенные в него файлы DBF
По большому счету, конечно можно держать файл базы данных в одной директории, а включенные в него файлы DBF в другой. Но это усложняет сам процесс разработки проекта. Например, создание резервной копии в простейшем случе заключается в простом копировании директории с рабочими файлами в другое место. Если же рабочие файлы отделены от файла базы данных, то потребуется уже копирование 2-х директорий. Соответственно усложнится код.
Кроме того, в этом случае несколько увеличится размер файла базы данных (точнее файла DCT - мемо-файла), поскольку непосредственно в нем хранится относительный путь к включенным в него таблицам. Если таблицы расположены в той же директории, что и сам файл базы данных, то этого относительного пути просто нет. Справедливости ради, следует заметить, что относительный путь к базе данных хранится и в заголовках таблиц, которые в эту базу данных включены. Но на размер таблиц это не влияет, поскольку под этот относительный путь всегда выделяется фиксированное место вне зависимости от факта его наличия.
Обслуживание файла базы данных
Собственно, обслуживание файла базы данных заключается в его регулярной "чистке". Поскольку файл базы данных - это обычная DBF-таблица, то и удаление из него происходит так же как и в таблице в 2 этапа: сначала записи только помечаются как удаленные, но физически не удаляются. А для физического удаления необходимо выполнить упаковку файла базы данных.
На этапе разработки для этой цели используется специальный пункт меню в режиме модификации базы данных: пункт главного меню Database->Clean Up DataBase. Фактически, этот пункт меню выполняет команду PACK для файла базы данных, поэтому требует эксклюзивного открытия базы данных (в режиме EXCLUSIVE). Если база данных открыта в режиме SHARED, то этот пункт меню будет недоступен.
Кроме собственно чистки файла базы данных от ранее удаленных записей, выполнение этой операции существенно уменьшает размер файла DCT в котором хранятся в том числе все "хранимые процедуры". Поэтому после внесения изменений в хранимые процедуры также желательно сделать чистку базы данных.
На этапе выполнения у клиента необходимость чистки базы данных возникает только в том случае если Вы динамически добавляете и удаляете какие-либо объекты в базу данных. Например, создаете Local View командой CREATE SQL VIEW. Или модифицируете какие-либо свойств по DBSetProp(). Или модифицируете таблицы по ALTER TABLE.
В этом случае чистка базы данных выполняется с использованием обычной команды PACK примерно таким образом
SET DATABASE TO MyBase CLOSE DATABASE OPEN DATABASE MyBase EXCLUSIVE SET DATABASE TO MyBase PACK DATABASE CLOSE DATABASE OPEN DATABASE MyBase SHARED SET DATABASE TO MyBase |
Разумеется, это только общая схема, здесь опущены различные проверки необходимые в полноценном приложении.
Если же Вы никаким образом не модифицируете файл базы данных на этапе работы у клиента, то и нет необходимости в чистке файла базы данных.
Вообще-то, я очень не рекомендую новичкам использовать команды по модификации файла базы данных. Это как раз одни из самых потенциально-опасных операций, могущих привести к необратимой порче всех исходных данных.
А надо ли вообще использовать файл базы данных?
Подобный вопрос очень часто задают программисты, которые раньше работали на FoxPro 2.x, где этого файла просто не было. Да и сам FoxPro вполне способен работать и со свободными таблицами безо всякой базы данных. Отвечу сразу - надо! А теперь попробую объяснить почему.
· Использование файла базы данных расширяет возможности таблиц DBF.
Например, в файле DBF в принципе нельзя дать полю название содержащее более 10 символов, но если он включен в базу данных, то название поля может уже содержать до 128 символов. Никакие правила (RULE), значения по умолчанию (DEFAULT), триггера и кое-что другое попросту невозможны в файле DBF вне файла базы данных. Точнее так - невозможно их автоматическое выполнение.
· Использовании файла базы данных позволяет выполнять операции, которые крайне сложно организовать другими способами
Например, такая операция как "транзакция" может быть реализована только среди таблиц DBF включенных в базу данных. В принципе, этот процесс можно организовать и со свободными таблицами, но это потребует от программиста значительных усилий. А такой замечательный объект как обновляемый Local View - сколько усилий требовалось при программировании в FoxPro 2.x для реализации того, что этот объект делает автоматически!
Вобщем, использование файла базы данных серьезно облегчает жизнь программиста


