Глава 10:FoxPro и электронные таблицы
Я начинал карьеру консультанта как специалист по Lotus 1-2-3. Мой шаблон для Lotus (справочник по недвижимости) был первой такого рода разработкой, продававшейся как отдельный продукт. Долгое время я считал, что вы можете сделать все в 1-2-3.
Действительно это так, но во многих случаях это будет не лучшим выбором. Текстовые процессоры обрабатывают текст быстрее программ, не предназначенных для такого типа работы. Именно разочарование в "2" (Lotus получил свое название от совмещения в одном продукте трех возможностей 1 - электронные таблицы, 2 - базы данных, 3 - графика) привело меня к новой тогда программе dBASE II.
Я до сих пор уважаю электронные таблицы. Когда вам нужно обработать несколько столбцов данных табличной формы - они как раз то, что нужно. Однако, если ваши цифры размещены в базе данных, имеет смысл использовать другие средства.
Предлагаемая в этой главе программа реализует электронную таблицу с 20 строками и 6 столбцами данных, суммы по строкам и столбцам пересчитываются, когда вы нажимаете клавишу, вызывающую функцию Recalc. (FoxPro работает быстро в определенных случаях, но немедленный пересчет массива в 120 элементов не входит в этот список).
Таблицы. В самом простом случае в каждой клетке содержится число определенного формата. Единственной процедурой анализа данных является модуль пересчета сумм; большинство электронных таблиц позволяют отключать глобальный пересчет для ускорения работы программы. Такой набор требований прекрасно подходит для программы на базе цикла обработки событий.
Программа начинает работу с пустым файлом .DBF. Обычно указатель перемещается только по клеткам, содержащим численные данные, но вы можете ввести заголовки строк, используя клавишу F3. При выходе наименования строк записываются первыми, за ними сохраняются цифры. Если вы нажимаете Enter, программа проверяет текущее значение переменной ScanOrder и перемещает указатель либо вправо, либо вниз в зависимости от значения переменной.
Событийно-управляемые электронные таблицы
Для большинства функций больше нет необходимости использовать цикл обработки событий. Переменная _curobj отслеживает номер текущего поля ввода. Координаты в массиве (и, следовательно, координаты столбца и строки) могут быть получены из _curobj.
Для получения дополнительной функциональности при перемещении курсора можно использовать клавиши-ускорители.
Одна из претензий к скорости работы FoxPro заключается в задержке перемещения курсора из поля в поле. Подобные задержки особенно раздражают при работе в электронной таблице. Я обнаружил, что единственным наиболее важным условием ускорения движения курсора является наличие большого количества памяти. Если принять во внимание это единственное предупреждение, можно считать программу вполне функциональной.
Программа
Вначале я инициализирую установки и глобальные переменные, управляющие приложением. Обратите внимание, что изменяя GPic, colwidth и Ncols вы можете легко увеличить число выводимых столбцов (Листинг 10-1(Программа Startup)).
Затем я назначаю "горячие клавиши" для приложения (Листинг 10-2). Обратите внимание на использование переменной Curr для изменения цвета текущей клетки. Я использую имя Curr для того, чтобы Алан Шварц имел предмет для критики (см. его великолепную статью о стандартах именования в декабрьском номере 92 г. журнала The Pinter FoxPro Letter /русское издание/, - прим. пер.).
Предложение READ VALID версии 2.0 используется для анализа условия завершения READ. В этом примере я толком не использую ее (см. процедуру Save Data, вызываемую по нажатию F6).
В конце я снимаю все назначения с "горячих клавиш" и возвращаюсь в командное окно, если программа не была вызвана из другой программы (Листинг 10-3(Очистка среды и выход)).
Если нажата Esc, команда READ завершается (Листинг 10-4(Вспомогательные функции)). Так как F6 ведет к сохранению данных и выходу, Esc означает, что либо пользователь хочет выйти без сохранения, либо просто нажал клавишу, чтобы посмотреть на результат. Они любят это.
В Листинге 10-5(Загрузка текущей страницы (с прицелом на будущее, пример работает только с 1 страницей)) программа выполняет загрузку данных таблицы в два массива (Labels и Data), выводимые на экран. Загрузка одной страницы данных происходит быстро. После загрузки начинается режим редактирования, которое начинается с поля GET Data(1,1). Если нажата клавиша F4 - Edit Label, программа определяет номер текущей строки и позволяет редактировать ее заголовок (Листинг 10-6 (Редактор заголовков))
Если нажата клавиша F6 (Save) программа просит подтверждение , очищает файл и записывает в него данные из всех непустых клеток таблицы, заголовки записываются первыми (Листинг 10-7(Сохраняем данные и выходим)).
Следующая функция вызывается из предложения VALID для полей ввода, организованных в процедуре LoadData. Функция определяет какая клавиша была нажата последней для выполнения соответствующего действия.
Обработка клавиши Enter базируется на текущем значении ScanOrder. Нажатие клавиши F5 меняет значение переменной на ROWS или COLUMNS (Листинг 10-8(Обработка последнего нажатия клавиши)).
Программа не имеет автоматического пересчета. Нажав клавишу, вызывающую функцию Recalc, пользователь выполняет расчет сумм по столбцам и строкам и выводит полученные результаты на экран (Листинг 10-9(Пересчет)) Единственно чего не хватало FoxPro 2.0 по сравнению с программами, построенными на цикле обработки событий, - это быстрого перемещения между многочисленными полями ввода без использования мыши. Некоторые пользователи не любят работать с мышью. Здесь я применил трюк, описанный ниже. Процедура в Листинге 10-10(Функция перехода к выбранному полю для пользователей без мыши и переключатель ROW/COL) делает как раз то, что нужно.
Заключение
Приведенная модель электронной таблицы может быть легко модифицирована для других целей. Добавить такие вещи как многостраничные таблицы, вызываемые при смещении за нижнюю или правую границу текущей страницы, формулы (здесь можно использовать функцию EVALUATE()) не представляет большой сложности. Приведенный пример может дать вам толчок к разработке собственных приложений такого типа.
Листинг 10-10
PROCEDURE JumpTo SAVE SCREEN TO F2Key
i = 1
FOR I = 1 TO NRows
FOR J = 1 TO NCols
K = ((I-1)*6 ) + J
@ 1+I, ((J-1)*ColWidth) + 15 ;
SAY "(" + TRANSFORM ( K , "@L ###" ) + ")"
ENDFOR J
ENDFOR I
@ 24, 0 CLEAR
mfld = 0
@ 24, 30 SAY 'Field to go to:' ;
GET mfld PICTURE '999' RANGE 0, 6 * 20
READ
RESTORE SCREEN FROM F2Key
IF mfld <> 0
_CurObj = mfld
ENDIF
PROCEDURE Toggle
IF ScanOrder = "COLUMNS"
ScanOrder = "ROWS"
ELSE
ScanOrder = "COLUMNS"
ENDIF