«Финансы без проблем»
Сетевая версия
Руководство пользователя и разработчика настройки: архитектура клиент-сервер, установка и администрирование ФБП:Сервера, работа с ФБП:Клиентом, права пользователей, язык запросов — и полное описание языка программирования ФБП: отчётные формы, операторы, функции, виды операций и проводки, лента фактов, управляющие строки N:.
Руководство описывает только сетевую версию
платформы и актуализировано под новые программы: ФБП:Сервер V01 (Windows 8.1/10/11, Server 2012+)
и ФБП:Клиент CLWP для Windows. Однопользовательские и DOS-варианты более не поддерживаются
и в руководство не входят.
Подготовлено на основе оригинального «Руководства пользователя. Сетевая версия»
(«Финансы без проблем» © Хакерс Дизайн, hdru.com).
Пользуйтесь оглавлением слева или поиском вверху страницы (Ctrl+K).
1. Введение: как это работает
«Финансы без проблем» (ФБП) — учётная система клиент-серверной архитектуры. В ней есть ровно один ФБП:Сервер и сколько угодно ФБП:Клиентов. Это руководство описывает только сетевую версию и актуализировано под новые программы: ФБП:Сервер V01 для Windows и ФБП:Клиент CLWP.
1.1. Толстый сервер, тонкие клиенты
ФБП:Сервер — «толстый» процесс с собственной быстрой RAM-only СУБД. Он хранит на диске данные и правила (журналы операций, план счетов, дерево видов операций, отчётные формы), а в памяти держит вычислительное ядро. Сервер в реальном времени пересчитывает состояние базы, так что к следующему запросу клиента готов уже готовый результат. Все значимые вычисления выполняет только сервер: регистрация и удаление операций, пересчёт баланса, вычисление формул, выполнение отчётных форм, контроль прав пользователей.
ФБП:Клиент — «тонкий». Он формирует запросы к серверу и отображает ответы, но не делает значимых вычислений и не блокирует сервер, конфликтуя за данные. Сервер обрабатывает запросы всех клиентов в порядке общей очереди.
1.2. Обмен — через общий каталог, а не через сеть
Самое неочевидное и самое важное свойство платформы: «сетевая версия» обменивается
данными не по сетевым протоколам, а через общий каталог обмена (историческое имя —
_box_). Никаких портов, сокетов и служб удалённого доступа: достаточно, чтобы
сервер и клиенты видели один и тот же каталог (например, через сетевой ресурс Windows)
и имели к нему доступ на запись.
Цикл одного запроса:
- Клиент создаёт в каталоге обмена файл-запрос со случайным именем из букв и цифр
(например
ZXC456A3.REQ), затем переименовывает его вZXC456A3.IN. Переименование — атомарный сигнал «файл готов целиком». - Сервер постоянно сканирует каталог обмена. Найдя
*.IN, он выполняет запрос, удаляет.IN, пишет ответ вZXC456A3.ANSи по завершении переименовывает его вZXC456A3.OUT. - Клиент читает
ZXC456A3.OUTи при следующем запросе удаляет его.
В каталоге обмена можно создавать подкаталоги — например, отдельный для каждого клиента или для шлюзов оборудования. Сервер сканирует их наравне с корнем каталога; это также удобно для разделения прав доступа средствами ОС (см. главу 6).
Нетребовательность к сети — следствие такой схемы: типичный запрос
(R OBOROTKA) занимает десятки байт, а ответ — несколько килобайт.
Тем не менее рекомендуемое размещение, в порядке убывания надёжности и скорости:
- лучший вариант — сервер, данные и каталог обмена на одной машине;
- хуже — каталог обмена на другой машине;
- самый тяжёлый — данные и сервер на разных машинах.
1.3. Что из чего состоит
| Компонент | Где живёт | Назначение |
|---|---|---|
ФБП:Сервер (Fbp.Server.exe) | Машина сервера | Ядро: данные, вычисления, права, формы. Работает как служба Windows; управляется Менеджером баз. См. главу 3. |
| Каталог данных (база знаний) | Машина сервера | acnt.a3p (план счетов), cas.rul (дерево видов операций),
журналы YYYYMM.f3p, формы *.rpt, первичные документы
TXA\, права _RIGHTS_.FBP, ключевые файлы
(см. главу 8). |
| Каталог обмена | Общий сетевой ресурс | Файлы запросов и ответов *.REQ/.IN/.ANS/.OUT, файлы UPTI.
См. главу 6. |
ФБП:Клиент (CLWP.EXE) | Машины пользователей | Ввод операций, журналы, отчёты, печать, экспорт. См. главу 4. |
1.4. Язык программирования ФБП
Прикладная логика системы — план счетов, дерево видов операций с проводками и,
главное, отчётные формы *.rpt — пишется на собственном языке ФБП.
Формы компилирует и выполняет сервер (директивы R, E,
см. главу 7); клиент дополнительно исполняет встречающиеся
в тексте форм управляющие строки N: — навигацию и запросы по клавишам
(см. главу 23).
1.5. Что нового в этой редакции руководства
- Описаны только сетевые программы: однопользовательские и DOS-варианты исключены как неактуальные.
- ФБП:Сервер — новая реализация V01: служба Windows, Менеджер баз, лицензирование, журналы, автоархивирование, гибернация базы (глава 3).
- ФБП:Клиент — новый клиент CLWP: современный интерфейс, поиск-выборка, экспорт в Excel,
управляющие строки
N:SHIFTF1:…N:SHIFTF9:иN:AUTO:(глава 4 и глава 23). - Явно указано, какие директивы и ключевые слова старого сервера не перенесены (глава 7, глава 8, глава 29).
2. Количественные ресурсы и ограничения
В этой главе собраны пределы платформы: одни вытекают из форматов файлов данных (они неизменны — новый сервер работает с существующими базами), другие — из реализации нового ФБП:Сервера V01. Исторические ограничения старого сервера, которые в новой реализации сняты, отмечены отдельно.
2.1. Журналы операций и уникальные коды
Операции года хранятся в двенадцати файлах YYYYMM.f3p — по одному на
месяц. Явно заданного ограничения на число операций нет; предел вытекает из формата
уникального кода операции вида MLLL-000 (M — буква месяца
A…L, далее три буквы и три цифры):
26 × 26 × 26 × 10 × 10 × 10 = 17 576 000 уникальных кодов
Суммарный размер всех двенадцати файлов *.f3p не может превышать
17 576 000 записей; реально, с учётом удалённых операций, — несколько миллионов
операций в год. При старте сервер находит код с максимальным значением и продолжает
нумерацию от него; код удалённой операции уже никогда не используется повторно.
Комментарий операции — до 56 литер, включая добавляемый сервером штамп (пользователь, время, уникальный код).
2.2. Операции типа null (разрыхление журналов)
При первом старте на базе, журналы которой не разрыхлены, сервер вносит в файлы
*.f3p пустые операции типа null. Когда пользователь вводит
операцию «в прошлое», ближайшая пустая операция заменяется новой — без пересоздания
файла месяца. При десятках тысяч операций в месяц это единственное решение, дающее
достаточную производительность ввода. Если пустых операций не нашлось, файл разрыхляется
повторно.
null не видны в клиентах. Новый сервер выполняет
разрыхление так же, как и прежний: файл месяца переписывается через временный файл
с резервной копией, прерванное разрыхление автоматически разбирается при следующем
старте.2.3. План счетов, факты, экстрапараметры
acnt.a3p(счета и субсчета) — явно заданного ограничения на число счетов нет. Обозначение счёта — от 1 до 10 символов, наименование — до 255.facts.b(лента фактов) иextra.b(экстрапараметры) — ограничений нет, лента, индексы фактов и экстрапараметры должны поместиться в ОЗУ сервера.extrd.dat(дисковая база экстрапараметров) — ограничен местом на диске; запись — до 255 байт. При наличии файла-ключаfastgedв ОЗУ строится зеркало тел записей (см. главу 8).
2.4. Формы и строки языка
- Файлов форм
*.rptв каталоге данных — исторически до 500. - Строковые значения языка форм (переменные, стек, временные строки) ограничены
255 символами — лишнее молча усекается, как в оригинальной реализации.
От этого зависят, например, накопители с дедупликацией по
[ps]. - Имена счетов в
*-ссылках,$D/$K/$P,@-обращениях усекаются до 10 символов.
2.5. Пользователи, имена, пароли
- Имя и пароль пользователя — до 12 литер; лишние символы молча усекаются. Имя — латинские буквы и цифры, начинается с буквы, регистр не различается; пароль различает регистр.
- Новый сервер поддерживает до 1000 пользователей в файле
_RIGHTS_.FBP. Лицензия нового сервера не ограничивает число имён (в прежних версиях серверы поставлялись на 2, 5, 10, 20 или 30 имён). - Пределы описателей прав: до 80 форм в праве
R, до 68 имён в правахJиD, до 15 ветвей в правеT.
2.6. Память сервера
Новый ФБП:Сервер — 64-разрядное приложение .NET; двухгигабайтный барьер
32-разрядных серверов снят. Ориентировочное потребление на большой боевой базе —
порядка 2–2,5 ГБ. Понятия «контексты D и D'» и параметры их размера из командной
строки старого сервера (-C/-U/-F/-X) в новом сервере отсутствуют —
память управляется автоматически (см. главу 29).
2.7. Прочие пределы
| Величина | Предел |
|---|---|
Строка запроса после подстановок //DDD// | 255 байт (буфер приёма — 10 000 байт) |
| Контексты в поле «пожеланий» запроса | 10 пар «имя + значение», по 10 символов |
| Ответы на вопросы операции и сумма в контексте | до 10 символов; имя контекста-вопроса — первые 9 символов вопроса |
Файлов *.IN, забираемых за один проход сканирования | 1024 |
| Индексы массивов в языке форм | 1 … 1 000 000, всего 26 массивов |
| Демонстрационный режим сервера без лицензии | 30 минут непрерывной работы |
| Незарегистрированный клиент CLWP | 20 минут непрерывной работы |
2.8. Групповые (многострочные) операции
Многострочная операция оформляется в дереве видов операций ветвями
{ и }: все проводки между ними регистрируются как одна
составная операция. Клиенты отображают такую операцию свёрнутой (одной записью)
или развёрнутой — по опции «Операции свернуто».
3. ФБП:Сервер — установка и администрирование
Новый ФБП:Сервер (версия V01) — самостоятельная 64-разрядная реализация сервера платформы для Windows. Он работает со всеми существующими клиентами (CLWP, CLW32, CGI) и с существующими базами знаний без их изменения: форматы файлов данных, протокол обмена и язык форм сохранены.
3.1. Состав поставки и требования
- Fbp.Server.exe — сам сервер (консольное приложение, обычно работает как служба Windows).
- Fbp.Server.Manager.exe — Менеджер баз: графическая программа для регистрации баз, управления службами, наблюдения за состоянием и архивирования (см. п. 3.5).
- FbpServer.lic — файл лицензии (см. п. 3.3).
Требования: Windows 8.1 / 10 / 11 или Windows Server 2012 и новее, 64-разрядная версия. Для Windows Server 2012 необходим установленный пакет Visual C++ 2015–2022 Redistributable (x64). Программы самодостаточны — установка .NET на машине не требуется.
Ответ сервера на директиву V:
"Финансы без проблем" V01.01 Александр Пронин. Для Windows 8.1,10,11,Server 2012+
3.2. Установка и первый запуск
Установка сервера — это копирование каталога с программами на машину сервера. Для работы нужны два каталога:
- Каталог данных (база знаний) — с файлами
acnt.a3p,cas.rul,YYYYMM.f3p,*.rpt,_RIGHTS_.FBPи др. Если базы ещё нет, возьмите демонстрационную или боевую базу от прежнего сервера — новый сервер читает её напрямую. - Каталог обмена — общий каталог, доступный клиентам (историческое имя —
_box_). Если каталог не существует, сервер создаст его сам при старте.
Пробный запуск из командной строки (консольный режим удобен для первой проверки):
Fbp.Server.exe <каталог_данных> <каталог_обмена>
Сервер загружает базу, строит баланс и начинает обслуживать каталог обмена.
Остановка — Ctrl+C в консоли или директива W DOWN от
пользователя с правом U (см. главу 7).
Штатная эксплуатация — как служба Windows под управлением Менеджера баз.
3.3. Лицензирование
Лицензия — файл FbpServer.lic рядом с Fbp.Server.exe.
Файл содержит код компьютера, имя владельца, ключ и электронную подпись; лицензия
привязана к конкретной машине и не ограничивает число пользователей базы.
| Ситуация | Поведение сервера |
|---|---|
| Лицензия этой машины найдена и верна | полноценная работа без ограничений |
| Файл лицензии отсутствует | демонстрационный режим — 30 минут непрерывной работы, затем штатная остановка |
| Лицензия чужая или повреждена | отказ в работе (код завершения 4) |
Код компьютера (16 шестнадцатеричных знаков) сервер сообщает при запуске без лицензии; по этому коду поставщик выдаёт ключ. Число лицензируемых имён пользователей, в отличие от прежних версий (серверы «на 2, 5, 10, 20, 30 имён»), не ограничивается — действует общий предел 1000 пользователей в файле прав.
3.4. Командная строка сервера
Fbp.Server <каталог_данных> <каталог_обмена> [ключи]
| Ключ | Назначение |
|---|---|
--servername S | метка сервера для ответа на директиву
I — вместо первой строки файла FIN.LBL из каталога данных |
--factmonths m1 m2 | диапазон месяцев запоминания
ta-фактов (аналог аргументов m1 m2 командной строки старого сервера) |
--log <каталог|файл> | расположение журнала;
по умолчанию — каталог базы, файл FbpServer-YYYY-MM-DD.log |
--idle-exit-min N | (V01.02) штатная остановка после N минут без запросов — режим «ожидание старта» (см. п. 3.9) |
--no-base-image | (V01.02) отключить полный образ базы (см. п. 3.9) |
--date YYYY-MM-DD | фиксация «сегодняшней» даты сервера (служебный, для стендов сверки) |
--hdbios N | оставлен для совместимости; на работу и ответ
V не влияет |
Коды завершения процесса сервера:
| Код | Смысл |
|---|---|
| 0 | штатная остановка (W DOWN, остановка службы, конец
демо-времени) |
| 1 | ошибка загрузки базы |
| 2 | аварийное завершение рабочего цикла (план счетов при этом дампится
в ACNT.EMG, см. п. 3.7) |
| 3 | база уже обслуживается другим экземпляром сервера
(файл _SRVNEW_.LCK) |
| 4 | отказ лицензии |
3.5. Менеджер баз
ФБП:Менеджер (Fbp.Server.Manager.exe) — постоянный инструмент
администратора. Он хранит реестр баз (файл FbpManager.bases.json рядом
с программой) и для каждой базы позволяет:
- установить и управлять службой Windows — установка, удаление, старт,
остановка, перезапуск выполняются только через диспетчер служб (SCM); имя службы —
FbpServerплюс необязательный суффикс, поэтому на одной машине может работать несколько баз; - наблюдать состояние — по файлу heartbeat
_STATUS_.FBP(см. п. 3.6): загрузка, обслуживание, пересчёт с указанием месяца и процента, память, число запросов, «лицо» сервера с подсветкой активности пользователей; двойной щелчок открывает отдельное окно активности базы; - читать журнал запросов — встроенный просмотр хвоста журнала с поиском;
- архивировать базу — полный или инкрементный ZIP-архив по расписанию (дни и время) или немедленно, без остановки сервера; перед архивом менеджер дожидается завершения пересчёта и записи плана счетов; архивы никогда не удаляются автоматически;
- управлять гибернацией (V01.02) — см. п. 3.9.
Крестик в заголовке не закрывает менеджер, а сворачивает его в область уведомлений (трей): значок окрашивается в цвет суммарного состояния серверов (зелёный — работают; жёлтый — запуск или пересчёт; красный — проблема; серый — работающих нет), а расписания архивов исполняются и из трея. Полный выход — пункт «Выход из менеджера». На одном компьютере работает один экземпляр менеджера — повторный запуск просто поднимает уже открытое окно.
3.6. Журналы и контроль состояния
- Журнал запросов
FbpServer-YYYY-MM-DD.log(в каталоге базы или по ключу--log, кодировка CP866): каждая обслуженная директива — время поступления, пользователь, длительность в миллисекундах, директива, ошибка, а при вводе новой операции — её уникальный код. Транспортные сбои (невозможность создать ответ, сорванное переименование и т.п.) также журналируются — у старого сервера они проходили молча. - Heartbeat
_STATUS_.FBPв каталоге базы (UTF-8, строки «ключ=значение», обновляется раз в 10 с, при пересчёте — каждые 0,5 с): состояние (loading/serving/stopping/down), аптайм, память, прогресс пересчёта, счётчики запросов и операций, признаки «план счетов изменён, но ещё не записан», счётчик итераций рабочего цикла и число необработанных запросов — по ним менеджер и внешние сторожа отличают живой сервер от зависшего. - Защита от двойного запуска — файл
_SRVNEW_.LCKв каталоге базы: второй сервер на той же базе завершится с кодом 3.
3.7. Сохранность данных и восстановление
- Отложенная запись плана счетов.
acnt.a3pперезаписывается не при каждом изменении, а через 60 секунд после последнего изменения (при непрерывном потоке запросов — принудительно через 600 секунд), а также при штатной остановке. Запись всегда безопасная: временный файл → резервная копия → замена. - Аварийный дамп. При аварийном завершении рабочего цикла (код 2) изменённый
план счетов сохраняется в
ACNT.EMG— основная база при этом не трогается; файл предназначен для ручного восстановления. - Карантин запросов. Если ответ на запрос не удалось создать, файл запроса
уходит в карантин
<имя>.BADи не теряется; сбой журналируется. - Архивирование. Штатное средство — архивы менеджера (см. п. 3.5). Рекомендуется ежедневный инкрементный и периодический полный архив.
3.8. Пауза, перезагрузка, перекомпиляция форм
Управление работающим сервером — директивой W от пользователя с правом
U (см. главу 7):
| Директива | Действие |
|---|---|
W ON | пауза: на все директивы, кроме W,
ответ E-94 («сервер ждёт») |
W OFF | перезагрузка базы: права, план счетов, дерево видов операций перечитываются, баланс пересчитывается — без остановки процесса |
W FORM | перекомпиляция новых и изменённых с момента старта
форм *.rpt — без перезагрузки базы |
W DOWN | штатная остановка сервера (код завершения 0; служба при этом не перезапускается автоматически) |
3.9. Гибернация и быстрый старт (V01.02)
Начиная с версии V01.02 сервер умеет «засыпать» и «просыпаться»:
- Ожидание старта (сон). С ключом
--idle-exit-min Nсервер, не получивший запросов N минут, штатно останавливается (heartbeatstate=standby). Менеджер следит за каталогом обмена: как только в нём появляется запрос, служба автоматически запускается, и запрос обслуживается. Переходы в сон и пробуждения пишутся в журнал. - Полный образ базы
_BASEIMG_.FBP. При штатной остановке сервер записывает образ вычислительного состояния; при следующем старте валидный образ восстанавливается за секунды вместо полной холодной загрузки и пересчёта (на большой базе — примерно 6 секунд вместо 80). Если образ устарел или повреждён — выполняется обычный холодный старт, сервер не падает. Отключить образ можно ключом--no-base-image. - Архивная пауза. Перед архивом менеджер может приостановить приём запросов
(файл
_ARCPAUSE_.FBP): сервер доделывает пересчёт, сохраняет план счетов и ждёт; по истечении срока пауза снимается сама. - Смена суток. При смене календарного дня база автоматически перезагружается
(как по
W OFF); если с новой датой база не открывается, сервер остаётся на прежней дате и перепроверяет её раз в минуту.
3.10. Файл M_PLUS — сдвиг «текущего» месяца
Если в каталоге данных есть файл M_PLUS с числом N, сервер при старте
считает «текущим» месяц, сдвинутый на N месяцев вперёд. Это удобно для прогонов
«будущего» периода без перевода системных часов. Файл читается один раз при старте;
переход через год не выполняется (сдвиг ограничен декабрём), а при наличии в каталоге
журнала другого года сдвиг отменяется.
3.11. О переходе из года в год
Специальная «новогодняя» версия старого сервера (3.NY/4.NY с Новогодним Адаптером
и подкаталогом обмена _ny_) в новую реализацию не перенесена.
Переход из года в год выполняется традиционно: запись конечного состояния директивой
Q, перенос журналов *.f3p и файлов состояния нового года,
продолжение работы обычным сервером.
4. ФБП:Клиент — установка и работа
Эта глава описывает CLWP — клиентскую программу сетевой версии для Windows, написанную заново на .NET. Она полностью повторяет протокол обмена и поведение прежнего клиента CLW32, поэтому работает с тем же ФБП:Сервером и теми же отчётными формами; интерфейс и часть возможностей при этом современнее. Новшества по сравнению с CLW32 в тексте помечены пометкой НОВОЕ.
4.1. О программе и начало работы
«Финансы без проблем» работает по схеме «Сервер — Клиент»: ФБП:Сервер хранит журнал операций, дерево видов операций, счета и отчётные формы, выполняет все вычисления и следит за правами доступа; Клиент на рабочем месте показывает данные, принимает ввод и передаёт Серверу запросы (директивы) через общий сетевой каталог обмена. Устройство обмена подробно описано в главе «Архитектура и обмен», сам протокол — в главе «Протокол обмена».
Установка на рабочем месте сводится к копированию каталога с исполняемым файлом:
дистрибутив может лежать на сервере, тогда достаточно скопировать каталог к себе
(например, в C:\CLW) и запустить программу. Рядом с CLWP.EXE
лежит то, что общее для всех баз: файл помощи CLWP_help.html и отчётные формы
(*.RPT), которые администратор кладёт в поставку для всех.
Основные возможности клиента:
- журнал операций: просмотр, ввод, правка, удаление, поиск и выборка;
- ввод операций через дерево видов операций с ветвями-вопросами и выбором счетов;
- отчётные формы Сервера (оборотный баланс и любые формы из списка) с автообновлением;
- собственные формы на клиенте — локальные
.RPT-файлы; - встроенный редактор форм с компиляцией и выполнением на Сервере;
- первичные документы, проводки, отчётный период;
- печать, запись в текстовый файл, экспорт в Excel;
- калькулятор с обращением к оборотам счетов и расчётом НДС;
- кнопки-макросы
Alt+F1…Alt+F9; - избранные и недавние команды, поиск команды по названию (
Ctrl+Q).
4.2. Программа и рабочий каталог базы (НОВОЕ)
Клиент отделяет саму программу от данных базы — так же, как это делал CLW32.
Исполняемый файл может быть один на всех и лежать в общем каталоге, а у
каждой базы — свой рабочий каталог. Тогда обновление программы сводится к замене
одного CLWP.EXE, и ничьи настройки при этом не теряются.
В рабочем каталоге базы хранятся:
CL.DIR— путь к каталогу обмена с Сервером;CLWP.настройки.xml— все настройки клиента для этой базы: опции, определения клавиш, аргументы и фильтры, отчётный период, шрифты, поля печати, размеры, место на экране и режим окон;- отчётные формы этой базы (
*.RPT) — см. п. 4.13; - каталог первичных документов (
TXA), если включено их хранение.
Рабочий каталог задаётся в свойствах ярлыка Windows:
| Поле ярлыка | Что указывать |
|---|---|
| Объект | Полный путь к общему исполняемому файлу,
например C:\CLW\CLWP.EXE. |
| Рабочая папка | Каталог этой базы, например
C:\FIN\Фирма_2026. Именно здесь программа ищет и создаёт
CL.DIR и CLWP.настройки.xml. |
Чтобы работать с несколькими базами, делают несколько ярлыков на один и тот же
CLWP.EXE, у каждого — своя «Рабочая папка». Копии клиента можно держать
открытыми одновременно: у каждой свой отчётный период, свои шрифты и размеры окон,
и они друг другу не мешают.
CLWP.EXE, как было раньше. При первом запуске
с новой рабочей папкой клиент один раз перенесёт туда прежние настройки,
чтобы не пришлось заново настраивать период, шрифты и размеры окон.
Настройки лежат в обычном текстовом файле, его можно открыть и прочитать любым редактором. Никаких других мест хранения у клиента нет.
4.3. Подключение к Серверу
При запуске программа показывает заставку и открывает окно «Подключение к Серверу». Позже его можно вызвать пунктом меню «Вход» — это вход под другим именем без перезапуска программы.
| Поле | Назначение |
|---|---|
| Каталог | Путь к каталогу обмена с Сервером (например,
Z:\_BOX_). Кнопка «Обзор» открывает диалог выбора папки.
Путь запоминается. |
| Пользователь | Имя, заведённое администратором на Сервере. Список имён загружается с Сервера. Флажок «Запомнить» подставляет имя при следующем запуске. |
| Пароль | Пароль пользователя. Если пароль не задан — поле оставляют пустым. |
Кнопка «Регистрация» отправляет Серверу запрос на вход. Если имя или пароль
неверны, в строке состояния появится сообщение об ошибке — ответы Сервера об ошибках
начинаются с E-. Кнопка «Отмена» закрывает окно без подключения.
Стартовые запросы. Сразу после входа клиент выполняет форму USERS,
если она есть на Сервере. Эта форма может содержать управляющие строки N:,
которые автоматически откроют нужные формы или запустят внешние программы, — так
администратор настраивает «рабочий стол» пользователя, например чтобы при входе сразу
открывался оборотный баланс. Синтаксис управляющих строк — в главе
«Управляющие строки N:».
4.4. Регистрация программы (НОВОЕ)
Не путайте с кнопкой «Регистрация» в окне подключения — та отправляет Серверу имя и пароль. Здесь речь о регистрации самой программы на вашем компьютере. Незарегистрированная копия работает 20 минут, после чего просит регистрационный ключ. Окно открывается из меню «Помощь → Регистрация программы…» и появляется само, когда время работы вышло.
В регистрации два понятия, и путать их не надо:
| Понятие | Что это |
|---|---|
| Номер компьютера | 14 знаков вида BHVQ0-PY01S-R2RQ,
которые программа считает с этого компьютера сама. Вы его только читаете и сообщаете
разработчику. |
| Регистрационный ключ | Длинная строка примерно из 120 знаков, которую разработчик выдаёт по вашему номеру компьютера. Вводится один раз. |
Как зарегистрироваться. Откройте окно регистрации: вверху — номер этого компьютера, ниже — имя компьютера в сети; кнопка «Копировать» кладёт обе строки в буфер обмена для письма разработчику. Полученный ключ положите в нижнее поле одним из трёх способов: кнопка «Из буфера», кнопка «Из файла…» или просто перетащите присланный файл мышью в окно. Набирать руками не нужно — лишние пробелы, переносы строк и дефисы программа отбрасывает сама. Нажмите «Зарегистрировать»; перезапускать программу не требуется.
Что стоит знать про ключ:
- Он привязан к компьютеру — на другой машине не подойдёт («Этот ключ выдан для другого компьютера»).
- Замена железа не страшна — номер не меняется от замены памяти, видеокарты, диска, док-станции или переименования компьютера. Меняется он только при переустановке Windows или форматировании системного диска — тогда нужен новый ключ.
- Регистрация одна на компьютер — сколько бы баз вы ни открывали с этой машины, регистрироваться нужно один раз; ключ хранится не в настройках базы, а отдельно.
- У каждого пользователя Windows свой ввод — под разными учётными записями Windows ключ вводится заново; номер компьютера одинаковый, поэтому годится тот же самый ключ — просто вставьте его ещё раз.
- Сохраните ключ — он пригодится после переустановки программы или при входе под другой учётной записью.
Ключ проверяется на самом компьютере, без обращения к Серверу и без интернета. Ограничение времени никак не связано с правами пользователя на Сервере: это разные вещи.
4.5. Главное окно
Главное окно — контейнер, внутри которого открываются все рабочие окна (журнал операций, формы, редактор). Сверху — меню и панель инструментов, снизу — строка состояния. По умолчанию главное окно открывается развёрнутым во весь экран, и дочерние окна тоже разворачиваются на всю его площадь; режим переключается в меню «Окно → Во весь экран».
Окно открывается там, где его закрыли (НОВОЕ). Размер главного окна, его место на экране и признак «развёрнуто во весь экран» запоминаются при выходе и восстанавливаются при следующем запуске — вместе с монитором: если работали на втором экране, там окно и откроется. Если того монитора больше нет (сменилось разрешение, настройки базы лежат на сетевом диске, с ней работают с разных машин), окно не потеряется за краем: клиент откроет его на имеющемся мониторе и подгонит под размер.
В заголовке главного окна — название программы, база, имя пользователя и год базы (год задаётся пунктом «Опции → Год базы…», см. п. 4.17). Имя развёрнутого рабочего окна в заголовок не дописывается: эти данные видны в самом окне.
Строка состояния копируется (НОВОЕ). В нижней строке рабочего окна показаны
запрос к Серверу и имя файла ответа. Текст выделяется мышью и копируется в буфер обмена
(Ctrl+C, Ctrl+A — выделить всё, либо меню по правой кнопке) —
удобно, когда нужно открыть или переслать файл ответа Сервера. Пока курсор в этой
строке, Пробел не пересчитывает форму; Esc возвращает курсор
в список (второй Esc закрывает окно).
Меню. Пункты «Документы» перечислены в порядке горячих клавиш
Alt+F2…Alt+F9:
| Пункт | Клавиша | Действие |
|---|---|---|
| Операции | Alt+F2 | Журнал операций за отчётный период. |
| Оборотный баланс | Alt+F3 | Системная форма оборотного баланса. |
| Формы на Сервере | Alt+F4 | Список отчётных форм Сервера. |
| Печать | Alt+F5 | Печать активного окна — сразу, без диалогов. |
| Печать с параметрами… | Ctrl+Alt+F5 | То же, но с диалогом: принтер, комплекты, ориентация, шрифт, поля (НОВОЕ). |
| Виды операций | Alt+F6 | Дерево видов операций. |
| Формы на Клиенте | Alt+F7 | Список локальных форм .RPT. |
| Запись в файл | Alt+F8 | Содержимое активного окна в текстовый файл. |
| Список Запросов | Alt+F9 | Окно прямой отправки директив Серверу. |
| Экспорт в Excel | Ctrl+E | Выгрузка таблицы активного окна в книгу Excel (НОВОЕ). |
| Отчетный Период | Ctrl+O | Установка периода, за который показываются данные. |
Остальные пункты меню: Вход — окно подключения к Серверу; Избранное —
часто используемые команды (п. 4.21); Опции — настройки (п. 4.17);
Редактор — работа с текстом форм (п. 4.15); Окно — расположение дочерних
окон (во весь экран, каскад, плитка вертикальная/горизонтальная) и список открытых окон;
Помощь — содержание (F1), таблица горячих клавиш, сведения о версии,
регистрация программы; Выход — завершение работы.
Alt+F4 в этой программе не закрывает приложение — клавиша занята
под «Формы на Сервере», как было в старом клиенте. Для выхода используйте меню
«Выход» или крестик окна.
Список окон с крестиками (НОВОЕ). В меню «Окно» первые девять строк списка
выбираются цифрами 1…9, галочка стоит у активного окна.
У правого края каждой строки стоит крестик ×: щелчок по нему закрывает это окно,
не переключаясь на него, и меню остаётся открытым — так закрывают несколько ненужных
окон подряд.
Значки окон (НОВОЕ). Каждое рабочее окно имеет собственный цветной значок,
по которому его легко узнать в списке окон и на панели задач:
Ж — журнал операций, О — отчётная форма, С — выбор счёта,
Д — дерево видов операций, Р — редактор форм, Ф — формы на клиенте,
З — список запросов, = — калькулятор. Клавиша Esc закрывает
окна в обратном порядке их открытия — как «шаг назад».
На панели инструментов — кнопки быстрого доступа: Операции, поля начала и конца отчётного периода, Формы, Об/Бал, Период, Запросы; правее — кнопки-макросы, назначенные пользователем (см. «Определения клавиш» в п. 4.17).
4.6. Отчётный период
Отчётный период определяет, за какой промежуток показываются журнал операций и
отчётные формы. Текущий период виден в двух полях панели инструментов и меняется пунктом
«Документы → Отчетный Период» (Ctrl+O) или кнопкой Период.
Окно сделано так же, как в старом клиенте; в нём три панели:
- Месяц — двенадцать месяцев года базы. Слева от названия — число операций в месяце и отметка «в этом месяце есть данные»; справа скобка показывает, какие месяцы попали в период и какими числами он начинается и заканчивается;
- Число — календарь показанного месяца; как и в старом клиенте, он вертикальный: недели идут столбцами, строки — дни недели (Пн…Вс);
- Пользователи — чьи операции показывать; несколько выбираются мышью с
CtrlиShift, флажок «Операции всех» берёт сразу всех.
Под календарём — цветная плашка «Начало периода» / «Конец периода»: флаг,
который говорит, какой конец периода задаст следующий выбранный день. После каждого
выбора флаг сам перекидывается на другой конец, поэтому два нажатия Enter
задают весь период. Ниже показаны сами даты периода и общее число операций в нём.
Клавиши F4 и F5 делают подсвеченный день началом и концом
периода соответственно.
Период всегда лежит внутри года базы — календарь не даёт выйти за 1 января и
31 декабря этого года. Изменения применяются только кнопкой «Подтвердить»;
«Отменить» и Esc закрывают окно, оставив прежний период.
Выбранный период запоминается и восстанавливается при следующем запуске клиента (НОВОЕ).
Быстрые периоды (НОВОЕ) — четыре кнопки внизу окна ставят период одним нажатием: «Месяц» — показанный месяц целиком, «Квартал» — квартал показанного месяца, «Год» — весь год базы, «С начала года» — с 1 января по конец показанного месяца.
Флажок «Операции свернуто» в этом же окне (как и в старом клиенте) управляет тем, показывать ли составные операции журнала свёрнутыми; та же настройка есть в меню «Опции».
P задаёт, на сколько
месяцев назад пользователь может уходить. Если Сервер отказал в запросе за прошлый
период — обратитесь к администратору (см. главу «Права
пользователей»).
4.7. Журнал операций
Журнал открывается пунктом «Документы → Операции», кнопкой Операции
или клавишей Alt+F2. В окне — таблица операций за отчётный период; внизу
строка состояния с числом строк и служебной информацией; левая её часть (запрос
и имя файла ответа) копируется — Ctrl+C.
Если другой пользователь ввёл или изменил операцию, в правой части строки состояния
появляется «Возможно устарело». Перечитать журнал — Пробел; при
включённом автообновлении он перечитается сам, как только вы переключитесь в это окно.
Колонки (НОВОЕ). Ширина каждой колонки подбирается по самому длинному значению в ней — суммы, даты, коды и номера видны целиком. Переносится по строкам только колонка «Текст операции» (вместе с комментарием) — она занимает всю оставшуюся ширину. Любую колонку можно расширить или сузить мышью за границу заголовка; заданная вручную ширина сохраняется при обновлении журнала.
Клавиши журнала: F7 — ввести операцию, Enter — правка
(перезапись), Del или F8 — удалить с подтверждением,
F4 — первичный документ, F6 — проводки, F9 —
курсор в строку поиска, Пробел — обновить, Esc — закрыть окно.
Полный список — в п. 4.24.
Поиск и выборка (НОВОЕ). Модальный диалог фильтра старого клиента заменён
встроенной панелью поиска в верхней части окна — такой же, как в отчётных формах.
Панель видна всегда; F9 лишь переводит курсор в первую строку поиска.
Панель содержит:
- две строки поиска и кнопку связки между ними — И / ИЛИ (щелчок переключает): при И подходят строки с обоими фрагментами, при ИЛИ — хотя бы с одним; заполнена одна строка — связка не действует;
- флажок «Учитывать регистр (Aa)»;
- переключатель «Поиск» / «Выборка»: в режиме поиска курсор переходит к следующей подходящей строке, в режиме выборки неподходящие строки скрываются;
- кнопки 🔍 (искать дальше) и ✕ (очистить и показать всё).
Отбор идёт по всем колонкам и выполняется на клиенте — Сервер не опрашивается,
поэтому поиск мгновенный; результат показывается в строке состояния. В режиме «Поиск»
строка ищется прямо по ходу набора; дальше Ctrl+↓ / Ctrl+↑
ходят по совпадениям вперёд и назад (работают и из таблицы, и из строки поиска, дойдя
до края — продолжают с другого конца), Enter в строке поиска заканчивает
поиск, оставляя курсор на найденной операции. Ctrl+Del очищает обе строки
поиска, не отрываясь от набора, — работает только в строке поиска: в таблице
Del удаляет операцию.
Свёрнутый показ. Опция «Операции свернуто» объединяет строки одной составной операции в одну запись — журнал становится компактнее. Разворачивать и сворачивать можно по ходу работы.
4.8. Ввод и правка операции
Ввод начинается клавишей F7 в журнале операций. Клиент показывает
дерево видов операций, полученное с Сервера; видны только ветви, на которые
у вас есть права. Ход ввода:
- Выбор вида операции в дереве —
Enterили двойной щелчок, отказ —Esc. - Ответы на вопросы: Сервер по очереди задаёт вопросы ветви — дата, сумма,
текстовые пояснения, выбор счёта или субсчёта. Ответ подтверждается
Enter, отказ от ввода —Esc. - Выбор счёта: если вопрос требует счёта, открывается окно со списком доступных
счетов и субсчетов; выбор —
Enter. При перезаписи операции курсор сразу стоит на прежнем ответе. - Запись: после последнего вопроса Сервер формирует операцию и её проводки, журнал обновляется.
Поиск-выборка в окне выбора счёта (НОВОЕ). Панель поиска есть и в окне выбора
счёта, но работает только выборкой: набранный текст сразу оставляет подходящие строки.
Поэтому Enter всегда означает «взять строку в операцию» — даже из строки
поиска берётся первая отобранная строка. Окна вопросов и списков счетов встают правее
дерева и ниже строки набираемой операции, не разворачиваясь во весь экран: до самой
записи видно и дерево, и то, что уже набрано. После ввода даты и положения операции
в дне курсор сам переходит в дерево — мышь не нужна.
Дерево помнит путь предыдущей операции. Однотипные операции идут подряд,
поэтому после записи клиент запоминает путь по дереву и при вводе следующей операции
подсвечивает на каждом уровне ту ветвь, что была в прошлый раз, — вы просто нажимаете
Enter, пока путь тот же. Свернули в сторону — дальше курсор встаёт на
первую ветвь уровня, как обычно. Ответы на вопросы при этом не подставляются:
поля всегда пустые. Ответы ограничены длиной, заданной в дереве (в типовых
конфигурациях — до 11 символов для коротких ответов); слишком длинный ответ Сервер
обрежет или отклонит.
Правка операции. Enter на строке журнала запускает
перезапись: Сервер задаёт те же вопросы заново, подставляя прежние ответы;
изменённая операция заменяет старую вместе со всеми проводками.
Удаление. Del или F8 удаляет операцию — с запросом
подтверждения, в котором показано, что именно будет удалено. Составная (групповая)
операция удаляется целиком.
D.
Без него Сервер вернёт отказ.
Многострочный ввод. Некоторые виды операций требуют ввода таблицы (например,
списка позиций документа). Для них открывается многострочная форма: Enter —
подтвердить строку, F2 — сохранить введённое, Esc — отказаться.
4.9. Виды операций
Дерево видов операций открывается пунктом «Документы → Виды операций» или
клавишей Alt+F6. Это справочник всех хозяйственных операций, настроенный
администратором на Сервере. Ветви дерева бывают:
- обычными — конечный вид операции, который можно ввести;
- ветвями-вопросами — задают вопрос и ветвятся в зависимости от ответа;
- ветвями-циклами — повторяют ввод, пока пользователь не откажется.
Кроме выбора операции, дерево служит справочником: по нему видно, какие операции предусмотрены в учёте предприятия и какие вопросы они задают. Некоторым ветвям Сервер может назначить горячие клавиши — тогда операция вводится одним нажатием, минуя дерево.
4.10. Проводки и первичные документы
Проводки. F6 на строке журнала показывает проводки, сформированные
операцией: дебет, кредит, сумма, пояснение. Проводки формирует Сервер по описанию вида
операции — вручную они не редактируются, изменить их можно только изменив саму операцию.
Первичные документы. F4 показывает первичный документ операции —
накладную, ордер, счёт, — если он предусмотрен видом операции. Документ приходит
с Сервера текстом и открывается в отдельном окне; его можно напечатать или записать
в файл.
Если включена опция «Хранить первичные документы», полученные документы
сохраняются в каталоге TXA. Это ускоряет повторный показ, но
сохранённый документ не обновляется автоматически: если операция изменилась,
документ нужно запросить заново.
4.11. Отчётные формы
Отчётная форма — основной инструмент анализа: оборотный баланс, ведомости, карточки
счетов, любые отчёты, написанные для вашего предприятия. Формы хранятся на Сервере;
список открывается пунктом «Документы → Формы на Сервере» (Alt+F4)
или кнопкой Формы; оборотный баланс вызывается сразу — Alt+F3 или
кнопка Об/Бал. Форму выбирают в списке и запускают Enter: Сервер
вычисляет её за текущий отчётный период и возвращает готовый текст, который клиент
показывает моноширинным шрифтом в отдельном окне. Внизу окна — строка состояния:
запрос, имя файла ответа Сервера, время выполнения и число строк; левая часть строки
копируется (Ctrl+C, Ctrl+A — выделить всю).
Курсор при открытии (НОВОЕ). Сразу после открытия формы курсор стоит в тексте
формы, на первой значащей строке: первой строке, у которой сразу за рамкой стоит
значащий знак, а не пробел (линии рамки и шапка колонок пропускаются) — в таблице это
первая строка данных. Так можно сразу листать строки и выполнять действия активной
строки, ничего не нажимая дополнительно. В строку поиска курсор переводится клавишей
Tab: первое нажатие — первая строка, второе — вторая, дальше обход кнопок
панели; Shift+Tab — назад, Esc из строки поиска — возврат
в текст формы.
Поиск в форме. Над текстом формы — та же панель поиска, что в журнале
операций: две строки, связка И/ИЛИ, учёт регистра, переключатель
«Поиск»/«Выборка». В режиме «Поиск» строка ищется по ходу набора;
Ctrl+↓ / Ctrl+↑ — следующее и предыдущее совпадение,
Enter в строке поиска заканчивает поиск, оставляя курсор на найденной
строке (следующий Enter выполняет её действие N:ENTER:),
Ctrl+Del очищает строки поиска. Каждая форма открывается с пустой строкой
поиска: отбор относится к той форме, в которой его набрали, — перейдя по кнопкам формы
в другую, вы увидите её целиком. Набранное раньше не пропадает — оно в выпадающем
списке строки поиска; пересчёт формы (Пробел, автообновление) строку
поиска сохраняет.
Закреплённая первая строка (НОВОЕ). Если первая строка формы начинается с пробела, она считается шапкой и закрепляется вверху окна: при прокрутке остаётся на месте, как закреплённая строка в Excel (закрепляется ровно одна строка). Такая строка выделена мягкой жёлтой плашкой.
Подсказка формы (НОВОЕ). Последняя строка формы, начинающаяся с символа
■ (Alt+254), в текст не попадает — это подсказка автора формы,
и клиент печатает её внизу окна на той же мягкой жёлтой плашке. Плашка появляется,
только когда подсказка есть.
Отбор по значению ячейки (НОВОЕ). Ctrl + щелчок левой кнопкой по
ячейке подставляет её значение в первую строку поиска, и форма тут же отбирается по
нему; границы ячейки клиент определяет сам — по линиям рамки и по двойным пробелам.
Режим панели при этом не меняется; чтобы снять отбор, очистите строку поиска. То же
без мыши — Ctrl+Enter в тексте формы: клиент берёт текущую строку, а ячейку
спрашивает маленьким списком (стрелки и Enter; одна ячейка в строке —
список не появляется).
Меню строки (НОВОЕ). Правая кнопка мыши в тексте формы (или
Shift+F10 с клавиатуры) открывает меню: Закрыть форму (прежнее
действие правой кнопки; файл ответа Сервера удаляется), Отбор по значению ячейки,
Копировать значение ячейки (то же делает Ctrl+C в тексте формы),
Копировать ссылку на форму (Ctrl+Shift+C, см. п. 4.22). Пункты
«по ячейке», вызванные с клавиатуры, спрашивают ячейку тем же списком, что и
Ctrl+Enter.
Масштаб (НОВОЕ). Ctrl + колесо мыши увеличивает и уменьшает шрифт
формы от 6 до 24 пунктов. Меняется только это окно и только до его закрытия — настройки
оформления и другие окна не затрагиваются; общий шрифт задаётся в «Опции → Оформление…».
Автообновление. Данные на Сервере меняются другими пользователями, и открытая
форма может устареть: клиент показывает в полосе состояния жёлтую пометку
«Возможно устарело». Поведение задаётся в «Опции → Автообновление»:
Нет — только предупреждение, пересчёт по Пробел; Да — форма
пересчитывается сама. В режиме «Да» сама пересчитывается только форма на переднем плане
(НОВОЕ); остальные окна получают пометку и пересчитываются в момент переключения на них.
Пометка «Период изменен» (смена отчётного периода) снимается только вручную —
Пробел. Всё это относится и к журналу операций; свою собственную запись,
правку или удаление журнал подхватывает сразу, без предупреждения.
Числа. Две опции влияют на вид чисел во всех формах: «Числа с запятыми» (разделение разрядов) и «Числа с копейками» (два знака после запятой). Обе передаются Серверу вместе с запросом, поэтому пересчёт формы после их изменения обязателен.
Действия строк формы. Форма может не только показывать данные, но и действовать:
реагировать на Enter, клавиши F1…F9,
Shift+F1…Shift+F9, открывать другие формы и запускать внешние
программы. Всё это описывается управляющими строками N: в тексте формы —
их синтаксис и возможности разобраны в отдельной главе
«Управляющие строки N:».
F4. В CLWP это
Ctrl+F4 — клавиша F4 освобождена для кнопок формы
N:F4:. При этом Ctrl+F4 не закрывает окно: закрытие —
Esc, крестик или пункт «Закрыть форму» в меню по правой кнопке.
4.12. Аргументы и фильтры
Это два разных механизма сужения отчёта, и различать их важно.
- Аргумент — грубый отбор на Сервере. Передаётся Серверу вместе с запросом формы и участвует в вычислении: Сервер обрабатывает только подходящие операции. Быстро, годится для больших объёмов — например, «только склад №2».
- Фильтр — тонкий отбор на клиенте. Применяется к уже полученному тексту формы: остаются строки, содержащие заданные фрагменты. Сервер при этом считает всё, поэтому на больших отчётах фильтр медленнее аргумента, зато отбирает по любому месту строки.
Наборы задаются в «Опции → Аргументы и фильтры…»: для каждой формы можно
описать до восьми аргументов и до восьми фильтров, а затем переключать их прямо в
открытой форме клавишами Shift+F1…Shift+F9.
N:SHIFTFn: для этого сочетания,
её действие имеет приоритет над переключением аргумента/фильтра — см. главу
«Управляющие строки N:».
4.13. Формы на клиенте
Кроме форм Сервера, можно держать собственные формы в файлах .RPT.
Список открывается пунктом «Документы → Формы на Клиенте» (Alt+F7);
рядом с именем файла показывается его первая строка — обычно название отчёта.
Формы этой базы лежат в её рабочем каталоге (п. 4.2), рядом с CL.DIR
и настройками — у каждой базы свой набор. В списке показываются ещё и формы из каталога
программы (НОВОЕ): администратор кладёт туда формы, общие для всех баз; при совпадении
имён побеждает форма своей базы.
| Клавиша | Действие |
|---|---|
Enter или двойной щелчок | Выполнить форму на Сервере и показать результат. |
F4 | Открыть форму в редакторе. |
Del | Удалить файл формы (с подтверждением). |
Esc | Закрыть окно. |
Локальная форма выполняется Сервером так же, как серверная: текст скрипта передаётся Серверу, Сервер считает и возвращает готовый отчёт. Разница только в месте хранения — файл лежит у вас, поэтому его можно свободно править, не имея прав на изменение форм Сервера.
4.14. Список запросов
Окно «Запросы к Серверу» (Alt+F9, кнопка Запросы)
позволяет отправить Серверу директиву напрямую — это инструмент опытного пользователя
и администратора: с его помощью проверяют формы, права, отдельные значения. Строка
запроса — текст директивы; кнопка «Отправить» или Enter выполняет
её; стрелки вверх и вниз перебирают стопку ранее отправленных запросов. Запрос,
начинающийся с >, запускает внешнюю программу, а не отправляется
Серверу.
Список ведёт себя как журнал всех запросов (НОВОЕ). Пока окно открыто, в список
попадает каждый запрос клиента к Серверу, а не только набранный здесь: открытие
формы, журнал операций, кнопки формы, запросы строк N:. Любой запрос можно
выбрать стрелками и повторить Enter — например, разобраться, какой
директивой открылась форма, или повторить её с другими аргументами. Список держит
последние 50 строк (самая старая уходит сверху); подряд идущие одинаковые запросы
не повторяются. Окно разворачивается по тем же правилам, что и отчётная форма,
и запоминает свой размер.
R — выполнить форму Сервера,
G — выполнить переданный текст формы, J — журнал операций,
L — первичный документ, C — компиляция формы,
U — пользователи. Ответ, начинающийся с E-, — сообщение
об ошибке. Полное описание директив — в главах «Директивы»
и «Протокол обмена».
4.15. Редактор форм
Встроенный редактор служит для написания и отладки отчётных форм. Он открывается из
меню «Редактор», клавишей F4 в списке форм на клиенте, переносом
открытой формы (Ctrl+F4), а также клавишей Ctrl+F7 — из окна
редактора и из любого другого окна клиента.
Несколько файлов одновременно (НОВОЕ). Каждый открытый файл получает своё окно
редактора, поэтому строки удобно переносить из одного файла в другой через буфер обмена
(Ctrl+C / Ctrl+V). Вверху каждого окна редактора — вкладки всех
открытых файлов: текущий выделен жирным, щелчок по вкладке переключает на другой файл,
звёздочка у имени — файл изменён и не записан. Окна видны и в меню «Окно»; там же их можно
расставить рядом. Если файл уже открыт, повторное открытие просто выводит его окно вперёд —
две копии одного файла затирали бы правки друг друга при записи. Пустое окно, открытое
пунктом «Редактор → Новый», занимается первым открываемым файлом.
| Клавиша | Действие |
|---|---|
F2 | Сохранить файл. |
Ctrl+F7 | Открыть файл — из окна редактора и из любого другого окна клиента (НОВОЕ; в CLW32 — F3). Каждый файл открывается в своём окне; в диалоге можно отметить сразу несколько файлов. |
Ctrl+V, Shift+Ins | Вставить из буфера обмена (НОВОЕ). Вставляется только текст (без чужих шрифтов и цветов), все вставленные строки сразу раскрашиваются. |
F4 | Поставить символ · (то же, что Alt+250) — разделитель строковых значений (НОВОЕ). Список шаблонов (готовых фрагментов языка форм) теперь открывается из меню «Редактор → Шаблоны». |
F5 | Поставить символ ■ (то же, что Alt+254) (НОВОЕ). Оба символа ставятся и кнопками внизу окна. |
F6 | Компилировать (НОВОЕ): изменённый текст записывается в свой файл, и Серверу уходит штатный запрос W FORM (перекомпилировать изменённые формы); ответ открывается обычной отчётной формой. |
F7 | Найти / найти дальше (НОВОЕ): если найденное уже видно на экране, окно не прокручивается; если не видно — прокручивается так, чтобы строка с найденным стала пятой сверху. |
F8 | Выполнить форму (НОВОЕ): Серверу уходит директива G имя_файла, за ней — текст формы из окна редактора (несохранённая правка тоже). Сервер компилирует и выполняет форму, ответ открывается обычной отчётной формой — так же, как «Выполнить» в окне «Формы на клиенте». |
F9 | Режим рисования линий по циклу: выключено → одинарные → двойные (двойных в CLW32 не было). |
Ins | Вставка / замена (индикатор Ins/Ovr в строке состояния). |
Alt+цифры | Перейти к строке: держа Alt, наберите номер цифрами верхнего ряда и отпустите Alt (НОВОЕ). |
Ctrl+Z | Отменить последнюю правку (НОВОЕ). |
Ctrl+Y, Ctrl+Shift+Z | Вернуть отменённое (НОВОЕ). |
Ctrl+T | Светлая / тёмная тема редактора (НОВОЕ). |
Esc | Закрыть редактор; если текст изменён — будет предложено сохранить. |
Подсветка синтаксиса. Цветом различаются (НОВОЕ): строки-комментарии (начинаются
со звёздочки), управляющие строки N:, ключевые слова языка форм
(if, for, goto, print и прочие),
обозначения функций в квадратных скобках (включая подпрограммы вида [:RTV…),
текст в апострофах, вставки значений ^имя, фигурные скобки и подстановки
~N, строки вывода в файл >FILE. Подсветку можно отключить
пунктом «Редактор → Синтаксис», цвета настраиваются в «Опции → Оформление…».
Парные скобки (НОВОЕ): когда курсор стоит у круглой или квадратной скобки, она
и её пара подсвечиваются фоном.
Тема и номера строк (НОВОЕ). Кнопка «Тема» внизу окна (или
Ctrl+T) переключает светлое и тёмное оформление редактора; у тёмной темы
свой набор цветов. Кнопка «№ строк» показывает или прячет полосу с номерами строк
слева. Выбор запоминается и восстанавливается при следующем открытии редактора.
Позиция курсора и переход к строке (НОВОЕ). Слева в строке состояния жирным
показано, где стоит курсор: «Стр 12 : Кол 5» — строка и колонка (обе считаются
с единицы). Для перехода к строке держите Alt и наберите номер строки цифрами
верхнего ряда клавиатуры, затем отпустите Alt — курсор встанет в начало
этой строки; пока номер набирается, в строке состояния видно «Перейти к строке 12…».
Если строка уже на экране, окно не сдвигается; если нет — прокручивается так, чтобы она
стала пятой сверху. Номер больше числа строк ведёт на последнюю. Цифры цифрового блока
с Alt по-прежнему набирают символы (Alt+250 — ·,
Alt+254 — ■).
Отмена и возврат правок (НОВОЕ). Ctrl+Z отменяет последнюю правку,
Ctrl+Y (или Ctrl+Shift+Z) возвращает отменённое. Отменяются
только правки текста — набор, удаление, вставка, линии, символы F4/F5;
подсветка синтаксиса в историю не попадает. Набранное подряд, без пауз, отменяется одним
нажатием. История начинается заново при открытии файла, смене темы (Ctrl+T)
и включении подсветки.
Цикл отладки формы: написать или открыть текст → F6 (компиляция:
Серверу уходит запрос W FORM, его ответ открывается отчётной формой; изменённый
текст перед этим сам записывается в файл) → исправить ошибки, на которые указал Сервер, и
снова F6 → F8 (выполнение, проверить результат в открывшемся окне)
→ F2 (сохранить готовую форму в файл .RPT).
4.16. Печать, запись в файл, экспорт в Excel
Печать. «Документы → Печать» (Alt+F5) печатает содержимое
активного окна — журнала операций, отчётной формы или первичного документа — сразу,
без единого диалога: принтер, число комплектов и поля берутся из настроек, а ориентация
листа и размер шрифта подбираются по ширине формы. Плашка в углу сообщает, на какой
принтер ушёл документ.
Когда для одного документа нужны другие параметры — «Документы → Печать с
параметрами…» (Ctrl+Alt+F5, НОВОЕ): один диалог, где сразу принтер,
комплекты, ориентация, шрифт, поля и кнопки «Печать» и «Просмотр».
Выбранное запоминается и становится умолчанием быстрой печати; те же параметры задаются
заранее в «Опции → Печать…». Предлагаются только равноширинные шрифты — колонки
формы держатся на одинаковой ширине знака. В окне предпросмотра F5 или
Enter печатают, Esc закрывает.
PRN/LPT
и преобразование кодировки OEM в Windows — не переносились: они больше не нужны.
Запись в файл. «Документы → Запись в файл» (Alt+F8)
сохраняет содержимое активного окна в текстовый файл; имя предлагается по умолчанию,
каталог — любой. Отчётные формы записываются строка в строку, журнал операций — с
разбивкой длинных строк.
Экспорт в Excel (НОВОЕ). «Документы → Экспорт в Excel»
(Ctrl+E) выгружает таблицу активного окна в книгу Excel (xlsx)
с сохранением колонок — в отличие от записи в текстовый файл, числа остаются числами
и пригодны для дальнейших расчётов.
4.17. Опции
Все настройки собраны в меню «Опции» и сохраняются между сеансами.
- Время ожидания ответа — сколько клиент ждёт ответа Сервера, прежде чем счесть запрос затянувшимся: от 30 секунд до 5 минут либо «Неограниченно» (фактически 6 минут — столько же ждал старый клиент). Увеличьте значение при медленной сети или тяжёлых отчётах. Что происходит по истечении — см. п. 4.18.
- Автообновление — Нет: формы только предупреждают об устаревании; Да: пересчитывается форма на переднем плане, фоновые — при переключении на них (п. 4.11).
- Числа с запятыми / Числа с копейками — формат чисел во всех отчётах: разделение разрядов и показ копеек; передаются Серверу с запросом.
- Хранить первичные документы — сохранять документы в каталоге
TXA; ускоряет повторный показ, но копия не обновляется автоматически (п. 4.10). - Операции свернуто — показывать составные операции одной строкой в журнале.
- Оформление… — шрифты и цвета журнала операций, отчётных форм и редактора, цвета подсветки синтаксиса и служебной информации. В старом клиенте это были три отдельных пункта; здесь они объединены в один диалог, а размеры и положение окон запоминаются автоматически.
- Тема (НОВОЕ) — оформление всего клиента: семь градаций от самой светлой к самой тёмной («Светлая — мягкая», «Светлая — обычная», «Светлая — системная», «Тёмная — мягкая», «Тёмная — обычная», «Тёмная — глубокая», «Тёмная — ночная»), отличающиеся только контрастом. Тема применяется ко всем окнам сразу, перезапуск не нужен; у каждой базы свой файл настроек, поэтому темой удобно различать базы.
- Печать… — принтер, число комплектов, ориентация, шрифт печати (равноширинный,
с кеглем) и поля — всё, чем печать пользуется по
Alt+F5. - Определения клавиш… — кнопки-макросы
Alt+F1…Alt+F9: для каждой задаются название (до 20 символов, оно появится на панели инструментов) и командная строка (до 41 символа — любая директива Сервера). - Аргументы и фильтры… — наборы аргументов и фильтров по формам (п. 4.12).
- Год базы… (НОВОЕ) — год, к которому относятся данные на Сервере; от него зависят год отчётного периода, границы календаря и надпись в заголовке главного окна. Год задаётся вручную, потому что в протоколе ФБП года нет: период и директивы ввода оперируют только месяцем и днём, а на запрос текущей даты Сервер отвечает системным годом своей машины. При входе подставляется год, названный Сервером; заданное вами значение запоминается отдельно для каждого каталога обмена. На Сервер год не передаётся — он влияет только на то, что вы видите в клиенте.
- Калькулятор — открывает окно калькулятора (
Ctrl+F3).
Alt+F2, эта клавиша перестанет открывать журнал
операций — он останется доступен через меню и кнопку панели. Свободна от встроенных
назначений только Alt+F1.
4.18. Долгий запрос к Серверу (НОВОЕ)
Тяжёлый отчёт, занятый Сервер или медленная сеть — и клиент ждёт ответа. В старом клиенте окно в это время просто замирало, отменить запрос было нельзя. Теперь ожидание видно и им можно управлять.
Если ответ не пришёл за две секунды, в правом нижнем углу главного окна появляется плашка «Запрос к Серверу»: текст запроса, бегущая полоса и счётчик секунд. Плашка не забирает фокус и ничего не блокирует — окна клиента остаются живыми, их можно двигать и листать. При коротком ответе плашка не появляется вовсе.
Кнопка «Прервать» отказывается от ожидания: если Сервер ещё не успел забрать файл запроса, запрос отменяется полностью; если уже забрал — ответ придёт «в пустоту», и клиент уберёт его сам при следующем обращении. Сообщений об ошибке при этом нет. Окно, которое только открывалось этим запросом, просто закроется; уже открытые окна останутся в прежнем виде.
Когда истекает время, заданное в «Опции → Время ожидания ответа», полоса замирает,
счётчик становится красным и рядом появляется кнопка «Ждать ещё» — она добавляет
столько же времени. Сам по себе клиент запрос не снимает: решение всегда за вами.
Обе кнопки работают с клавиатуры из любого окна, пока плашка видна: Esc —
«Прервать», Enter — «Ждать ещё».
4.19. Калькулятор
Калькулятор вызывается Ctrl+F3 или пунктом «Опции → Калькулятор».
Окно немодальное (НОВОЕ): его можно оставить открытым и продолжать работать
с журналом и формами. Возможности:
- обычные арифметические выражения со скобками;
- обращение к оборотам счетов — значение запрашивается у Сервера и подставляется в выражение;
- расчёт НДС — выделение и начисление;
- история вычислений; результат предыдущего доступен как «итог» /
ans; Enter— вычислить,F10— перенести результат в поле ввода того окна, из которого был вызван калькулятор,Esc— закрыть.
4.20. Нейросеть GigaChat (НОВОЕ)
Меню «Нейросети» → «GigaChat (Сбер)» открывает окно чата: можно спросить у нейросети то, что обычно ищут в интернете, — ставку налога, порядок заполнения отчёта, формулировку для договора, — не выходя из клиента. Окно немодальное и одно на сеанс: повторный выбор пункта меню показывает уже открытое окно, переписка не разрывается. Меню названо во множественном числе не случайно: сетей со временем будет несколько, пока подключена одна.
Как получить ключ. Доступ к GigaChat даёт не автор клиента, а Сбер, и у каждого пользователя ключ свой — он привязан к аккаунту и к личному счётчику токенов. Ключ бесплатный. Порядок: в окне чата нажмите «Настроить доступ…» и ссылку «Открыть личный кабинет developers.sber.ru»; войдите по Сбер ID и создайте проект «GigaChat API», выбрав тип доступа — для физического лица или для юридического лица / ИП; в проекте откройте «Настройки API → Авторизационные данные» и нажмите «Сгенерировать новый Client Secret»; скопируйте строку «Ключ авторизации» в поле окна «Настроить доступ…», выберите там же тот же тип доступа и нажмите «Сохранить».
Ключ и тип доступа хранятся в файле настроек рабочего каталога базы
(CLWP.настройки.xml, п. 4.2); полный путь показан в окне настройки.
Работаете с несколькими базами — ключ придётся вставить в каждую.
Как пользоваться. Вопрос набирается в поле внизу, Enter —
отправить; пока идёт ответ, поле ввода недоступно. Переписка ведётся с памятью:
к каждому новому вопросу клиент прикладывает предыдущие, поэтому можно уточнять.
История сохраняется в рабочем каталоге базы в файле
CLWP.ЧатИИ.История.xml и восстанавливается при следующем открытии окна.
Кнопка «Очистить переписку» стирает всё — и содержимое окна, и файл на диске
(с подтверждением; восстановить очищенное нельзя). F1 из окна чата
открывает раздел помощи о чате.
4.21. Избранное и недавние команды (НОВОЕ)
Чтобы не набирать одни и те же запросы изо дня в день, в главном меню есть пункт «Избранное» — в нём три части: свои сохранённые команды, подменю «Недавние (Список Запросов)» и служебные пункты. Списки хранятся в профиле Windows и привязаны к имени пользователя: за одним компьютером каждый видит только своё избранное.
Недавние. Клиент запоминает команды, запущенные вручную: набранные в
окне «Список Запросов», вызванные кнопкой-макросом или Alt+Fn, выбранные
из самого «Избранного». Служебные обращения форм к Серверу (кнопки формы, дозапросы,
автообновление) в список не попадают. Помнится до 15 штук; последняя команда стоит
первой, повторный запуск поднимает её наверх. Пункт «Очистить список» стирает недавние.
Избранное. «Добавить в избранное…» открывает окно с двумя полями: в поле
Команда уже подставлена последняя выполненная команда, поле Название —
подпись для меню (пустое — видна сама команда). «Настроить избранное…» показывает
таблицу «Название / Команда»: строки редактируются прямо в ячейках, новая добавляется
в пустой строке внизу, лишняя удаляется Del по заголовку строки; порядок
строк — это порядок пунктов в меню.
Поиск команды. Пункт «Найти команду…» или Ctrl+Q открывают окно,
где в одном списке собраны пункты главного меню, избранные и недавние команды. Набор
текста сужает список: слова могут идти в любом порядке, регистр не важен
(«опер журн» найдёт «Документы → Журнал операций»). Стрелки двигают выбор,
Enter выполняет, Esc закрывает.
4.22. Ссылки на формы (НОВОЕ)
Чтобы показать коллеге не картинку, а ту же самую форму, у любой отчётной формы можно
взять ссылку и передать её — письмом, в сообщении, запиской. Ссылка — это строка
запроса формы, та самая, что видна в строке состояния внизу окна; получатель может
вставить её куда угодно — в окно «Список Запросов», в макрос Alt+Fn,
в «Избранное», — и она везде сработает.
Копировать ссылку — Ctrl+Shift+C в открытой форме, либо правая
кнопка мыши → «Копировать ссылку на форму», либо меню «Документы → Копировать ссылку
на форму». Строка кладётся в буфер обмена, внизу окна на пару секунд появляется
подтверждение. Обычное Ctrl+C под ссылку не занято: оно по-прежнему
копирует выделенное в строке состояния и в полях ввода.
Открыть по ссылке — Ctrl+Shift+V или «Документы → Открыть по
ссылке…»: окно с одним полем, куда уже подставлено содержимое буфера обмена;
Enter — выполнить, Esc — отказаться. Если ссылка пришла
письмом и склеилась с подписью, берётся первая непустая строка. Строка выполняется тем
же путём, что команды избранного и макросы, поэтому понимает не только отчётные формы
(R), но и журнал операций (J), дерево видов операций
(T), формы на клиенте (LW, FCL) и запуск внешней
программы (>). Выполненная ссылка попадает в «Недавние».
Shift+Fn)
— они уходят на Сервер служебными байтами, а не текстом запроса; отчётный период
— это общая настройка сеанса, и чужая ссылка молча переставила бы её во всех ваших
окнах; контекст незавершённой операции — у получателя такой операции нет.
Если у формы нет строки запроса (формы из редактора или из списка форм на клиенте),
клиент сообщит: копировать нечего.
4.23. Поля ввода: история, календарь, расчёт (НОВОЕ)
История ранее введённого. В вопросах отчётных форм и в строке запроса окна
«Список Запросов» клиент запоминает введённое и подсказывает при наборе; полный список
открывает F4 (или Ctrl+↓), выбранное подставляется в поле.
История хранится между запусками и отдельно для каждого пользователя; на каждый вопрос
помнится до 15 последних ответов, повтор поднимается наверх. Стереть накопленное можно
пунктом «Опции → Забыть историю полей…» — он убирает только вашу историю.
Календарь у поля даты. Если вопрос спрашивает дату, рядом с полем появляется
кнопка ▼, а F4 открывает календарь. Выбранная дата подставляется
в том же виде, в каком поле её показывало: было две цифры года — будет две, было
четыре — будет четыре. Enter в календаре берёт выделенный день,
Esc закрывает без изменений. У прочих полей календаря нет:
F4 там показывает историю.
Расчёт прямо в поле. В поле суммы или числа можно набрать не готовое число,
а выражение — со сложением, вычитанием, умножением, делением и скобками.
Первый Enter считает его и подставляет результат в поле, ничего
никуда не отправляя; второй Enter подтверждает ответ. Запятую можно
набирать вместо точки — считается одинаково, а в поле подставляется число с точкой, как
ждёт Сервер. Деление на ноль клиент покажет сообщением и ответ не отправит. Выражения
с функциями языка форм в поле не считаются — для них есть калькулятор
(Ctrl+F3).
4.24. Горячие клавиши
Все клавиши клиента, разложенные по окнам.
Общие (работают в любом окне)
| Клавиша | Действие |
|---|---|
F1 | Помощь. В окне помощи: F3 — искать далее, Shift+F3 — назад, Ctrl+F — строка поиска. |
Alt+F1 | Свободна — только под пользовательский макрос. |
Alt+F2 | Журнал операций. |
Alt+F3 | Оборотный баланс. |
Alt+F4 | Формы на Сервере (приложение не закрывается). |
Alt+F5 | Печать (сразу, без диалогов). |
Ctrl+Alt+F5 | Печать с диалогом параметров. |
Alt+F6 | Виды операций (дерево). |
Alt+F7 | Формы на клиенте. |
Alt+F8 | Запись в файл. |
Alt+F9 | Список запросов. |
Ctrl+F3 | Калькулятор. |
Ctrl+O | Отчётный период. |
Ctrl+E | Экспорт в Excel. |
Ctrl+Q | Поиск команды: пункты меню, избранное и недавние в одном списке. |
Ctrl+C / Ctrl+A | Копировать выделенное в строке состояния / выделить её целиком (нижняя строка окна: запрос и файл ответа Сервера). |
Ctrl+Shift+C | Копировать ссылку на открытую отчётную форму (её строку запроса). |
Ctrl+Shift+V | Открыть форму по ссылке из буфера обмена. |
Esc | Закрыть текущее окно. |
Пользовательский макрос, назначенный на Alt+Fn, отменяет встроенное
действие этой клавиши.
Журнал операций
| Клавиша | Действие |
|---|---|
F7 | Ввод новой операции. |
Enter | Правка операции. |
Del / F8 | Удаление операции. |
F4 | Первичный документ. |
F6 | Проводки. |
F9 | Курсор в строку поиска (сама панель видна всегда). |
Tab / Shift+Tab | Из списка — в первую строку поиска, второе нажатие — во вторую; дальше по кнопкам панели (и обратно). |
Ctrl+↓ / Ctrl+↑ | Режим «Поиск»: следующая / предыдущая подходящая операция. Из таблицы и из строки поиска. |
Enter в строке поиска | Закончить поиск: курсор в таблицу, на найденную операцию. |
Ctrl+Del в строке поиска | Очистить обе строки поиска, не отрываясь от набора. Работает только в строке поиска: в таблице Del удаляет операцию. |
Home / End | В начало / в конец. |
Пробел | Обновить. |
Отдельного окна поиска по F9, как в старом клиенте, больше нет:
панель поиска постоянно находится вверху окна журнала операций.
Отчётный период
| Клавиша | Действие |
|---|---|
F4 | Поле начала периода. |
F5 | Поле конца периода. |
Tab / Shift+Tab | Следующий / предыдущий месяц целиком. |
Отчётная форма
| Клавиша | Действие |
|---|---|
Пробел | Пересчитать. |
Enter | Действие N:ENTER:. |
F1…F9 | Кнопки формы N:Fi:. |
F2 | Подчинённая форма (детализация). |
Shift+F1…Shift+F9 | Аргументы и фильтры либо N:SHIFTFi:. |
Ctrl+F4 | Перенести в редактор (окно не закрывается). |
Tab / Shift+Tab | Первая строка поиска, затем вторая (и обратно). |
Ctrl+↓ / Ctrl+↑ | Режим «Поиск»: следующая / предыдущая найденная строка. Из текста формы и из строки поиска. |
Enter в строке поиска | Закончить поиск: курсор в текст формы, на найденную строку. |
Ctrl+Del в строке поиска | Очистить обе строки поиска, не отрываясь от набора; курсор остаётся на найденной строке. |
Ctrl+Enter | Отбор по значению ячейки текущей строки. |
Ctrl+C | Копировать значение ячейки текущей строки. |
Shift+F10 | Меню строки (как по правой кнопке мыши). |
Поля ввода (вопросы операции и форм, строка запроса)
| Клавиша | Действие |
|---|---|
F4 / Ctrl+↓ | Список ранее введённого в этот же вопрос (в вопросах формы и в строке запроса; при вводе операции истории нет); в поле даты — календарь. |
Enter | В поле суммы: первое нажатие считает набранное выражение, второе подтверждает ответ. |
Окно выбора счёта (ввод операции)
| Клавиша | Действие |
|---|---|
Enter | Взять строку в операцию — в том числе из строки поиска. |
Esc | Отказаться от выбора. |
Окно помощи
| Клавиша | Действие |
|---|---|
Ctrl+C | Копировать выделенный текст. |
Ctrl+A | Выделить весь текст. |
Ctrl+F | Курсор в строку поиска. |
Ctrl+↓ / Ctrl+↑ | Искать далее / назад (F3 и Shift+F3 — то же самое). |
Ctrl+Del | Очистить строку поиска и снять подсветку. |
Esc | Закрыть окно помощи. |
Редактор форм
| Клавиша | Действие |
|---|---|
F2 | Сохранить. |
Ctrl+F7 | Открыть файл (из любого окна клиента). |
F4 / F5 | Поставить символ · / ■. |
F6 | Компилировать (запрос W FORM). |
F7 | Найти / найти дальше (окно сдвигается, только если найденное не видно). |
F8 | Выполнить (G имя + текст формы). |
F9 | Линии: нет → одинарные → двойные. |
Ins | Вставка / замена. |
Alt+цифры | Перейти к строке с этим номером. |
Ctrl+Z | Отменить правку. |
Ctrl+Y, Ctrl+Shift+Z | Вернуть отменённое. |
Формы на клиенте
| Клавиша | Действие |
|---|---|
Enter | Выполнить форму. |
F4 | Открыть в редакторе. |
Del | Удалить файл формы. |
Список запросов
| Клавиша | Действие |
|---|---|
Enter | Отправить запрос. |
↑ / ↓ | Стопка прежних запросов. |
Калькулятор
| Клавиша | Действие |
|---|---|
Enter | Вычислить. |
F10 | Перенести результат в поле ввода вызвавшего окна. |
Esc | Закрыть. |
Чат с нейросетью
| Клавиша | Действие |
|---|---|
Enter | Отправить вопрос (курсор в поле ввода). |
F1 | Раздел помощи о чате. |
| — | Кнопка «Очистить переписку»: стереть окно и файл истории. |
Плашка «Запрос к Серверу»
| Клавиша | Действие |
|---|---|
Esc | Прервать запрос. |
Enter | «Ждать ещё» (когда время ожидания истекло). |
4.25. Пользователи и права
Имена, пароли и права (T, R, J, D,
P, E, U) заводит администратор на Сервере — см.
главу «Права пользователей». Клиент лишь показывает то, что
Сервер разрешает: недоступные ветви операций не видны в дереве, недоступные формы — в
списке форм, а на запрещённое действие Сервер отвечает отказом E-…,
который клиент показывает в строке состояния окна, в котором выполнялось действие.
4.26. Если что-то не работает
| Признак | Что проверить |
|---|---|
| Не удаётся зарегистрироваться | Правильность пути к каталогу обмена и доступ к нему на запись; имя пользователя и пароль; работает ли Сервер. |
| Долгий ответ или сообщение об ожидании | Увеличьте «Опции → Время ожидания ответа»; проверьте загрузку сети и Сервера. |
Ответ начинается с E- | Это сообщение Сервера об ошибке —
текст после E- объясняет причину (нет прав, ошибка в форме, неверный запрос). |
| Нужной ветви нет в дереве операций | Нет права T на эту ветвь —
обратитесь к администратору. |
| Нужной формы нет в списке | Нет права R на эту форму. |
| Не удаётся удалить операцию | Операция введена другим пользователем, а права
D нет; либо операция относится к закрытому периоду. |
| Данные в форме устарели | Нажмите Пробел или включите
«Опции → Автообновление → Да»: форма на переднем плане пересчитывается сама, остальные —
когда вы к ним переключитесь. |
Клавиша Alt+Fn делает не то | На неё назначен пользовательский макрос — проверьте «Опции → Определения клавиш…». |
| Первичный документ не соответствует операции | Включено «Хранить первичные документы», показана сохранённая копия — запросите документ заново. |
| Чат с нейросетью: «доступ не настроен» | Ключ ещё не введён. Нажмите «Настроить доступ…» — как получить ключ, написано там же и в п. 4.20. |
| Чат с нейросетью: отказ с кодом 401 или 403 | Ключ скопирован не целиком либо тип доступа не совпадает с тем, на кого оформлен доступ в личном кабинете (физлицо / юрлицо). Исправляется в окне «Настроить доступ…». |
| Чат с нейросетью: отказ с кодом 402 или 429 | Кончился бесплатный запас токенов или слишком часто идут запросы — остаток смотрите в личном кабинете developers.sber.ru. |
| Нейросеть не знает данных вашей базы | Так и задумано: в запрос не передаётся ничего из базы — ни счетов, ни сумм, ни операций (п. 4.20). |
| Чат отвечает не о том, о чём спрашиваете | К новому вопросу прикладываются предыдущие, и старая тема тянет ответы за собой. Нажмите «Очистить переписку» и задайте вопрос заново. |
| Внизу окна чата: «отправлены последние N сообщений из M» | Так и задумано: на сервер уходит только хвост переписки (не более 20 сообщений и 8000 знаков). В окне видно всё (п. 4.20). |
5. Имена, пароли и права пользователей
ФБП имеет собственную, не зависящую от сетевой ОС систему разделения прав.
Список пользователей и их прав хранится в файле _RIGHTS_.FBP в каталоге
данных сервера.
5.1. Файл _RIGHTS_.FBP
Если при первом старте сервера файла прав нет, он создаётся автоматически с
единственным пользователем SUPERVISOR без пароля и с максимальными
правами.
Формат файла — текстовый (допустимы строки и с CRLF, и с LF):
- строка
имя_пользователя [пароль]— с начала строки, без ведущих пробелов; пароль отделяется от имени хотя бы одним пробелом; - каждому праву предшествует хотя бы один пробел;
- имя — латинские буквы и цифры, начинается с буквы, регистр не различается; пароль — те же символы, регистр различается; предельная длина имени и пароля — 12 литер;
- всего — до 1000 пользователей.
5.2. Виды прав
| Право | Разрешает |
|---|---|
T | использовать ветви дерева видов операций для ввода
операций (директива O) |
R | выполнять отчётные формы (директива R) |
J | видеть операции других пользователей в журнале |
D | удалять операции других пользователей |
P | вводить и удалять операции, предшествующие текущему дню |
E | получать сведения о счетах (директива E) |
U | управление: получать имена, пароли и права (директива
U); одновременно — право применять директивы K,
Q, M, W |
Уточнения прав:
- Право T — список доступных ветвей дерева; разделитель и ограничитель —
знак
·(код 250, Alt+250). Все ветви:T ·ALL·. Ветви можно указывать до третьего уровня, разделитель уровней — знак`(код 96):T ·Касса`приход·Расчетный счет·. - Право R — список форм через пробел; все формы:
R ALL. Идентифицируются только имена форм, начинающиеся с буквы, — отсюда традиционный запрет на обозначения счетов, начинающиеся с цифры. - Права J и D — можно ограничить списком имён пользователей через запятую:
J SVETA,D OLGA,SUPERVISOR.
5.3. Право P и доступ в прошлое
| Запись | Разрешённый период |
|---|---|
P (без уточнения) | любой месяц прошлого |
P -1 | только текущий месяц |
P -2 | текущий и предыдущий месяцы (и так далее —
-N отсчитывает N месяцев от текущего, включая его) |
P AH | перечисление букв месяцев без пробелов в любом
порядке (A — январь, H — август) |
5.4. Пример файла прав
SUPERVISOR SUPER123 T ·ALL· R ALL J D P E U
OLGA T ·Касса· R ALL J D P -1
SVETA T ·ALL· R OBOROTKA,SALDO J OLGA P -2
DIMON T ·Склад· R ALL
AUTOMAT T ·Импорт· R ALL
Здесь SUPERVISOR — администратор с полными правами;
OLGA работает только с ветвью «Касса», видит чужие операции и может
вводить операции в текущем месяце; AUTOMAT — технологическая учётная
запись для шлюза обмена.
5.5. Директива U — просмотр прав
| Форма | Ответ |
|---|---|
U: | список пользователей с помесячными маркерами ta-фактов и числами операций |
U+ | файл прав целиком, с паролями (только при праве
U) |
U (без права U) | словесное описание прав текущего пользователя |
Встроенных средств редактирования прав нет — файл правится обычным текстовым
редактором в каталоге данных. В новом сервере изменения вступают в силу после
перезагрузки базы директивой W OFF (см. главу 7); директива U лишь показывает содержимое файла.
U открывает управляющие директивы (K,
Q, M, W) — выдавайте его только
администраторам. Технологическим учётным записям шлюзов давайте минимально
необходимый набор прав.6. Протокол обмена: запросы, ответы, пожелания
Эта глава описывает, как клиент и сервер передают друг другу данные через каталог обмена. Понимание протокола нужно при настройке прав доступа, написании собственных программ обмена (шлюзов) и диагностике сбоев.
6.1. Цикл одного запроса
- Клиент создаёт в каталоге обмена канал — случайное имя из букв и цифр
(обычно восемь знаков, например
ZXC456A3), и пишет запрос в файлZXC456A3.REQ. - Готовый запрос переименовывается в
ZXC456A3.IN— это сигнал серверу «файл готов целиком». - Сервер, постоянно сканируя каталог, находит
*.IN, выполняет запрос, удаляет.IN, пишет ответ вZXC456A3.ANSи по завершении переименовывает его вZXC456A3.OUT. - Клиент читает
*.OUT. При следующем запросе прежний.OUTудаляется; если клиент этого не делает, сервер оставляет ответы в.ANS.
· (код 250). Вместо любого символа в строке запроса можно подставить его
код в виде //DDD// (ровно три цифры).6.2. Начальный диалог
Подключившись, клиент сначала посылает директиву I: сервер проверяет
имя и пароль, возвращает метку данных (первая строка файла FIN.LBL),
дату и время сервера — так клиент синхронизирует свои часы с сервером — и признаки
прав T и P. Затем клиент запрашивает директивой
T доступные ему ветви дерева видов операций; сведения о проводках в
листах дерева от клиента скрыты.
Далее клиент посылает директивы по мере действий пользователя: R —
выполнить форму, J — показать журнал, O — зарегистрировать
операцию и т.д. (полный список — глава 7). Несколько
директив в одном файле-запросе выполняются сервером как одна транзакция.
6.3. «Пожелания» клиента
Каждая строка запроса имеет невидимую для пользователя часть — пожелания:
32 байта в начале строки после имени и пароля, затем разделитель · и сама
директива:
Имя·Пароль·ABCDEFGH[f1 ][f2 ]·Директива
| Байт | Смысл |
|---|---|
A | число строк на операцию при выводе журнала
(например 6) |
B | код опций «числа с запятыми» / «с копейками» (0…3) |
C | флаг «хранить первичные документы» (1/0) |
D | месяц начала отчётного периода (A =
январь … L = декабрь) |
E | зарезервировано |
F | месяц конца периода |
G | день начала периода (A = 1-е число) |
H | день конца периода |
[f1], [f2] | аргументы формы — строки по 12 байт, дополненные пробелами |
Результат выполнения директивы зависит от пожеланий (например, отчётный период
влияет на формы и журнал), но в общем случае это не гарантируется — форма может
игнорировать переданный период. Между пожеланиями и директивой могут вставляться
контексты (например, ответы на вопросы операции и блок MODOKEY) —
до 10 пар «имя + значение» по 10 символов; форма читает их функцией
[ct 'имя'].
6.4. UPTI и автообновление отчётов
В корне каталога обмена и в каждом его подкаталоге сервер поддерживает файл
UPTI: в нём — дата и время последнего изменения данных и время последнего
запуска сервера. Файл обновляется при старте сервера, после каждого модифицирующего
запроса (O, D, A, K,
P), после завершения пересчёта, а также принудительно — директивой
P ! без пересчёта состояния.
Клиент периодически проверяет UPTI: изменился — открытые отчёты
помечаются устаревшими и обновляются (по настройке автообновления). Так работает
«живость» отчётов у всех пользователей без рассылки сообщений.
6.5. Подкаталоги обмена
В каталоге обмена можно создавать подкаталоги — сервер сканирует их наравне с корнем (рекурсивно). Типовые применения:
- свой подкаталог каждому пользователю — вместе с правами ОС это ограничивает доступ к чужим запросам (см. п. 6.7);
- отдельные подкаталоги для шлюзов и автоматики (обмен с оборудованием, выгрузки);
- выделенные подкаталоги для «тяжёлых» клиентов.
6.6. Сбои транспорта и как их видит новый сервер
- Карантин. Если сервер не смог создать файл ответа, запрос не теряется:
файл
.INпереносится в карантин<имя>.BAD(с перезаписью), сбой пишется в журнал. Файлы.BADавтоматически не переобрабатываются — разбор за администратором. - Повторная обработка. Если сервер выполнил запрос, но не смог удалить
.IN, запрос будет обработан повторно — дубли модифицирующих директив возможны (так же вёл себя старый сервер); повтор виден в журнале запросов и снимается вручную. - Сорванное переименование ответа. Если
.ANSне удалось переименовать в.OUT, ответ для клиента теряется (как у старого сервера); оставшийся.ANSбудет стёрт стартовой очисткой. - Стартовая очистка. При каждом старте сервер стирает в каталоге обмена
все файлы (каталоги сохраняются) и переписывает
UPTI. - Аутентификация. Неверная пара имя/пароль — ответ
E-03и обрыв обслуживания файла-запроса.
6.7. О безопасности данных
Граница защиты платформы проходит по каталогу обмена. Базовое правило:
Дополнительные меры:
- заведите каждому пользователю свой подкаталог обмена и дайте доступ только в него — тогда даже содержимое чужих запросов недоступно;
- права внутри системы (кто что может запросить) задаются файлом
_RIGHTS_.FBP— см. главу 5; - помните, что формы могут писать в файлы (переадресация вывода,
printstrв файл,deletefile,renamefile) — выполняются они с правами учётной записи службы сервера; контролируйте состав форм и праваR.
7. Язык запросов к серверу
Вся работа сетевой версии ФБП — это постоянный диалог клиентов и сервера, а основа
диалога — запросы к серверу. Часть запросов клиент формирует автоматически (когда вы
открываете журнал, вводите операцию, запускаете форму), но любой запрос можно ввести и
вручную. Знание языка запросов нужно и программисту форм: управляющие строки
N: (см. главу «Строки N:») конструируют именно такие
запросы, а функция языка форм [jf s] интерпретирует строку как директиву
J.
Глава описывает язык запросов в актуальном виде — применительно к ФБП:Серверу V01 (решение SRVNEW). Директивы, существовавшие в старом сервере (версии fnt*), но не перенесённые в новый, собраны в разделе 6.23; сводка отличий — также в главе «Отличия от старого сервера».
7.1. Общие правила
Запрос — это файл-запрос, который клиент помещает в свой канал связи в общем
каталоге обмена; механика канала (.REQ → .IN →
.ANS → .OUT) описана в главе
«Протокол обмена». Запрос состоит из одной или нескольких
строк-директив.
- Первая латинская буква строки однозначно определяет вид директивы; можно использовать и строчные, и прописные буквы. Остаток строки — аргумент директивы.
- Если файл-запрос содержит несколько строк, сервер выполняет их как одну транзакцию: все модификации (ввод, правка, удаление операций и счетов) применяются вместе.
- Разделитель и ограничитель строковых значений — знак
·(средняя точка, код 250; вводится Alt+250 на цифровой клавиатуре). - Вместо любого знака в директиве можно указывать его код — для преодоления затруднений
при выводе некоторых знаков из программ. Синтаксис:
//DDD//, гдеDDD— ровно три цифры, образующие число от 0 до 255. ДирективыR AXиR //065//Xэквивалентны (65 — код латинскойA). - Буфер строки запроса — 10000 байт; после всех подстановок
//DDD//строка усекается до 255 байт.
Ответ сервера — одно- или многострочный текст в кодировке CP866, строки разделяются парой CRLF. Два особых случая помечаются префиксами в начале строки:
| Префикс | Смысл | Пример |
|---|---|---|
E- | Ошибка: далее код и смысл ошибки | E-06: неправильно указан вид операции |
Q- | Требуется уточнение: далее код и смысл уточнения | возникает, когда форма содержит оператор вопроса или функции ввода, а ответов в директиве нет |
Встречающиеся коды ошибок: E-03 — доступ запрещён / нет права на действие;
E-04 — неправильная команда (в том числе неизвестная или не перенесённая в
новый сервер директива); E-06 — неправильно указан вид операции;
E-14 — нет счёта-предка; E-18 — ошибочный ключ;
E-93 — доступ к серверу монополизирован другим клиентом (см.
M); E-94 — сервер находится в состоянии W ON (см.
W).
E-03: доступ запpещен и обрывает
обслуживание всего файла-запроса — остальные строки пакета не выполняются.7.2. Сводная таблица директив
В таблице перечислены все буквы, которые знает диспетчер запросов, а также
исторические директивы старого сервера. Статусы: поддержана — директива работает в
ФБП:Сервере V01; пустой ответ — запрос принимается, но ответ имеет нулевую длину;
не реализована — ответ E-04: непpавильная команда;
клиентская — сервером не обрабатывается.
| Буква | Директива | Статус в ФБП:Сервере V01 |
|---|---|---|
A | создать/исправить субсчёт (Account) | поддержана |
B | прервать выполнение формы (Break) | не реализована (E-04) |
C | компилировать форму (Compile) | не реализована (E-04) |
D | удалить операцию (Delete) | поддержана |
E | вычислить выражение (Evaluate) | поддержана |
F | получить список форм (Forms) | поддержана |
G | компилировать и выполнить форму (Go) | поддержана (V01.02; PNG-графика не перенесена) |
H | показать состояние дискового кэша | не реализована (E-04) |
I | получить синхронизацию (Information) | поддержана |
J | получить список операций (Journal) | поддержана |
K | удалить субсчёт (Kill) | поддержана (право U + файл-ключ freeacnt) |
L | получить документ (Load) | поддержана |
M | монополизировать доступ к серверу (Monopoly) | поддержана |
N | управляющие строки форм (N:) | клиентская; сервером не обрабатывается — см. главу о строках N: |
O | добавить/исправить операцию (Operation) | поддержана |
P | принудительный пересчёт состояния (Past) | поддержана |
Q | записать конечное состояние (Quit) | поддержана (право U) |
R | выполнить форму (Run) | поддержана |
S | получить статистику сервера (Statistics) | поддержана |
T | получить ветви дерева (Tree) | поддержана |
U | получить права (User) | поддержана |
V | получить версию сервера (Version) | поддержана |
W | управление сервером (Wait) | поддержана (право U) |
X | — | не существует (E-04) |
% | использовать Профилер | не реализована (E-04) |
? | получить помощь | поддержана |
7.3. Директива R — выполнение формы
R — выполнить форму (Run)
Выполняет форму (файл *.rpt каталога данных). Ответ — текст формы, или
сообщение об ошибке, или запрос уточнения (Q-), если в форме есть оператор
вопроса или функции ввода данных, а ответов в директиве нет. Запуск формы проверяется по
правам пользователя: при отсутствии права — E-03: нет пpава на запуск фоpмы
… (см. главу «Права пользователей»).
Синтаксис: R форма [·ответ· <·ответ·>]. форма —
наименование формы; ответ — строковые значения, обрамлённые знаками
· (код 250). Ответы передаются заранее оператору вопроса ? и
функциям ввода [im...], [ir...], [iy...],
[is...], [ia...].
R BALANCE
R 10 ·3·
Вторая директива выполняет 10.RPT; при встрече оператора вопроса или
функции ввода та сразу получит ответ 3.
Вместе с запросом клиент передаёт невидимую часть — опции, контексты
[ct...] и аргументы формы [f1], [f2] (границы
отчётного периода попадают в форму как переменные MF, DF,
ML, DL) — см. «Протокол обмена».
7.4. Директива O — ввод и правка операции
O — добавить операцию (Operation)
Добавляет операцию к соответствующему файлу *.f3p и «подсбивает» баланс.
Сервер присваивает операции штамп: он начинается знаком · и состоит из
имени пользователя, времени добавления и восьмизначного уникального кода; элементы
разделяются знаком ·. Штамп размещается в последних позициях комментария
операции, дополняя его длину до 56.
Синтаксис: O [PD=p] [DC=d] [MC=m] [s] ·компонент·<компонент>·[··комментарий·]
s— сумма операции; по умолчанию0;MC=m— месяц операции (1..12); по умолчанию месяц реальной даты;DC=d— день операции; по умолчанию день реальной даты;PD=p— позиция в пределах дня:0— в общем порядке,-1— в начале дня,+1— в конце дня;компонент— часть вида операции (путь по дереву); если начинается знаком с кодом 254 — это обозначение субсчёта, входящего в вид операции; компонент, начинающийся со знака?, — параметр-вопрос, значение которого уточняется при вводе;комментарий— предельная длина в сетевой версии уменьшена на длину штампа.
Если вид операции предусматривал создание первичного документа, ответом-подтверждением
будет текст этого документа; иначе — восьмизначный уникальный код. При
неудаче ответ — строка вида E-....
O 1000000 ·Касса·приход ниоткуда···непонятно за что·
Та же операция 1 января в начале дня:
O PD=-1 DC=1 MC=1 1000000·Касса·приход ниоткуда···непонятно за что ·
Редактирование операции — слово KEY с тем же уникальным кодом:
O KEY=HAAA-678 1000000 ·Касса·приход ниоткуда···непонятно за что·
Пример ошибки (ветви в дереве нет):
O ·нет такого вида операции·
E-06: неправильно указан вид операции
Групповые операции. Поддерживаются виды { и } —
скобки группы: операции между ними образуют одну групповую операцию.
Структура уникального кода: буквамесяца трбуквыкода - трицифрыкода.
Буква месяца: A — январь, …, L — декабрь. Уникальность кода —
только в пределах года.
7.5. Директива D — удаление операции
D — удалить операцию (Delete)
Удаляет операцию по уникальному ключу и «подсбивает» баланс.
Синтаксис: D уникальный_код или
D { уникальный_код уникальный_код } — групповое удаление операций с ключами
из указанного интервала; кодов может быть много.
Если ключ (или хотя бы один ключ интервала) не связан с операцией — ответ
E-18 ошибочный ключ... При успехе — ответ удалено.
D HAAA-678
удалено
замещает накопленный ответ всего пакета: строки, выработанные предыдущими
директивами того же файла-запроса, в ответ не попадут.Особые правила для групповых операций: удаление операций { и
} запрещено — сервер сам удалит их, когда в группе будет удалена последняя
операция; при удалении операции из группы сумма операции { устанавливается
равной количеству оставшихся в группе операций.
7.6. Директива J — журнал операций
J — получить список операций (Journal)
Выдаёт список операций из файлов *.f3p. Просмотр чужих операций
ограничивается правами (при отсутствии права — E-03: нет пpава на пpосмотp
опеpаций пользователя …).
Синтаксис: J [MC=m1[,m2]] [d1[,d2]] [USER=u[,u]] [ALL] [{]
m1,m2— месяц или интервал месяцев; по умолчанию — месяц реальной даты;d1,d2— день или интервал дней. Если заданыm1,m2иm2>m1, интервал дней трактуется как «со дня d1 месяца m1 по день d2 месяца m2»; еслиd1не указан, но естьm1— все дни месяца m1;USER=u— имена пользователей, чьи операции включать; безUSER— только операции текущего пользователя; сALL— операции всех пользователей;{— включать операции «свёрнуто»: операции видов{и}выступают скобками группы, группа показывается как одна операция;- элементы директивы могут следовать в произвольном порядке.
J " операции текущего пользователя за сегодня
J MC=1 USER=SVETA { " свернуто, SVETA, за январь
J MC=1,8 ALL " все пользователи, январь..август
J 5,15 " текущий пользователь, с 5-го по 15-е текущего месяца
J KEY=CAAA-170 " операция с уникальным кодом CAAA-170
Опции выборки:
KEY=— выбор операции по уникальному ключу;SUM=— интервал сумм операций (сравнение с точностью ±0.000001);WORD=— только операции, содержащие указанный отрывок текста (в виде операции или комментарии); строка с пробелами обрамляется знаками·;PATH=— путь в дереве видов операций; всегда идёт в конце директивы.
J MC=1,12 SUM=1000 " операции за год, сумма = 1000
J SUM=2000,3000 " сегодняшние, суммы в интервале 2000..3000
J MC=6 WORD=60-1 " июньские, с текстом "60-1"
J MC=6 WORD=·а б· " строка с пробелами обрамляется знаками ·
J PATH=Касса·расход " виды, начинающиеся с указанных ветвей
J MC=8 SUM=120,130 WORD=Вася PATH=Расч
Совместно использованные опции объединяются логическим «И».
Функция языка форм [jf s] интерпретирует строку s как
директиву J: результат — первая строка ответа, а все строки ответа и их
количество доступны из extrd.dat через [ged 'jf.N'],
[ged 'jf.1'] и т.д.
7.7. Директива A — создание и правка субсчёта
A — создать субсчёт (Account)
Создаёт субсчёт с указанными счётом-предком, обозначением и наименованием. Баланс не
разрушается, «подсбивка» не происходит. Начальное сальдо и начальные значения всех
параметров, кроме 9-го, инициализируются нулями; в девятый параметр заносится
1 — «признак новизны» субсчёта (проверка в формах: [bp ...,9]).
Синтаксис: A ·предок·обозначение·наименование·
A ·10·10-0001M·Особый материал·
субчет 10-0001M создан " ответ при успехе
E-14: нет счета-предка " ответ, если счета 10 нет
Приёмы ввода нового субсчёта: если за выводом списка стоит форма (например
41.rpt) или ввод идёт через ветвь-вопрос с уточнением вида ·X 41,
нужна проверка на новизну по 9-му параметру — без неё новый субсчёт не отразится в списке
на экране (хотя запишется в acnt.a3p) и станет виден лишь при регистрации
следующей операции.
Предостережения по именам счетов: не рекомендуется заводить счета типа
a и A (им можно противопоставить только одну форму
A.RPT); не следует заводить счета, начинающиеся с цифры (при описании прав в
_rights_.fbp идентифицируются только формы, начинающиеся с буквы).
Правка существующего счёта — уточнение E: можно менять тип счёта
(AA=, функция [aa...]), начальный остаток (BA=,
[ba...]), наименование (N2=, [n2...]),
наименования параметров (NP1=…NP9=, [np...]),
начальные остатки параметров (BP1=…BP9=,
[bp...]):
A E ·счет· BA=число
A E ·счет· N2=·строка·
A E ·счет· AA=число
A E ·счет· NP1=·строка· ... A E ·счет· NP9=·строка·
A E ·счет· BP1=число ... A E ·счет· BP9=число
Обозначение счёта и строка после N2 обрамляются знаками ·
(код 250). Создание счетов первого уровня и субсчетов к счёту без субсчетов требует
файла-ключа freeacnt — см. главу
«Ключевые слова каталога данных».
7.8. Директива K — удаление субсчёта
K — удалить субсчёт (Kill)
Удаляет субсчёт с указанным обозначением; после удаления сервер перекомпилирует дерево видов операций и делает «пересбивку баланса».
Синтаксис: K обозначение
В ФБП:Сервере V01 директива исполняется только пользователем с правом
U и только при наличии файла-ключа freeacnt в
каталоге данных (см. «Ключевые слова каталога данных»).
Пример: K Y1.
Опасности: удаление может вызвать ошибки компиляции и «подсбивки» (ссылки на субсчёт в
дереве и операциях); обозначение удалённого счёта могло остаться в выражениях
[get a, i] (результат непредсказуем), в полях фактов (такой факт несёт
заведомо ложную информацию), в extrd.dat.
K только в крайней необходимости и
доверяйте её одному лицу. Сервер не следит за последствиями удаления — целостность
и логичность базы полностью на усмотрении администратора. «Мозолящие глаза» счета лучше
не удалять, а делать невидимыми.7.9. Директива E — вычисление выражения
E — вычислить выражение (Evaluate)
Вычисляет выражение на языке форм; ответ — результат вычисления.
Синтаксис: E выражение
E 2+2 " ответ: 4
E [ea 50] + [ea 51] " сумма остатков в кассе и на расчетном счете
Право E пользователя ограничивает набор допустимых «основных функций»
языка форм — см. главу «Права пользователей».
7.10. Директива F — список форм
F — получить список форм (Forms)
Выдаёт список форм (*.rpt) каталога данных: упорядочен по алфавиту и
разделён на группы — обычные формы, первичные документы, формы-истории, общие
определения.
Синтаксис: F или F+. Вариант F+ показывает
отметки об использовании в формах функций (флаги зависимостей):
A Ngscuf > *Это форма A
B Y..... > *Это форма B
Расшифровка для формы A: кэш не включён (N); используются
[ged...] (g), [sed...] (s),
[ct...] (c), [user] (u),
[f1] и/или [f2] (f); переменные MF (пробел) и ML
(>). Форма B кэшируется (Y) и зависит от MF, DF, DL и ML.
F+ сервер компилирует все формы
(чтобы определить флаги) — на большой базе форм это заметно по времени. Флаг
кэширования (Y/N) — наследие дискового кэша старого сервера; в
новом сервере кэш ответов форм не перенесён (см. 6.23).7.11. Директива V — версия сервера
V — получить версию сервера (Version)
Сообщает в однострочном ответе версию и модификацию сервера.
V
"Финансы без проблем" V01.01 Александр Пронин. Для Windows 8.1,10,11,Server 2012+
(в версии V01.02 ответ содержит V01.02).
7.12. Директива I — синхронизация
I — получить синхронизацию (Information)
Информация о метке данных на сервере, текущем годе, дате и времени; используется
клиентами для начального диалога. Синтаксис — единственная буква I.
При верной паре имя/пароль ответ начинается строкой YES, далее:
| Строка | Назначение | Пример |
|---|---|---|
| 1 | Согласие предоставить информацию | YES |
| 2 | Метка сервера (первая строка файла FIN.LBL; если файла нет — NONAME) | ТОО 'Юго-Запад' |
| 3 | Текущий год | 2026 |
| 4 | Текущий месяц | 8 |
| 5 | Текущее число | 29 |
| 6 | День недели (0 = воскресенье) | 6 |
| 7 | Время, часы | 16 |
| 8 | Время, минуты | 48 |
| 9 | Время, секунды | 17 |
| 10 | Признак доступных ветвей дерева (T или -) | T |
| 11 | Признак права вмешательства в прошлое (P или -) | P |
Далее — по одной строке на каждое особое разрешение форм из файла прав. В новом
сервере выводится только общий случай: строка ALL Список фоpм; конкретные
имена форм (в отличие от старого сервера) в ответе I не перечисляются.
При неверной паре имя/пароль ответ — единственная строка NO.
7.13. Директива T — дерево видов операций
T — получить ветви дерева (Tree)
Выдаёт многострочным ответом информацию о доступных пользователю ветвях и листьях
дерева видов операций (схематичное изображение доступных ветвей; сведения о проводках в
листьях от клиента скрыты). Синтаксис — единственная буква T.
Состав ответа фильтруется по праву T пользователя: ветви, не разрешённые
ему в _rights_.fbp, в ответ не попадают (см.
«Права пользователей»). Ответ на T можно сохранить и
переопределить через форму USERS — см. главу
«Строки N:».
7.14. Директива S — статистика сервера
S — получить статистику сервера (Statistics)
Многострочный ответ с накопленной статистикой обслуживания запросов. Синтаксис —
единственная буква S. Ответ открывается таблицей «Статистика сеpвеpа»: в
разрезе пользователь/категория директив — количество обработанных запросов и затраченное
время. Категории: O (ввод операций), D (удаление),
A (счета), J (журналы), R (формы),
E (выражения), X (все прочие директивы).
Статистика сеpвеpа
Кто\запpос:│ O │ D │ A │ J │ R │ E │ X │ Итого
...
Пользователю без права U показывается только его собственная строка.
При праве U выводится полная форма ответа: строки всех пользователей, итоги
по категориям, среднее и худшее время обработки, время старта сервера, коэффициент
загруженности сервера и список запросов с худшими временами обработки (по каждой
категории — пользователь и текст запроса).
7.15. Директива Q — запись конечного состояния
Q — записать конечное состояние (Quit)
Записывает конечное состояние счетов в виде файлов ACNT.E,
EXTRA.E и FACTS.E — требуется при переходе к новому году (как в
однопользовательских версиях). Синтаксис — единственная буква Q. Исполняется,
только если пользователь имеет право U (иначе — E-03: нет пpава на
запись конечного состояния счетов).
7.16. Директива L — первичный документ операции
L — получить документ (Load)
Выдаёт многострочным ответом сохранённый при вводе операции первичный документ — текст
файла TXA\<месяц>\<ключ>.TXA из каталога данных.
Синтаксис: L уникальный_код_операции
L IAAB-045
Если директива относится к операции }, сервер выдаёт не только документ
этой операции, а документы всех операций группы от { до
}, последовательно соединённые в одно целое. Просмотр чужих документов
ограничивается правами (E-03: нет пpава на пpосмотp документов пользователя
…).
7.17. Директива U — права пользователей
U — получить права (User)
Информация о правах пользователей, их именах и паролях (файл
_rights_.fbp в каталоге данных; встроенных средств редактирования нет —
правится любым текстовым редактором, см. «Права
пользователей»).
U
U+
U:
U:— выводит список пользователей с помесячными маркерами запоминания ta-фактов и числами операций каждого пользователя по месяцам; требует праваU(иначе —E-03: нет пpава на U:); может использоваться при написании других клиентских частей;U+— выводит файл прав с паролями (только если текущий пользователь имеет правоU);U— при правеUвыводится содержимое_rights_.fbpцеликом (без паролей); без праваUсервер подробно объясняет на естественном языке права текущего пользователя.
7.18. Директива M — монополизация доступа
M — монополизировать доступ (Monopoly)
Монополизация доступа клиента к серверу по каналу обмена; требуется право
U (иначе — E-03: нет пpава на монополизацию доступа).
M ON " монополизировать доступ
M OFF " отказаться от монополии
Пока действует монополия, запросам, приходящим по чужим каналам, сервер отвечает
E-93: доступ к сеpвеpу монополизиpован дpугим клиентом.
7.19. Директива W — управление сервером
W — управление подключением к данным (Wait)
Для всех форм директивы требуется право U (иначе — E-03: нет пpава
на использование диpективы W).
W ON " приостановить обслуживание: «отключить» сервер от данных и правил —
" можно безопасно править правила и данные однопользовательской версией
W OFF " снова «подключить» сервер к правилам и данным (перезагрузка базы)
W FORM " перекомпилировать новые и изменённые формы без перезапуска
W DOWN " штатно завершить работу сервера
Пока действует W ON, на все директивы, кроме W,
сервер отвечает E-94: сеpвеp находится в состоянии W ON. W OFF
перезагружает базу данных и правила; W DOWN — штатная остановка сервера
(процесс завершается с записью несохранённого состояния).
W FORM — удобное новшество: сервер перекомпилирует
только новые и изменённые файлы *.rpt, не перезапускаясь и не прерывая
обслуживание. Ответ — строка пеpекомпиляция фоpм завеpшена. В новом сервере
эта директива заменяет директиву C старого сервера (см.
6.23).7.20. Директива G — выполнение формы из тела запроса (V01.02)
G — компилировать и выполнить форму (Go)
Директива G совмещает компиляцию формы из тела запроса (как историческая
C — см. п. 7.23) и её выполнение (как
R): форма выполняется сразу, без перезагрузки сервера
и без появления в списке форм базы. Так клиент может запускать отчётные формы, которых
ещё нет среди скомпилированных *.rpt базы.
В строке запроса после буквы G следует слово-имя (для G оно
не используется — форма передаётся в теле запроса; обычно пишут NONAME),
а дальше, если в форме есть вопросы, — ответы на них, как у R:
G NONAME ·ответ1·ответ2·. Строки файла запроса после строки директивы до
конца файла — текст формы.
Сервер переписывает текст формы в файл TEMP~~~~.RPT каталога данных
(файл остаётся после выполнения и перезаписывается следующим G),
компилирует его и выполняет форму. Ответ — как у R: текст формы, запрос
уточнения (Q-) или сообщение об ошибке; ошибка компиляции —
E-26: <строка>:<позиция> <текст>. Директива требует права
на все формы (R ALL), иначе — E-03: нет пpава на использование
диpективы G. Пустой текст формы (например, G NONAME без тела) даёт
пустой ответ нулевой длины — не ошибку.
В версиях V01/V01.01 директива не была перенесена и всегда отвечала пустым ответом;
выполнение формы из тела запроса появилось в V01.02. PNG-графика, которую клиенты
старого сервера получали через G, не перенесена (см. главу
«Графика в формах»).
7.21. Директива P — принудительный пересчёт состояния
P — принудительный пересчёт состояния (Past)
«Сообщение о том, что в прошлом было изменение». Не вносит изменений в файлы операций
(*.f3p), а информирует сервер о необходимости пересчёта.
P ! " только обновить файл(ы) upti — автообновление отчётов
" в клиентах; пересчёта состояния НЕ происходит
P - " выключить автоматический пересчёт состояния
P " включить автоматический пересчёт состояния
P [MC=m] [DC=d]" пометить пересчёт с месяца m / дня d
P KEY=ключ " пометить пересчёт с позиции операции с указанным ключом
P key=GDFG-987
P MC=1
Управляющие формы директивы (P !, P -, включение пересчёта)
требуют права U; пометка пересчёта связана с правом P —
вмешательством в прошлое (см. «Права пользователей»).
7.22. Директива ? — помощь
? — получить помощь
Директива ? без аргумента выдаёт содержимое файла HELP.HLP
(общий перечень директив); ? R — справку по конкретной директиве. Сервер
читает файл HELP\<буква>.HLP из подкаталога HELP каталога
данных.
?
? R
Если справки по указанной букве не предусмотрено — ответ E-04: нет диpективы
…; если файл не найден — E-04: нет файла ….
7.23. Директивы, не перенесённые в новый сервер
Следующие директивы существовали в старом ФБП:Сервере (версии fnt*), но в ФБП:Сервере
V01 не реализованы — на них сервер отвечает E-04: непpавильная команда.
Справки приведены для тех, кто переносит старые клиентские программы и скрипты.
C — компилировать форму (Compile) — не реализована
В старом сервере компилировала форму, строки которой следовали за директивой в файле
запроса; при ошибках возвращала сообщение с номером строки и позицией в строке. Клиенты
формировали её автоматически при редактировании формы и проверке по F8.
Чем заменить: директивой W FORM — сервер сам
перекомпилирует новые и изменённые *.rpt без перезапуска; ошибки компиляции
при этом видны в журнале сервера. Проверку «на лету» можно выполнять обычным запуском
формы директивой R.
H — показать состояние cache — не реализована
В старом сервере (для администраторов с правом U) показывала составной
индекс дискового кэша ответов форм: имя файла в каталоге cache, признак
актуальности, число тиков последнего выполнения, саму строку запроса с невидимыми
частями. Разновидность H- очищала индекс кэш.
Компенсация: дисковый кэш ответов форм в новом сервере отсутствует как
механизм — формы выполняются при каждом запросе. Флаг кэширования
(Y/N) в ответе F+ оставлен лишь для совместимости
формата. О наблюдаемой производительности форм можно судить по директиве
S (категория R, худшие запросы).
B — прервать выполнение формы (Break) — не реализована
В старом сервере прерывала выполнение зациклившейся или долго работающей формы — особенно полезна была при отладке новых форм из клиента.
Компенсация: штатного прерывания формы в новом сервере нет. Отлаживайте формы на
копии базы; в крайнем случае работу сервера можно завершить директивой
W DOWN (штатная остановка) и запустить сервер
заново.
% — использовать Профилер — не реализована
В старом сервере (с версии 3.03) встроенный Профилер показывал распределение времени
между фазами пересчёта состояния, файлами-коэффициентами, командами виртуальной машины и
строками исходного текста форм (%, % имя, %- —
обнуление счётчиков; отключение — файлом NOPROFIL).
Компенсация: Профилер в новый сервер не перенесён. Общую картину расходов
времени даёт статистика S: средние и худшие времена по
категориям запросов и список запросов с худшими временами обработки.
X — директива не существует
Буква X никогда не входила в перечень директив — ни в старом, ни в новом
сервере; ответ на неё — тот же E-04: непpавильная команда. Упомянута здесь,
потому что встречается в ошибочных запросах и в описании категории X
статистики S (куда попадают все прочие
директивы — к букве X это отношения не имеет).
7.24. О безопасности и потенциально опасных конструкциях
Справка из старого руководства. Начиная с версии 3.20 старого сервера, в ответе
на директиву S был раздел «Потенциально опасные конструкции в *.rpt»: в нём
перечислялись формы, где встречаются форматные вставки с переадресацией вывода в файл,
оператор printstr с переадресацией в файл, операторы deletefile
и renamefile. В новом сервере этот раздел статистики не перенесён, однако
само перечисление остаётся полезным ориентиром при аудите форм: такие конструкции позволяют
форме писать и удалять файлы на сервере, поэтому формы с ними должны быть доступны только
доверенным пользователям.
Практические рекомендации прежние:
- разграничивайте права пользователей в
_rights_.fbp(см. «Права пользователей») — праваU,P,Eдавайте только доверенным лицам: правоUоткрывает доступ к паролям (U+), управлению сервером (W,M,Q) и удалению счетов (K); - средствами операционной системы давайте каждому пользователю сетевой доступ только к каталогу обмена (или его подкаталогу), но не к каталогу данных — см. «Архитектура»;
- помните, что строки
N:в формах конструируют произвольные запросы к серверу (см. «Строки N:») — форма фактически наследует и расширяет возможности своего автора.
8. Ключевые слова (файлы-ключи) каталога данных
Ключевые слова — это файлы-ключи в каталоге данных сервера: важно само присутствие файла с нужным именем (он может быть пустым), а файл должен существовать до старта сервера.
fastfact,
fastged, free-at, freeacnt, M_PLUS.
Игнорируются (можно удалить из каталога данных — эффекта нет): fastrun,
noprofile, logmode, notail, ukraine,
ta1. Подробности — ниже и в главе 29.8.1. fastfact — «быстрые факты»
Включает индексирование ленты фактов: при построении индекса учитываются прототипы
и значения полей фактов. Конструкции search/news/total
ускоряются во много раз. Цена — расход памяти растёт (иногда в разы), а добавление
фактов (fact) замедляется примерно вдвое.
8.2. fastged — ускорение доступа к дисковой базе
В оперативной памяти строится зеркало тел записей extrd.dat
(зеркало заметно меньше файла на диске). Функция [ged ...] ускоряется
в 10–20 раз.
8.3. free-at — свободные @-обращения
Сервер перестаёт проверять, что субсчёт в @-обращении имеет предком счёт из листа
дерева видов операций. Это компенсирует запрет *-подстановок в
@-обращениях: вместо серии ветвей 50 @61, 50 @71,
50 @76 можно обойтись одной ветвью 50 @X и формой
X.RPT. Подводный камень: клавиша заведения субсчёта в списке субсчетов
клиента берёт имя формы как родителя счёта.
8.4. freeacnt — свободные счета
Разрешает пользователю с правом U: создавать счета первого уровня,
создавать субсчета к счёту, у которого ещё нет субсчетов, и удалять счета и субсчета
директивой K. Без этого файла директива K не выполняется.
K: остатки и обороты удалённых счетов в журналах операций остаются.
Пользуйтесь freeacnt осознанно.8.5. M_PLUS — сдвиг текущего месяца
Файл содержит число N — сдвиг «текущего» месяца сервера вперёд при старте (см. п. 3.10). В отличие от прочих ключей, содержимое файла значимо.
8.6. Ключевые слова, не поддержанные новым сервером
| Ключ | Что делал в старом сервере | Чем компенсируется |
|---|---|---|
fastrun | повышение приоритета процесса сервера | не требуется; приоритетом службы можно управлять средствами Windows |
noprofile | отключение хронометрирующей части Профилера | профилер (директива %) в новом сервере не реализован —
отключать нечего |
logmode | протоколирование работы сервера в файл
log | новый сервер ведёт журнал запросов всегда:
FbpServer-YYYY-MM-DD.log (см. п. 3.6) |
notail | форма не дополнялась замечаниями о незавершённых вычислениях в прошлом | — |
ukraine | изложение числительных функцией
[wn ..] на украинском языке | — |
ta1 | проводка между счетами создавала только два ta-факта (экономия памяти) | — |
8.7. О дисковом кэше ответов форм
Старый сервер умел кэшировать результаты выполнения форм в подкаталоге
cache с файлом config.txt (директивы NO,
ALL±, THESE±, EXCEPT±; показ и очистка —
директивой H). В новом сервере дисковый кэш ответов не
реализован: формы выполняются при каждом запросе, а устаревание отчётов на
клиентах отслеживается через файлы UPTI (см. главу 6). Если в каталоге данных остался подкаталог cache от старого
сервера, он просто не используется.
Часть II. Язык программирования ФБП
Эта часть — полное описание языка, на котором пишется настройка учётной системы: отчётные формы, первичные документы, файлы-коэффициенты, проводки в дереве видов операций. Читать можно подряд: материал идёт от простого к сложному и не требует знакомства с языком — достаточно общего представления о бухгалтерском учёте и о том, как устроена сетевая версия (часть I).
Порядок глав:
- 9–10 — введение и быстрый старт: первая форма за десять минут;
- 11–15 — файлы форм, вывод текста, переменные, операторы, массивы;
- 16 — лента фактов, главный механизм накопления данных;
- 17–19 — справочник функций языка;
- 20–22 — обращения к счетам, экстрапараметры, виды операций и проводки;
- 23 — управляющие строки
N:: интерактивные отчёты в клиенте; - 24–25 — графика и web-доступ (исторические механизмы, со статусом в новом сервере);
- 26–28 — производительность и отладка, примеры и приёмы, приложения (ограничения языка, сообщения об ошибках).
9. Введение в язык форм
«Финансы без проблем» (ФБП) — бухгалтерская система, в которой почти всё поведение определяется не жёстко зашитым кодом, а программами на встроенном языке ФБП, которые пишет сам пользователь. На этом языке описывают:
- отчётные формы (файлы
*.rpt) — отчёты, списки, диалоги, документы; - виды операций и проводки (дерево
cas.rul) — что происходит со счетами при регистрации хозяйственной операции; - файлы-коэффициенты — алгоритмы расчёта сумм проводок;
- первичные документы (формы, связанные с операциями).
Это руководство учит именно программированию: как устроены формы, какие есть операторы и функции, как обращаться к счетам и оборотам, как строить диалоги и отчёты. Установка программы и повседневная работа бухгалтера здесь не рассматриваются.
9.1. Где «живут» программы на языке ФБП
У языка ФБП есть несколько точек приложения, и важно сразу понимать, где какой код выполняется:
| Место | Файл | Что там пишут |
|---|---|---|
| Отчётная форма | имя.rpt | Текст отчёта с операторами и функциями; выполняется при запуске формы. |
| Файл-коэффициент | имя.rpt | Алгоритм, который вычисляет сумму проводки; вызывается из листа дерева видов операций. |
| Лист дерева видов операций | cas.rul | Проводки (дебет, кредит, коэффициент/формула), псевдопроводки. |
| Общие определения | first.rpt, library.rpt, *.lib | Переменные и подпрограммы, доступные всем формам. |
| Первичный документ | имя.rpt → *.txa | Форма печатного документа, связанного с операцией. |
9.2. Кто выполняет программы: сервер и клиент
В сетевой версии ФБП есть ФБП:Сервер — единственный процесс, который хранит данные и выполняет все программы на языке ФБП: регистрирует операции, пересчитывает баланс, выполняет отчётные формы. ФБП:Клиент CLWP — «тонкий»: он лишь показывает ответы сервера и передаёт ему запросы. Поэтому форма, написанная вами, всегда работает «внутри» сервера и имеет прямой доступ ко всем данным учёта.
9.3. Главная «магия» ФБП: виртуальный пересчёт
Если вы изменили лист дерева видов операций — например, добавили проводку с расчётом налога, — то интерпретация всех ранее введённых операций этого вида изменится сразу: остатки и обороты счетов пересчитаются автоматически. Данные (операции) и правила (дерево, формы) в ФБП независимы, поэтому настройку можно менять «на живую», не переформатируя базу.
9.4. Как выглядит программа: первый пример
Отчётная форма — это обычный текстовый файл. Строки текста попадают в отчёт как есть,
строки-операторы выполняются, а форматные вставки из знаков ^ заменяются
значениями переменных. Вот законченная форма:
* форма hello.rpt — первая программа
X = 2 + 2
Привет! Дважды два = ^^^^X
Остаток на счете 50 (Касса): ^^^^^^^^^^[ea 50]
Запустив такую форму, вы получите примерно следующее:
Привет! Дважды два = 4
Остаток на счете 50 (Касса): 12500.00
Здесь видны сразу три базовых элемента языка: комментарий (строка со звёздочки),
оператор присваивания и вызов функции [ea 50] — остаток счёта.
Подробно всё это разбирается в главах «Переменные и выражения» и
«Функции».
9.5. Условные обозначения в этом руководстве
[ea X]— функции языка записываются в квадратных скобках;·— средняя точка (символ с кодом 250), служебный разделитель в строках директив и уточнений;//250//— способ записать любой символ его кодом (ровно три цифры), если сам символ неудобно вводить;- в примерах строки, начинающиеся с
*, — комментарии.
9.6. Как читать это руководство
Если вы новичок — идите подряд от главы «Быстрый старт»: каждая
глава опирается на предыдущие. Если нужен конкретный оператор или функция — пользуйтесь
поиском вверху страницы (клавиши Ctrl+K) или оглавлением слева; главы
17–19 образуют полный справочник функций,
глава «Примеры и приёмы» — сборник готовых решений.
probe.rpt в каталоге данных, наберите пример и запустите форму (в клиенте
CLWP — из списка форм на сервере: клавиши Alt+F4, затем Enter
на имени формы).9.7. Где выполняется язык
- Отчётные формы
*.rptв каталоге данных компилирует и выполняет сервер (директивыR,E); результат — текст ответа в кодировке CP866, который отображает клиент. - Первичные документы — формы, выполняемые сервером при регистрации
операции (псевдопроводка «создать документ»); текст документа пишется в
TXA\<месяц>\<ключ>.TXA, история версий — в файлы.DES. - Файлы общих определений:
FIRST.RPTподключается в начало каждой формы,LIBRARY.RPTи все файлы*.libкаталога данных компилируются в одну библиотеку подпрограмм. - Управляющие строки
N:в тексте форм исполняет не сервер, а клиент — см. главу 23.
9.8. Компиляция и перекомпиляция форм
Новый сервер компилирует все формы при старте (и при перезагрузке базы
W OFF). Формы, добавленные или изменённые «на живую», перекомпилируются
без перезапуска сервера директивой W FORM (ответ — «пеpекомпиляция фоpм
завеpшена»; нужно право U). Директива старого сервера C
(компиляция формы из клиента) не перенесена — взамен используйте
W FORM.
FORMS.ERR и
FORMS.EMG новый сервер не создаёт (директива S покажет их
только если такие файлы остались в каталоге от старого сервера). Ошибку компиляции
конкретной формы видно при её выполнении: сервер отвечает
E-26: форма содержала ошибки и не была загружена, а удобный цикл
отладки на клиенте — в редакторе форм CLWP: F6 (скомпилировать: файл
записывается, серверу уходит запрос W FORM, ответ открывается отчётной
формой) → F8 (выполнить текст прямо из окна редактора — директива
G) → F2 (сохранить).9.9. Ширины строк — обязательная совместимость
Новый сервер воспроизводит ограничения оригинала, от которых зависит поведение программ:
- обозначения счетов — 10 символов: в
*-ссылках,$D/$K/$P,@-обращениях имена усекаются до 10 символов; литералы разрешаются полным именем при компиляции, но проверка существования счёта — по усечённому; - строки переменных, стека и временные строки — 255 символов с молчаливым
усечением; это влияет, в частности, на накопители строк с дедупликацией по
функции
[ps]; - запись дисковой базы экстрапараметров
extrd.dat— 255 байт.
9.10. Функции, заслуживающие отдельного упоминания
| Функция | Назначение и статус |
|---|---|
[jf s] | журнальный запрос из формы: выполняет директиву
J с параметрами строки s; строки ответа доступны в
экстрапараметрах jf.1…jf.N. Реализована в новом сервере. |
[uf s] | выгрузка таблицы прав пользователей в
экстрапараметры (uf.1…uf.N); режимы «+» (с паролями) и
«:». В старом сервере была фактически заглушкой — в новом реализована. |
[ct s] | значение контекста запроса (ответы на вопросы
операции, MODOKEY, аргументы) — см. п.
23.10. |
[ged ...]/[sed ...] | дисковая база
экстрапараметров extrd.dat; при файле-ключе fastged
работает по зеркалу в памяти — в 10–20 раз быстрее
(п. 8.2). |
9.11. Графика в формах
Директива G, строившая в старом сервере PNG-графику из массивов
формы, в новом сервере возвращает пустой ответ (графика не перенесена — она
была заглушена и в последних сборках старого сервера). Формы с графикой следует
переделать на текстовый вывод или на внешние средства (экспорт в Excel в клиенте
CLWP).
9.12. Кодировки
Данные, формы и весь обмен с сервером — в кодировке CP866. Клиент CLWP
перекодирует текст автоматически; при написании собственных программ обмена и
редактировании *.rpt сторонними редакторами следите за кодировкой:
путаница OEM↔Windows — типичная причина «кракозябр» в комментариях операций и
отчётах. В строках запроса любой символ можно передать подстановкой
//DDD// (три цифры кода).
10. Быстрый старт: ваша первая форма за 10 минут
Эта глава — практикум «с нуля до первого работающего отчёта». Мы убедимся, что сервер и клиент установлены, создадим файл формы, наберём простейшую программу, запустим её и научимся реагировать на сообщения об ошибках. Дальше по книге всё будет только дополнять эти базовые навыки.
10.1. Если программа ещё не установлена
Чтобы попробовать «Финансы без проблем» в работе, нужны две программы: ФБП:Сервер (служба Windows, управляется Менеджером баз) и ФБП:Клиент CLWP. Порядок их установки и настройки подробно описан в части I этого руководства. Для выполнения упражнений этой главы достаточно, чтобы сервер был запущен, а клиент подключался к нему.
10.2. Создаём файл формы
Формы хранятся в обычных текстовых файлах с расширением *.rpt. В сетевой
версии формы бывают клиентскими — они хранятся на компьютере клиента и выполняются
программой CLWP, и серверными — они хранятся на сервере. Список форм на клиенте
открывается клавишами Alt+F7, список форм на сервере — Alt+F4.
Начнём с клиентской формы: нажмите Alt+F7.
В списке показываются имена и первые строки отчётных форм, первичных документов, файлов-коэффициентов, форм-историй и файлов общих определений. Действия над файлами выполняются клавишами:
| Клавиша | Действие |
|---|---|
Enter | выполнить (запустить) форму |
F4 | открыть форму в редакторе |
Del | удалить форму |
Создайте файл с именем, например, hello.rpt и откройте его в редакторе
форм клавишей F4 из списка форм на клиенте.
10.3. Основные клавиши редактора
Встроенный редактор форм CLWP прост, но всё необходимое в нём есть. Минимум, которым вы будете пользоваться постоянно:
| Клавиша | Действие |
|---|---|
стрелки, Home / End | перемещение курсора; в начало / конец строки |
Ctrl+Home / Ctrl+End | в начало / конец файла |
Ins | вкл/выкл режим вставки |
Enter | вставить строку (в режиме вставки) |
Del | удалить символ |
F2 | сохранить текст в файл |
Ctrl+F7 | открыть файл формы (каждый файл — в своём окне; работает из любого окна клиента) |
Ctrl+Z / Ctrl+Y | отменить правку / вернуть отменённое |
Alt+цифры верхнего ряда | перейти к строке с этим номером |
F4 / F5 | поставить символы · и ■ (то же, что Alt+250 / Alt+254); шаблоны конструкций языка — в меню «Редактор → Шаблоны» |
F6 | скомпилировать форму (файл записывается, серверу уходит запрос W FORM, ответ открывается отчётной формой) |
F7 | поиск по образцу от текущей позиции |
F8 | выполнить форму (текст уходит серверу директивой G — даже несохранённый) |
F9 | вкл/выкл режим рисования линий (для рамок в отчётах) |
Ctrl+T | переключить тёмную тему редактора |
10.4. Первая форма: комментарий, присваивание, форматная вставка
Форма — это текстовый файл, в котором смешаны три вещи: обычный текст (он попадёт
в отчёт как есть), операторы (они выполняются, но ничего не печатают сами) и
форматные вставки из знаков ^ (вместо них в отчёт подставляются
значения переменных). Наберите в hello.rpt такой текст:
* Первая форма: знакомимся с языком
B=234.1; A=B+12.2
Результат вычисления: ^^^^^^A^^^
Разберём по строкам:
- Строка, начинающаяся со звёздочки
*, — комментарий: она никуда не выводится и нужна только для тех, кто читает форму. B=234.1; A=B+12.2— два оператора присваивания в одной строке, разделённые точкой с запятой. После выполненияAстанет равным 246.3. Текст после оператора в той же строке тоже считается комментарием.- В третьей строке слова «Результат вычисления:» — обычный текст, а
^^^^^^A^^^— форматная вставка. Шесть знаков^перед именем переменной отводят шесть позиций под целую часть числа, три знака после — три позиции под дробную часть.
Запустите форму (как — см. следующий подраздел) и в отчёте появится:
Результат вычисления: 246.300
Число выровнено по правому краю отведённого поля: перед 246.300 стоят
три пробела, добирающие целую часть до шести знаков.
^ — это видимый признак переполнения, а не ошибка. Просто увеличьте
количество ^ перед именем переменной.\ в конце строки подавляет перевод
строки при выводе. Всё это подробно разобрано в главе
«Текст и вывод».10.5. Запуск формы
В клиенте CLWP форму можно запустить двумя способами: в списке форм на клиенте
(Alt+F7) подведите селектор к имени формы и нажмите Enter —
или прямо из редактора клавишей F8 (текст уходит серверу директивой
G, даже несохранённый). Перед выполнением форму полезно скомпилировать
клавишей F6: файл записывается, сервер перекомпилирует изменённые формы
(запрос W FORM) и отвечает отчётной формой с сообщениями об ошибках.
R форма [·ответ· …] — выполнить форму
Форму, хранящуюся на сервере, запускают директивой R, набранной в строке
запроса к серверу (список запросов открывается клавишами Alt+F9).
форма — имя файла без расширения .rpt.
Если форма задаёт вопросы (оператор ? или функции ввода), ответы можно
передать заранее — после имени, обрамив каждый знаками · (символ с кодом
250, вводится Alt+250 на цифровой клавиатуре).
R HELLO
R 10 ·3·
Вторая директива выполняет форму 10.rpt; первый же вопрос в ней получит
ответ 3 автоматически. Подробно язык запросов описан в главе
«Язык запросов к серверу» (часть I).
10.6. Форма с вводом значения
Отчёт становится в сто раз полезнее, если перед построением спросить у пользователя параметры — дату, сумму, название. Для этого есть функции ввода; вот две самые ходовые.
[ir s, nn, mm] — ввод числа с 3.1
Выводит вопрос s и ждёт число. nn — значение по умолчанию
(число или формула, подставляется, если просто нажать Enter), mm —
количество знаков после десятичной точки.
A=[ir 'Введите номер поручения:',X,0][is s, sd, mm] — ввод строки с 3.1
Выводит вопрос s и ждёт строку длиной не более mm символов;
sd — значение по умолчанию.
A=[is 'Введите название фирмы:',A,20]Соберём форму с вводом целиком:
* Форма ask.rpt — спрашиваем и считаем
S=[ir 'Введите сумму:', 100, 2]
N=[is 'Кому платим?', ' ', 30]
Получатель: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^N
Сумма: ^^^^^^^^^^^S^^
T=S*1.1
Сумма с надбавкой 10%: ^^^^^^^^^^^T^^
Есть и более простое средство — оператор вопроса:
? переменная строка
Он выводит строку на экран и запрашивает значение переменной.
Но функции [ir]/[is] удобнее: у них есть значения по умолчанию
и контроль формата. Все функции ввода и оформления диалогов (включая меню
[im] и выбор субсчёта [ia]) подробно описаны в главе
«Функции: ввод и оформление».
10.7. Если синтаксическая ошибка
Ошибаться в первых формах будете много — это нормально, язык сообщает об ошибках
вполне дружелюбно. Если при компиляции (F6) или выполнении
(F8) формы встретилась ошибка, сервер сообщит о ней в открывшейся
отчётной форме. Исправьте строку и запустите снова — при выполнении из редактора
(F8) текст можно даже не сохранять: серверу уходит содержимое окна.
Некоторые сообщения анализатора говорят сами за себя, например «@-обращение к несуществующему счету» (счёт не описан в списке счетов — введите его и его субсчета) или «Неправильно указан вид операции» (дерево изменилось после ввода операций — укажите вид операции заново). Полный перечень сообщений и способы реакции на них собраны в главе «Приложения».
10.8. Куда идти дальше
Теперь вы умеете создавать, редактировать и запускать формы. Заодно осмотритесь
в клиенте: журнал операций открывается клавишами Alt+F2, ввод новой
операции в нём — клавишей F7. Дальше путь такой:
| Хочу… | Глава |
|---|---|
Разобраться в типах файлов форм, общих определениях first.rpt, библиотеках | 11. Файлы форм и общие файлы |
| Красиво оформить вывод: форматные вставки, растекатели, вывод в файл | 12. Текст и вывод |
| Понять переменные, выражения и типы данных | 13. Переменные и выражения |
| Условия, циклы, подпрограммы — все операторы языка | 14. Операторы |
Получать остатки и обороты счетов: [ea], [od] и десятки других | 17. Функции: данные учёта |
Все функции ввода и оформления: [ir], [is], [im], [ia] | 18. Функции: ввод и оформление |
| Научить программу делать проводки: дерево видов операций | 22. Виды операций и проводки |
Управлять сервером запросами: директивы R, O и другие | 7. Язык запросов к серверу (часть I) |
| Готовые решения и приёмы из практики | 27. Примеры и приёмы |
hello.rpt и пробуйте новые конструкции в нём. Форма из этой главы —
отличный полигон для экспериментов.11. Файлы форм: создание, компиляция, общие файлы
Программы на языке ФБП хранятся в обычных текстовых файлах с расширением .rpt
в рабочем каталоге сервера (а локальные формы — на компьютере клиента). В этой главе
разбирается «хозяйственная» сторона вопроса: как создавать и редактировать формы, как
система проверяет и выполняет их текст, какие служебные файлы (FIRST.RPT,
LIBRARY.RPT, PROTO.RPT, библиотеки *.lib) позволяют
не повторять общий код в каждой форме, и как отправить результат формы не на экран,
а в файл.
11.1. Списки форм в клиенте CLWP
Все тексты на языке ФБП — отчётные формы, первичные документы, файлы-коэффициенты,
формы-истории, файлы общих определений — собраны в списках форм. Чтобы попасть в список
форм, хранящихся на клиенте, выберите в меню Документы → Формы на Клиенте или
нажмите Alt+F7 (список форм на сервере открывается по Alt+F4).
Для каждого файла показываются его имя и первая строка — поэтому принято начинать форму
со строки-комментария с понятным названием.
| Клавиша | Действие в списке форм |
|---|---|
Enter | выполнить (запустить) форму |
F4 | открыть форму в редакторе |
Del | удалить файл формы (с подтверждением) |
Отдельных клавиш для создания и переименования формы в списке нет: переименуйте или
создайте файл .rpt средствами ОС (например, в Проводнике Windows), а новый
текст можно набрать и в редакторе, сохранив его клавишей F2.
11.2. Встроенный редактор
Форму можно набрать и во внешнем редакторе (это простой текстовый файл в кодировке CP866 — см. предупреждение в главе «Введение»), но встроенный редактор клиента CLWP удобнее: он связан с серверным анализатором синтаксиса и при ошибке компиляции сам показывает место сбоя.
| Клавиша | Действие в редакторе |
|---|---|
F2 | сохранить файл |
Ctrl+F7 | открыть файл |
F4 / F5 | поставить символ · / ■ (то же, что Alt+250 / Alt+254); шаблоны — готовые фрагменты языка форм — теперь в меню «Редактор → Шаблоны» |
F6 | компилировать: изменённый текст записывается в файл, серверу уходит запрос W FORM; ответ открывается отчётной формой |
F7 | найти / найти дальше |
F8 | выполнить форму: серверу уходит директива G с текстом из окна (даже несохранённым); ответ открывается отчётной формой |
F9 | включить/выключить режим рисования линий (по циклу: выключено → одинарные → двойные) |
Ctrl+T | светлая / тёмная тема редактора |
Обычные приёмы редактирования Windows (выделение мышью и Shift+стрелками,
копирование и вставка Ctrl+C/Ctrl+V, переходы
Ctrl+Home/Ctrl+End) работают как в любом текстовом редакторе.
Подробное описание редактора — в разделе
«Редактор форм» главы о клиенте CLWP.
11.3. Интерпретатор и компилятор
Когда вы запускаете форму, её текст не «читается построчно» в момент вывода, как в классических пакетных файлах: форма сначала компилируется в промежуточный код, который затем выполняется — это сделано ради быстродействия.
Компиляцией форм управляет ФБП:Сервер. Проверить форму можно прямо из редактора
клавишей F6: изменённый текст записывается в файл, серверу уходит запрос
W FORM, и ответ с сообщениями об ошибках открывается отчётной формой.
Перекомпиляция форм на сервере выполняется командой W FORM (требуется
право U; подробности — в главе «Язык запросов
к серверу»).
W FORM перекомпилирует только изменённые формы,
а FIRST.RPT, PROTO.RPT и первичные документы не перекомпилируются
вовсе — после их правки требуется перезагрузка сервера (W ON,
W OFF). Учтите это, меняя общие определения «на живую».*.rpt можно шифровать (технология Enigma): расширение
сохраняется, шифрованные и обычные файлы допустимо смешивать. Первая строка формы остаётся
видимой — поэтому по-прежнему делайте её осмысленным комментарием.11.4. Синтаксический анализатор и его сообщения об ошибках
Проверка текста выполняется ещё до запуска формы. Редактор CLWP подсвечивает синтаксис —
разными цветами раскрашиваются операторы, комментарии, текст формы и ошибочные места;
клавиша F6 запускает полный анализ на сервере, включая проверку существования
всех упомянутых счетов (без неё при обычном наборе проверяется формальный синтаксис —
скобки, запятые и т.п.).
Компилятор дерева видов операций обнаруживает большинство формальных ошибок «на первой
секунде» попытки построить баланс. В клиенте CLWP изменения в окне «Счета…» приводят
к тому, что отсутствующие счета перечёркиваются и перекрашиваются в окне «Дерево…»;
изменения в «Дерево…» цветом выделяют ставшие несоответствующими операции в окне
«Операции…». Сообщение об ошибке выводится в нижней полосе главного окна; кнопка
«Где ошибка» (мышью) или Alt+E (с клавиатуры) активирует окно
с ошибкой и ставит на неё курсор. Повторное нажатие может открыть ещё одно окно
с дополнительной информацией: например, при делении на нуль в операции первое нажатие
покажет место в «Дерево…», второе — в «Операции…».
Полный перечень сообщений анализатора с пояснениями:
| Сообщение | Причина и что делать |
|---|---|
| ПУСТАЯ СТРОКА В ОПИСАНИИ ПРОВОДКИ | В листе дерева видов операций и проводок есть пустая строка — удалите её. |
| НЕПРАВИЛЬНО ОПИСАНА ПРОВОДКА | Неправильное описание проводки в листе дерева: проверьте порядок «дебетуемый счёт, кредитуемый счёт, коэффициент». |
| НЕПРАВИЛЬНЫЙ КОЭФФИЦИЕНТ В ОПИСАНИИ ПРОВОДКИ | Неправильно задано числовое выражение коэффициента в описании проводки. |
| @-ОБРАЩЕНИЕ К НЕСУЩЕСТВУЮЩЕМУ СЧЕТУ | @-обращение ссылается на счёт, не описанный в списке счетов. Нужно ввести новый счёт и его субсчета. |
| @-ОБРАЩЕНИЕ К СЧЕТУ БЕЗ СУБСЧЕТОВ | @-обращение должно ссылаться на счёт, имеющий субсчета: либо субсчета ещё не созданы, либо упомянут не тот счёт. |
| НЕИЗВЕСТНЫЙ (ИЛИ СОСТОЯЩИЙ ИЗ СУБСЧЕТОВ) ДЕБЕТУЕМЫЙ СЧЕТ / …КРЕДИТУЕМЫЙ СЧЕТ | Счёт не описан в списке счетов либо состоит из субсчетов, но @-обращение не применяется — для такого счёта обращайтесь через @. |
| НЕТ ОПИСАНИЙ ПРОВОДОК ДЛЯ ЭТОЙ ОПЕРАЦИИ | Нет листа с описаниями проводок для данного вида операции — добавьте лист в дерево. |
| НЕПРАВИЛЬНО УКАЗАН ВИД ОПЕРАЦИИ | Ветвь дерева изменилась после того, как виды операций были указаны; при редактировании операции заново укажите вид. |
| В ОПИСАНИИ ПРОВОДКИ НЕТ ССЫЛКИ НА ФАЙЛ-КОЭФФИЦИЕНТ | Возникает при редактировании дерева по F4, если текущее описание проводки не содержит коэффициента или содержит числовой коэффициент. |
11.5. Файлы-коэффициенты
Файл-коэффициент — это обычный файл .rpt, содержащий алгоритм на языке
форм, который вычисляет сумму проводки. Он нужен там, где сумма не совпадает с суммой
операции: расчёт налогов, процентов, амортизации и т.п. Файл-коэффициент вызывается из листа
дерева видов операций — имя файла дописывается в строке проводки после счетов (подробно о
дереве — глава «Виды операций и проводки»).
Обмен данными с вызвавшей проводкой идёт через предопределённые переменные:
| Переменная | Смысл |
|---|---|
$ | на входе — сумма операции; в эту же переменную файл-коэффициент возвращает вычисленную сумму проводки (то есть $ — и передаваемый, и возвращаемый параметр) |
$D | обозначение дебетуемого счёта |
$К | обозначение кредитуемого счёта |
Создать файл-коэффициент можно двумя способами: как обычную форму — новым файлом
.rpt в редакторе (F2 — сохранить) или средствами ОС — либо прямо
из дерева проводок: дописать в строке проводки после пробела имя файла-коэффициента
и нажать F4.
Пример. К проводке @70 68-3 (удержание подоходного налога) дописано имя
файла-коэффициента TAX. Начало этого файла:
* Подоходный налог с физических лиц
*
D=[AK $D] Доход, начисленный сотруднику с начала года
U1=[AP $D,68-3] Уже удержанный подоходный налог (город)
U2=[AP $D,68-31] Уже удержанный подоходный налог (федеральный)
G=D*0.01 вычеты в Пенсионный фонд 1%
M=[ed MIN] Подлежащие вычету минимумы
P=[ep @70] Сумма льгот, накопленная к моменту начисления
if D in 0..10000 D=D-P-2*M; L=M*2
elseif D in 10000..30000 D=D-P-M; L=M
else D=D-P; L=0
endif
*
* ... далее — расчёт налога по шкале и итоговое присваивание:
$=J2
Здесь видно несколько важных приёмов файлов-коэффициентов: строки со звёздочки —
комментарии (комментарий допускается и в конце оператора, после выражения); обращения к
данным учёта записываются в квадратных скобках ([AK …], [AP …],
[ed …], [ep …] — см. главу «Функции: данные
учёта»); несколько операторов в одной строке разделяются точкой с запятой; результат
возвращается присваиванием $=….
FIRST.RPT перед файлами-коэффициентами
не выполняется (см. ниже) — поэтому коэффициент не должен полагаться на переменные,
установленные в FIRST.RPT. Общие подпрограммы для коэффициентов размещайте в
LIBRARY.RPT (раздел 11.8).11.6. Файл общих определений FIRST.RPT
Если в рабочем каталоге сервера есть файл FIRST.RPT, он выполняется перед
выполнением каждого первичного документа и отчётной формы. Туда выносят всё, что должно
быть общим для форм: употребительные константы, подпрограммы, значения общих переменных —
реквизиты предприятия, Esc-последовательности управления принтером и т.п.
* FIRST.RPT — общие определения
FIRMA='ОАО "Ромашка"'
ESC=[ch 27]
CONDENSED=ESC+[ch 15] * узкий шрифт принтера
Ограничение уже упоминалось: перед файлами-коэффициентами FIRST.RPT не
выполняется. Это разумно: коэффициент вызывается при каждой проводке, и лишние вычисления
замедлили бы пересчёт.
11.7. Файл PROTO.RPT — прототипы фактов
Лента фактов (глава «Лента фактов») хранит записи из безымянных
частей. Чтобы система могла проверять правильность операторов fact,
search и им подобных, синтаксис фактов описывают в файле
PROTO.RPT — в виде прототипов. Знак % отмечает место части
факта, остальные символы — разделители:
**********************************
приход товара, %, %
передача товара, %, %
**********************************
Прототипы можно сделать более выразительными — тогда и операторы читаются как фразы:
************************************************
товара % есть % единиц по цене %
поставщик % передал % единиц товара % на сумму %
************************************************
с ними законны записи вида fact товара T есть Q единиц по цене P и
total поставщик Z передал ?? единиц товара ?? на сумму ?S.
Сервер автоматически проверяет соответствие прототипа из PROTO.RPT и факта,
использованного в файлах форм. Прототипы помогают и при вводе: в редакторе формы нажмите
F4 (шаблоны), выберите прототип из списка и нажмите Enter —
заготовка оператора вставится в текст.
11.8. LIBRARY.RPT и библиотеки *.lib
Подпрограммы и определяемые пользователем функции (операторы call,
return (выражение), вызовы [:метка] — см. главу
«Операторы») можно собрать в файле LIBRARY.RPT: они станут
доступны из любой формы или файла-коэффициента.
FIRST.RPT, библиотека подходит и для
файлов-коэффициентов — поэтому общий расчётный код, нужный и формам, и коэффициентам,
следует класть именно в LIBRARY.RPT.В рабочем каталоге сервера может быть несколько файлов библиотек
*.lib с функциями и подпрограммами — это позволяет разбивать общий код
на тематические модули. Файлы *.lib защищаются шифрованием Enigma.
11.9. Вывод результата формы в файл
Результат выполнения отчётной формы показывается на экране клиента и может быть записан
в файл клавишей Alt+F8. Но форма может и сама писать в произвольные файлы:
для этого строку вывода завершают знаком > (начать файл заново) или
>> (добавить в конец файла), затем пишут ключевое слово file
и через пробел(ы) — имя переменной, чьё строковое значение задаёт имя файла:
строка-вывода >file переменная
строка-вывода >>file переменная
Пример из руководства (он работает и в файлах-коэффициентах):
a=[dir 0]+'1.txt'
\>file a
^^^^^^^^^^^b >>file a
Разбор по шагам:
[dir 0]— функция, возвращающая имя каталога (см. карточку ниже); имя файла собирается строковым выражением, здесь получается1.txtв каталоге данных;\>file a— выводится пустая строка с подавленным переводом строки (начальный\): файл усекается до нулевой длины;^^^^^^^^^^^b >>file a— значениеbдописывается в файл; оно попадает в первую строку, потому что при усечении перевода строки не было. Если бы вместо\>file aбыло написано>file a, первая строка файла была бы пустой, а значениеbпопало бы во вторую строку.
[dir n] — имя каталога данных или каталога обмена
n=0 — каталог данных Сервера; n=1 — каталог обмена Клиентов
с Сервером. Возвращаемая строка всегда завершается знаком \.
a=[dir 0]+'1.txt' * файл 1.txt в каталоге данных
f=[dir 1]+'TXA\'+[stamp 3]+'.TXA' * файл в подкаталоге TXA каталога обмена>file — это не
каталог данных Сервера! Всегда составляйте полное имя через [dir 0] или
[dir 1], иначе файл окажется не там, где вы ожидаете.Похожие возможности даёт и оператор printstr … to > file f — он описан в
главе «Текст и вывод» (раздел 12.4).
12. Текст и вывод: форматные вставки
Отчётная форма — это прежде всего текст. Строки, которые не являются операторами,
попадают в отчёт как есть; чтобы подставить в этот текст значения переменных, служат
форматные вставки из знаков ^. В этой главе — как они устроены, как
выводить длинные строки, как «склеивать» вывод в одну строку и как тонко управлять
представлением чисел.
12.1. Механика ^-полей
В любом месте текста формы (но не внутри операторов) допустима форматная вставка:
цепочка знаков ^, затем имя переменной, затем, возможно, ещё знаки
^:
^...^имя_переменной^...^
При выполнении формы вставка заменяется значением переменной, причём знаки
^ задают формат числа:
- количество ведущих
^(до имени) — число знаков под целую часть; - количество завершающих
^(после имени) — число знаков под дробную часть.
Пример:
B=234.1; А=B+12.2
^^^^^^А^^^
После вычислений A = 246.3; в отчёт попадёт 246.300 — шесть
знаков целой части (значение дополняется ведущими пробелами) и три знака дробной.
^ — это видимый признак переполнения, а не «мусор».
Чтобы такого не случалось, отводите поле с запасом; для слишком длинных строк используйте
вырезку [cp s,nn,mm] (см. главу
«Функции: строки, даты, математика»).12.2. Вывод строк и растекатели
Форматные вставки работают и со строковыми значениями: строка просто занимает место
вставки. Но что делать, если строка длиннее строки отчёта и должна выводиться «в несколько
этажей»? Для этого служат растекатели — цепочки знаков ^ без имени
переменной на строках, следующих за форматной вставкой:
S='qwertysdf ghjkzxcvbn mqwer tyuiop'
^^^^^^^^^^^^^^^^^S
^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^
Правила растекания:
- растекатели располагаются на строках, следующих за форматной вставкой;
- общее число
^во вставке и растекателях должно быть не меньше длины выводимой строки; - одновременно может «растекаться» только одна форматная вставка.
[length s]) или обрезайте строку ([cp …]).12.3. Обратный слэш: вывод без перевода строки
Знак \ в конце строки формы подавляет перевод строки при выводе (сам
\ не выводится). Следующая выводимая строка продолжит текущую — так можно
строить вывод в одну строку из цикла, удобно для «широких» форм с заранее неизвестным числом
полей.
for i=1 to 10
^^i \
endfor
-----
Результат выполнения:
1 2 3 4 5 6 7 8 9 10
-----
Пустая строка формы просто переводит строку — без неё ----- появились бы сразу
после 10.
12.4. Оператор printstr
printstr s — вывод строки без форматирования
Выводит строковое выражение s в отчёт. В отличие от форматных вставок,
printstr не завершает вывод переводом строки (CR LF) и не добавляет
лишних пробелов. Чтобы получить перевод строки между двумя printstr, вставьте
между ними пустую строку.
printstr 'qwerty'
printstr 'asdf'
* выведет: qwertyasdfЕсли те же два оператора разделить пустой строкой, будет выведено две строки:
qwerty и asdf.
Вывод printstr можно переадресовать в файл (s — выводимая
строка, f — строка с именем файла):
printstr s * обычный вывод
printstr s to > file f * начать новый файл f, записать строку s
printstr s to >> file f * добавить строку s в конец файла f
printstr s to file f * то же, что и предыдущий вариант
Сравните с перенаправлением >file / >>file для обычных
строк вывода — раздел 11.9 главы «Файлы форм». Те же правила про полное
имя файла действуют и здесь: используйте [dir 0] / [dir 1].
printstr особенно удобен при генерации HTML и других текстовых
форматов, где лишние пробелы и переводы строк имеют значение — см. главу
«Web-приложения».12.5. Спецкомментарии форматирования: *.on/*.off, *,on/*,off
Особые строки-комментарии позволяют глобально (в пределах формы) управлять тем, как числа превращаются в текст. Они действуют и в формах, и в файлах-коэффициентах — до конца формы либо до отменяющего комментария:
| Спецкомментарий | Действие |
|---|---|
*.on | разрешает выдавать дробную часть числа |
*.off | запрещает выдавать дробную часть числа |
*,on | разрешает запятые в целой части числа (разделение тысяч) |
*,off | запрещает запятые в целой части |
*.,df | возврат к поведению по умолчанию (для форм — к пожеланиям ФБП:Клиента) |
По умолчанию действует сочетание «как у *,on + *.off»: запятые
есть, дробной части нет.
Полный поучительный пример (функция [sn nn,mm,kk] преобразует число в строку
по формату — см. главу «Функции: строки, даты, математика»):
a=[sn 1200.345,17,3]
^^^^^^^^^^^^^^^^a
*.on
*,on
a=[sn 1200.345,17,3]
^^^^^^^^^^^^^^^^a
*.off
*,on
a=[sn 1200.345,17,3]
^^^^^^^^^^^^^^^^a
*.on
*,off
a=[sn 1200.345,17,3]
^^^^^^^^^^^^^^^^a
*.off
*,off
a=[sn 1200.345,17,3]
^^^^^^^^^^^^^^^^a
Результат выполнения формы:
1,200
1,200.345
1,200
1200.345
1200
[sn …], но и
форматных вставок — и действуют до конца формы. Забытый *,off в начале
формы — типичный источник трудноуловимых расхождений в печати: одна и та же форма выдаёт числа
по-разному в зависимости от того, что осталось «включённым». Возвращайте умолчание явно —
комментарием *.,df.13. Переменные, выражения и формулы
Почти вся «начинка» отчётной формы — это формулы: ими вычисляются итоги, проверяются условия, формируются суммы проводок в файлах-коэффициентах. Формула в ФБП строится из чисел, переменных, знаков операций, круглых скобок и вызовов функций — в целом всё похоже на школьную арифметику, но со своими правилами имён, приоритетов и неожиданными возможностями вроде решения систем линейных уравнений.
13.1. Калькулятор: полигон для выражений
Прежде чем писать формулы в форме, их удобно обкатать во встроенном
калькуляторе клиента CLWP (вызов — Ctrl+F3). Он работает
с фиксированной точкой и имеет скобочную логику, то есть понимает выражения
произвольной вложенности.
Enter— завершить ввод выражения;F10— выход с переносом вычисленного значения (если калькулятор вызван при редактировании числа);Esc— выход без переноса.
[ea 50] или оборот.
А с помощью функции [sed ...] можно оперативно присвоить значение
переменной — удобно для проверки формул «на живых» данных.13.2. Типы данных: числа и строки
Язык ФБП не требует объявлять типы: переменная просто получает значение при присваивании. Значений два вида — числа и строки.
Числа хранятся с фиксированной точкой. Все арифметические операции и сравнения работают с числами обычным образом. Важная тонкость — понятие истинности: выражение считается ложью, только если его абсолютное значение меньше 0.000001; любое другое значение — истина. То есть отрицательные числа в условиях трактуются как «истина», а не как «ложь».
Строки встречаются в выражениях реже, но язык их понимает: все операции
сравнения (<, >, =, <> и т.д.)
применимы как к числам, так и к строкам. Строковые значения появляются и как признаки
ошибок: например, операторы линейной алгебры возвращают строку 'fail'
при неудаче (см. 13.8). Создание и обработка строк
подробно разобраны в главе «Функции: строки, даты,
математика».
0 (ложь) или
1 (истина), его можно присваивать и использовать в арифметике:
X = A > B занесёт в X единицу, если A
больше B.13.3. Имена переменных
Переменные в ФБП намеренно «короткие» — как в записи формул на бумаге.
Имя переменной — это одна или две буквы либо буква и цифра.
Примеры допустимых имён: Т, А1, x2,
ZТ. Русские и латинские буквы равноправны.
SummaNds в языке нет. Поэтому опытные авторы форм вырабатывают свои
соглашения (например, S — сумма, K — количество) и
снабжают форму комментариями (строки с *).Имена массивов — отдельная история: это одиночные латинские буквы (см. главу «Массивы»). Есть и особые предопределённые имена — о них ниже.
13.4. Предопределённые переменные
При запуске формы значения всех переменных не определены — кроме нескольких, которые сервер инициализирует сам. Это сведения об отчётном периоде и (в файлах-коэффициентах) о текущей операции.
| Переменная | Значение | Где доступна |
|---|---|---|
MF | Номер первого месяца отчётного периода | везде |
ML | Номер последнего месяца отчётного периода | везде |
MC | Номер текущего месяца (реальная дата) | только файлы-коэффициенты |
DC | День текущей операции | только файлы-коэффициенты |
YC | Номер отчётного года | только файлы-коэффициенты |
OC | Номер операции | только файлы-коэффициенты |
$ | Сумма текущей операции | только файлы-коэффициенты |
Отдельная группа — переменные реальной даты. Они автоматически инициализируются сервером и в файлах-коэффициентах, и в отчётных формах:
| Переменная | Значение |
|---|---|
YR | Реальный год |
MR | Реальный месяц |
DR | Реальный день в месяце |
WR | Реальный день недели (0 — воскресенье, 1 — понедельник, …) |
YC, MC, DC, YR, MR,
DR, WR: такие присваивания были источником
труднообнаруживаемых нестабильных ошибок. Обратите внимание: MF,
ML, OC и $ в список запрещённых не входят.13.5. Выражения и приоритет операций
Формула может содержать числа, переменные, знаки операций и круглые скобки,
а также вызовы функций обращения к данным учёта — например, [ea 50]
подставляет в формулу остаток счёта 50 (см. главу
«Функции: данные учёта»).
| Операции | Знаки | Приоритет |
|---|---|---|
| Отрицание | ~ | самый высокий |
| Умножение, деление, логическое «и», остаток | *, /, &, % | высокий (одинаковый) |
| Сложение, вычитание, логическое «или» | +, -, | | средний (одинаковый) |
| Сравнения | <, >, =, >=, <=, <> | самый низкий |
Пояснения к неочевидным операциям:
&— логическое «и»;|— логическое «или»;~— отрицание. Операнды трактуются по правилу истинности из 13.2: ноль (точнее, |x| < 0.000001) — ложь, остальное — истина;%— остаток от целочисленного деления;- сравнения дают
0или1, и их низкий приоритет означает, чтоA + 1 > Bчитается как(A + 1) > B.
Типичное выражение в вычисляющем операторе (подробно об операторах — глава «Операторы»):
* сложить B с начальным дебетовым остатком счёта 01
A1 = B + [BD 01]
x = [sed 1,2] допустимо просто
[sed 1,2].13.6. Строковые выражения
Строки в выражениях участвуют прежде всего в сравнениях: к ним применимы все
шесть операций сравнения, результат — те же 0 или 1.
Это позволяет, например, сравнивать наименования субсчетов или проверять
строковые признаки ошибок:
* проверка признака неуспеха от lsolve/invertm
X = [y 1] <> 'fail'
Полный набор строковых функций (выделение подстрок, склейка, преобразования) рассматривается в главе «Функции: строки, даты, математика», а правила вывода строк в текст отчёта — в главе «Текст и вывод».
13.7. Даты в выражениях
Специального типа «дата» в языке форм нет: даты представлены числовыми
переменными — год, месяц, день по отдельности. Их дают предопределённые
переменные из 13.4: границы отчётного периода
MF/ML, сведения о текущей операции
(DC, MC, YC — в файлах-коэффициентах)
и реальная дата (YR, MR, DR, WR).
Поскольку это обычные числа, с ними работает вся арифметика и все сравнения. Например, в файле-коэффициенте можно разветвить расчёт по месяцу операции:
* в файле-коэффициенте: другой процент для операций декабря
! MC = 12
P = 20
! MC <> 12
P = 10
А в отчётной форме переменные реальной даты удобны для шапки отчёта —
переменная WR позволяет учесть даже день недели (0 — воскресенье).
Для функций работы с датами (сдвиг даты, разность дат и т.п.) см. главу
«Функции: строки, даты, математика».
13.8. Элементы линейной алгебры
В язык встроены средства для работы с квадратными матрицами: одна функция (определитель) и два оператора (решение системы линейных уравнений и обращение матрицы). Это редкость для бухгалтерских систем, но полезно, скажем, для распределения затрат по модели «затраты–выпуск».
Матрица хранится в массиве, разложенная построчно: для матрицы
n × n элемент (i, j) соответствует элементу массива
с номером (i-1)*n+j. Сами массивы подробно описаны в главе
«Массивы»; здесь достаточно знать, что запись
[a k, значение] заносит значение в k-й элемент массива
a, а [a k] — читает его.
[det a,n] — определитель матрицы
a — латинская буква, имя массива с матрицей n × n;
n — размер. Возвращает определитель матрицы.
* определитель матрицы Гильберта 4x4
n=4
for i=1 to n
for j=1 to n
[a (i-1)*n+j, 1/(i+j-1)]
endfor
endfor
x=[det a,n]
^^^^^^^^^x^^^^^^^^^^^^^^
Результат: 0.00000016534392.
lsolve a,b,y,n — решение системы линейных уравнений
Решает систему a · y = b. Параметры: a — массив
с матрицей n × n; b — массив с правой частью (вектор);
y — массив, куда будет занесено решение (вектор); n —
размер. Об ошибках сообщает не прерыванием, а значением первого элемента
результата: если массив a (или b) содержал строковое
значение, элементу [y 1] присваивается 'string';
при неуспешном решении системы — 'fail'.
[a 1, 20, 23, 17, 90]
[a 5, 33, -4, 12, 0]
[a 9, 77, 34, 11, -2]
[a 13, 10,108, 44, 99]
[b 1, 1, 2, 3, 4]
lsolve a,b,y,4
for i=1 to 4
x=[y i]
^^^^^^^^^^x^^^^^^^^^^
endfor
Результат:
0.0208762740
0.0042390130
0.1106699174
-0.0155156820invertm a,c,n — обращение матрицы
a — массив с исходной матрицей n × n;
c — массив, куда будет занесена обращённая матрица;
n — размер. Имена a и c могут совпадать —
тогда матрица обращается «на месте». Признаки ошибок — как у
lsolve: если a содержал строковое значение,
[c 1] получает 'string', при неуспешном обращении —
'fail'.
n=4
for i=1 to n
for j=1 to n
[a (i-1)*n+j, 1/(i+j-1)]
endfor
endfor
*
invertm a,b,n
*
for i=1 to 4
for j=1 to 4
x=[b (i-1)*4+j]
^^^^^^^^^x^^^^^^^^^ \
endfor
endfor
Результат (матрица, обратная к матрице Гильберта 4×4):
16.000000000 -120.000000000 240.000000000 -140.000000000
-120.000000000 1200.000000000 -2700.000000000 1680.000000000
240.000000000 -2700.000000000 6480.000000000 -4200.000000000
-140.000000000 1680.000000000 -4200.000000000 2800.000000000lsolve и invertm всегда проверяйте
первый элемент результата: значения 'string' и 'fail'
означают, что решения нет, и пользоваться остальными элементами массива нельзя.
Сравнение со строкой — обычная операция: ! [y 1] <> 'fail'.for … endfor (глава «Операторы»),
заполнение массива [a k, …] (глава
«Массивы»), форматные вставки ^ и знак
\ в конце строки для слияния вывода в одну строку (глава
«Текст и вывод»), строка * — комментарий.14. Операторы управления и подпрограммы
До сих пор мы писали формы, которые выполнялись «сверху вниз». Этой главы достаточно, чтобы программировать по-настоящему: спрашивать данные у пользователя, выполнять части формы по условию, повторять вычисления в циклах и выносить повторяющийся код в подпрограммы и собственные функции.
14.1. Общие правила записи операторов
- Оператор начинается с ключевого слова или знака; перед ключевым словом могут идти пробелы — отступы делают форму читаемее.
- Несколько операторов можно записать в одной строке, разделив их знаком
;:
A=23; B=[EA 50]; C=[ED 68]
Операторы языка форм делятся на группы: вычисляющий оператор и ввод (эта глава), условия и циклы (эта глава), операторы для работы с массивами (глава «Массивы»), оператор выполнения проводки в файле-коэффициенте (глава «Виды операций и проводки»), операторы ленты фактов (глава «Лента фактов») и средства организации подпрограмм (эта глава).
14.2. Вычисляющий оператор
Самый частый оператор языка: вычислить формулу и присвоить результат переменной.
переменная = формула — вычисление и присваивание
Вычисляет формулу (числа, переменные, функции, знаки операций — см. главу «Переменные и выражения») и записывает результат в переменную.
А1=B+[BD 01]
— сложить B с начальным дебетовым остатком счёта 01 и присвоить результат
переменной A1.
Если функция вызывается только ради побочного эффекта (например, [sed 1,2]
сохраняет значение в дисковую базу), значение можно не присваивать — допускается
сокращённая запись, где оператор начинается сразу со скобки [:
[sed 1,2] * вместо x=[sed 1,2]
14.3. Оператор вопроса ?
Часто форме нужны сведения, которых нет в учётных данных: период, код товара, дата. Оператор вопроса запрашивает их у пользователя при выполнении формы.
?переменная вопрос — ввод значения при выполнении формы
Выводит строку-приглашение и ждёт, пока пользователь введёт значение переменной.
?A ввести переменную A:[is], [im], [ia] —
см. главу «Функции: ввод и оформление».14.4. Условный оператор !
Условный оператор — исторически первый способ ветвления в языке форм: он включает или выключает выполнение последующих строк в зависимости от условия.
! выражение — выполнять дальнейшее, только если выражение истинно
Выражение считается ложью, если его абсолютное значение меньше 0.000001; во всех
остальных случаях — истиной. Если условие ложно, все операторы до следующего условного
оператора не выполняются. После последнего оператора формы подразумевается неявный
!, закрывающий открытое условие.
X=A>B
! X Y=25
Здесь X станет 1 или 0 по результату сравнения A>B; если
X истинно, выполнится Y=25.
Результат любого сравнения (<, >, =,
>=, <=, <>) — число 0 или 1;
сравнения применимы и к числам, и к строкам. Условия комбинируются операциями
& (И), | (ИЛИ), ~ (отрицание),
% (остаток от деления). Условие можно записать прямо в операторе вместе
с действиями:
! A>B X=1 Y=1 * если A>B, то выполнить X=1 и Y=1
|x| < 0.000001. Отрицательное число — тоже «истина»!Частный случай — проверка вхождения в замкнутый интервал (границы включаются):
! выражение in выражение..выражение — проверка вхождения в интервал
Истинно, если значение первого выражения принадлежит интервалу от второго до третьего выражения включительно.
! A in 1000..2000 * 1000 <= A <= 2000
! (X in A..B) | (X in C..D)! нельзя использовать внутри операторов
if, for и while — для условий внутри этих блоков
применяйте вложенный if.14.5. Оператор if / elseif / else / endif
Более наглядная замена !: блоки ветвления, которые можно вкладывать друг
в друга и в циклы.
if … elseif … else … endif — структурное ветвление
Синтаксис (.... — любые операторы языка, строки текста формы и т.д.):
if выражение
....
elseif выражение
....
else выражение
....
endif
Разделы elseif и else необязательны; разделов
elseif может быть сколько угодно.
if нельзя использовать условный оператор
!.14.6. Оператор цикла # — перебор субсчетов
Самая «бухгалтерская» конструкция языка: цикл, который перебирает субсчета (объекты) указанного счёта и для каждого выполняет тело цикла — так строятся ведомости и списки.
# счёт … # — цикл по субсчетам счёта
Цикл начинается знаком #, далее в той же строке — обозначение счёта.
Строки до строки, состоящей из единственного #, — тело цикла. Внутри тела на
обозначение выбранного субсчёта ссылаются тем же знаком #.
Название Цена, ед Остаток,руб Остаток,шт
# 10
A=[NA #]; P=[EP #]; ER=[EA #]; EQ=ER/P
^^^^^^^^A ^^^^^^^^P ^^^^^^^^^ER ^^^^^^^^^EQ
#
— простая ведомость по остаткам материалов (счёт 10).
После # может идти не только обозначение счёта, но и
*-обозначение — косвенная ссылка на счёт через переменную:
A=`70`
# *A
B=[n1 #]
^^^^^^^^^^B
#
Ключевое слово sort после обозначения счёта задаёт порядок обхода:
для каждого субсчёта вычисляется выражение, и субсчета перебираются по возрастанию его
значений. Пример — перечисление в порядке возрастания остатков:
#68 sort [ea #]; n=[n1 #]; m=[ea #]
^^^^^^^^n ^^^^^^^^^^^^m^^
#
А так — сортировка по алфавиту наименований:
#70 sort [n2 #]; n=[na #]
^^^^^^^^^^^^^^^^^^^^^^^n
#
[na], [ea] и других
обращениях к данным счетов — в главе «Функции: данные учёта»;
об @- и *-обращениях — в главе «@-обращения и контекст».14.7. Оператор for / endfor
Классический цикл со счётчиком: повторить тело заданное число раз, наращивая или уменьшая переменную.
for переменная=выражение to|downto выражение … endfor — цикл со счётчиком
Переменная пробегает значения от первого выражения до второго; to — по
возрастанию, downto — по убыванию.
for i=10 downto 1
^^i
endfor
for i=1 to [get %,x]
....
endforto (или downto) вычисляется
на каждом витке цикла. Вынос его в переменную ускоряет цикл, но меняет смысл, если
функция в выражении возвращает разные значения: в первом варианте новое значение
[get %,x] может изменить общее число витков.
n=[get %,x] * граница зафиксирована
for i=1 to n
....
endforВнутри for нельзя использовать условный оператор ! —
применяйте if.
14.8. Оператор while / endwhile
Цикл «пока условие истинно» — удобен, когда число повторений заранее неизвестно.
while выражение … endwhile — цикл с условием
Повторяет тело, пока выражение истинно (по тому же правилу: ложь — это абсолютное значение меньше 0.000001).
i=1
while i<10
^^i \
i=i+1
endwhile
Результат: 1 2 3 4 5 6 7 8 9 (знак \ в конце строки с
форматной вставкой сливает вывод в одну строку — см. главу
«Текст и вывод»).
Внутри while нельзя использовать условный оператор !.
14.9. Операторы stop и error
stop — прекратить выполнение формы
Прекращает выполнение формы или файла-коэффициента. Обязателен в конце основной части формы перед разделом подпрограмм (см. 14.13).
error — прервать файл-коэффициент с сообщением
Прекращает выполнение файла-коэффициента и передаёт все оставшиеся символы
строки, в которой находится оператор, как сообщение пользователю. Клиент при этом
открывает журнал операций и указывает на операцию, в которой сработал
error, — так файл-коэффициент сообщает бухгалтеру об ошибке в данных.
if Z=0
error Не задано количество!
endif14.10. Оператор goto и метки
Переход на произвольную точку формы — примитивно, но именно на метках строятся подпрограммы и собственные функции.
goto метка / :метка — безусловный переход
Передаёт управление строке, в которой описана метка. Метка — слово длиной
до 10 символов, расположенное после первого символа : в строке.
:НАЧАЛО
бесконечность
goto НАЧАЛО
— форма, создающая бесконечно растущий файл (пример того, как делать не надо).
14.11. Комментарии в формах
Комментарии начинаются символом *: все символы после *
программой игнорируются. Звёздочку ставят и в начале отдельной строки-комментария:
* это комментарий на всю строку
A=2 * а это пояснение к оператору
*.on, *.off, *,on,
*,off, *.,df не просто игнорируются, а управляют форматом вывода
чисел — см. главу «Функции: строки, даты, математика»
(функция [sn]).14.12. Оператор printstr
Выводит строку «как есть»: без автоматического перевода строки и без лишних пробелов,
которые добавляют форматные вставки ^.... Незаменим при выводе HTML-разметки
и точно сформированного текста.
printstr s — вывод строки без перевода строки
s — строковое выражение. Вывод не завершается переводом строки (CR LF).
Чтобы получить перевод строки между двумя printstr, вставьте между ними
пустую строку.
printstr 'qwerty'
printstr 'asdf'
выведет qwertyasdf; те же операторы, разделённые пустой строкой, выведут
две строки.
printstr умеет и переадресовывать вывод в файл (s —
выводимая строка, f — строка с именем файла):
printstr s * обычный вывод
printstr s to > file f * начать новый файл f, записать строку s
printstr s to >> file f * добавить строку s в конец файла f
printstr s to file f * то же, что и предыдущий вариант
14.13. Подпрограммы: call и return
Если один и тот же фрагмент нужен в нескольких местах формы, его описывают один раз
в конце формы и вызывают оператором call.
call метка / :метка … return — вызов подпрограммы
Подпрограмма начинается с метки :L и завершается оператором
return. Вызов передаёт управление на метку; return возвращает
выполнение на следующий за call оператор.
...
call L * вызов подпрограммы
...
stop
*****
:L
это тело подпрограммы
returnstop:
иначе выполнение основной части «провалится» в подпрограмму и та выполнится лишний раз.Разделы, совместно используемые несколькими формами, описывают в файле общих
определений first.rpt, а подпрограммы в файле LIBRARY.RPT
доступны из любой формы или файла-коэффициента — см. главу
«Файлы форм и общие файлы».
14.14. Параметры подпрограмм и оператор local
Подпрограмме можно передать значения: в call указывают фактические
параметры, а после метки — формальные.
- В
CALLпосле имени метки — фактические параметры: выражение или выражения через запятую в круглых скобках. - После метки — формальные параметры: переменная или переменные через запятую в круглых скобках.
- При входе в подпрограмму формальные параметры получают значения фактических.
- Формальные параметры — локальные переменные подпрограммы; их экземпляры
автоматически уничтожаются при выполнении
RETURN. - Параметры передаются «по значению»: изменение формального параметра внутри подпрограммы не меняет фактический параметр в вызывающей программе.
local переменная {, переменная} — локальные переменные подпрограммы
Создаёт новые экземпляры указанных переменных, которые автоматически уничтожаются
при выполнении оператора return. Одноимённые переменные вызывающей программы
не затрагиваются.
A=5
call P
^^A
stop
:P
local A,B
A=1; B=2
^^A ^^B
return
Результат выполнения:
1 2
5
Переменная A основной части сохранила значение 5, несмотря на
одноимённую локальную переменную в подпрограмме.
Пример подпрограммы с параметрами:
call SUM(1,2)
stop
:SUM(a,b)
local c; c = a+b
^^^^^c
return
Результат выполнения: 3.
14.15. Определяемые пользователем функции
Подпрограмма может не только что-то делать, но и возвращать значение — тогда её можно вызывать прямо в формулах, как встроенную функцию.
[:метка параметры] и return (выражение) — своя функция
Если в операторе RETURN указать возвращаемое значение — выражение в
круглых скобках, — то к подпрограмме можно обращаться как к функции:
[:метка]
[:метка параметры]
параметры — выражение или выражения, разделённые запятыми.
x=[:max 3,5]
^^^^^x
stop
:max(x,y)
if x > y return (x); else return (y); endif
Результат выполнения: 5.
Допускаются рекурсивные вызовы функций. Пример — вычисление факториала N! = N·(N−1)·…·1:
x=[:factorial 5]
^^^^^^^x
stop
:factorial(n)
if n=0 return (1); else return (n*[:factorial n-1]); endif
Результат: 120.
local и формальные параметры): рекурсивные вызовы не портят переменные друг
друга, потому что каждый вызов получает свои экземпляры.15. Массивы
Массивы нужны там, где обычных переменных не хватает: накопить в цикле сотни значений, отсортировать их, обратиться к элементу по вычисленному номеру. В языке ФБП массивы устроены предельно просто: они не объявляются, именуются одной латинской буквой и могут хранить как числа, так и строки.
15.1. Обращение к элементам: чтение и присваивание
Имя массива — одна латинская буква, записанная после открывающей квадратной скобки; далее через пробел идёт выражение-индекс. Та же запись служит и функцией чтения, и оператором присваивания — в зависимости от числа аргументов:
| Запись | Смысл |
|---|---|
[a i] | функция: значение i-го элемента массива a |
[a j,v] | оператор: присвоить j-му элементу массива a значение v |
x = [a i]
[a j,v]
Есть и групповое присваивание: если после индекса перечислить несколько значений через запятую, они попадут в элементы подряд, начиная с указанного:
[m 1,'Jan','Feb','Mar','Apr','May','Jun']
Здесь [m 1] получит значение 'Jan', [m 2] —
'Feb' и так далее.
15.2. Индексы, имена и ограничения
- Индекс элемента — от 1 до 1000000. Значение индекса всегда округляется до ближайшего целого.
- Всего можно создать 26 массивов — по числу латинских букв.
- Малые и большие буквы в именах массивов не различаются:
[A 1]и[a 1]— один и тот же элемент. - Массив и одноимённая переменная — совершенно разные объекты: можно одновременно
иметь массив
zи переменнуюz, они никак не влияют друг на друга. - При старте формы или файла-коэффициента все элементы всех 26 массивов получают нулевые значения — предварительная инициализация не нужна.
- В элементе с индексом 0 хранится индекс последнего элемента, которому было
присвоено значение, — то есть текущая длина массива:
t = [m 0].
prolog и everydebet (из-за побочных эффектов при выполнении
проводок оператором с кодом 177), а в разделе epilog использовать их можно —
например, чтобы отсортировать накопленные значения перед печатью.array a,b,c — обнуление массивов
Обнуляет перечисленные массивы, освобождая занимаемую ими память. При старте формы и файла-коэффициента этот оператор выполняется автоматически для всех массивов, так что вручную он нужен лишь для повторной очистки в середине работы:
array a,b,c15.3. Сортировка: оператор sort array
Сортировать большие списки «вручную» не придётся — есть встроенный оператор в двух вариантах.
sort array a[,b] — сортировка массива
Первый вариант — sort array a: сортирует массив a
по возрастанию значений элементов на месте (сам массив изменяется).
Второй вариант — sort array a,b: массив a
не изменяется; результат создаётся в массиве b в виде
новых номеров элементов. Если элемент [a 1] после сортировки
должен оказаться пятым, то [b 1] будет равно 5.
sort array a * a отсортирован по возрастанию
sort array a,b * b — таблица новых номеров, a прежнийsort array k,b обходите элементы в порядке [b 1],
[b 2], … — и данные будут упорядочены по возрастанию ключа, при этом исходный
массив останется нетронутым.15.4. Типичные приёмы работы с массивами
Накопление в цикле с запоминанием длины. Значение [a 0] всегда
подсказывает, сколько элементов уже заполнено, — это удобная «длина массива»:
for i=1 to 10
[a i, i*i]
endfor
n=[a 0] * n равно 10 — индекс последнего заполненного элемента
Сбор данных в форме-истории и сортировка в конце. В разделе
everydebet массивы недоступны, поэтому значения копят через
экстрапараметры, а в epilog переносят в массив и сортируют:
prolog
n=0
every debet
n=n+1
[set X, n, ss]
epilog
for i=1 to n
[a i,[get X, i]]
endfor
sort array a
for i=1 to n
y=[a i]
^^^^^^^^^^^y
endfor
Массив как «холст». Массивы — основа графических операторов
(makepng, drawline и др.): точке изображения с координатами
(x, y) соответствует элемент с индексом (y-1)*w+x. Это подробно разобрано
в главе «Графика». Там же описаны и операции линейной алгебры
([det a,n], lsolve, invertm), где матрица n×n
хранится в массиве по тому же правилу: элемент (i, j) — это индекс (i-1)*n+j.
16. Лента фактов и ta-факты
Остатки и обороты счетов отвечают на вопрос «сколько?», но не «что именно произошло?». Механизм фактов позволяет запоминать сами события: «пришёл товар А12 в количестве 5», «поставщик Z передал товар на сумму 100». Формы могут потом искать такие события, считать их итоги, сортировать и удалять. Механизм появился в версии ultraF.
16.1. Что такое факт и как хранится лента фактов
Факт — запись из одной или нескольких частей; каждая часть может быть числовой или строковой. Части не имеют имён и закреплённых типов — говорят просто о первой, второй и т. д. частях. Какой смысл вкладывать в каждую часть, решаете вы сами: это может быть событие, отношение между объектами, любое наблюдение.
Организация хранения:
- Все факты образуют общий список facts — «ленту фактов». Порядок фактов в ленте совпадает с порядком следования операций, породивших их.
- Каждый факт автоматически снабжается отметкой о дате операции (значения
предопределённых переменных
YC,MC,DC). - При удалении операций соответствующие факты вычёркиваются из списка автоматически.
- Факты размещаются в оперативной памяти сервера и воссоздаются заново при каждом его старте.
facts.e со всеми фактами года. Перенесите его
в каталог данных нового года и переименуйте в facts.b: при старте сервера
эти факты будут «подхвачены». Файл facts.b — обычный текстовый файл.16.2. Операторы ленты фактов: обзор
| Оператор | Действие |
|---|---|
fact | внести новый факт в ленту фактов |
search | найти подходящий по образцу факт |
rewind facts | перемотать ленту фактов в начало |
news | дать последнюю «новость» о факте |
total | суммирование подходящих частей фактов |
erase | вычеркивание фактов из ленты |
nerase | вычеркивание последнего подходящего факта |
select | выбор подходящих фактов в буфер |
rewind buffer | перемотать буфер в начало |
sort buffer | отсортировать факты в буфере |
range | задать интервал дат для отбора фактов |
Сервер хранит указатель на «текущий» факт (current), который необходим
для работы search: каждый удачный поиск сдвигает указатель дальше по ленте.
16.3. Оператор fact
fact e1, e2, ... eN — внести факт в ленту
Записывает новый факт: первая часть получит значение e1, вторая —
e2 и т. д. Части — формулы языка форм или строки (кавычки для строк
необязательны). Синтаксис записи управляемый — его можно настроить прототипами в файле
proto.rpt (см. 16.11).
Важно: оператор можно использовать только в файлах-коэффициентах — факт всегда привязан к операции и её дате.
fact приход товара, K, Q
fact передача товара, K, QТак, файл-коэффициент прихода товара заносит факт «приход товара, код, количество», а файл-коэффициент передачи — факт о передаче. Дальше отчётные формы работают уже с этой лентой.
16.4. Поиск: rewind facts и search
rewind facts — перемотать ленту в начало
Устанавливает указатель current на первый факт ленты. Перед началом
поиска с самого начала ленты перемотка обязательна:
rewind factssearch p1, p2, ... pN — найти факт по образцу
Ищет в ленте (начиная с указателя current) первый факт, подходящий
под образец. Каждая часть образца — это:
- формула языка форм — часть факта должна совпасть с её значением;
- конструкция
?переменная— в эту переменную запишется значение соответствующей части найденного факта; ??— эта часть факта не интересует (подходит любое значение).
Факт считается подходящим, если значения всех частей-формул совпали с соответствующими
по номеру частями факта. При успехе переменным из частей ?переменная
присваиваются значения частей факта, а указатель current смещается на
следующий факт — поэтому повторный search продолжит поиск дальше,
и цикл «перемотка → поиск в цикле» перебирает все подходящие факты.
Тонкости образца:
- Если образец содержит только
?переменная— подходящим является каждый факт (так печатают всю ленту). - Если частей в образце больше, чем частей в подходящем факте, переменным из
избыточных частей присваивается строковое значение
NO ELEM. - Признак результата — функция
[success](см. 16.13): 1 при удаче, 0 при неудаче. - Дату операции найденного факта дают функции
[fact_y],[fact_m],[fact_d].
Форма list0.rpt — печать всей ленты фактов без отметок о датах:
* Все элементы списка без отметок о датах
rewind facts
:L
search ?X, ?Y, ?Z
! [success] = 1
^^^^^^^^^^^^^^^^^^^^^X ^^^^^^^^^Y ^^^^^^^^^^Z
goto L
!
* конец формы
Форма list1.rpt — поиск по образцу с константой и с датами
(только передачи товара A11):
* Только передачи товара A11 с датами передач
Y='A11'
rewind facts
:L
search передача товара, Y, ?Z
! [success] = 1
M=[fact_m]; D=[fact_d]
^D ^M передача товара ^^^^^^^^^Y ^^^^^^^^^^Z
goto L
!
* конец формы
search (или другого оператора поиска) обязательно сделайте
rewind facts — иначе поиск продолжится со старой позиции указателя
и факт может быть не найден:
fact приход товара 'A12'
...
b1=0
rewind facts
search приход товара ?b1
Эта тонкость относится ко всем операторам поиска, включая nerase.16.5. Оператор news: последняя «новость»
news p1, p2, ... pN — найти последний подходящий факт
Части образца интерпретируются так же, как для search, но поиск
всегда начинается от конца списка и движется к началу — до первого подходящего
факта. Это и есть «новость»: самое свежее событие нужного вида.
rewind factsна поведениеnewsне влияет.- Указатель
currentне изменяется. - Если интервал дат задан оператором
range, тоnewsигнорирует меньшую границу и продолжает поиск до начала ленты фактов. [success]работает как индикатор результата.
Форма list2.rpt — когда был последний приход товара A12:
* Поиск последнего подходящего факта - "новости"
news приход товара, 'A12', ?Z
! [success] = 1
M=[fact_m]; D=[fact_d]
^D ^M приход товара A12 ^^^^^^^^^^^Z
!
* конец формы
16.6. Оператор total: суммирование по фактам
total p1, p2, ... pN — просуммировать части фактов
Части образца — как у search, но в переменных из частей
?переменная накапливаются суммы соответствующих частей всех
подходящих фактов (перед вызовом такую переменную следует обнулить).
- Поиск идёт от начала списка к концу;
rewind factsне влияет, аrange— влияет (суммирование внутри интервала дат). - Указатель
currentне изменяется. [success]— 1, если найден хотя бы один подходящий факт;[found]— количество найденных фактов.
* Сколько всего было передано товара с кодом A11 ?
S=0
total передача товара, 'A11', ?S
Всего отгружено A11: ^^^^^^^^^^S
* конец формы
ОШИБКА TOTAL - сложение строки с числом. Следите, чтобы суммируемые
части фактов были числовыми.16.7. Вычеркивание фактов: erase и nerase
erase p1, p2, ... pN — вычеркнуть все подходящие факты
Вычёркивает из списка facts все подходящие по образцу факты.
Доступен только в файлах-коэффициентах. При удалении операции, вызвавшей
erase, все вычеркнутые ею факты восстанавливаются — как и положено
при виртуальном пересчёте.
rewind factsне влияет; указательcurrentне изменяется.[success]— 1, если вычеркнут хотя бы один факт;[found]— количество вычеркнутых.
nerase p1, p2, ... pN — вычеркнуть последний подходящий факт ultraF от 4.04.97
Вычёркивает из списка последний подходящий факт: сначала действует как
news, затем удаляет найденный факт. [success] — индикатор
успеха.
erase на nerase там, где оба оператора
эквивалентны по действию (например, когда вычёркивается заведомо один факт), даёт
очень значительный выигрыш во времени пересчёта. Не забывайте про
rewind facts перед поиском только что внесённого факта:
fact приход товара 'A12'
...
b1=0
rewind facts
nerase приход товара ?b116.8. Выборка и сортировка: select, sort buffer, rewind buffer
Лента фактов упорядочена по датам операций, а select позволяет просматривать
подходящие факты в ином порядке — например, по возрастанию какой-то части факта
или по алфавиту. Для этого найденные факты помещаются во временный список
buffer, который можно отсортировать и обойти.
select p1, p2, ... pN — выбрать факты в буфер
Ищет все подходящие факты в facts и помещает их во временный список
buffer. Поиск в прямом направлении; rewind facts не влияет;
указатель current не изменяется.
[success]— 1 при наличии находок;[found]— количество найденных фактов;[selected]— количество фактов, фактически помещённых вbuffer. Если ёмкость буфера достаточна,[selected]равно[found]; иначе[selected]= 10000 (ёмкость списка).
sort buffer e1 — сортировка буфера
Сортирует список buffer по значению части факта, номер которой равен
модулю e1 (e1 — формула с положительным или отрицательным
числовым значением). Если e1 отрицательно — порядок по убыванию
(обратный алфавитному для строк).
sort buffer 3 * по третьей части факта, по возрастаниюrewind buffer — перевести search на буфер
Устанавливает указатель current на первый элемент buffer.
После rewind facts оператор search ищет в списке
facts, после rewind buffer — в buffer.
rewind buffer не влияет на news,
total, erase и select — они всегда ищут только
в списке facts. В буфере работает только search.Форма list5.rpt — все передачи товара, упорядоченные по количествам:
* Перечень всех передач товара с упорядочением
* по количествам
select передача товара, ??, ??
sort buffer 3
rewind buffer
:L
search передача товара, ?Y, ?Z
! [success] = 1
M=[fact_m]; D=[fact_d]
^M ^D передача товара ^^^^^^^^Y ^^^^^^^^^Z
goto L
!
* конец формы
16.9. Интервал дат: оператор range
rewind facts range YYYYMM.DD,YYYYMM.DD — поиск в интервале дат
Задаёт интервал дат, внутри которого ищут search, select,
news и total. Первое число — начало периода, второе — конец;
YYYY — год (может отсутствовать), MM — месяц,
DD — день.
rewind facts range 1.06,1.06Правила интерпретации границ:
- Границы трактуются просто как числа:
DD=0илиDD=1означают начало месяцаMM;DD=31или больше — конец месяца независимо от его реальной длины. newsигнорирует меньшую границу и ищет от конца интервала до начала ленты.- Обычный
rewind factsграницы интервала не отменяет. - Удобно использовать предопределённые переменные
MF,ML(первый и последний месяц отчётного периода) иDF,DL(первый и последний день). Границы отчётного периода каждый клиент устанавливает для себя (в CLWP — клавишами Ctrl+O).
range значительно уменьшает время построения
форм с фактами: лента фактов индексируется по датам,
и rewind facts range выполняется за малое постоянное время вместо полного
просмотра ленты.16.10. Шаблоны поиска: {}-способ и `-способ
Образцы для search, news, erase,
nerase, select и total не обязаны заново
перечислять все части факта. Есть два способа формировать шаблон гибче.
{}-способ. Вместо полной записи прототипа (выражение / ?переменная /
?? для каждого поля) указывается несколько пар выражений в фигурных
скобках; выражения внутри пары разделяются запятой:
- первое выражение пары — числовое: номер поля факта;
- второе — желаемое значение этого поля.
Поля, не «охваченные» парами, на поиск не влияют (эквивалентны ??).
Например, вместо
search Товар ??, X, ??, Y
можно записать:
search Товар {3,X} {5,Y}
Номера полей могут быть сколь угодно сложными выражениями — это позволяет динамически формировать шаблоны:
? X по какому полю искать
? Y значение поля
news Товар {X,Y}
Прототип факта можно не указывать вообще — news {X,Y} ищет любой факт,
у которого в поле с номером X значение Y. Первое слово
прототипа — это просто поле факта с номером 1, поэтому записи эквивалентны:
news {1,'Товар'} {X,Y}
news Товар {X,Y}
[fact_f i] при работе с фактами с большим количеством полей. Для оператора
total он напрямую не подходит для суммирования (суммы накапливаются только
в ?переменных), но его можно использовать для получения
[found] — то есть просто для подсчёта подходящих фактов.`-способ (обратный апостроф, код 96). Наряду с традиционными указаниями полей
(??, ?переменная, выражение) в шаблоне можно использовать
конструкцию
`выражение
Если такое выражение выдаёт строку или число, поведение будет таким, как если бы эта
строка или число находились в тексте шаблона вместо выражения — шаблон формируется
косвенно, в момент поиска. Например, если на вопросы формы ничего не отвечать (три раза
Enter), будет выполнен поиск search q ?A, ?B, ?C; а если на вопрос «Имя?»
ответить «Вася», это будет понято как search q 'Вася', ?B, ?C.
total: суммирование идёт в ?переменной, и неважно,
указана она прямо или через `.16.11. Прототипы фактов: файл proto.rpt
Синтаксисом записи фактов можно управлять, описав в файле proto.rpt
прототипы фактов. В прототипе знак % обозначает место части факта,
а всё остальное (например, запятые) — разделители между частями:
**********************************
приход товара, %, %
передача товара, %, %
**********************************
Прототипы могут быть гораздо выразительнее — факт читается как обычная фраза:
************************************************
товара % есть % единиц по цене %
поставщик % передал % единиц товара % на сумму %
************************************************
Тогда в файле-коэффициенте пишут fact товара T есть Q единиц по цене P,
а в форме — total поставщик Z передал ?? единиц товара ?? на сумму ?S.
Сервер автоматически проверяет соответствие прототипов из proto.rpt
и фактов, использованных в файлах форм.
16.12. ta-факты: детальная информация о проводках
ФБП:Сервер может самостоятельно запоминать через механизм фактов детальную
информацию о каждой выполненной проводке. Это даёт возможность видеть проводки
операций, анализировать счета, получать оборотные ведомости за любой период — без
написания собственных fact-записей.
Пример: при обработке операции с ключом CAAA-170 выполняется проводка
«дебет X, кредит Y, сумма 100», после которой остаток X становится 1100, остаток Y — 900.
Сервер добавит два факта:
fact ta 'X', 100, 0, 'Y', 1100, 'CAAA-170'
fact ta 'Y', 0, 100, 'X', 900, 'CAAA-170'
Структура прототипа ta (на примере первой записи):
| Поле | Значение | Смысл |
|---|---|---|
| 1 | 'X' | счёт |
| 2 | 100 | на какую сумму дебетуется счёт X |
| 3 | 0 | на какую сумму кредитуется счёт X |
| 4 | 'Y' | корреспондирующий (кредитуемый) счёт |
| 5 | 1100 | остаток счёта X после проводки |
| 6 | 'CAAA-170' | штамп операции |
Для второй записи роли зеркальны: счёт Y, кредитование 100,
корреспондент X, остаток 900.
На ta-фактах построены встроенные в Сервер формы:
__SYS000 * Список проводок по операции
__SYS001 * Обороты счетов
__SYS002 * Обороты субсчетов
__SYS003 * Анализ счета
__SYS004 * Анализ корреспонденции
__SYS005 * Корреспонденции счета синтетически
__SYS006 * Корреспонденции счета детально
Управление режимом:
- Сервер может работать как с запоминанием ta-фактов, так и без него; запоминать их можно не во всех месяцах — диапазон месяцев указывается при запуске Сервера.
- При включённых ta-фактах возможен просмотр проводок в операциях по F6 (в журнале операций CLWP).
- В режиме с ta-фактами потребность Сервера в оперативной памяти существенно увеличивается.
- Если ta-факты отключены, для форм
__SYS...границы выбранного периода выравниваются на начало и конец указанных месяцев.
[bp]/[ep] и
экстрапараметрами (глава «Экстрапараметры и дисковая база»).Через ta-факты можно строить собственные формы. Например, обороты между счетами
X и Y за период в днях (аналог функции [op X,Y]):
**** пример формы ****
S=0
if DF=0 DF=1; endif
if DL=0 DL=31; endif
rewind facts range MF+DF/100, ML+DL/100
total ta 'X',?S, ??, 'Y', ??, ??
^^^^^^^^S^^
**** конец формы ****
А так считаются обороты по дебету счёта X (аналог [od X]):
**** пример формы ****
S=0
if DF=0 DF=1; endif
if DL=0 DL=31; endif
rewind facts range MF+DF/100, ML+DL/100
total ta 'X',?S, ??, ??, ??, ??
^^^^^^^^S^^
**** конец формы ****
[ta m1,m2] — проверка режима запоминания ta-фактов
m1, m2 — номера первого и последнего месяцев диапазона.
Возвращает 1, если ta-факты запоминаются для всех месяцев диапазона, и 0,
если хотя бы для одного — нет. Полезна, чтобы форма могла проверить, имеет ли смысл
обращаться к ta-фактам.
16.13. Функции ленты фактов
Эти функции используются и в файлах-коэффициентах, и в отчётных формах — они сообщают о результатах операторов поиска.
[success] — признак успешного поиска
Равна 1, если поиск факта по шаблону в ленте фактов (или в буфере) операторами
search, news, erase, nerase был
успешным; 0, если ни один подходящий факт не найден. Для total —
1, если найден хотя бы один подходящий факт.
news приход товара, 'A12', ?Z
! [success] = 1
Дата последнего прихода: ^[fact_d].^[fact_m][found] — количество найденных фактов
Количество фактов, найденных по шаблону операторами select,
total, erase (для erase — число вычеркнутых).
[selected] — количество фактов в буфере
Количество фактов, помещённых во временный список buffer оператором
select. Если ёмкость buffer достаточна,
[selected] = [found], иначе [selected] =
10000 (ёмкость списка).
[fact_y] [fact_m] [fact_d] — дата найденного факта
Если поиск факта (search, news, erase,
nerase) успешен, возвращают дату найденного факта: год, месяц и день
соответственно (числовые значения).
M=[fact_m]; D=[fact_d]
^D ^M передача товара ^^^^^^^^^Y[fact_f i] — поле найденного факта по номеру
Выдаёт поле последнего найденного факта с номером i (числовое выражение).
При i=1 — первое слово прототипа факта; при i=0 — количество
полей в факте.
[fact_f] можно только если
[success] = 1 — иначе значение не определено.Функция позволяет обрабатывать факт целиком, не расписывая шаблон по полям. Вместо:
news Товар ?X, ?Y, ?Z, ?T
if [success]
^^^^^^^^^^^^^^^X ^^^^^^^^^^^^^^^Y ^^^^^^^^^^^^^^^Z ^^^^^^^^^^^^^^^T
endif
можно записать:
news Товар ??,??,??,??
if [success]
for i=1 to [fact_f 0]
x=[fact_f i]
^^^^^^^^^^^^^^^x \
endfor
endif
Это особенно удобно при большом количестве полей и при записи шаблона без указаний
?переменная (форма ??) — в том числе в сочетании с
{}-способом (см. 16.10).
16.14. Производительность при работе с фактами
- Файл-ключ
fastfact(см. главу 8 части I; прежняя опция «Быстрые факты»): лента фактов индексируется, иsearch,newsи другие поиски выполняются за малое постоянное время; платой служит замедление оператораfactпримерно в два раза и рост расхода памяти. Внешняя логика операторов не меняется. - Индексация по датам:
rewind facts rangeвыполняется за малое постоянное время — всегда задавайте интервал дат, если он известен. neraseвместоeraseтам, где вычёркивается один факт, — очень значительный выигрыш во времени пересчёта.
[set], [plus], [get]) — рассматривается в главе
«Экстрапараметры и дисковая база»; об общем устройстве форм
и файлов-коэффициентов см. главу «Файлы форм и общие файлы».17. Функции: данные учёта
Эта глава — первая часть справочника функций языка форм. Здесь собраны функции, которые читают данные бухгалтерского учёта: остатки и обороты счетов, суммы проводок, параметры субсчетов, наименования и обозначения. Именно они — «рабочая лошадка» почти любой отчётной формы: чтобы построить отчёт, вы запрашиваете у сервера числа через эти функции и выводите их форматными вставками (см. главу «Текст и вывод»).
17.1. Как вызываются функции
Обращение к функции заключается в квадратные скобки: внутри сначала идёт имя функции (обычно двухбуквенное), затем через запятые — параметры: обозначения счетов, номера месяцев и т.п. Параметры-месяцы могут быть не только числами, но и формулами и переменными:
[EA 51] - остаток счета 51 на конец отчетного периода
[OK 70] - оборот счета 70 по кредиту за отчетный период
[OK 70,M,L] - оборот счета 70 по кредиту с месяца M по месяц L
(M и L - имена переменных)
Три понятия, без которых нельзя читать дальше:
- отчётный период — интервал месяцев, для которого строится форма; если в функции месяц не указан, берётся именно он;
- файл-коэффициент — программа, выполняющаяся внутри регистрируемой операции; ряд
функций (
AD/AK/MD/MK/AP/MP) ведёт себя в нём иначе, чем в отчётной форме; - развёрнутое сальдо — для счёта с субсчетами это сумма односторонних (только дебетовых или только кредитовых) остатков его субсчетов.
17.2. Остатки по счетам (сальдо)
Шесть функций сальдо имеют одинаковый синтаксис: [XX xx] или
[XX xx, mm], где xx — обозначение счёта, mm — номер
месяца (число или формула). Без mm берётся отчётный период. Мнемоника имён:
B — beginning (начало), E — end (конец); вторая буква: A — остаток
«со знаком», D — по дебету, K — по кредиту.
| Функция | Момент | Что возвращает |
|---|---|---|
[ba xx] | начало | остаток со знаком |
[ea xx] | конец | остаток со знаком |
[bd xx] | начало | остаток по дебету (развёрнутое сальдо по дебету) |
[ed xx] | конец | остаток по дебету (развёрнутое сальдо по дебету) |
[bk xx] | начало | остаток по кредиту (развёрнутое сальдо по кредиту) |
[ek xx] | конец | остаток по кредиту (развёрнутое сальдо по кредиту) |
[ba X] — остаток на начало периода со знаком
Синтаксис: [ba xx] или [ba xx, mm]. Параметры: xx —
обозначение счёта; mm — номер месяца (необязателен). Результат — число:
сальдо счёта на начало отчётного периода (или месяца mm); дебетовый остаток
положителен, кредитовый — отрицателен.
Было на счете 50 на начало: ^^^^^^^^^^[ba 50][ea X] — остаток на конец периода со знаком
Синтаксис: [ea xx] или [ea xx, mm]. Самая употребительная функция
языка: сальдо счёта xx на конец отчётного периода (или месяца mm).
Остаток на счете 51: ^^^^^^^^^^^^^[ea 51][bd X] — дебетовый остаток на начало
Синтаксис: [bd xx] или [bd xx, mm]. Остаток по дебету на начало
периода/месяца; для счёта с субсчетами — сумма дебетовых остатков субсчетов (развёрнутое
сальдо по дебету).
[ed X] — дебетовый остаток на конец
Синтаксис: [ed xx] или [ed xx, mm]. Остаток по дебету на конец
периода/месяца; развёрнутое сальдо по дебету для счетов с субсчетами. Удобна для активно-
пассивных счетов (например, расчётов), где нужны «чужие долги» без «наших».
[bk X] — кредитовый остаток на начало
Синтаксис: [bk xx] или [bk xx, mm]. Остаток по кредиту на начало
периода/месяца; развёрнутое сальдо по кредиту.
[ek X] — кредитовый остаток на конец
Синтаксис: [ek xx] или [ek xx, mm]. Остаток по кредиту на конец
периода/месяца; развёрнутое сальдо по кредиту.
* задолженность перед поставщиками (счет 60)
Итого мы должны: ^^^^^^^^^^^^^^^[ek 60][ea] и
парой [ed]/[ek] вы не увидите. Она проявляется на активно-пассивных счетах с
субсчетами: [ea] «сворачивает» дебет и кредит, а [ed] и
[ek] показывают их раздельно.17.3. Обороты по счетам
Обороты отвечают на вопрос «сколько прошло по счёту», а не «сколько на нём осталось».
У функций AD/AK/MD/MK — двойная семантика: в отчётной форме они смотрят на
прошлое относительно конца отчётного периода, а в файле-коэффициенте — относительно
текущей проводки регистрируемой операции.
[od X] — обороты по дебету
Синтаксис: [od xx] или [od xx, m1, m2]. Результат — обороты счёта
xx по дебету за отчётный период или за интервал месяцев m1..m2
(номера могут быть числами или формулами).
* поступления в кассу за год
Поступило: ^^^^^^^^^^^^^^^[od 50][ok X] — обороты по кредиту
Синтаксис: [ok xx] или [ok xx, m1, m2]. Обороты по кредиту за
отчётный период или за интервал месяцев.
[OK 70,M,L] * оборот счета 70 по кредиту с месяца M по месяц L[ad X] — нарастающий оборот по дебету от начала года
Синтаксис: [ad xx]. В отчётной форме — обороты по дебету от начала года до
конца отчётного периода. В файле-коэффициенте — от начала года до текущей проводки
(не включая её). Именно «коэффициентный» смысл позволяет, например, начислять проценты на
накопленную сумму.
[ak X] — нарастающий оборот по кредиту от начала года
Синтаксис: [ak xx]. То же, что [ad], но по кредиту счёта.
[md X] — оборот по дебету за месяц
Синтаксис: [md xx]. В отчётной форме — обороты по дебету за последний
месяц отчётного периода. В файле-коэффициенте — от начала текущего месяца до текущей
проводки.
[mk X] — оборот по кредиту за месяц
Синтаксис: [mk xx]. То же, что [md], но по кредиту счёта.
[ad] [ak] [md] [mk] (и [ap] [mp] ниже) имеют
двойную семантику — форма и файл-коэффициент считают разные интервалы. Нельзя
бездумно переносить фрагмент кода из формы в файл-коэффициент и обратно: логику накопления
придётся пересматривать. Текущий режим выполнения можно проверить функцией
[re] (см. главу 19).17.4. Суммы проводок между счетами
Эти функции отвечают на вопрос «сколько прошло между двумя конкретными счетами» — например, сколько оплатил данный покупатель через данный расчётный счёт.
[op X, Y] — сумма проводок за период
Синтаксис: [op xx, yy] или [op xx, yy, m1, m2]. Результат — сумма
проводок между счетами xx (дебет) и yy (кредит) за отчётный период
или за интервал месяцев m1..m2.
* сколько оплачено поставщику 60-01 с р/счета 51
Оплачено: ^^^^^^^^^^^^^^[op 51, 60-01][ap X, Y] — сумма проводок от начала года
Синтаксис: [ap xx, yy]. В отчётной форме — сумма проводок между счетами от
начала года до конца отчётного периода; в файле-коэффициенте — от начала года до текущей
проводки.
[mp X, Y] — сумма проводок за месяц
Синтаксис: [mp xx, yy]. В отчётной форме — сумма проводок между счетами за
последний месяц отчётного периода; в файле-коэффициенте — от начала текущего месяца до
текущей проводки.
17.5. Параметры субсчетов
Субсчета могут иметь параметры — значения, задаваемые при редактировании счетов и
начальных условий (например, адрес склада, договорная цена). Параметры нумеруются с 1.
Это не то же самое, что экстрапараметры [set]/[get] — о них глава
«Экстрапараметры и дисковая база».
[bp X] — параметр на начало периода
Синтаксис: [bp xx], [bp xx, nn], [bp xx, nn, mm].
Результат — значение nn-го параметра субсчета xx на начало отчётного
периода (или месяца mm). Без nn берётся первый параметр.
[BP xx] - значение 1-го параметра субсчета xx на начало отчетного периода
[BP xx, nn] - значение nn-го параметра на начало отчетного периода
[BP xx, nn, mm]- значение nn-го параметра на начало месяца mm[ep X] — параметр на конец периода
Синтаксис: [ep xx], [ep xx, nn], [ep xx, nn, mm].
Значение nn-го параметра субсчета на конец отчётного периода (или месяца
mm); в файле-коэффициенте — значение непосредственно перед текущей проводкой.
17.6. Обозначения и наименования
Отчёт, состоящий из одних чисел, нечитаем. Эти функции возвращают строки — обозначения и наименования счетов, чтобы подписать строки и колонки отчёта.
[n1 X] — обозначение счёта
Синтаксис: [n1 xx]. Результат — строка с обозначением счёта/субсчета
(например, 50 или 60-01).
[n2 X] — наименование счёта
Синтаксис: [n2 xx]. Результат — строка с наименованием счёта/субсчета
(например, Касса).
Счет ^^^^^^^^^[n1 50] — ^^^^^^^^^^^^^^^^^^^^[n2 50][na X] — обозначение и наименование
Синтаксис: [na xx]. Строка, содержащая и обозначение, и наименование счёта —
удобна для подписей «в один приём».
[pa X] — обозначение счёта-«родителя»
Синтаксис: [pa xx]. Строка с обозначением счёта, субсчетом которого является
указанный. Так из обозначения субсчета 60-01 можно получить 60.
[np X] — наименование параметра
Синтаксис: [np xx] или [np xx, nn]. Строка с наименованием
nn-го параметра субсчетов счёта xx; по умолчанию nn = 1.
Позволяет подписывать колонки значений [bp]/[ep] их наименованиями.
17.7. Сведения о счетах
[aa X] — тип счёта
Синтаксис: [aa xx]. Результат — число:
| Значение | Тип счёта |
|---|---|
| 1 | активный |
| -1 | пассивный |
| 0 | активно-пассивный |
| 2 | внебалансовый |
[as X] — количество субсчетов
Синтаксис: [as xx]. Результат — число субсчетов указанного счёта. В паре с
[sa] (обозначение субсчета по номеру, см. главу
19) позволяет организовать перебор всех субсчетов счёта.
17.8. Доступ к журналу операций и ta-фактам
Иногда из формы нужно добраться не до итоговых цифр, а до самих операций — например,
показать в отчёте документы, относящиеся к событию, или журнал операций в нестандартном
виде. Для этого служат функции [ta] и [jf].
[ta m1,m2] — запоминаются ли ta-факты
Синтаксис: [ta m1,m2], где m1, m2 — номера первого и
последнего месяцев диапазона. Возвращает 1, если ta-факты запоминаются для всех
месяцев диапазона, и 0, если хотя бы для одного месяца они не запоминаются.
Запоминание ta-фактов включается для нужного месяца файлом-ключом fastfact
(это используется при настройке базы знаний). О самой ленте фактов — глава
«Лента фактов».
[jf S] — «дай операцию или список операций»
Синтаксис: [jf s], где s — строковое выражение, интерпретируемое
так же, как директива J ФБП:Сервера (см. главу
«Язык запросов к серверу»).
[jf 'o key=GAAA-001']
[jf 'o key=G7']
[jf 'all mc=1,12']
У функции есть результат и побочный эффект:
- результат — первая строка ответа на соответствующую директиву
J; - побочный эффект — в файл
extrd.datпомещаются все строки ответа и их количество:[ged 'jf.N']— количество строк,[ged 'jf.1']— первая строка (совпадает с результатом[jf]),[ged 'jf.2']— вторая и т.д. (о дисковой базеextrd.datи функции[ged]— глава 21).
Типовые применения: показ в отчёте операций, относящихся к событию; вывод журнала операций в нестандартном виде.
[jf] касается лишь служебного файла
extrd.dat). Поэтому отчётные формы можно запускать многократно и экспериментировать
без риска для учёта.18. Функции: ввод данных и оформление чисел
Отчётная форма — это не только печать цифр: часто перед построением отчёта нужно спросить
пользователя «за какой месяц?», «по какому контрагенту?», «продолжать?». Для таких диалогов
служат функции ввода — они показывают окно или меню и возвращают ответ пользователя как
обычное значение, которое можно присвоить переменной. Вторая половина главы — функция
[sn] и спецкомментарии, управляющие тем, как числа превращаются в строки
(разделители тысяч, дробная часть).
18.1. Функции ввода: диалоги с пользователем
Все пять функций ввода вызываются в правой части присваивания и возвращают результат — число или строку. По сравнению с оператором вопроса (см. главу «Операторы») они компактнее: вопрос, значение по умолчанию и приём ответа умещаются в одну строку. Окна ввода показывает ФБП:Клиент CLWP.
[iy S] — вопрос «Да/Нет»
Синтаксис: [iy s], где s — строка вопроса. Выводит окно с вопросом
и меню из двух пунктов «Да»/«Нет»; возвращает 1 при ответе «Да» и 0 при ответе
«Нет». Назначение — изменение хода выполнения формы.
A=[IY 'Продолжить дальше?'][ir S, n, k] — ввод числа
Синтаксис: [ir s, nn, mm], где s — строка вопроса,
nn — значение по умолчанию (число или формула), mm — количество
знаков после десятичной точки. Возвращает введённое число.
A=[IR 'Введите номер поручения:',X,0][is S, S0, n] — ввод строки
Синтаксис: [is s, sd, mm], где s — строка вопроса,
sd — значение по умолчанию, mm — предельная длина вводимой
строки. Возвращает введённую строку.
A=[IS 'Введите название фирмы:',A,20][im H, S1, S2, ...] — меню из произвольных пунктов
Синтаксис: [im h, s1, s2, ...], где h — заголовок меню, а
s1, s2, ... — пункты. Возвращает номер выбранного пункта (нумерация с 1
по порядку следования пунктов).
A=[IM 'Тип счета:','активный','пассивный','внебалансовый'][ia X] — выбор субсчета из меню
Синтаксис: [ia xx]. Показывает меню из обозначений и наименований
субсчетов счёта xx и возвращает строку — обозначение выбранного субсчета.
Идеальна для форм вида «отчёт по произвольному контрагенту».
A=[IA 70]
B=[IA План]A=[IA 60] — спросить контрагента, затем
использовать A в функциях данных учёта: [ea A], [op 51,A].
Так одна и та же форма обслуживает всех контрагентов без правки текста.18.2. Функция [sn]: число в строку по формату
Форматные вставки (^^^^) оформляют числа «по своему усмотрению», а
[sn] позволяет задать формат явно: длину строки и количество знаков после точки.
Это нужно, когда число вставляется внутрь другой строки или требуется точное выравнивание.
[sn n, len, k] — форматированное число строкой
Синтаксис: [sn nn, mm, kk], где nn — число, mm —
длина строки результата, kk — количество знаков после десятичной точки.
Результат — строка.
a=[sn 1200.345,17,3]
^^^^^^^^^^^^^^^^a
На точный вид результата влияют спецкомментарии — см. следующий подраздел.
18.3. Спецкомментарии, управляющие [sn] и форматными вставками
Пять специальных комментариев переключают два независимых свойства вывода чисел: показывать ли дробную часть и разделять ли тысячи запятыми. Они действуют и в отчётных формах, и в файлах-коэффициентах — от места появления до конца формы либо до отменяющего комментария.
| Комментарий | Действие |
|---|---|
*.on | разрешает выдавать дробную часть числа |
*.off | запрещает выдавать дробную часть числа |
*,on | разрешает запятые в целой части числа (разделение тысяч) |
*,off | запрещает запятые в целой части |
*.,df | возврат к поведению по умолчанию (для форм — к пожеланиям ФБП:Клиента) |
По умолчанию действует сочетание «запятые есть, дробной части нет» (*,on +
*.off). Полный пример из руководства:
a=[sn 1200.345,17,3]
^^^^^^^^^^^^^^^^a
*.on
*,on
a=[sn 1200.345,17,3]
^^^^^^^^^^^^^^^^a
*.off
*,on
a=[sn 1200.345,17,3]
^^^^^^^^^^^^^^^^a
*.on
*,off
a=[sn 1200.345,17,3]
^^^^^^^^^^^^^^^^a
*.off
*,off
a=[sn 1200.345,17,3]
^^^^^^^^^^^^^^^^a
Результат выполнения формы:
1,200
1,200.345
1,200
1200.345
1200
[sn], но и на
форматные вставки — и действуют до конца формы. Забытый где-то в середине формы
*,off меняет вид всех последующих чисел — это источник трудноуловимых
расхождений при печати. Возвращайте поведение по умолчанию комментарием *.,df.[sn] преобразование
«строка → число» выполняет [vl], а [intsn] выдаёт целую часть числа
строкой без разделителей — обе описаны в главе
«Функции: строки, даты, математика, файлы, система».19. Функции: строки, даты, математика, файлы, система
Заключительная часть справочника функций: всё, что не относится напрямую к данным учёта — работа со строками и числами, даты и время, математика, сведения о системе и пользователях, вызов внешних программ и файловые сервисы.
19.1. Строки
Строковые функции нужны для разбора наименований, склейки подписей, перекодировки и подготовки данных для форматных вставок.
[cp S, n, k] — вырезка из строки
Синтаксис: [cp s, nn, mm], где s — исходная строка,
nn — номер первого символа вырезки, mm — количество символов.
Главное назначение — предотвращение переполнений форматных вставок слишком длинными
строками: перед выводом строку обрезают до ширины колонки.
[length S] — длина строки
Синтаксис: [length строка]. Результат — число символов:
[length 'qwerty'] = 6.
[length ''] равно 1, а не 0. Учитывайте
это в проверках вида «строка пуста?».[strip S] — обрезка пробелов
Синтаксис: [strip строка]. Удаляет ведущие и завершающие пробелы:
[strip ' абвгде '] → абвгде. Полезна перед сравнением строк,
введённых пользователем.
[ps S1, S2] — позиция подстроки
Синтаксис: [ps 'фрагмент','строка в которой его ищем']. Возвращает позицию
первого вхождения (нумерация символов с 1); если фрагмент не найден — 0.
n2=[ps 'klw','ghiklwstr']
^^^n2
Результат: 4.
[vl S] — строка → число
Синтаксис: [vl s]. Преобразует строку в число, если это возможно:
[vl '1234'] → число 1234. Если преобразование невозможно, возвращается
исходная строка: [vl '1234f'] → '1234f' — ошибки не
возникает. (В ранних версиях было доступно только обратное преобразование через
[sn].)
[vl] при неудаче возвращает строку, а не 0 и не
ошибку, тип результата стоит контролировать функцией [type], иначе дальнейшая
арифметика над «числом» может оказаться арифметикой над строкой.[type V] — тип переменной
Синтаксис: [type переменная]. Возвращает 1, если переменная — строка,
и 0, если число.
[intsn n] — целая часть строкой без форматирования
Синтаксис: [intsn число]. Результат — строка с целой частью числа, без
пробелов и запятых (в отличие от [sn], на которую влияют спецкомментарии).
Диапазон числа: от -2147483648 до +2147483648.
a=[intsn yc]
^^^^a
Результат: 1999 (а не 1,999) — даже при включённой опции
«числа с запятыми». Функция незаменима при сборке служебных индексов вида
[ged 'tf.'+[intsn i]].
[ch n] — символ по коду
Синтаксис: [ch nn]. Возвращает строку из одного символа с кодом
nn. Употребительна для управления принтером ESC-последовательностями
(27 — код ESC):
F1=[CH 27]+'M'
^^^^F1[sa X, n] — обозначение субсчета по номеру
Синтаксис: [sa xx, nn], где xx — счёт, имеющий субсчета,
nn — номер субсчета. Возвращает строку — обозначение nn-го субсчета.
Главное назначение — организация перебора субсчетов в цикле в паре с [as xx]
(количество субсчетов, см. главу 17).
[hc S, i] — код символа строки
Синтаксис: [hc s,i]. Возвращает число — код i-го символа строки
s (обратная к [ch]). Применения — перекодировка строк, подсчёт
контрольных сумм.
19.2. Числа: целая и дробная части, округление, число прописью
[tr n] — целая часть
Синтаксис: [tr nn]. Возвращает целую часть числа. Приём округления до целого:
[tr 12.56+0.5] → 13.
[ce n] — дробная часть «в сотых»
Синтаксис: [ce nn]. Выделяет дробную часть числа, но выраженную
как число сотых: [ce 12.3456] = 34.56, а не
0.3456. Приём округления дробной части:
[tr ([ce 12.3456]+0.5)] = 35[ro n] — округление
Синтаксис: [ro nn]. Округляет число. Само руководство предупреждает: на
практике для округления надёжнее использовать сочетание [tr] и
[ce], чем [ro].
[wn n] — число прописью
Синтаксис: [wn nn] или [wn X, руб.]. Возвращает строку —
числительное, изложенное словами; второй необязательный аргумент — обозначение единицы
измерения. Незаменима в платёжных документах («Сумма прописью»).
19.3. Даты и время
[dt m, d] — дата строкой
Синтаксис: [dt mm, nn], где mm — месяц, nn — день
(числа или формулы). Возвращает строку с датой — для подписей в отчётах.
[da d, m, y] — номер дня от «начала эры»
Синтаксис: [da dd, mm, yy] или [da]. Возвращает количество дней,
прошедших от 1 ноября 1990 года («начало эры Хакерс Дизайн») до указанной даты — или
до текущей операции. Запись [da] эквивалентна [da DC, MC, YC]
(предопределённые переменные дня, месяца и года текущей операции). Разность двух таких
номеров — точное число дней между датами, что используется, например, для автоматического
начисления процентов по кредитам.
[antida n] — дата по номеру дня
Синтаксис: [antida yy]. Обратная к [da]: возвращает в упакованном
виде дату, соответствующую номеру дня. Формат упаковки виден из примера:
[da 3,28,1996] = 1975, а [antida 1975] =
199603.28 — то есть ггггмм.дд.
[dw d, m, y] — день недели
Синтаксис: [dw dd, mm, yy] или [dw]. Возвращает день недели:
0 — воскресенье, 1 — понедельник и т.д. Запись [dw] эквивалентна
[dw DC, MC, YC].
[tm] — текущее время
Синтаксис: [tm]. Возвращает строку вида часы:минуты. Применения:
«штамп» времени на формах; текущее время можно узнать даже из калькулятора, введя
[TM].
19.4. Режим выполнения и контекст
Одна и та же программа может выполняться как отчётная форма, файл-коэффициент или первичный документ — и функции этой группы позволяют узнать, «где мы», кто пользователь и что передано форме извне.
[re] — номер режима выполнения
Синтаксис: [re]. Возвращает: 0 — внутри файла-коэффициента,
1 — внутри отчётной формы, 2 — внутри первичного документа. Назначение —
предотвращать работу форм в неподходящем режиме:
![re]>0
Это не отчетная форма, а файл коэффициент
stop[co] — комментарий текущей операции
Синтаксис: [co]. Возвращает строку — комментарий из текущей операции.
Используется только внутри форм первичных документов, активируемых псевдопроводкой
«создать документ» (см. главу «Виды операций и проводки»). В других
режимах бессмысленна — контролируйте режим через [re].
[ex X] — существование субсчета
Синтаксис: [ex обозначение субсчета]. Возвращает 1, если субсчет с
таким обозначением имеется, и 0, если отсутствует. Позволяет форме аккуратно
обходиться со счетами, которые ещё не заведены.
[stamp n] — штамп операции
Синтаксис: [stamp n], где n: 1 — имя пользователя,
зарегистрировавшего операцию; 2 — время регистрации операции; 3 — уникальный
код операции. Используется только в файлах-коэффициентах.
[user] — имя пользователя
Синтаксис: [user]. В файле-коэффициенте — имя пользователя, регистрирующего
операцию; в отчётной форме — имя пользователя, для которого сервер выполняет форму.
[f1], [f2] — аргументы формы
Синтаксис: [f1] — значение первого аргумента формы, [f2] —
второго. Значения для различных кнопок (и сами кнопки) задаются пользователем в клиентской
части: меню «Опции», раздел «Аргументы и фильтры».
[ct S] — контекст предыдущего @-обращения
Синтаксис: [ct S]. В формах, отвечающих за @-обращения,
выдаёт первое слово строки, выбранной в предыдущем @-обращении к счёту S в
текущем листе дерева; если предыдущих @-обращений не было — пустую строку. Назначение —
облегчить выбор, используя результаты предыдущего. Об @-обращениях — глава
«@-обращения и контекст».
19.5. Математика с 3.22
Группа математических функций: тригонометрия, корень, модуль и перевод между градусами и радианами. Аргументы тригонометрических функций — в радианах.
| Функция | Результат |
|---|---|
[abs x] | модуль (абсолютное значение) |
[fsin x] | синус |
[fcos x] | косинус |
[arctan x] | арктангенс |
[sqrt x] | квадратный корень |
[rad x] | переход от градусов к радианам |
[dgr x] | переход от радиан к градусам |
[abs x] — модуль числа
Синтаксис: [abs x]. Возвращает абсолютное значение числа.
[fsin x], [fcos x], [arctan x] — тригонометрия
Синтаксис: [fsin x] — синус, [fcos x] — косинус,
[arctan x] — арктангенс. Углы задаются и возвращаются в радианах; для перевода
используйте [rad] и [dgr].
[sqrt x] — квадратный корень
Синтаксис: [sqrt x]. Возвращает квадратный корень из числа.
[rad x], [dgr x] — градусы и радианы
Синтаксис: [rad x] — переводит градусы в радианы; [dgr x] —
радианы в градусы.
* синус 30 градусов
x=[fsin [rad 30]][det a, n] — определитель матрицы с 3.22
Синтаксис: [det a,n], где a — имя массива, содержащего квадратную
матрицу n×n, n — размер. Матрица хранится в массиве построчно:
элемент (i,j) соответствует элементу массива с номером (i-1)*n+j
(о массивах — глава «Массивы»). Пример — определитель матрицы
Гильберта 4×4:
n=4
for i=1 to n
for j=1 to n
[a (i-1)*n+j, 1/(i+j-1)]
endfor
endfor
x=[det a,n]
^^^^^^^^^x^^^^^^^^^^^^^^
Результат: 0.00000016534392. Родственные средства линейной алгебры —
операторы lsolve (решение системы линейных уравнений) и invertm
(обращение матрицы) — описаны в главе «Операторы».
19.6. Кодировки и внешний мир
[win S], [dos S] — перекодировка строк с 3.22
Синтаксис: [win s] — преобразование строки из кодировки CP866 в Win1251;
[dos s] — обратно, из Win1251 в CP866. Нужны при обмене текстами с
Windows-программами и при подготовке HTML: тексты форм пишутся в CP866 (см. главу
«Файлы форм»), а браузер ожидает Win1251.
[ru S1, S2, n] — вызов внешней программы
Синтаксис: [ru s1, s2, n], где s1 — имя вызываемой программы,
s2 — строка аргументов, n — что делать с экраном: 0 —
очистить и затем восстановить; 1 — оставить как есть (в расчёте на то, что программа
ничего не выводит). Возвращает первую строку файла ru.txt или строку
NO RU.TXT, если файл отсутствует: обратную связь внешняя программа передаёт,
записывая результат в ru.txt. Применение — обмен с внешними базами данных.
[ru] неэффективна при многократных вызовах: каждый вызов — это
запуск программы и чтение ru.txt.[hz f, t] — звуковой сигнал
Синтаксис: [hz f, t], где f — частота в герцах,
t — длительность в миллисекундах. Если t = 0, звук не
выключается и звучит до вызова [hz 0,0].
19.7. Файлы и система
[fe S] — существование и размер файла
Синтаксис: [fe s], где s — имя файла. Возвращает -1, если
файл не существует, иначе — размер файла в байтах.
[crc S] — контрольная сумма файла
Синтаксис: [crc s]. Вычисляет CRC (Cyclic Redundancy Check) файла по тому же
32-битному алгоритму, что и pkzip (PkWare). Применение — проверка целостности файлов
(*.rpt, *.b, cas.rul).
Результат — восьмисимвольная строка с CRC в шестнадцатеричном представлении; если файл
отсутствует — односимвольная строка '0'. Отличить «нет файла» от настоящего
CRC 00000000 можно по длине строки результата.
[unicfile] — уникальное имя файла с 3.22
Синтаксис: [unicfile]. Возвращает строку — уникальное имя файла. Используется,
когда форма создаёт временные файлы (например, картинки для Web-приложения) и имена не должны
сталкиваться.
[dir n] — рабочие каталоги
Синтаксис: [dir n], где n = 0 или 1. n=0 — имя
каталога данных сервера, n=1 — имя каталога обмена Клиент↔Сервер.
Возвращаемые имена каталогов всегда завершаются знаком \.
См. также тему «вывод данных в файл» в главе «Текст и вывод».
[ver] — версия программы
Синтаксис: [ver]. Возвращает номер версии исполняемой программы; в сетевой
версии форму выполняет ФБП:Сервер, поэтому результат относится к версии сервера.
[sf n, k] — специальная функция с 3.14
Особая функция с зарезервированными кодами. Известные значения:
| Вызов | Результат |
|---|---|
[sf 0,98] | время первого старта NULLCG.CGI в виде цепочки цифр |
[sf 0,99] | строка с текущим временем в формате log-файлов Web-серверов |
[sf 0,9] | длинная строка, новая при каждом вызове; применяется для борьбы с кэшами браузеров |
Варианты 0,98, 0,99 и 0,9 предназначены для отладки
Web-приложений, работающих с NULLCG.CGI — см. главу
«Web-приложения».
[pw S1, S2] — проверка пароля
Синтаксис: [pw s1,s2], где s1 — имя пользователя,
s2 — пароль. Результат: 0, если пользователя s1 с паролем
s2 нет в файле _rights_.fbp, иначе — номер пользователя в этом
файле.
[uf S] — список пользователей
Синтаксис: [uf s], где s — ' ', '+'
или ':'. Действует аналогично директиве U ФБП:Сервера. Результат —
количество строк, помещённых в extrd.dat; [ged 'uf.N'] — то же
количество, [ged 'uf.' + [intsn i]] — i-я строка ответа.
[tf U] — дерево видов операций
Синтаксис: [tf u], где u — имя пользователя или
'ALL'. Аналог директивы T ФБП:Сервера от имени пользователя
u. Возвращает количество строк дерева видов операций, помещённых в
extrd.dat (дублируется в [ged 'tf.N']):
[ged 'tf.'+[intsn i]]—i-я строка дерева в формате ответов сервера на директивуT;[ged 'tfb.'+[intsn i]]— баллонi-й строки дерева или 0, если баллон не был определён.
Доступные пользователю виды операций и баллоны разбираются в главе «Виды операций и проводки».
[sed]/[ged] и
экстрапараметры [set]/[plus]/[get] — они описаны в главе
«Экстрапараметры и дисковая база», а функции ленты фактов
([success], [found], [fact_f] и др.) — в главе
«Лента фактов». Собственные функции с возвратом значения
(return (выражение), вызов [:метка]) — в главе
«Операторы».19.8. Табличный вывод V01.02
[table …] — таблица псевдографикой с произвольным числом строк
Функция формирует таблицу последовательно: описание и колонки, заголовок, строки данных,
закрытие. Число строк заранее задавать не нужно — row можно вызывать в обычном
цикле формы. Каждая подкоманда возвращает число 0, но получать это значение
не обязательно. Запись rc=[table 'header','T'] равнозначна отдельному вызову
[table 'header','T']: rc здесь — произвольная переменная,
а не имя таблицы и не обязательный элемент синтаксиса.
| Подкоманда | Назначение |
|---|---|
[table 'open','T'] | открыть таблицу T с одинарной рамкой |
[table 'open','T','double'] | двойная рамка; также допустимы single и none |
[table 'column','T','Код',12] | добавить колонку с заголовком «Код» и шириной 12; выравнивание по умолчанию — left |
[table 'column','T','Остаток',15,2] | числовая колонка: два знака после запятой, выравнивание вправо |
[table 'header','T'] | вывести верхнюю границу, заголовки из column и разделитель; заголовки по умолчанию по центру |
[table 'header','T','left'] | выравнивание заголовков влево; также допустимы center и right |
[table 'rowsep','T'] | включить линии-разделители между записями; по умолчанию их нет |
[table 'row','T',K,N] | вывести одну запись; при wrap она может занимать несколько строк |
[table 'close','T'] | вывести нижнюю границу и закрыть таблицу |
Где задаются заголовки. Третий аргумент каждой команды column —
это название колонки. Команда header выводит верхнюю рамку, строку с названиями
всех объявленных колонок и разделитель под ними. Без дополнительного параметра заголовки
выравниваются по центру. Для другого положения используются
[table 'header','T','left'], center или right.
Выравнивание заголовков не меняет выравнивание данных. Строки данных добавляются командой
row.
Выравнивание строковых значений: left, right или
center; если параметр не указан, используется left. Ширина
колонки включает всё пространство между вертикальными линиями. Дополнительные пробелы
слева и справа от значения не добавляются: текст первой ячейки начинается сразу после
рамки, поэтому его можно передать через #1 в N:. Длинные
значения обрезаются по ширине. При стиле none рамок нет, а поля разделяются
одним пробелом.
Пример с двумя колонками — «Код» и «Наименование»:
[table 'open','T']
[table 'column','T','Код',6]
[table 'column','T','Наименование',20,'left']
[table 'header','T']
[table 'row','T','A-001','Товар первый']
[table 'row','T','A-002','Товар второй']
[table 'close','T']
Результат:
┌──────┬────────────────────┐
│ Код │ Наименование │
├──────┼────────────────────┤
│A-001 │Товар первый │
│A-002 │Товар второй │
└──────┴────────────────────┘
Здесь верхняя линия, строка с заголовками и разделитель выведены одной командой
header. Нижняя линия выводится командой close.
Если данные формируются в цикле, row вызывается внутри него:
for i=1 to n
[table 'row','T',K,N]
endfor
Числовые колонки. Число можно передавать в row непосредственно,
без [sn] и [intsn]. Число знаков после запятой указывается
после ширины колонки; числовое значение автоматически форматируется и выравнивается
вправо. Отрицательные числа выводятся со знаком -.
[table 'open','N']
[table 'column','N','Остаток',10,2]
[table 'header','N']
[table 'row','N',1250.5]
[table 'row','N',-1250.5]
[table 'close','N']
Результат:
┌──────────┐
│ Остаток │
├──────────┤
│ 1250.50│
│ -1250.50│
└──────────┘
Вместо сокращения [table 'column','N','Остаток',10,2] можно записать
полную форму [table 'column','N','Остаток',10,'right',2]. Допустимая
точность — от 0 до 22 знаков. Если точность не задана, число выводится без дробной
части. Для вывода числа как строки с другим выравниванием его можно по-прежнему
преобразовать через [sn] или [intsn].
Перенос длинного текста — wrap. Без этого параметра длинный
текст обрезается по ширине колонки. Если указать wrap, сервер переносит
его между словами; слово длиннее колонки разрывается по символам. Код и остальные
значения остаются на первой строке записи, а ячейки продолжения — пустыми. Числа
не переносятся. Допустимы обе формы:
[table 'column','T','Наименование',12,'left','wrap']
[table 'column','T','Наименование',12,'wrap'] * то же самое, left по умолчанию
Разделители между записями — rowsep. Эта необязательная
подкоманда включает горизонтальную линию перед каждой записью, кроме первой.
Внутри многострочной записи линий нет. Включать её нужно до первой строки данных:
[table 'open','T']
[table 'column','T','Код',6]
[table 'column','T','Наименование',12,'wrap']
[table 'header','T']
[table 'rowsep','T']
[table 'row','T','A-001','Очень длинное название товара']
[table 'row','T','A-002','ABCDEFGHIJKLMNO']
[table 'close','T']
Результат:
┌──────┬────────────┐
│ Код │Наименование│
├──────┼────────────┤
│A-001 │Очень │
│ │длинное │
│ │название │
│ │товара │
├──────┼────────────┤
│A-002 │ABCDEFGHIJKL│
│ │MNO │
└──────┴────────────┘
Один вызов row — одна запись, даже если из-за wrap она
занимает несколько строк. Разделитель ставится только между такими записями. Без
rowsep их нет; после последней записи выводится обычная нижняя рамка
close. Для стиля none разделители не рисуются.
Число значений в row должно совпадать с числом колонок.
Общая ширина таблицы вместе с рамками не может превышать 255 символов CP866. До завершения
формы каждую таблицу нужно закрыть через close; нарушение последовательности
вызовов приводит к ошибке E-27.
Для переходов по строкам используются обычные управляющие строки N: —
см. пример в главе 23.
20. Обращения к счетам: @-обращения и контекст
Когда бухгалтер вводит операцию, дерево видов операций может потребовать уточнить,
какой именно субсчёт участвует в проводке — например, какое подотчётное лицо
по счёту 71 или какой товар по счёту 41. Такое требование записывается в листе дерева
@-обращением — знаком @ перед обозначением счёта (@71,
@41). Программа покажет список субсчетов, пользователь выберет нужный, и его
обозначение будет подставлено в проводку. @-обращения позволяют держать дерево видов
операций компактным: вместо отдельной ветви на каждый субсчёт достаточно одной ветви
с @-обращением.
Эта глава объясняет, как устроен показ списков субсчетов (и как его программировать
самому), как управлять поведением форм @-обращений словами pragma и
multiline, как формы узнают об «окружении» регистрируемой операции через
функцию [ct] и контексты, и как работают *-подстановки в сетевой
версии ФБП.
20.1. Как выполняется @-обращение
Обнаружив в листе дерева @-обращение (скажем, @71),
ФБП:Клиент посылает Серверу директиву R 71, рассчитывая, что в каталоге
данных есть форма 71.RPT, которая построит список субсчетов — обычно
циклом по субсчетам счёта. Если такой формы нет, список субсчетов выводится
внутренними средствами Сервера — но при этом показ параметров отсутствует.
Вот типичная форма, отвечающая за @-обращение к счёту 71 (подотчётные лица):
* Список подотчетных лиц (форма 71.RPT)
#71 цикл по субсчетам
N=[n1 #] извлекаем обозначение текущего субсчета
M=[n2 #] извлекаем наименование текущего субсчета
^^^^^^^^^N ^^^^^^^^^^^^^^^^^^^M
^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^
#
* конец формы
Здесь работают знакомые средства: цикл #71 … # (см. главу
«Операторы»), функции [n1 #] и [n2 #] —
обозначение и наименование текущего элемента цикла (см. главу
«Функции: данные учёта»). Пустые строки-«рамки» из
^ внизу оставляют место, чтобы пользователь мог выбрать строку мышью
или клавишами.
pragma (см. 20.3).20.2. @-обращения в формулах и файлах-коэффициентах
@-обращение — это не только «показать список»: выбранным субсчётом можно пользоваться в формулах листа дерева. Например, в листе переоценки материалов остаток выбранного субсчёта счёта 10 получают прямо в формуле проводки:
@10 88 [EA @10] * (К-1)
В проводках, выполняемых оператором проводки в файле-коэффициенте, тоже могут
участвовать @-обращения к счетам с субсчетами (наряду со счетами без субсчетов,
собственно субсчетами, *-обращениями к переменным и текущим субсчётом #
цикла). Но здесь действует важное правило:
20.3. Ключевое слово pragma: ответ на меню формы из дерева
Форма @-обращения может начинаться с меню (функция [im…]), и от выбранного
пункта зависит дальнейший ход её выполнения. Ключевое слово pragma позволяет
ответить на это меню прямо из дерева видов операций: для одного вида операции
форма покажет полный список, для другого — только часть, хотя используется одна и та же
форма.
Пусть форма 41.RPT начинается с меню:
* начало формы 41.RPT
A=[im 'Меню показа','весь список товаров','только имеющиеся на складе']
! A=1 goto ...
! A=2 goto ...
....
* конец формы 41.RPT
Требуется: для операции «Товары-прием на склад:» выбирать пункт 1 («весь список»),
а для «Товары-резервирование:» — пункт 2. Для этого в соответствующих листьях дерева
после проводок ставится псевдокомментарий с ключевым словом pragma и номером
нужного пункта меню.
pragma в листе дерева
должен стоять коэффициент (в круглых скобках) или файл-коэффициент (без
скобок). Если сумма проводки вас не интересует — укажите коэффициент (0).20.4. Ключевое слово multiline: куда вводить многострочные ответы
Если при вводе операции на вопросы (ветви-вопросы дерева или поле ввода суммы) дан неопределённый ответ — ничего не ввели, просто нажали Enter — то клиент показывает столбцы для многострочного ввода ответов. По умолчанию эти столбцы накладываются на результат выполнения формы, соответствующей первому @-обращению в листе дерева.
Слово multiline, указанное в нужном месте листа дерева, переадресует
столбцы ввода ответов к другому @-обращению — например, если именно его форма
(41.RPT) выводит удобный для многострочной пометки список.
multiline можно сочетать со словом pragma в том же листе.
20.5. Функция [ct] и контексты операции
Контекст формируется во время ввода хозяйственной операции: с его помощью
в отчётные формы, отвечающие за списки объектов учёта, передаётся «окружение», в котором
регистрируется операция. Функция [ct] возвращает значение контекста
в отчётной форме.
[ct S] — контекст предыдущего @-обращения или операции
S — строка, имя контекста. В формах, отвечающих за @-обращения, функция
выдаёт первое слово строки, полученной в предыдущем @-обращении к счёту
S в текущем листе дерева. Если предыдущих обращений не было — пустую строку.
Назначение — облегчить выбор в @-обращении, используя результаты предыдущих.
* в форме 41.rpt — результаты выбора @62 и @S
A62=[ct '62']
AS=[ct 'S']Существует несколько видов контекстов операции:
| Вид контекста | Имя контекста | Значение |
|---|---|---|
| Выбранные субсчета | обозначение родительского счёта | обозначение выбранного субсчёта |
| Ответы на вопросы операции | первые 9 символов вопроса | ответ, ограничен 10 символами |
MODOKEY | слово MODOKEY (только заглавные латинские буквы) | дата регистрации и уникальный ключ операции |
| Сумма | 'Сумма' | введённая сумма операции, ограничена 10 символами |
Пример с ответами на вопросы: пусть в дереве есть ветви платежка и
сумма, в баллоне к первой указано ·R FORM1, в баллоне ко второй —
·R FORM2. Тогда передать в форму FORM2 результат выбора из
FORM1 можно вызовом [ct 'платежка']. (В формах FORM1 и FORM2
первая строка — заголовок, а текст формы должен быть «прижат» к левой стороне экрана.)
Контекст MODOKEY: дата и ключ регистрируемой операции
Уникальный ключ операции присутствует, если операция перебивается (штампуется).
Контекст MODOKEY разбирается так (месяц, день, код операции):
CT=[ct 'MODOKEY'] - получаем контекст
MO=[vl [cp CT,1,2]] - месяц
DO=[vl [cp CT,3,2]] - день
K=[ch 64+MO]+[cp CT,5,3]+'-'+[cp CT,8,3] - код операции
Типичная задача, которую решает MODOKEY, — данные вносятся «в прошлое».
Пусть цена товара зависит от курса доллара, и форма 41.rpt должна показывать
курс на день регистрации операции, а не последний введённый. Фрагмент
news курс доллара ?d дал бы курс на текущую дату — это неправильно.
Решение — взять дату из контекста и ограничить поиск фактов (лента фактов подробно
рассмотрена в главе «Лента фактов»):
* фрагмент формы 41.rpt — курс доллара на дату операции
CT=[ct 'MODOKEY']
MO=[vl [cp CT,1,2]]
DO=[vl [cp CT,3,2]]
if [type MO] MO=MC; endif
if [type DO] DO=DC; endif
rewind facts range 1.01,MO+DO/100
news курс доллара ?d
Курс доллара ^^^^d^^^ ^^^^DO
Здесь курс хранится фактами вида fact курс доллара d (в файле-коэффициенте
вида операций «Новый курс доллара»). Если форма выполняется вне ввода операции, контекста
нет — [vl …] вернёт строку, и проверки [type …] подставят
текущие MC и DC. При регистрации операции, скажем, 12 марта
форма покажет курс, действовавший именно на 12 марта.
20.6. Аргументы и фильтры форм @-обращений
Для каждой формы (*.rpt) в клиенте CLWP можно определить свой набор
аргументов и связать поведение формы с их значениями — аргументы доступны форме как
[f1] и [f2] (см. главу
«Функции: строки, даты, математика»). Это удобно для фильтрации
длинных списков: одна и та же форма показывает разные подмножества субсчетов в зависимости
от выбранного аргумента.
Пример: на счёте 41 учитываются товары, а признаком группы служит
пятый символ обозначения субсчёта:
Счета и начальные условия:
41 [А] Товары
41-01000 Пиво Жигулевское
41-01001 Пиво Бадаевское
41-01002 Пиво Клинское
41-02000 Колбаса вареная
41-02001 Сосиски
41-02002 Сардельки
Пятый символ 1 — группа «Напитки», 2 — «Колбаса». В клиенте
(пункт «Опции → Аргументы и фильтры…», см. п. 4.12)
для аргумента «Напитки» задаётся [f1]=1, для «Колбасы» —
[f1]=2; переключаются аргументы прямо в открытой форме клавишами
Shift+F1…Shift+F9. Форма отбирает субсчета по аргументу:
*** пример формы 41.RPT ***
Список товаров:
#41 - перебрать в цикле все субсчета счета 41;
T3=[cp[n1 #],5,1] - "вырезка" из обозначения субсчетов 5-го символа;
if [f1]=T3 - проверка аргумента [f1] и "вырезанного" символа;
T1=[n1 #] - обозначения субсчетов;
T2=[cp[n2 #],1,16] - наименования субсчетов, ограниченное 16-ю символами;
^^^^^^^T1 ^^^^^^^^^^^^^^T2
endif
#
*** конец формы 41.RPT ***
Особенности клиента CLWP:
- режим Фильтров даёт более тонкий отбор, чем один аргумент: фильтр применяется к уже полученному тексту формы и оставляет строки с заданными отрывками. Например, из группы «Колбасы» можно отобрать субсчета, начинающиеся с отрывка «Сард», и определить для них фильтр «Сардельки».
[f1]/[f2] — строки по 12 байт
(дополняются пробелами).20.7. *-подстановки и файл-ключ FREE-AT
*-подстановка счёта (имя счёта подставляется из переменной или ответа на вопрос)
в сочетании с @-обращением в сетевой версии ФБП ограничена:
@-обращением в качестве
дебетуемого/кредитуемого счёта с последующим использованием *-подстановки —
запрещено. Выход — использовать в ветвях-вопросах уточнение ·R
с подсоединением формы (см. главу «Виды операций и проводки»).Две типовые формы, заменяющие *-подстановку. Первая выводит сразу весь план счетов
вместе с субсчетами (цикл #План, функции [as #] — число
субсчетов текущего счёта, [sa #,i] — обозначение i-го субсчёта):
Счета и субсчета:
#План - перебрать в цикле весь план счетов;
b1=[n1 #] - обозначение счета;
b2=[cp[n2 #],1,25] - наименование счета, ограниченное 25-ю символами;
^^^^^^^b1 ^^^^^^^^^^^^^^^^^^^^^^^b2
...................................
if [as #]>0 - если счет имеет субсчета, то:
for i=1 to [as #] - для всех субсчетов
s1=[sa #,i] - обозначение субсчета;
s2=[cp[n2 *s1],1,25] - наименование субсчета, ограниченное 25-ю символами;
^^^^^^^s1 ^^^^^^^^^^^^^^^^^^^^^^^s2
endfor
...................................
endif
# - конец цикла по плану счетов.
Вторая форма уточняет выбор последовательно — сначала счёт, потом субсчёт
([ia …] — меню выбора из плана счетов или списка субсчетов):
Счета и субсчета:
a=[ia План] - показать меню из всего плана счетов;
if [as *a]=0 - если счет не имеет субсчетов, то
b1=[n1 *a] - обозначение счета;
b2=[cp[n2 *a],1,25] - наименование счета, ограниченное 25-ю символами;
^^^^^^^b1 ^^^^^^^^^^^^^^^^^^^^^^^^^b2
else - если счет имеет субсчета, то
a=[ia *a] - вывод меню из списка субсчетов;
s1=[n1 *a] - обозначение субсчета;
s2=[cp[n2 *a],1,25] - наименование субсчета, ограниченное 25-ю символами;
^^^^^^^s1 ^^^^^^^^^^^^^^^^^^^^^^^^^s2
endif
Файл-ключ FREE-AT — выбор любого субсчёта в @-обращении
В каталоге данных сервера можно завести файл-ключ FREE-AT (пустой файл
с таким именем; он действует и в новом ФБП:Сервере V01 — см.
п. 8.3 части I). В его присутствии Сервер не проверяет,
имеет ли субсчёт, введённый в @-обращении, предком именно тот счёт, который указан
в листе дерева: из формы, разлистывающей список субсчетов, может быть введён
любой субсчёт. Это средство в значительной степени компенсирует запрет на
* в @ в сетевой версии.
Пример: деньги в кассу поступают от покупателей (61), подотчётных лиц
(71) и разных дебиторов (76). Без послабления нужны три ветви:
50 @61
50 @71
50 @76
С ключом FREE-AT достаточно одной ветви 50 @X и формы
X.RPT, которая сначала спрашивает счёт, а затем разлистывает его субсчета
(цикл #*A — по субсчетам счёта, чьё имя в переменной A):
Заголовок
A=[im 'какой счет','61','71','76']
if A=1 A='61'; elseif A=2 A='71'; else A='76'; end
*
#*A
n=[na #]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^n
#
Условия: в плане счетов должны быть и 61, и 71, и
76, и X — все с субсчетами (для фиктивного счёта
X достаточно одного фиктивного субсчёта). Выбранный субсчёт подставляется
в фразу операции, а FREE-AT отключает проверку родителя. Дерево при этом
сокращается втрое.
X — всегда, независимо от того, какой список сейчас
показан: в качестве имени счёта-родителя выбирается имя формы. Обход: форма
X.RPT запоминает пользователя и счёт-родитель в дисковой базе
([sed …], см. главу «Свои данные»), а отдельная
форма MAKESUBA.RPT, ассоциированная с пользовательской клавишей, создаёт
субсчёт нужному счёту:* доработанная X.RPT — запоминает счёт-родитель
Заголовок
A=[im 'какой счет','61','71','76']
if A=1 A='61'; elseif A=2 A='71'; else A='76'; endif
[sed [user] + ' parent account',A]
*
#*A
n=[na #]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^n
#
* форма MAKESUBA.RPT — создание субсчета нужного счета
p=[ged [user] + ' parent account']
if p = 0
Форма запущена вне ввода операции
stop
endif
a=[is 'Обозначение субсчета', ' ', 9]
n=[is 'Наименование субсчета', ' ', 20]
Подтвердите создание субсчета нажатием на строку ниже
N:ENTER:a ·#1·#2·#3 #4 #5 #6·
^^^^^^^^^p ^^^^^^^^^^a ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^n
[sed [user] + ' parent account', 0]
Строка [sed [user] + ' parent account',A] запоминает, кто запустил
X.RPT, и обозначение счёта-родителя; [ged …] читает значение
(и возвращает 0, если ничего не записано); запись 0 тем же ключом очищает
его. В директиве N:ENTER:a ·#1·#2·#3 #4 #5 #6· знак · (код 250) —
разделитель, а #1, #2… — подстановки параметров фразы операции
(подробно о директивах N: — в главе
«Директивы N:»). Теперь для создания субсчёта используют не
встроенную команду списка, а пользовательскую клавишу: MAKESUBA.RPT знает,
кто запустил X.RPT и какой счёт-родитель нужен.
21. Свои данные: экстрапараметры и дисковая база
Кроме остатков, оборотов и обычных параметров счетов программа на языке ФБП может хранить собственные данные двумя способами:
- экстрапараметры — дополнительные именованные значения, привязанные к счетам
и субсчетам; они живут в оперативной памяти сервера и пересчитываются вместе с балансом
(функции
[set],[plus],[get]); - дисковая база
extrd.dat— произвольные пары «ключ → значение», которые сразу записываются на диск и сохраняются между сеансами (функции[sed],[ged]).
Экстрапараметры подходят для величин, которые должны автоматически пересчитываться при изменении прошлого (как и весь учёт ФБП), а дисковая база — для справочной информации, не зависящей от операций: реквизитов контрагентов, настроек и т.п.
21.1. Экстрапараметры: что это и чем они отличаются от параметров
Каждому счёту/субсчёту может быть сопоставлено неограниченное количество дополнительных параметров — числовых или строковых (обычных параметров у счёта не больше девяти, и меняются они только псевдопроводками присваивания). В отличие от обычных параметров, экстрапараметры открываются и модифицируются в файлах-коэффициентах произвольно, а их значения на любой момент времени — расчётная база для показателей отчётов.
21.2. Функции [set] и [plus]: запись экстрапараметров
[set A, S, V] — установить экстрапараметр
A — обозначение счета; S — имя экстрапараметра (число или
строка); V — значение (число или строка). Устанавливает экстрапараметр
S счёта A в значение V. Всегда возвращает
0 — функцию вызывают ради побочного эффекта.
[set X, n, ss] * запомнить сумму ss под номером n[plus A, S, V] — увеличить экстрапараметр
Увеличивает экстрапараметр S счёта A на V:
для чисел это арифметическое сложение, для строк — конкатенация (в зависимости от
типов). Всегда возвращает 0.
[plus 50, 'Итого', SS] * накопить сумму проводкиОбе функции могут использоваться только в листьях дерева и файлах-коэффициентах
— с одной оговоркой для отчётных форм (см. 21.3). Поскольку
результат всегда 0, удобна сокращённая запись вызова ради побочного эффекта — оператор
сразу со скобки, без фиктивного присваивания: [set X, n, ss] вместо
y = [set X, n, ss].
21.3. [set]/[plus] в отчётных формах: фиктивный счёт % и оператор array %
В отчётных формах [set] и [plus] должны ссылаться на
фиктивный счёт %, который следует определить в списке счетов.
Обратное тоже верно: в файлах-коэффициентах и листьях дерева
[set]/[plus] на счёт % ссылаться не должны.
Применение — промежуточное накопление структурированной информации в отчётных формах:
например, в разделе every debet формы-истории можно собирать суммы
проводок, а в epilog — переносить их в массив и сортировать:
prolog
n=0
every debet
n=n+1
[set X, n, ss]
epilog
for i=1 to n
[a i,[get X, i]];
endfor
sort array a
for i=1 to n
y=[a i]
^^^^^^^^^^^y
endfor
array % — обнуление экстрапараметров счёта %
Обнуляет все экстрапараметры счёта %, накопленные в форме вызовами
[set %…]. Наряду с обнулением освобождается занятая ими память.
array %21.4. Функция [get]: чтение экстрапараметров
[get A, S], [get A, S, M], [get A, S, M, D] — значение экстрапараметра
Возвращает значение экстрапараметра S счёта A. Момент,
на который берётся значение, зависит от места вызова и аргументов:
- в листьях дерева и файлах-коэффициентах — значение к моменту выполнения текущей проводки; в отчётных формах — на конец отчётного периода;
- с третьим аргументом
M— значение на конец месяцаM; - с аргументами
MиD— значение в месяцеMна конец дняD.
n=[get %,x] * значение, накопленное формой
for i=1 to n
...to в операторе for вычисляется
на каждом витке цикла, поэтому [get …] выгодно вынести в переменную, как
в примере выше.21.5. Дисковая база extrd.dat: [sed] и [ged]
Экстрапараметры пересоздаются при каждом запуске сервера, поэтому для данных,
которые должны храниться постоянно (и не зависеть от пересчёта баланса),
есть другой механизм — встроенное обращение к внешней дисковой базе данных, файлу
extrd.dat (он создаётся автоматически в каталоге данных сервера). Данные
могут быть числовыми и строковыми.
[sed i, v] — сохранить значение в дисковой базе
i — индекс (числовой или строковый), v — значение
(числовое или строковое). Сохраняет v в extrd.dat,
ассоциируя его с i. Всегда возвращает 0. Данные сразу выгружаются
на диск и не занимают оперативную память. Запись значения 0 по существу
очищает ключ.
[sed [user] + ' parent account',A] * запомнить, кто и что выбрал
[sed 'ИНН-' + [n1 #], inn][ged i] — извлечь значение из дисковой базы
Извлекает значение, ассоциированное с индексом i. Если с индексом ещё
ничего не ассоциировано — возвращает 0.
p=[ged [user] + ' parent account']
if p = 0
Форма запущена вне ввода операции
stop
endifОбе функции можно использовать в листьях дерева, файлах-коэффициентах, отчётных
формах и первичных документах. Типичная область применения — запоминание справочной
информации (реквизиты контрагентов: ИНН, банк) для автоматического заполнения
платёжек, счетов-фактур и др.: одна форма записывает реквизиты через
[sed …], другая извлекает их через [ged …]. Файл
extrd.dat — текстовый, его можно посмотреть любым просмотрщиком.
'jf.N', 'jf.1',
'tf.N', 'uf.N', 'ld.'+[intsn i],
'lt.N', 'lb.N' и т.п. — это тот же механизм
extrd.dat, заполняемый соответствующими функциями ([jf …],
[tf …], [uf …]) и операторами сканирования
(loaddir, loadtxt, loadbin). См. главы
«Функции: данные учёта» и
«Операторы».21.6. Замечания о быстродействии дисковой базы
Файл-ключ fastged в каталоге данных сервера включает зеркало
extrd.dat в оперативной памяти — это ускоряет функцию
[ged …] в 10–20 раз. Если формы много читают из дисковой базы, ключ
окупается.
22. Виды операций и проводки: программируем учёт
До сих пор мы говорили о языке отчётных форм — о программах, которые читают данные учёта. Эта глава — о том, как данные в учёт попадают: о дереве видов операций. Дерево — это тоже программа на языке ФБП, только специального назначения: она определяет, какие вопросы задаст программа при вводе хозяйственной операции и какие бухгалтерские проводки выполнит по ответам. Именно здесь «программируется учёт» — схемы проводок, аналитика, расчёт сумм. Именно поэтому изменение дерева приводит к виртуальному пересчёту всего журнала операций (см. главу 9): операции хранят только ответы, а проводки вычисляются по правилам дерева каждый раз заново.
22.1. Дерево видов операций: фразы, ветви и листья
Правила, которыми руководствуется программа при вводе операции, представлены в виде дерева. При регистрации операции программа предлагает человеку выбирать части фразы, выражающей смысл операции: она последовательно проходит через ветви дерева (объединяя ветви одного уровня в меню) и доходит до листьев. В каждом листе записано, какую проводку или группу проводок следует выполнить для этого вида операции. Помимо обычных вариантов меню ветви могут быть ветвями-вопросами и ветвями-циклами — о них ниже.
Например, дерево из ветвей «Расчётный счёт» → «приход» → «сдана касса» и «Расчётный счёт» → «расход» → «передано в кассу» порождает две фразы-вида операций. При вводе операции бухгалтер «выкладывает» такую фразу, выбирая пункты меню, вводит сумму — и программа выполняет проводки из листа, соответствующего выбранной фразе.
Работа с деревом. Дерево видов операций открывается в клиенте CLWP по
Alt+F6; здесь создаются новые ветви и редактируются листы с проводками. Ввод
операции выполняется в журнале операций (Alt+F2, затем F7). Дерево
хранится на сервере, а клиент получает его запросом T (см. главу
«Язык запросов к серверу»).
Ctrl+O) и выполните форму «Обороты счетов» (список форм на сервере —
Alt+F4). Программа сама проверит весь журнал и предложит перебить операции, не
соответствующие новому описанию. Повторяйте построение оборотов, пока форма не будет
построена без таких предложений — состояние всех счетов будет пересчитано автоматически.22.2. Формат проводки: дебет, кредит и откуда берётся сумма
Лист дерева — это список проводок. Каждая проводка записывается одной строкой простого и строгого формата:
дебет кредит коэффициент/формула/файл-коэффициент
Здесь дебет и кредит — обозначения счетов (или заменяющие их конструкции:
@-обращение, *-обращение, # в цикле). Третий элемент
определяет сумму проводки, и тут есть три принципиально разных способа:
| Третий элемент проводки | Как вычисляется сумма проводки |
|---|---|
числовой коэффициент (например, 0.18) |
Сумма операции умножается на коэффициент. Если коэффициент не указан, он равен 1. |
| формула (выражение языка форм) | Сумма проводки равна значению выражения — никакого умножения на сумму операции не происходит. |
| файл-коэффициент (имя файла с алгоритмом на языке форм) | Сумма проводки равна значению, которое алгоритм вернёт через переменную $ (см. 22.8). |
$ в описаниях проводок и файлах-коэффициентах
определена всегда и равна сумме операции, введённой бухгалтером. Формула
$*I/100 в листе дерева означает: «взять сумму операции, умножить на значение
переменной I (например, ответ на ветвь-вопрос о ставке налога) и разделить
на 100».Пример листа дерева для фразы «Реализация»: первая проводка с числовым коэффициентом (на сумму операции, умноженную на 1), вторая — с формулой (НДС по ставке из переменной):
62 46
46 68-2 $*I/100
Максимальное количество проводок в одном листе дерева — 15. Если этого недостаточно, используйте оператор выполнения проводок в файле-коэффициенте (см. 22.8) — там ограничения на число проводок нет.
22.3. @-обращения: выбор субсчёта при вводе операции
Аналитический учёт в ФБП ведётся по субсчетам. Чтобы не писать отдельную ветвь дерева
на каждого контрагента или сотрудника, в описании проводки можно сослаться на счёт,
имеющий субсчета, с префиксом @:
@76 51
При вводе операции программа покажет меню из обозначений и названий субсчетов
счёта 76; выбранный субсчёт будет ассоциирован с операцией и подставлен в проводку. Такой
приём избавляет от однородных ветвей дерева: одна ветвь «Оплата от покупателя» с
@76 заменяет десятки ветвей по каждому покупателю.
В одном листе допускается несколько @-обращений, причём к разным счетам:
@70 @69-1
@70 68-3
Если один и тот же счёт упоминается в листе с @-обращением несколько раз
(здесь — @70), список субсчетов появится при регистрации операции только
один раз: во все остальные проводки подставится уже выбранный субсчёт.
@-обращение
к несуществующему счёту или к счёту без субсчетов — ошибка («@-обращение к
несуществующему счету», «@-обращение к счету без субсчетов»). И наоборот: счёт, состоящий
из субсчетов, нельзя указывать в проводке без @ («Неизвестный (или состоящий
из субсчетов) дебетуемый счет»).22.4. Ветви-вопросы: данные, которых нет в счетах
Не всё, что нужно для проводки, хранится на счетах: ставка налога, количество, номер документа — такие данные проще спросить при вводе операции. Для этого служит ветвь-вопрос:
? переменная вопрос — ветвь-вопрос
При проходе через такую ветвь программа вместо меню показывает текст вопрос,
а введённый ответ присваивает указанной переменной. Дальше имя переменной можно
использовать в листе дерева: в формуле, в файле-коэффициенте или в указании счёта через
*-обращение (см. 22.6). Ветвь-вопрос не должна иметь
параллельных ветвей.
?I ндс,%
?N количествоНапример, ветвь ?I ндс,% спросит при вводе операции ставку НДС, а проводка
46 68-2 $*I/100 использует ответ в формуле. Помните: переменная $
(сумма операции) определена всегда, остальные переменные получают значения из ответов на
ветви-вопросы.
[ct ...]: имя контекста — первые 9 символов вопроса, значение ограничено
10 символами (см. главу «@-обращения и контекст»).22.5. Уточнения ветвей-вопросов: ·C, ·N, ·S, ·R, ·X
По умолчанию ветвь-вопрос показывает поле редактирования, куда ответ вводят с клавиатуры.
Это поведение можно изменить: вместо свободного ввода предложить меню, потребовать число
в диапазоне, преобразовать ответ в строку или показать целую форму-список. Уточнения
записываются в тексте баллонной помощи ветви-вопроса. Разделитель · —
средняя точка, символ с кодом 250 (вводится удержанием Alt и набором
250 на цифровом блоке клавиатуры).
·C·заголовок·пункт·пункт·… — меню вместо поля ввода
Ветвь-вопрос предложит меню с заданным заголовком; выбранный пункт становится ответом. Пунктами могут быть и числа, и фразы. Показ меню, в отличие от показа форм, происходит без обращения к серверу — то есть без задержек.
·C·%·20·10·
·C·тип расхода·затрата·из прибыли··N·умолчание·мин·макс· — настаивать на вводе числа
Программа потребует ввести число в заданном диапазоне; значение по умолчанию подставляется
в поле ввода. Вариант ·N (без параметров) просто следит, чтобы ответ
интерпретировался как число — это защищает от нежелательных знаков: программа «настоит»
на вводе 16.67, а не 16,67 (десятичный разделитель — точка).
Конструкция ·N·0· задаёт ввод числа с умолчанием 0.
·N·10·0·20· * число от 0 до 20, по умолчанию 10·S — принудительно преобразовать ответ в строку
Сервер будет считать ответ строкой, даже если он имеет вид числа: введённое
0023456 останется строкой '0023456' с ведущими нулями. Уточнение
·S может следовать за любым другим уточнением в следующей строке.
·R L
·S·R форма·ответ·… и ·X форма·ответ·… — форма как список выбора
Вместо поля ввода будет показана отчётная форма; когда пользователь выбирает в ней строку,
клиент выделяет первое слово этой строки (до первого пробела) и использует его как
ответ на вопрос. После имени формы можно передать ответы на вопросы самой формы. Разница:
·R даёт «готовый» ответ, а ·X позволяет отредактировать
полученный из формы ответ.
·R 70 ( ·X 70 )
·R 10 ·1· ( ·X 10 ·1· )·, и
·S приоритетнее ·N, если употреблены одновременно. Запись
·X AAAA ·SU-NDS· будет воспринята просто как ·S — и числа станут
считаться строками.22.6. *-обращения: счёт из значения переменной
В описаниях проводок наряду с обозначениями счетов и @-обращениями можно
использовать обращение вида:
* переменная — счёт, заданный переменной
Смысл: взять счёт, обозначение которого совпадает со значением переменной. Обычно переменная получает значение в ветви-вопросе. Работает в сетевой версии ФБП.
* ветви-вопросы дерева:
?D дебет
?K кредит
* лист дерева:
*D *KКак это работает: при регистрации операции на вопрос «дебет» ответим @76,
а на вопрос «кредит» — 51. Программа предложит список субсчетов счёта 76;
выберем, скажем, 76-01 Первый. Тогда переменная D получит значение
76-01, переменная K — значение 51, и проводка
*D *K эквивалентна записи 76-01 51.
*-обращений в сетевой версии
см. «Руководство пользователя по сетевой версии».22.7. Ветви-циклы: одна операция — проводки по всем субсчетам
Часто нужно проделать однотипные проводки для всех субсчетов счёта: начислить амортизацию на все объекты счёта 01, переоценить материальные запасы при изменении курса, начислить зарплату всем сотрудникам. Для этого служит ветвь-цикл:
# счёт комментарий — ветвь-цикл
После прохода через такую ветвь программа перебирает субсчета указанного счёта, и для
каждого из них выполняются действия, обусловленные предыдущими ветвями и листом дерева
(телом цикла). Внутри тела цикла знак # обозначает очередной субсчёт.
* ветвь дерева:
# 70 начисление зарплаты всем сотрудникам
* лист дерева (выполняется для каждого субсчёта счёта 70):
# 68-3 $*0.12Обратите внимание на масштаб: в листе может быть до 15 проводок, значит для каждого субсчёта будет выполнена вся группа проводок. В журнале — одна операция, а проводки сделаны для всех субсчетов!
continue if выражение — пропустить субсчёт в цикле
Псевдопроводка в листе дерева: если выражение принимает значение 1, оставшиеся проводки тела цикла для текущего субсчёта пропускаются, и цикл продолжается со следующего субсчёта. Типичное применение: сотрудник уволен — начислений ему не делаем.
continue if [ep #]=0 * пропустить, если параметр субсчёта нулевойbreak if выражение — досрочно завершить цикл
Если выражение принимает значение 1, оставшиеся проводки и псевдопроводки тела цикла пропускаются и цикл завершается досрочно.
break if $<0 * прекратить перебор при отрицательной суммеbreak if или
continue if находятся в листе дерева между @-обращениями к разным
счетам: клиентская часть ничего не знает об этих операторах, поэтому нежелательный
выбор субсчёта будет предложен в любом случае.22.8. Файлы-коэффициенты и оператор выполнения проводки
Когда сумму проводки нельзя выразить коэффициентом или короткой формулой — например,
подоходный налог со шкалой и вычетами — алгоритм расчёта выносят в файл-коэффициент:
обычный файл *.rpt с программой на языке форм. В проводке после дебета и кредита
указывается имя этого файла. Создать файл-коэффициент можно прямо из дерева: допишите в
строке проводки после пробела имя файла и откройте его на редактирование.
Соглашение о параметрах файла-коэффициента:
| Переменная | Смысл |
|---|---|
$ | На входе — сумма операции; в эту же переменную алгоритм возвращает вычисленную сумму проводки (то есть $ — и передаваемый, и возвращаемый параметр). |
$D | Обозначение дебетуемого счёта. |
$K | Обозначение кредитуемого счёта. |
Вот настоящий файл-коэффициент tax.rpt — расчёт подоходного налога
(в листе дерева проводка выглядит как @70 68-3 tax):
* Подоходный налог с физических лиц
*
D=[AK $D] Доход, начисленный сотруднику с начала года;
U1=[AP $D,68-3] Уже удержанный с начала года под/налог 9%,17% (город);
U2=[AP $D,68-31] Уже удержанный с начала года под/налог 3% (федер);
G=D*0.01 вычеты в Пенсионный фонд 1%
M=[ed MIN] Подлежащие вычету минимумы;
P=[ep @70] Сумма льгот, накопленная к моменту начисления;
if D in 0..10000 D=D-P-2*M; L=M*2
elseif D in 10000..30000 D=D-P-M; L=M
else D=D-P; L=0
endif
*
D=D-G учтем вычеты 1% в Пенсионный Фонд
...
J1=[tr T1-U2+0.5] доначисленный в этом месяце подоходный налог.
J2=[tr T2-U1+0.5]
$=J2
**** конец файла-коэффициента TAX ****
Здесь видны приёмы языка форм: комментарии (* в начале строки или текст после
выражения), обращения к данным учёта в квадратных скобках ([AK $D] — накопленный
оборот, [AP $D,68-3] — оборот между счетами, [ed MIN] и
[ep @70] — экстрапараметр и параметр счёта, подробнее — в главах
17 и 21), условный оператор с проверкой
диапазона in, несколько операторов в строке через ;. Результат
возвращается присваиванием $=....
first.rpt выполняется перед отчётными
формами и первичными документами, но не выполняется перед файлами-коэффициентами —
все нужные определения файла-коэффициента должны быть в нём самом (или в
library.rpt, доступном и отсюда). Подробности — в главе
«Файлы форм и общие файлы».▒ дебет кредит (выражение) — оператор выполнения проводки в файле-коэффициенте
Внутри файла-коэффициента можно выполнять проводки напрямую — строкой, начинающейся со знака проводки (символ с кодом 177). Синтаксис — как в листьях дерева: сначала дебетуемый счёт, затем кредитуемый, далее выражение, обязательно в скобках.
▒ 50 51 ($)
▒ 68-2 46 ($*0.18)В проводках файла-коэффициента могут участвовать счета без субсчетов, собственно субсчета,
@-обращения, *-обращения к переменным и текущий субсчёт
# цикла. Ограничений на количество проводок в файле-коэффициенте нет —
этим и обходят лимит в 15 проводок листа. Но два ограничения есть:
- из файла-коэффициента нельзя вызвать другой файл-коэффициент;
- все требуемые
@-обращения должны быть описаны в листе дерева: при повторном@-обращении в файле-коэффициенте подставляются те же субсчета, что были выбраны в листе, — дополнительного выбора не происходит. Это связано с тем, что фраза операции «складывается» максимум из 12 «кирпичиков» (ветвей дерева и@-обращений), и ограничение действует также для проводок в файле-коэффициенте.
F6 (при включённом запоминании ta-фактов).22.9. Псевдопроводки: параметры счетов, документы, горячие клавиши
Псевдопроводки имеют тот же синтаксис, что и обычные проводки, но не имеют смысла «дебет-кредит». Они применяются в листьях дерева для трёх задач: присваивать новые значения параметрам субсчетов, создавать первичные документы и определять горячие клавиши.
22.9.1. Параметры счетов и псевдопроводка «=n»
У каждого счёта есть 9 параметров, связанных со всеми его субсчетами: параметр
может выражать цену единицы материала, норму амортизации основного средства, процент налога,
уплаченного при покупке объекта, и т.д. В формах значения параметров читаются функциями
[bp ...] и [ep ...] (см. главу
«Функции: данные учёта»). А изменять значения параметров можно
динамически — псевдопроводками в листьях дерева:
субсчёт =n — присвоить значение параметру
В качестве дебетуемого указывается субсчёт, параметр которого нужно изменить, а в качестве
кредитуемого — обозначение =n, где n — цифра, номер параметра.
Присваиваемое значение определяется, как обычно: по сумме операции, формуле или
файлу-коэффициенту.
* записать сумму операции в параметр 1 выбранного субсчёта счёта 41:
@41 =1
* увеличить параметр 3 на 5% от суммы операции:
@41 =3 [ep @41,3]+$*0.05Для складских задач («а сколько этого товара есть сейчас?») при вводе операции полезен расчётный параметр: в плане счетов и начальных условий задаётся наименование расчётного параметра и формула его расчёта — например, для счёта 41 «Товары» формула остатка, делённого на цену из первого параметра, — и при вводе операции программа сразу показывает вычисленное количество. Тонкость: ссылаться на расчётный параметр в файлах форм нельзя.
22.9.2. Псевдопроводка «создать документ»
С операциями могут быть связаны первичные документы — накладные, ордера, счета — автоматически создаваемые при вводе операции. Формы документов пишутся на том же языке, что и отчётные формы и файлы-коэффициенты:
создать документ имя-формы [аргумент] — псевдопроводка первичного документа
Вместо имён счетов указываются ключевые слова создать документ (или
create document), далее — имя файла, где содержится форма документа. После
имени формы может идти аргумент — обозначение счёта или заменяющая его конструкция
(#, @, *); в форме документа на переданный аргумент
ссылются как $P.
создать документ nakl @41
create document orderКак это устроено. Для хранения документов в каталоге данных должен быть подкаталог
TXA, а на клиентских местах включена опция «Хранить первичные». При старте
сервер создаёт в TXA 12 подкаталогов — по одному на месяц (A —
январь … L — декабрь), и каждый документ (*.txa) хранится в
подкаталоге своего месяца. Рядом сервер ведёт файл дескриптора *.des:
первая строка — дата и время операции; если при пересчёте баланса штамп операции не
совпадает с дескриптором, документ создаётся заново, а предыдущая версия дописывается в
дескриптор — так накапливается вся история модификации документа. Документ, созданный
операцией «в прошлом» или перебивкой, можно увидеть в журнале операций клавишей
F4 (с задержкой, зависящей от скорости пересчёта).
В режиме ввода и просмотра операций первичные документы можно создавать, просматривать и удалять; в журнале слева от записи операции появляется символ, означающий, что для неё есть документ на диске.
IM, IS, IR, IA,
IY — сервер их игнорирует. Причина: для работы первичного документа вводится
операция, и диалог внутри документа создал бы неопределённость — сервер был бы вынужден либо
продолжать ввод других операций, игнорируя неоконченные вычисления, либо простаивать в
ожидании диалога. В остальном статус формы обычный: функция [re] выдаёт в ней
значение 2, доступны $P и определения из first.rpt.TXA, документ сначала ищется
в нём; создать документ там можно функцией [dir 1] и операторами вывода в файл
>file / >>file (см. главу «Текст и
вывод»):F=[dir 1]+'TXA\'+[stamp 3]+'.TXA'
ЗАГОЛОВОК ДОКУМЕНТА >file F
строки документа >>file F
22.9.3. Псевдопроводка «горячая клавиша»
Для самых частых видов операций стоит организовать ускоренный ввод:
горячая клавиша название — кнопка быстрого ввода
В лист дерева к группе проводок добавляется псевдопроводка с ключевыми словами
горячая клавиша (или hot key) и названием клавиши. В режиме ввода
операций на экране появится клавиша-кнопка с этим названием; щелчок по ней автоматически
«выкладывает» всю фразу или её часть до первой ветви-вопроса.
горячая клавиша Сдана кассаДля каждого пользователя можно организовать свой набор горячих клавиш — через
переопределение системных запросов в форме USERS (см. главу
«Директивы N:»). В клиенте CLWP горячих клавиш может быть до
восьми.
22.10. Ограничения, редактирование дерева и ошибки компилятора
Соберём в одном месте числовые ограничения дерева видов операций — их полезно помнить при проектировании:
| Ограничение | Значение |
|---|---|
| Ветвей первого уровня дерева | до 15 |
| Ветвей следующего уровня у каждой ветви | до 15 |
| Длина фразы операции (ветви дерева и @-обращения) | до 12 «кирпичиков» |
| Проводок в одном листе дерева | до 15 (обходится файлом-коэффициентом) |
| Параметров у каждого счёта | 9 |
| Длина ответа на вопрос операции (клиент CLWP) | 11 символов |
| Горячих клавиш (клиент CLWP) | до 8 |
Редактирование дерева. В дереве доступен поиск отрывка по образцу. Дерево можно
резать и клеить: отрезанный фрагмент ветви со всеми проводками временно сохраняется,
а затем приклеивается в новом месте. Фрагменты дерева можно сохранять в файлах с расширением
rul (удобно для переноса между настройками) и распечатывать.
Компилятор дерева обнаруживает большинство формальных ошибок «на первой секунде» попытки построить баланс. Вот его сообщения и их смысл:
| Сообщение | Причина и что делать |
|---|---|
| ПУСТАЯ СТРОКА В ОПИСАНИИ ПРОВОДКИ | В листе дерева есть пустая строка — уберите её. |
| НЕПРАВИЛЬНО ОПИСАНА ПРОВОДКА | Нарушен формат «дебет кредит коэффициент». |
| НЕПРАВИЛЬНЫЙ КОЭФФИЦИЕНТ В ОПИСАНИИ ПРОВОДКИ | Ошибка в числовом выражении коэффициента. |
| @-ОБРАЩЕНИЕ К НЕСУЩЕСТВУЮЩЕМУ СЧЕТУ | Счёт не описан в списке счетов — введите его вместе с субсчетами. |
| @-ОБРАЩЕНИЕ К СЧЕТУ БЕЗ СУБСЧЕТОВ | @ может ссылаться только на счёт, имеющий субсчета. |
| НЕИЗВЕСТНЫЙ (ИЛИ СОСТОЯЩИЙ ИЗ СУБСЧЕТОВ) ДЕБЕТУЕМЫЙ/КРЕДИТУЕМЫЙ СЧЕТ | Счёт не описан либо состоит из субсчетов, а @-обращение не применено. |
| НЕТ ОПИСАНИЙ ПРОВОДОК ДЛЯ ЭТОЙ ОПЕРАЦИИ | Для вида операции нет листа с проводками — добавьте лист в дерево. |
| НЕПРАВИЛЬНО УКАЗАН ВИД ОПЕРАЦИИ | Ветвь дерева изменилась после ввода операции — при редактировании операции укажите вид заново. |
| В ОПИСАНИИ ПРОВОДКИ НЕТ ССЫЛКИ НА ФАЙЛ-КОЭФФИЦИЕНТ | Возникает при переходе от проводки к файлу-коэффициенту, если в проводке нет коэффициента или задан числовой коэффициент. |
22.11. Сквозной пример: от плана счетов до введённой операции
Пройдём весь путь настройки на маленьком, но законченном примере: учтём движение денег между кассой и расчётным счётом.
Шаг 1. Счета. В «Счетах и начальных условиях» заводим два счёта без субсчетов:
50 Касса
51 Расчетный счет
Шаг 2. Ветви дерева. Открываем дерево видов операций (Alt+F6) и
создаём ветвь первого уровня Расчетный счет. Затем добавляем ветви второго
уровня, повторяя действия для всего нужного: получаем ветви приход и
расход, а внутри каждой — завершающие ветви сдана касса и
передано в кассу. Дерево порождает две фразы:
Расчетный счет - приход - сдана касса
Расчетный счет - расход - передано в кассу
Шаг 3. Листы с проводками. Выбираем последнюю ветвь первой фразы
(сдана касса) и открываем лист дерева. Деньги пришли на расчётный счёт из кассы,
поэтому записываем проводку без коэффициента (по умолчанию он равен 1 — проводка на всю
сумму операции):
51 50
Аналогично для фразы «расход - передано в кассу» лист будет зеркальным:
50 51
Шаг 4. Ввод операции. Переходим в журнал операций (Alt+F2), нажимаем
F7 и Enter. После ввода даты и выбора положения операции в течение
дня появляется меню из ветвей первого уровня — у нас это единственная ветвь «Расчетный
счет»; далее — меню второго уровня («приход» / «расход») и третьего. Выкладываем фразу
«Расчетный счет - приход - сдана касса», вводим сумму — и по F6 смотрим
сделанные программой проводки: дебет 51, кредит 50, сумма операции.
Шаг 5 (развиваем пример). Аналитика и вопросы. Добавим аналитику по контрагентам и ставку НДС. Заводим счёт 76 с субсчетами-покупателями и строим вторую ветвь первого уровня:
Реализация
?I ндс,% * ветвь-вопрос: ставка налога
оплачено покупателем
В баллонной помощи ветви ?I ндс,% пишем уточнение-меню, чтобы ставку
выбирали, а не вводили:
·C·%·20·10·
Лист для фразы «Реализация - ?I ндс,% - оплачено покупателем»:
51 @76
@76 68-2 $*I/100
горячая клавиша Оплата от покупателя
При вводе такой операции программа покажет меню ставок НДС (20 или 10), затем список
субсчетов счёта 76 (один раз, хотя @76 встречается дважды), выполнит две
проводки — оплату на всю сумму и выделенный налог по формуле $*I/100, — а
кнопка «Оплата от покупателя» позволит в дальнейшем выкладывать фразу одним щелчком.
23. Управляющие строки N: — навигация и запросы из форм
Обычная отчётная форма — «слепок» данных: она показывает информацию, но не умеет
реагировать на действия пользователя. Управляющие строки N: превращают
форму в интерактивный экран: по нажатию клавиши из неё запускаются другие формы,
открывается операция в журнале, регистрируются операции и заводятся субсчета — не
выходя из отчёта. Формы со взаимными ссылками образуют настоящие приложения: список
накладных, из которого по Enter открывается сама накладная, и т.п.
Механика такова: строки N:... в тексте формы не выводятся в отчёт, а
запоминаются клиентом. Когда пользователь нажимает привязанную клавишу, клиент
конструирует из шаблона строку запроса и посылает её серверу — так, будто запрос введён
вручную в списке запросов (см. главу 7).
N: обрабатывает именно клиент, а не сервер:
сервер про них ничего не знает. Поэтому все приёмы этой главы работают только при
просмотре формы в ФБП:Клиенте. Возможности разбираются ниже по новому клиенту
CLWP; там, где поведение отличается от прежнего клиента CLW32, это оговорено.23.1. Синтаксис и распознаваемые клавиши
Строка управляющая, если начинается с N: (или n:) —
регистр имени клавиши не важен. Клиент читает текст между первым и вторым
двоеточием и сравнивает со списком известных клавиш:
| Строка | Клавиша / действие |
|---|---|
N:F1: … N:F12: | функциональные клавиши
F1…F12; назначенные клавиши показываются в подсказке внизу
окна формы |
N:SHIFTF1: … N:SHIFTF9: | новое в
CLWP — сочетания Shift+F1…Shift+F9 |
N:ENTER:, N:RETURN:, N:CR: |
клавиша Enter (три написания — одна клавиша) |
N:AUTO:запрос | без клавиши: выполняется один раз при первом показе окна формы (см. п. 23.5) |
N:NAME:текст | историческая подпись экранной кнопки запроса; в CLWP кнопки нет — строка игнорируется |
N:запрос («голая» строка) | весь остаток после
N: — запрос, выполняемый при каждой загрузке/перечтении формы
(см. п. 23.6) |
N:>программа | запуск внешней программы или командного файла на машине клиента (серверу не передаётся) |
Не распознаются: N:ESC:,
N:SHIFTF10:…N:SHIFTF12:, N:F13: и любые другие
имена вне списка. Такая строка считается голой: весь её текст после
N: (включая «SHIFTF10:…») уйдёт серверу как запрос при каждой загрузке
формы — почти наверняка ошибка. Используйте только клавиши из таблицы.
N:SHIFTF1:…N:SHIFTF9: понимает только CLWP. Прежний
клиент CLW32 (и DOS-клиенты) считает их голыми строками и выполнит их текст как
запрос при загрузке формы. Если форма должна работать и в старых клиентах,
Shift-клавишам назначайте только безобидные запросы или продублируйте действие на
обычных F1…F12.23.2. Новые клавиши Shift+F1…Shift+F9
В прежнем клиенте девять сочетаний Shift+F1…Shift+F9
заняты переключением аргументов и фильтров формы. В CLWP форма может перехватить
эти сочетания для своих целей:
N:SHIFTF1:R OST ·#1·
N:SHIFTF2:J KEY=#1
Приоритет таков: если для выделенной строки действует строка
N:SHIFTFn:, нажатие Shift+Fn выполняет её запрос; если
формой строка не определена — сочетание, как и прежде, переключает n-й
аргумент/фильтр (см. главу 4). Таким образом,
N:SHIFTFn: — способ дать форме до девяти дополнительных действий,
не трогая занятые F1…F12 и Enter.
■ (код 254,
Alt+254), не печатается, а показывается жёлтой плашкой внизу окна.23.3. Область действия и цепочки запросов
Управляющая строка действует не на всю форму, а на строки отчёта, следующие после неё, — до ближайшей следующей строки на ту же клавишу, которая её заменяет. Это позволяет в разных частях одной формы назначить одной клавише разные действия:
N:F9:r test1
...
N:F9:r test2
...
N:F9:
Строка без запроса (N:F9: в конце примера) только помечает
конец области действия прежней привязки и сама ничего не выполняет.
Цепочки (новое в CLWP). Если на одну клавишу в одной области действия назначено несколько строк, нажатие выполняет все их подряд, сверху вниз. Классический приём — открыть журнал по значению строки и закрыть форму:
N:ENTER:J KEY=#1
N:ENTER:#CLOSE
Директивы O (регистрация операции), A (заведение
субсчёта) и D (удаление) из одной цепочки копятся и уходят серверу
одним пакетом в конце цепочки; если показывать нечего, окно не открывается
(«невидимые формы»). Отказ E-… и однострочный ответ показываются
сообщением. Цепочку обрывает команда #NULL
(см. п. 23.7).
23.4. Динамические ссылки на данные строки: #1…#9
Главная сила управляющих строк — запросы, построенные из содержимого строки,
на которой стоит курсор. Ссылки #1…#9 — номера слов
выделенной строки. «Слова» выделяются так: если в строке есть разделители
псевдографики │, разбивка идёт по ним, иначе — по пробелам;
#1 — слово, начинающееся с крайнего левого положения.
Подстановка выполняется посимвольно и работает в любом месте запроса —
например, J KEY=#1 подставит первое слово строки, приклеенное к
KEY=:
N:ENTER:R F16 ·1·#1·#3·
Форма F16.rpt получит первое и третье слова выделенной строки как
ответы на свои вопросы (знак ·, код 250, обрамляет ответы) — подхватить
их можно функцией [ia ...]. Другой пример — переход из отчёта в журнал
операций с установкой курсора на нужную операцию (если форма вывела её уникальный
код первым словом строки):
N:ENTER:J KEY=#1
Правила подстановки:
##— литеральный знак#;#N— ровно одна цифра 1…9;#10— это слово №1 и знак0;- ссылка на несуществующее слово даёт пустую строку; пустой результат у первого запроса цепочки обрывает цепочку, у остальных — пропускает запрос;
#0— особая ссылка: команда не исполняется, если строка начинается с пробела (без учёта псевдографики);- подстановки нет у голых строк
N:иN:AUTO:— при их выполнении строка отчёта ещё не выделена.
Ссылки из строк таблицы [table]
При выводе таблицы функцией [table] управляющая
строка размещается непосредственно перед вызовом row. Она действует на
сформированную строку данных; псевдографика при выделении слов #1…#9
не учитывается:
for i=1 to n
N:ENTER:R CARD ·#1·
[table 'row','T',K,N,[sn S,15,2]]
N:ENTER:
endfor
Если код карточки находится в первой колонке, #1 передаст его в форму
CARD. Пустая строка N:ENTER: завершает область действия привязки,
чтобы она не распространялась на итоги и другие строки после таблицы. Если для колонки
включён wrap, код и остальные параметры находятся на первой строке
записи; в строках продолжения длинного текста эти ячейки пустые.
23.5. Автозапуск: N:AUTO:
Строка N:AUTO:запрос выполняется один раз на окно, сразу при
первом показе формы — без нажатия клавиш; при последующих обновлениях формы она не
повторяется. Туда ставят то, что нельзя выполнить дважды, — автоматическую
регистрацию операции (O), заведение субсчёта (A):
N:AUTO:#CLOSE
В сочетании с #CLOSE получаются «невидимые» формы — например, форма
обнуления экстрапараметров: выполняется и закрывается, не показываясь пользователю.
N:AUTO: нет области действия, и в ней нельзя
использовать ссылки #i и команду #NULL.23.6. «Голые» строки N:
Строка N:запрос без имени клавиши выполняется при каждой
загрузке и каждом обновлении формы (в отличие от одноразовой N:AUTO:).
Это удобно для служебных действий, которые должны повторяться при перечтении:
поддержание экстрапараметров, регистрация фактов просмотра и т.п.
N:R test2
N:>SetFirst.bat 1
Вторая строка примера — запуск внешней программы на машине клиента: запрос,
начинающийся с >, серверу не передаётся.
23.7. Специальные команды: ##, #CLOSE, #0, #NULL
| Конструкция | Назначение |
|---|---|
## | литеральный знак # в запросе |
#CLOSE | закрыть окно формы после выполнения запроса (команда клиенту, серверу не передаётся) |
#NULL #i | проверка присутствия данных: если
i-го слова в строке нет, клиент обрывает выполнение цепочки |
#0 | команда не исполняется, если строка начинается с пробела (без учёта псевдографики) |
Проверки #NULL комбинируются: несколько команд #NULL
подряд — условие И; несколько ссылок в одной команде — ИЛИ.
23.8. Пример: взаимодействующие формы LIST и NAKL
Классическая пара «список → документ». Форма LIST разлистывает список
накладных, собранный фактами; по Enter на выбранной строке открывается
форма NAKL с самой накладной:
N:ENTER:R NAKL ·#1·
p0=[user]
Список чеков пользователя ^^^^^^^^^^^^^^^^^^^^^^p0
i=1
:POVTOR
search оператор p0 накл ?nk сумма ??
if [success]=1
i=i+1
¦^^^^^^^^^nk¦
goto POVTOR
endif
По Enter выполняется форма NAKL, которая получает номер
накладной (#1 — первое слово выделенной строки) и ищет его в ленте
фактов:
* Накладная
?nk number
^^^^^^^^^^^^^^nk
t=[type nk]
if t=0 nk=[intsn nk]; endif
rewind facts
search оператор ?? накл [strip nk] сумма ?sm
if [success]=1
Н А К Л А Д Н А Я
номер: ^^^^^^^^^^nk сумма ^^^^^^^^^^^sm^^
endif
23.9. Форма USERS и переопределение системных запросов
Особая форма USERS (users.rpt) выполняется клиентом
при входе, и все её запросы клиент отправляет серверу автоматически — так
пользователю настраивают «рабочее место» сразу после подключения.
К системным запросам относятся, в частности, T (дерево видов
операций), F (список форм на сервере) и встроенные системные формы
__SYS001…__SYS006. В форме USERS их можно
переназначить — например, по имени пользователя:
* Пример отчетной формы USERS:
if [user]='anyuser'
__SYS001 = __SYS01S
__SYS002 = __SYS02S
__SYS005 = __SYS05S
__SYS006 = __SYS06S
F='R FORMS'
^^^^^^^^^^^^F
endif
Здесь для пользователя anyuser вместо встроенных
__SYS001, __SYS002 и т.д. выполняются собственные формы
__SYS01S, __SYS02S и т.д., а вместо стандартного ответа на
запрос F — форма FORMS.
23.10. Передача контекста между формами: [ct]
Формы, обслуживающие ветви-вопросы дерева видов операций (уточнения
·R/·X в баллонах), выполняются в контексте вводимой
операции. Функция [ct s] возвращает в форме значение контекста с именем
s — так форма второго вопроса может использовать ответ, выбранный в
форме первого вопроса.
| Контекст | Имя | Значение |
|---|---|---|
| Выбранный субсчёт | обозначение родительского счёта | обозначение выбранного субсчёта |
| Ответ на вопрос операции | первые 9 символов вопроса | ответ, ограничен 10 символами |
MODOKEY | только заглавными латинскими буквами | дата регистрации и уникальный ключ операции (ключ присутствует, если операция перебивается) |
| Сумма | Сумма | введённая сумма, ограничена 10 символами |
Разбор контекста MODOKEY (позиции 1–2 — месяц, 3–4 — день, 5–7 и
8–10 — части кода операции вида CAAA-002):
CT=[ct 'MODOKEY'] - получаем контекст;
MO=[vl [cp CT,1,2]] - месяц;
DO=[vl [cp CT,3,2]] - день;
K=[ch 64+MO]+[cp CT,5,3]+'-'+[cp CT,8,3] - код операции;
23.11. Типичные ошибки и подводные камни
1. Пропали строки формы-источника. Если форма
form1 запускает form2 (N:Enter:r form2) и
текст form1 содержит только расчётную часть или вызовы функций
[ir...], [is ...], [ia ...], то после строки
N:Enter:r form2 следует оставить хотя бы две пустые строки.
2. Неизвестное имя клавиши — это голая строка. Опечатка
вроде N:SHIFTF10: или N:ESC: не вызовет ошибки — текст
будет отправлен серверу как запрос при каждой загрузке формы
(см. п. 23.1).
3. В N:AUTO: и голых N: нет ссылок #i. Эти запросы
выполняются без выделенной строки — ссылки #i и проверки
#NULL в них не работают.
O): откройте два окна — ввод операции
и список запросов (Alt+F9). Введите операцию вручную — в списке
запросов сконструируется готовая строка, которую можно скопировать в управляющую
строку N:.24. Графика в формах
makepng результата не дают. (Сама директива G
протокола начиная с V01.02 работает — она компилирует и выполняет форму из тела запроса,
см. п. 7.20; не работает именно вывод картинок.) Эта глава сохранена
как историческая справка —
она нужна, чтобы читать и разбирать старые формы, в которых графические операторы встречаются.Отчётная форма умеет не только печатать текст, но и строить картинки: диаграммы,
графики, схемы. Для этого изображение рисуется в массиве (по точкам, линиям и фигурам), а затем
сохраняется в файл формата PNG оператором makepng. Дальше файл можно показать
пользователю — например, вставить в web-страницу, которую строит форма, выполняемая через
NULLCG.CGI (см. главу «Web-приложения через NULLCG.CGI»).
Всё рисование происходит в обычном массиве (см. главу «Массивы»): каждый элемент массива отвечает за одну точку изображения. Графические операторы — это удобная «обёртка» над массивом: они сами вычисляют нужные индексы и защищают от выхода за границы картинки.
24.1. Система координат и связь с массивом
Изображение — прямоугольник шириной w и высотой h точек.
Действуют простые соглашения:
- все видимые точки имеют положительные целые координаты:
1 ≤ x ≤ w,1 ≤ y ≤ h; - левый верхний угол изображения — точка
x=1, y=1(ось Y направлена вниз, как принято в компьютерной графике, а не в математике); - точке
(x,y)соответствует элемент массива с индексом(y-1)*w + x; - в описаниях синтаксиса ниже:
a— латинская буква (имя массива),w,h— ширина и высота в точках,c— строка (код цвета).
Если элементу массива не присваивалось значение, при создании файла он считается равным
[ch 0] (чёрная непрозрачная точка). Числовое значение элемента игнорируется —
вместо него тоже берётся [ch 0]: цвет задаётся только строкой.
24.2. Как кодируется цвет
Цвет точки определяется первыми четырьмя знаками строкового значения элемента массива.
Каждый знак — это один байт, полученный функцией [ch n] (см. главу
«Функции: строки, даты, математика»):
| Знак строки | Компонент | Значение |
|---|---|---|
| 1-й | Red (красный) | код 0–255: 0 — нет красного, 255 — максимум |
| 2-й | Green (зелёный) | код 0–255 |
| 3-й | Blue (синий) | код 0–255 |
| 4-й | Alpha (прозрачность) | [ch 0] — полная непрозрачность, [ch 255] — полная прозрачность |
Если строка короче четырёх знаков, недостающие компоненты считаются равными
[ch 0]. Поэтому строка из одного знака [ch 0] — чёрный цвет,
а из одного [ch 255] — самый яркий красный.
[ch 255] - самый яркий красный
[ch 0] + [ch 255] - самый яркий зеленый
[ch 0] + [ch 0] + [ch 255] - самый яркий синий
[ch 0] - черный
[ch 0]+[ch 0]+[ch 0]+[ch 255] - полная прозрачность
[ch 255] + [ch 153] + [ch 153] - розоватый
c=[ch 255]+[ch 0]+[ch 128].
Четвёртый знак (Alpha) можно не задавать вовсе — тогда точка непрозрачна.24.3. Создание файла изображения
makepng a, w,h, f — сохранить массив в PNG-файл
Создаёт изображение в формате PNG из элементов массива a размером
w×h точек. f — строковое выражение с именем файла
(включая полный путь).
w=127; h=127; f='c:\p1.png'
for y=1 to h
for x=1 to w
r=[ch 2*y]; g=[ch 2*x]; b=[ch x+y]
[a (y-1)*w+x, r+g+b]
endfor
endfor
makepng a,w,h,f
Пример заполняет массив «вручную», обращением к элементам по формуле
(y-1)*w+x, — получается плавный цветной градиент 127×127.
makepng
воспринимался только синтаксически (изображение не создавалось) — там для просмотра картинок
из массивов служил оператор showimg (см. ниже). Это стоит учитывать при разборе
старых форм.24.4. Рисующие операторы
Операторы этой группы изменяют элементы массива, избавляя от ручного вычисления индексов. Все они допускают координаты за пределами изображения — лишние точки просто отбрасываются.
drawpixel a,w,h, x,y, c — поставить точку
Делает то же, что присваивание [a (y-1)*w+x, c], но если x выходит
за диапазон 1..w или y — за 1..h, присваивания не происходит:
оператор безопасен при любых координатах.
w=127; h=127; f='c:\p1.png'
for y=1 to h
for x=1 to w
r=[ch 2*y]; g=[ch 2*x]; b=[ch x+y]
drawpixel a,w,h, x,y, r+g+b
endfor
endfor
makepng a,w,h,f
Это в точности тот же градиент, что и в примере к makepng, но без ручного
вычисления индекса.
drawline a,w,h, x1,y1, x2,y2, c — прямая линия
Рисует прямую линию цвета c от точки (x1,y1) к точке
(x2,y2). Координаты концов могут лежать за пределами изображения — видна будет
только часть линии, попавшая в кадр.
w=120; h=100
drawline a,w,h, 50,50, -20,-10, [ch 255]
drawline a,w,h, 1, 1, 100, 40, [ch 0]+[ch 0]+[ch 255]
makepng a,w,h, 'c:\p3.png'drawbar a,w,h, x1,y1, x2,y2, c — закрашенный прямоугольник
Рисует закрашенный прямоугольник цвета c: левый верхний угол —
(x1,y1), правый нижний — (x2,y2). Выходы за границы изображения
допускаются. Этим же оператором удобно заливать фон всей картинки.
w=120; h=100
drawbar a,w,h, 1, 1, w, h, [ch 255]
drawbar a,w,h, 20, 20, 40,50, [ch 0]+[ch 255]
makepng a,w,h, 'c:\p4.png'drawtxt a,w,h, x,y, n,t, c — надпись на изображении
Выводит строку текста t цвета c начиная от точки (x,y).
Число n задаёт шрифт и направление вывода:
| n | Шрифт | Направление |
|---|---|---|
| 1 | 5×12 | слева направо |
| 2 | 10×18 | слева направо |
| 11 | 5×12 | сверху вниз |
| 12 | 10×18 | сверху вниз |
| 21 | 5×12 | снизу вверх |
| 22 | 10×18 | снизу вверх |
w=100; h=100; c=[ch 255]+[ch 255]
drawtxt a,w,h, 10,10, 1, 'n=1', c
drawtxt a,w,h, 10,25, 2, 'n=2', c
drawtxt a,w,h, 50,50, 11, 'n=11', c
drawtxt a,w,h, 65,50, 12, 'n=12', c
drawtxt a,w,h, 10,60, 21, 'n=21', c
drawtxt a,w,h, 25,60, 22, 'n=22', c
makepng a,w,h, 'c:\p5.png'
Вертикальные надписи (n=11,12,21,22) полезны для подписей вдоль оси Y графика.
drawarc a,w,h, x,y, f1,f2, r, e, k, c — дуга, сектор, закрашенный сектор
Рисует дугу окружности или эллипса с центром в точке (x,y) — или целый сектор:
f1, f2— начальный и конечный угол в градусах;r— радиус;e— признак эллиптичности:e=1— окружность;0<e<1— эллипс с большей горизонтальной осью;e>1— эллипс с меньшей горизонтальной осью;k— уточнение вида:k=0— дуга,k=1— сектор (дуга плюс два радиуса),k=2— закрашенный сектор;c— цвет.
Пример — круговая диаграмма («пирог») из пяти закрашенных секторов с чёрными контурами на прозрачном фоне:
w=130; h=130; x=65; y=65; r=60; e=1
c0=[ch 0]; c1=[ch 255]; c2=[ch 0] + [ch 255]
c3=[ch 0]+[ch 0]+[ch 255]; c4=[ch 255]+[ch 255]
c5=[ch 255]+[ch 0]+[ch 255]
drawbar a,w,h, 1,1,w,h, [ch 0]+[ch 0]+[ch 0]+[ch 255]
drawarc a,w,h, x,y, 0, 15, r,e,2, c1
drawarc a,w,h, x,y, 15, 55, r,e,2, c2
drawarc a,w,h, x,y, 55,120, r,e,2, c3
drawarc a,w,h, x,y, 120,280, r,e,2, c4
drawarc a,w,h, x,y, 280,360, r,e,2, c5
drawarc a,w,h, x,y, 0, 15, r,e,1, c0
drawarc a,w,h, x,y, 15, 55, r,e,1, c0
drawarc a,w,h, x,y, 55,120, r,e,1, c0
drawarc a,w,h, x,y, 120,280, r,e,1, c0
drawarc a,w,h, x,y, 280,360, r,e,1, c0
makepng a,w,h, 'c:\p6.png'
Обратите внимание: сначала рисуются закрашенные сектора (k=2), затем те же
сектора чёрным цветом c0 в режиме k=1 — так «пирог» получает
аккуратные разграничительные линии.
drawbar.fillarea a,w,h, x,y, c — заливка области
Закрашивает цветом c область, содержащую точку (x,y) и ограниченную
контуром того же цвета c. Если контур не встретился или незамкнут, заливка идёт
до границы изображения.
w=100; h=100; c=[ch 255]
drawline a,w,h, 1,30, 90,10, c
drawline a,w,h, 1,70, 90,10, c
fillarea a,w,h, 1,31, c
makepng a,w,h, 'c:\p7.png'
Здесь две линии образуют замкнутую вместе с левым краем картинки область, и
fillarea закрашивает её изнутри, начав с точки (1,31).
24.5. Другие операторы показа изображений (историческая справка)
В старых однопользовательских версиях платформы существовали операторы показа изображения прямо из массива, без файла. В сетевой версии они отсутствуют, но могут встретиться в старых формах.
showimg a,w,h,x,y — показ изображения в ultraH-32
Позволял просматривать изображения из массивов вместе с текстом отчёта прямо в ultraH-32.
x,y — смещения в точках от строки, соответствующей оператору showimg.
Если отчёт содержал хотя бы один showimg, использовался графический режим
640×480 с 256 или 32768 цветами; текст выводился шрифтом 8×16, цвет и фон наследовались из
текстового режима (опция «Палитра»). Прокрутка — клавишами Home, End, PgDn, PgUp и стрелками,
завершение просмотра — Esc.
showimg a,w,h,10,20showimg отсутствует в языке ФБП:Сервера — там
использовался makepng с показом полученного файла (например, через web-страницу,
см. главу «Web-приложения через NULLCG.CGI»).insertimage a,w,h,x,y — изображение в ultraLX (Linux)
Родственный оператор версии ultraLX для Linux: создавал изображение из элементов массива
a (размер w×h, смещение x,y) при показе
отчёта. Играл ту же роль, что showimg в ultraH-32.
24.6. Пример: простая столбиковая диаграмма
Соберём всё вместе: нарисуем диаграмму продаж по кварталам — фон, оси, четыре столбика
и подписи. Данные здесь заданы прямо в форме (массив v); в реальной форме их
получают функциями оборотов [od ...], [op ...] и т.п. (см. главу
«Функции: данные учёта»).
* диаграмма продаж по кварталам
w=220; h=160
[m 1,45,70,30,90]
* фон и оси
drawbar a,w,h, 1,1,w,h, [ch 255]+[ch 255]+[ch 255]
drawline a,w,h, 30,10, 30,140, [ch 0]
drawline a,w,h, 30,140, 210,140, [ch 0]
* столбики: масштаб 1 единица = 1.4 точки
for i=1 to 4
bh=[tr [m i]*1.4]
x1=40+(i-1)*45
drawbar a,w,h, x1,140-bh, x1+25,140, [ch 0]+[ch 0]+[ch 255]
drawtxt a,w,h, x1+5,145, 1, 'Q'+[intsn i], [ch 0]
endfor
drawtxt a,w,h, 5,10, 11, 'продажи', [ch 0]
makepng a,w,h, 'c:\sales.png'
Здесь виден типовой приём: «мир» диаграммы (числа 30–90) пересчитывается в точки картинки
умножением на масштаб, а столбик рисуется от базовой линии y=140 вверх —
то есть координата y2=140 у drawbar больше, чем y1.
24.7. Уникальные имена файлов и уборка: [unicfile] и deleteobsolete
Когда форму с картинкой запускают многие пользователи (типичный случай — web-приложение
через NULLCG.CGI), каждый должен получить свой файл изображения, а отработанные файлы
нужно своевременно удалять, чтобы каталог не разрастался. Для этого служат функция
[unicfile] и оператор deleteobsolete.
[unicfile] — уникальное имя файла
Выдаёт строку — уникальное имя файла. К нему остаётся добавить путь и расширение:
u=[unicfile]; e='.png'
f0='c:\webshare\wwwroot\dynamic\' + u + edeleteobsolete d, n — удаление устаревших файлов
Удаляет файлы, заданные маской d, от момента создания которых прошло более
n секунд.
deleteobsolete f1,1000d может включать только расширения
.PNG, .GIF, .HTM; маска .* не допускается.
Это защита от случайного удаления файлов данных.Законченный пример динамической картинки для web-страницы (Web-сервер работает с
каталогом c:\webshare\wwwroot, в нём создан подкаталог dynamic с пустым
index.html, чтобы браузер не показывал содержимое каталога; ФБП:Сервер работает
с данными из c:\data, и при обращении к
http://localhost/cgi-bin/nullcg.cgi выполняется форма c:\data\ax.rpt):
Это форма ax
*
u=[unicfile]; e='.png'
f0='c:\webshare\wwwroot\dynamic\' + u + e
f1='c:\webshare\wwwroot\dynamic\*' + e
f2='http://localhost/dynamic/' + u + e
*
deleteobsolete f1,1000
... заполняем массив a ...
makepng a,100,100,f0
printstr '<img src=' + f2 + '>'
Схема работы: deleteobsolete чистит PNG старше 1000 секунд, форма рисует
новый файл с уникальным именем, а printstr вставляет в страницу тэг
<img> со ссылкой на него. Подробнее о построении web-страниц — в главе
«Web-приложения через NULLCG.CGI».
25. Web-приложения через NULLCG.CGI
NULLCG.CGI — это CGI-скрипт, шлюз между Web-сервером и ФБП:Сервером. Он принимает запросы браузера, передаёт их ФБП:Серверу и генерирует HTML-страницы, которые браузер видит как особое клиентское место ФБП. Так на языке форм можно строить web-приложения — с формами ввода, кнопками, таблицами и картинками — и для Internet, и для локальной офисной сети.
- Работает на Windows в комбинации с ФБП:Сервером; в отличие от старого МикроСервера, без ограничений на язык ФБП — доступен весь язык форм.
- NULLCG.CGI не входит в комплект сетевой версии — исторически это был отдельный продукт (приобретался на Расчётном Пункте). В его комплект входили исходные тексты Расчётного Пункта, Платного Консультационного Пункта и исходники nullcg.cgi на C — это одновременно и готовые образцы web-приложений.
- Нужен установленный Web-сервер с поддержкой CGI (например, Microsoft IIS).
25.1. Пользователи, имена и пароли
Количество пользователей web-приложения не ограничено, а их имена и пароли определяются
программно, в самих формах — например, через факты, extrd.dat или
обозначения и наименования счетов. В файле _rights_.fbp следует указать общее
имя USER.
При любом запросе NULLCG.CGI передаёт серверу контекст $$TISIG (его видно
при включённом logmode). Сервер извлекает имя пользователя из
extrd.dat по ключу (схематично):
x=[ged ah+'.ax.who']
где ah — комбинация IP-адреса пользователя и времени первого старта NULLCG.CGI,
ax — «корневая» форма ax.rpt, who — имя поля. Если
x окажется числом (в том числе нулём), операции будут штамповаться именем
UNKNOWN.
ax.rpt имя пользователя обязательно должно быть
введено в предопределённое поле who — иначе все его операции уйдут в журнал под
именем UNKNOWN.Приложение — это цепочка форм, передающих друг другу управление. Промежуточная информация
хранится в extrd.dat индивидуально для каждого пользователя: уникальность
достигается комбинацией IP-адреса и времени первого старта NULLCG.CGI (см. функции
[ha] и [sf ...] ниже).
25.2. Структура web-формы
Начальная («корневая») форма приложения — AX.RPT: сразу после старта NULLCG.CGI
посылает серверу запрос R AX (выполнить форму AX). Любая форма web-приложения —
одновременно HTML-страница: результат выполнения формы становится содержимым страницы, а
нажатие кнопки на странице передаёт управление обратно NULLCG.CGI, и выполняется предусмотренное
действие (например, переход к BX.RPT через поле nextform).
При генерации страницы NULLCG.CGI вставляет тэг <pre> перед текстом
из *.out-файла. Поэтому форму, содержащую конструкции HTML, надо начинать тэгом
</pre> — он «закрывает» автоматически открытый preформатированный блок.
Тэги <form> и </form> в формах-гибридах
не используются: NULLCG.CGI предваряет страницу одним тэгом <form>
автоматически.
25.3. Комментарий <!--hybride-->
Форма-гибрид — форма ввода со смесью HTML и конструкций языка ФБП. В самом начале такой формы обязателен комментарий:
<!--hybride-->
25.4. Переходы между формами и обмен данными
Переход между формами выполняется нажатием кнопки Send:
<input type=submit name=Send value="название кнопки">
После нажатия Send введённая на странице информация автоматически передаётся в
EXTRD.DAT через [sed...]: запрос предваряется цепочкой директив
e [sed i,v], где i — комбинация имени формы, имени HTML-поля,
IP-адреса пользователя и времени первого старта NULLCG.CGI, а v — значение поля
(введённый текст или имя нажатой кнопки). Таким образом, в следующей форме можно через
extrd.dat прочесть всё, что произошло в предыдущей до нажатия кнопки.
Функции [ha] и [sf ...]
[ha] — IP-адрес пользователя
Выдаёт IP-адрес пользователя. Числа адреса разделены подчёркиваниями: для локального
адреса это строка 127_0_0_1.
[sf ...] — специальная функция
Несколько разновидностей по числовым аргументам:
| Вызов | Результат |
|---|---|
[sf 0,98] | время первого старта NULLCG.CGI в виде цепочки цифр |
[sf 0,9] | длинная строка, новая при каждом вызове — применяется для «борьбы» с кэшами браузеров |
[sf 0,99] | время в формате, типичном для log-файлов Web-серверов |
EXTRD.DAT можно обнулить — оно будет удалено
при рестарте ФБП:Сервера.25.5. Служебное поле document: передача данных между формами
Скрытое поле document (type=hidden) задаёт имя текущей формы — оно становится
частью ключа при сохранении значений полей в extrd.dat. Пример формы-гибрида
AX.RPT:
</pre>
<!--hybride-->
<input type=hidden name="document" value="ax">
Имя: <input name="field1" value="Иван">
Фамилия: <input name="field2" value="Петров">
<input type=submit name=Send value="Отправить">
В поле value допускается запись ax вместо ax.rpt.
Порядок и место размещения поля document в форме значения не имеют. После нажатия
Send NULLCG.CGI посылает серверу список из семи директив в одном *.in файле.
Извлечение значений полей. В first.rpt определяется переменная —
комбинация IP-адреса и времени первого старта NULLCG.CGI:
ah=[ha]+'_'+[sf 0,98]
В следующей за AX.RPT форме значения полей читаются функцией [ged ...]
(см. главу «Экстрапараметры и дисковая база»):
b=[ged ah+'.ax.Send']
b=[ged ah+'.ax.field1']
где ax — имя формы, Send, field1 — имена полей.
Доступны и служебные ключи:
[ged ah+'.ax.N']— сколько всего полей;[ged ah+'.ax.1']— имя первого поля,[ged ah+'.ax.2']— второго и т.д.
25.6. Служебное поле nextform: запуск следующей формы
<input type=hidden name="nextform" value="y">
При нажатии Send на сервер уйдёт директива r y (выполни форму
y). Поле может стоять в любом месте формы. Данные, только что введённые
в предыдущей форме, в новой форме уже доступны через extrd.dat.
25.7. Служебное поле execute: директива серверу
Из любой формы можно отправить директиву ФБП:Серверу — зарегистрировать операцию, ввести
новый субсчёт и т.д. (о директивах см. главу «Язык запросов к
серверу»). Для этого служит скрытое поле execute.
Ключевая особенность: данные, введённые в ax.rpt, попадают в
extrd.dat только после нажатия Send, поэтому извлечь их и подставить в директиву
можно лишь в следующей форме (bx.rpt). Отсюда типовая цепочка из
промежуточных форм: ax.rpt (ввод) → bx.rpt (показать введённые
данные, предложить кнопку регистрации или «откат назад») → передача директивы и переход
к следующей форме.
Наиболее распространённая ошибка — недостаточное количество ^^^
в поле value: директиву собирают в строковой переменной и выводят оператором
printstr, который не добавляет ни пробелов, ни перевода строки:
b='"o ·Касса·расход··номер:·'+K+'"'
printstr '<input type=hidden name=execute value='+b+'>'
Обратите внимание на разделитель · — знак с кодом 250, стандартный разделитель
в директиве o регистрации операции (см. главу
«Язык запросов к серверу»).
Место поля execute в форме не имеет значения. Порядок директив в *.in файле
всегда одинаков: сначала все [sed...], затем то, что предписывает поле
execute, и наконец то, что nextform.
create document LINE0, где
LINE0 — пустой файл.25.8. Тэги <input> и <select>, собственные кнопки
Стандартный ввод-вывод ФБП (?, is, ir,
im, iy, ia) в приложениях NULLCG.CGI
не используется — он заблокирован. Вместо него — HTML-тэги <input>
и <select> (они же служат для многострочного ввода).
Наряду со штатными кнопками Send и Reset допускаются собственные и графические кнопки:
<input type=submit name=Send value="Отправить данные">
<input type=reset name=Reset value="Очистить данные">
Графическая кнопка готовится заранее в виде файла (например, knob.gif) и
подключается стандартными средствами HTML.
25.9. Проблемы Back/Forward и кэша браузеров
Клавиши Back/Forward. Пользователь может зарегистрировать операцию, вернуться кнопкой
Back и нажать кнопки снова — и в журнале накапливаются «ненужные» повторные операции.
Стандартных способов блокировать клавиши браузера нет. В исходных текстах Расчётного Пункта
есть готовые процедуры для решения этой проблемы: serial (блокирование повторов),
distiller и cleaner (чистка таких операций).
Кэш браузера. Включённый cache может помешать активизации CGI: браузер покажет старую
страницу вместо нового запроса к серверу. Приём против этого — функция [sf 0,9],
выдающая новую длинную строку при каждом вызове: вставленная в URL, она делает каждый запрос
уникальным, и кэш не срабатывает.
25.10. Подключение изображений
Web-формы хорошо сочетались с графическими операторами: форма строила диаграмму оператором
makepng и вставляла её в страницу тэгом <img>. Чтобы каждый
пользователь видел свой (а не чужой или устаревший) файл, имя файла получали функцией
[unicfile], а старые файлы удаляли оператором deleteobsolete —
подробно с законченным примером это разобрано в разделе
«Уникальные имена файлов и уборка» главы
«Графика в формах».
G
возвращает пустой ответ, см. главу «Графика в формах»), поэтому
динамические картинки через makepng сейчас не работают; статические изображения
(подготовленные заранее файлы) подключаются в web-формах по-прежнему, средствами HTML.26. Производительность и отладка
Формы на языке ФБП выполняет виртуальная машина внутри ФБП:Сервера. Обычно скорости хватает, но когда данных много — тысячи операций, длинная лента фактов, большая дисковая база — разница между «правильно написанной» и «просто написанной» формой измеряется минутами. Эта глава о трёх вещах: какие рычаги ускорения даёт система, как найти медленное место и какие приёмы ускорения применять в первую очередь.
26.1. Файлы-ключи, влияющие на скорость
Поведением ФБП:Сервера управляют файлы-ключи — пустые (или с произвольным содержимым) файлы в каталоге данных. Важно само присутствие файла. Полный список ключей, поддерживаемых новым сервером, — в главе 8 части I; здесь — два ключа, непосредственно влияющих на скорость форм.
fastfact, fastged) должны
лежать в каталоге данных до старта Сервера — он замечает их только при
запуске.Файл-ключ fastfact — «быстрые факты»
Главный ускоритель форм, работающих с лентой фактов. Сервер строит для ленты
индексирующую структуру, и операторы search, news,
total и др. ускоряются во много раз: вместо сканирования ленты выполняются
«прыжки» по индексу. При индексировании учитываются и прототипы фактов, и значения их
полей. Внешняя логика операторов не меняется — формы переписывать не нужно.
Цена: расход памяти на хранение фактов увеличивается (иногда в несколько раз), а оператор
fact замедляется примерно в 2 раза — то есть пересчёт состояния становится
медленнее. Если в файлах-коэффициентах есть ускоряемые search/news,
выигрыш в формах обычно перекрывает потерю.
Включение: создать файл fastfact в каталоге данных и перезапустить Сервер
(по умолчанию режим выключен).
Файл-ключ fastged — ускорение [ged …]
Ускоряет функцию [ged …] в 10–20 раз за счёт зеркала данных из
extrd.dat в оперативной памяти (размер зеркала в несколько раз меньше размера
файла на диске). Включение — файл fastged в каталоге данных. Имеет смысл при
формах, интенсивно читающих дисковую базу (см. главу
«Экстрапараметры и дисковая база»).
cache с файлом config.txt, показ и очистка — директивой
H). В новом сервере этот механизм не реализован: формы выполняются
при каждом запросе (см. п. 8.7 части I).26.2. Поиск медленных мест: журнал запросов сервера
В старом ФБП:Сервере был встроенный профилер (директива %), показывавший
распределение времени между фазами пересчёта состояния, файлами-коэффициентами и строками
исходного текста форм. В новом сервере профилер не реализован: на директиву
% он отвечает ошибкой E-04, как и на другие неподдержанные
директивы (см. главу 7 части I).
Рабочий инструмент поиска медленных мест — журнал запросов сервера
FbpServer-YYYY-MM-DD.log, который ведётся всегда (см.
п. 3.6 части I). Для каждой обслуженной директивы в журнал
записываются время поступления, пользователь и длительность в миллисекундах.
Просмотрите записи с наибольшей длительностью — и вы увидите, какие формы (директивы
R) и какие пересчёты состояния (ввод операций) дороже всего обходятся вашей
базе; дальше действуйте по списку приёмов из 26.3.
26.3. Типичные приёмы ускорения форм
Прежде чем что-то переписывать, найдите по журналу запросов самые медленные формы — почти всегда время сосредоточено в двух-трёх местах. Дальше действуйте по списку:
- Работаете с лентой фактов — включите «быстрые факты» (файл-ключ
fastfact). Поиск факта в ленте любой длины начинает занимать примерно одно и то же малое время (см. 26.1). - Сужайте поиск по датам. Оператор
rewind facts rangeзадаёт интервал дат дляsearch,select,news,total; лента индексируется по датам, и позиционирование выполняется за малое постоянное время. Измерение из документации: 100 повторений «rewind facts range 1.06,1.06+ подсчёт 10 фактов среди 200010» — примерно 0,2 с вместо ~22 с. Удобны переменныеMF, ML, DF, DL(границы отчётного периода). Подробности — в главе «Лента фактов». - Заменяйте
eraseнаnerase, где это эквивалентно:neraseсначала ищет последний подходящий факт (какnews) и удаляет только его — такая замена сильно ускоряет пересчёт. - Выносите инварианты из циклов. Выражение после
to/downtoвforвычисляется на каждом витке; выгодно заранее присвоить его переменной (но помните: изменение этой переменной в теле цикла влияет на число витков). То же относится к «тяжёлым» функциям внутри тела цикла — если значение не зависит от итерации, вычислите его один раз до цикла. - Интенсивно читаете дисковую базу — включите
fastged(ускорение[ged …]в 10–20 раз). - Если тормозит пересчёт состояния, ищите в журнале запросов записи о вводе операций с большой длительностью: основное время пересчёта обычно уходит на выполнение файлов-коэффициентов — их и надо оптимизировать в первую очередь.
27. Примеры и приёмы
Эта глава — сборник готовых решений, проверенных многолетней практикой пользователей ФБП. Здесь не вводится ничего нового: все приёмы построены на средствах, описанных в предыдущих главах, — но собраны в законченные «рецепты», каждый из которых решает типовую задачу.
Как пользоваться главой. Читайте постановку задачи — если она похожа на вашу, переносите код в свою форму почти без изменений, подставляя свои счета, имена фактов и вопросы. Каждый раздел самостоятелен: можно читать в любом порядке. В конце разделов собраны подводные камни, о которых полезно знать до того, как вы на них наступите.
27.1. Сумма прописью с правильными падежами
Задача. В печатных документах (счетах, накладных) сумму требуется писать словами:
не «1250.37», а «Одна тысяча двести пятьдесят рублей 37 копеек». Функция [wn …]
строит числительное (см. главу «Функции: строки, даты, математика»),
но не склоняет слова «рубль» и «копейка» — это приходится делать самим.
Идея. Падеж определяется последней цифрой числа, поэтому вместо точных сравнений
используются диапазоны in с небольшими погрешностями (так надёжнее при
вещественной арифметике). Подпрограмму помещают в first.rpt (см. главу
«Файлы форм и общие файлы»), чтобы она была доступна всем формам.
Вход — сумма в переменной S, выход — строка в переменной wn.
:wnf
kp=[tr [ce S]+0.5];rb=[tr S];kc='00';ss=[wn rb] коп.руб.коп.симв.руб.прописью
if ~rb ss='Ноль ';endif сумма меньше рубля
if kp in 9.999..99.999 kc=[sn kp,2,0]
elseif kp in 1..9 kc='0'+[sn kp,1,0] копейки символьно
else endif
ru='рублей ';cs=[tr [ce rb/100]+0.5] падежи рубля
if cs in 0.9999..1.0001 ru='рубль '
elseif cs in 1.999..4.0001 ru='рубля '
elseif [ce cs/10]/10 in 0.9999..1.0001 ru='рубль '
elseif [ce cs/10]/10 in 1.9999..4.0001 ru='рубля '
else endif
ko='копеек'
if kp in 0.999..1.001 ko='копейка' падежи копейки
elseif kp in 1.999..4.001 ko='копейки'
elseif [ce kp/10]/10 in 0.999..1.001 ko='копейка'
elseif [ce kp/10]/10 in 1.999..4.001 ko='копейки'
endif
wn=ss+ru +kc +' '+ko сумма прописью
return wnf
Пояснения для новичка. kp — копейки (дробная часть, округлённая до целого),
rb — рубли, kc — копейки двумя знаками («05», «37»). Приём
[ce cs/10]/10 выделяет предпоследнюю цифру: он нужен, чтобы числа 11–14
(«одиннадцать рублей», а не «рубль») попали в общий случай. Строки-комментарии справа
от операторов ФБП просто игнорирует. Вызов из формы:
S = [ea 50]
goto wnf
В кассе: ^^^^^^^^^^^^^^^^^^^^^^^^^wn
first.rpt должны быть компактными и быстрыми:
этот файл участвует в пересчёте баланса, и каждый лишний оператор там сказывается на
скорости всей системы.27.2. Почему нельзя зацикливать формы с вопросами
Задача. Хочется, чтобы форма-ввод спрашивала данные снова и снова, пока пользователь не закончит, — например, при вводе длинной накладной. Так делать нельзя, и вот почему.
Как сервер задаёт вопросы. Встретив в форме вопрос (?x,
[is…], [ir…] и т.п.), на который ещё нет ответа, сервер прерывает
выполнение и возвращает клиенту сообщение вида Q-?:введи x. Клиент спрашивает
пользователя и запускает форму заново уточнённой директивой R Z ·123·
(· — знак с кодом 250). На следующий вопрос директива станет
R Z ·123·qwerty· — и так далее: форма каждый раз выполняется с начала,
а все накопленные ответы передаются в строке директивы.
Подводные камни. Длина строки директивы ограничена 255 символами: у зацикленной
формы цепочка ответов растёт, пока не упрётся в предел, после чего осмысленно задаётся только
последний вопрос. Кроме того, на каждый новый вопрос сервер заново пробегает все накопленные
ответы и выполняет каждый встречный [sed …] — это 10–50 мс и заметная активность
диска на каждый повтор.
Правильные решения. Во-первых, не зацикливайте формы с вопросами — лучше ассоциировать
с формой кнопку и запускать её заново. Во-вторых, концентрируйте все [sed …]
в заключительном блоке формы. Вместо:
:M
?x введи x
[sed ...]
?y введи y
[sed ...]
goto M
пишите:
?x введи x
?y введи y
* здесь все [sed] сконцентрированы в последнем блоке:
[sed...]
[sed...]
R разобраны в главах
«Функции: ввод и оформление» и
«Язык запросов к серверу».27.3. Эквивалент формы-истории: факты ta и [jf]
Задача. В отчёте по проводкам нужен доступ к компонентам самой операции — комментарию, номеру документа (первые шесть символов комментария) — не создавая параллельных собственных фактов.
Идея. Если включено запоминание ta-фактов, простая проводка порождает факт
ta dt,sd,sk,kt,ea,m3, где dt — счёт/субсчёт дебета, sd и
sk — суммы дебета и кредита, kt — субсчёт кредита, ea —
результат проводки в дебетуемом счёте, m3 — штамп операции. Найдя факт, по штампу
достаём саму операцию функцией [jf …]. Схема поиска:
rewind facts range t1,t2
search ta x1,x2,x3,x4,x5,x6
Здесь x1..x6 — либо конкретные значения полей, либо ?un
(поле не важно, но вернуть в переменную un), либо ?? (поле не важно).
При [success] = 1 компоненты операции отыскиваются так:
J = [jf 'o key=' + m3]
Пояснения для новичка. [jf] выполняет директиву J (показ операции,
см. главу «Язык запросов к серверу») и возвращает первую строку
ответа; остальные строки доступны через дисковую базу: [ged 'jf.N'] — число строк,
[ged 'jf.1'], [ged 'jf.2']… — сами строки.
Плюс по сравнению с формами-историями: не нужно фильтровать «пустые» операции
(null) и границы групп { } — в ленте фактов есть только реальные проводки.
А помещение штампа операции в первые 8 байт строки отчёта позволяет клиенту CLWP перейти
по этой строке к соответствующей операции в журнале операций.
extrd.dat хранится кусками примерно по 80 байт,
а сам текст может превысить 256 байт — одной строковой переменной мало: собирайте куски
конкатенацией в массив или в резерв из 3–4 переменных.27.4. «Выделение» операции в журнале: переопределение __SYS000
Задача. Клиент не передаёт в директиве R код операции, на которой стоит
курсор журнала операций, — а форме этот код нужен (например, чтобы построить отчёт «от этой
операции»).
Идея. Системная форма показа проводок __SYS000.RPT вызывается по F6
в журнале операций (Alt+F2) клиента CLWP — то есть именно тогда, когда пользователь «смотрит»
операцию. Подменим её своей копией, которая попутно запомнит код операции в дисковой базе
(приём «нажатие F6 = выделение операции»). Шаг 1 — сохраните следующую форму под именем
__SYS00.RPT:
* Список проводок по операции
? O операция
OO=[strip O]
u=[user];[sed u+'+stamp3',OO]
====== ^^^^^^OO ======
Дебет Кредит Сумма
rewind facts
X=0
:LOOP
search ta ?A, ?S, 0, ?K, ??, O
if [success]=0 goto QUIT;endif
AS=0
if [pa *A]='План' AS=[as *A];endif
if AS = 0
X=X+1
S=[sn S,13,2]
^^^^^^^^A ^^^^^^^^K ^^^^^^^^^^^^S
endif
goto LOOP
:QUIT
if X = 0
Нет ta-фактов для этой операции
endif
и добавьте в users.rpt переопределение системной формы:
__sys000 = ___sys00
Шаг 2 — в целевой форме читайте «выделенную» операцию:
o = [ged [user]+'stamp3']
Пояснения для новичка. Индекс дисковой базы составлен из имени пользователя
([user]), поэтому разные пользователи не мешают друг другу. Поиск
search ta ?A, ?S, 0, ?K, ??, O берёт только те ta-факты, где сумма дебета нулевая
(поле 3 = 0), — это вторая половина пары фактов проводки; проверка через [pa *A]
отсекает предков счетов, оставляя строки самого плана счетов. Таким же приёмом, например,
имитируют режим «Баланс до текущей».
27.5. Многоуровневая оборотная ведомость (факты father и pa)
Задача. Нужна оборотная ведомость по синтетическим счетам произвольной глубины —
«от двух до шести» уровней. Примем соглашение: счёт-предок получается из потомка отрезанием
последнего знака (5 – 50 – 500 – 5000 – 50000 – 500000). Все реальные счета —
счета первого уровня ФБП, а иерархию храним фактами:
fact father 1 '5' '50'
fact father 2 '50' '500'
Идея. Три отдельных приёма: генерация фактов-«родителей» по префиксам имён счетов;
наполнение агрегатных фактов pa по ta-фактам; вывод ведомости «по одному разу
на счёт» через экстрапараметры фиктивного счёта % (см. главу
«Экстрапараметры и дисковая база»). В PROTO.RPT нужны
прототипы father %, %, % и pa %, %, %, %, %, %.
Построение иерархии (форма H.RPT):
* Построение иерархии
array %
p='План'
for i=1 to [as *p]
rewind facts
n=[sa *p,i]
if [length n] = 6
n1=[cp n,1,[length n]-1]
fact father 5, n1, n
n2=[cp n,1,[length n]-2]
news father 4, n2, n1
if [success] = 0
fact father 4, n2, n1
endif
... (аналогично n3, n4, n5)
endif
endfor
$=0
Обратите внимание на пару news + fact: сначала ищем факт, и
только если его нет — создаём. Это защита от дубликатов при повторных запусках.
Наполнение — по каждому ta-факту генерируются pa-факты для всех предков (структура как у ta, первое поле — номер уровня):
:loop
search ta ?x1, ?x2, ?x3, ?x4, ?x5, ?x6
if [success]
news father 5, ?y1, x1; news father 5, ?z4, x4
fact pa 5, y1, x2, x3, z4, x5
news father 4, ?y2, y1; news father 4, ?z5, z4
fact pa 4, y2, x2, x3, z5, x5
... (уровни 3,2,1)
goto loop
endif
Ведомость по уровню N — обход pa-фактов с агрегированием total, а отмечание
уже выведенных счетов — экстрапараметром счёта %:
array %
:loop
search pa N, ?x, ?d, ?k, ?y, ?zz
if [success]
if [get %,x]=0
[set %,x,1]
d=0; k=0; z=0
total pa N, x, ?d, ?k, ??, ?z
b= z - d + k
^^^^^^^^^x ^^^^^^^^^^^^^^b ^^^^^^^^^^^^^^d ^^^^^^^^^^^^^^k ^^^^^^^^^^^^^^z
endif
goto loop
endif
Пояснения для новичка. Приём if [get %,x]=0 … [set %,x,1] — универсальный
способ пройти по списку «по одному разу на каждый ключ»: фиктивный счёт % здесь
играет роль набора отметок в оперативной памяти. Остаток считается как
«сальдо − дебет + кредит» (b = z - d + k). Красивое оформление такой ведомости
даёт средство директив N: (см. главу «Директивы N:»;
учтите, что директива N:NAME: клиентом CLWP игнорируется).
27.6. Партионный учёт: всё о «куске» одним оператором news
Задача. Продукция хранится мерными кусками произвольной длины на носителях с дополнительными признаками (провода в бухтах, лекарства в партиях). По выбору строки из списка нужно извлечь всю информацию о выбранном куске.
Идея. Объявим в PROTO.RPT прототип факта (см. главу
«Лента фактов»):
Марка провода % длина куска % носитель % код операции %
Когда пользователь выбрал строку в форме и стал известен код операции оприходования
O, вся информация о куске извлекается одним оператором:
news Марка провода ?M длина куска ?L носитель ?N код операции O
После успешного поиска M — марка, L — длина куска,
N — носитель. Операции отпуска снабжаются фактами вида
fact Отпущено GAAA-017 покупателю М дата …, и по ним строится накладная.
27.7. Динамические шаблоны поиска: {}-способ и `-способ
Задача. Шаблон поиска в search/news обычно жёстко зашит
в форму: порядок полей фиксирован, неважные поля помечаются ??. А если пользователь
сам хочет выбрать, по какому полю искать?
Идея. В шаблоне допустимы пары {номер_поля, значение}; поля,
не охваченные парами, считаются ??. Запись
search Товар {3,X} {5,Y}
эквивалентна search Товар ??, X, ??, Y. Можно обойтись и вовсе без прототипа:
news {X,Y}, а news {1,'Товар'} {X,Y} — то же, что
news Товар {X,Y}. Главное: номера полей — любые выражения, поэтому шаблон
собирается на лету из ответов пользователя:
? X по какому полю искать
? Y что искать
news Товар {X,Y}
if [success]
нашли: ^^^^^^^^^^^[fact_f 2]
endif
Ещё один приём — `-способ (знак `, код 96): `выражение
в шаблоне вычисляется, и результат подставляется как литерал шаблона. Этот способ подходит
и для total (куда суммировать — есть), тогда как {}-способ с total
работает только для [found].
В паре с динамическими шаблонами удобна функция [fact_f i] — i-е поле последнего
найденного факта ([fact_f 0] — число полей, [fact_f 1] — первое слово
прототипа). Типовой обход факта с неизвестной заранее структурой:
news Товар ??,??,??,??
if [success]
for i=1 to [fact_f 0]
^^^^^^^^^^^^[fact_f i]
endfor
endif
[fact_f] осмыслен только при [success] = 1 —
всегда проверяйте результат поиска перед обращением к полям факта.27.8. Каскадные @-обращения: [CT]
Задача. При вводе операции пользователь сначала выбирает фирму, потом — только из счетов этой фирмы, потом — только из товаров выбранного счёта. Каждый следующий выбор должен зависеть от предыдущего.
Идея. Функция [CT s] возвращает первое слово строки, выбранной
в предыдущем @-обращении к счёту s в текущем листе дерева; если @-обращений
к этому счёту не было — пустую строку. Следующий пункт дерева операции (см. главу
«Виды операций и проводки») строит свой список выбора, исходя из
значения [CT …] предыдущего пункта: фирма → её счета → товары по счёту.
·R имяформы ·ответы·: пользователь выбирает строку из отчёта формы,
а в ответ ветви попадает первое слово этой строки.27.9. Сортированный обход субсчетов: # счёт sort выражение
Задача. Цикл # счёт … # обходит субсчета в порядке списка счетов
(см. главу «Операторы»). А если в отчёте их нужно упорядочить,
скажем, по наименованию или по остатку?
Идея. Ключевое слово sort с выражением задаёт порядок обхода —
субсчета перебираются по возрастанию значения выражения:
# 70 sort [n2 #]
n=[na #]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^n
#
Здесь субсчета счёта 70 печатаются в алфавитном порядке наименований. Обход по остаткам —
sort [ea #]. Выражение вычисляется для каждого субсчёта, и в нём доступен
текущий субсчёт #.
27.10. Подпрограммы с параметрами и функции пользователя
Задача. Код формы разрастается: одни и те же фрагменты повторяются, переменные подпрограмм портят переменные вызывающей формы. Хочется настоящих функций — с параметрами и возвращаемым значением.
Идея (см. главу «Операторы»). Три средства:
local переменная {, переменная}— локальные переменные подпрограммы, уничтожаются приreturnи не затрагивают одноимённые переменные вызывающей программы:
A=5
call P
^^A
stop
:P
local A,B
A=1; B=2
^^A ^^B
return
Эта форма печатает 1 2 (внутри подпрограммы), затем 5 — внешняя
переменная A сохранилась.
- Параметры подпрограмм передаются «по значению»: вызов
call SUM(1,2), метка с формальными параметрами:SUM(a,b):
call SUM(1,2)
stop
:SUM(a,b)
local c; c = a+b
^^^^^c
return
- Функция пользователя возвращает значение оператором
return (выражение), а вызывается как[:метка]или[:метка параметры]. Рекурсия допустима:
x=[:max 3,5]
stop
:max(x,y)
if x > y return (x); else return (y); endif
x=[:factorial 5]
stop
:factorial(n)
if n=0 return (1); else return (n*[:factorial n-1]); endif
Вторая форма вычислит 120. Общие для всех форм подпрограммы и функции
выносят в LIBRARY.RPT и в файлы *.lib рабочего каталога
(их можно защитить шифрованием Enigma).
27.11. Рабочие приёмы с массивами
Задача. Массивы (см. главу «Массивы») — главный контейнер для списков внутри формы. Несколько приёмов экономят десятки строк кода.
Групповое присваивание. Начальные значения заносятся одним оператором:
[m 1,'Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
Текущая длина. [m 0] возвращает число элементов массива — удобно
для обхода без счётчиков-флагов. Индексы допустимы от 1 до 1000000 и округляются до
ближайшего целого, так что [m i] и [m [tr i]] — один и тот же
элемент.
Сортировка. sort array a сортирует массив «на месте». Вариант
sort array a,b массив A не меняет, а в B записывает новые номера: если
[a 1] после сортировки оказался пятым, то [b 1] = 5. Это позволяет
отсортировать один массив, а переупорядочить по тем же номерам сколько угодно других —
например, отсортировать суммы и тем же порядком вывести наименования.
sort array a,b
for i=1 to [a 0]
^^^^^^^^^^[n [b i]] ^^^^^^^^^^^^^^[a [b i]]
endfor
Очистка. array a,b,c обнуляет массивы с освобождением памяти;
при старте формы это выполняется автоматически для всех 26 массивов.
m и
[m 1] не связаны. После завершения формы сохранность массивов не гарантируется.
В разделах PROLOG и EVERYDEBET форм-историй массивы запрещены (в EPILOG — можно).27.12. Вывод в одну строку: знак \ и операторы через ;
Задача. Форма должна печатать заранее неизвестное число полей подряд — например, список значений через пробел — а каждая форматная строка формы обычно завершается переводом строки.
Идея. Знак \ в конце выводимой строки подавляет перевод строки —
следующая порция вывода продолжит ту же строку отчёта:
for i=1 to 10
^^i \
endfor
получится 1 2 3 4 5 6 7 8 9 10. Пустая строка формы, наоборот, просто переводит
строку — ею «закрывают» накопленный вывод после цикла.
Попутно полезное сокращение: несколько операторов в одной строке записываются через
; (A=1; B=2), а в старом условном операторе ! после
условия можно дать сразу цепочку операторов:
! a > b x=1; y=2; z=3
Для читаемости вложенных конструкций перед операторами допустимы пробелы — делайте отступы, как в примерах этого руководства.
27.13. Картинки из формы: makepng, [unicfile] и deleteobsolete
Задача. Отчёт должен содержать диаграмму — столбики, линии, «торт», — а для Web-отчёта (см. главу «Web-приложения») — картинку, которую браузер сможет показать.
Идея (см. главу «Графика»). Рисунок строится в массиве:
точка (x,y) — элемент (y-1)*w+x, координаты от 1. Заполненный массив сохраняется
оператором makepng в PNG-файл. Для Web-страниц важны два помощника:
[unicfile] даёт уникальное имя файла (чтобы параллельные запросы и кэши браузеров
не мешали друг другу), а deleteobsolete маска, n удаляет файлы по маске старше
n секунд — иначе каталог картинок растёт бесконечно. Типовая форма:
u=[unicfile]; e='.png'
f0='c:\webshare\wwwroot\dynamic\' + u + e
f1='c:\webshare\wwwroot\dynamic\*' + e
f2='http://localhost/dynamic/' + u + e
deleteobsolete f1,1000
... заполняем массив a ...
makepng a,100,100,f0
printstr '<img src=' + f2 + '>'
Пояснения для новичка. Рисуют операторы drawpixel (точка),
drawline (линия), drawbar (закрашенный прямоугольник),
drawtxt (текст), drawarc (дуга/сектор), fillarea
(заливка области). Цвет — строка из четырёх знаков Red/Green/Blue/Alpha, например красный:
[ch 255]+[ch 0]+[ch 0]. Маска для deleteobsolete допускает только
расширения .PNG/.GIF/.HTM — .* не допускается.
makepng, сохраняющие
рисунок в файл, при этом работают.pie — объёмный «торт», разрезанный на куски (в массиве V — проценты, в C — цвета,
в D — вынос кусков от центра), и draw3dplot — трёхмерная поверхность функции
(массив значений + вектор на глаз наблюдателя; внутри используются lsolve и
sort array для правильного закрытия невидимых частей).27.14. Линейная алгебра: [det], lsolve, invertm
Задача. В расчётных формах встречаются системы линейных уравнений, определители, обратные матрицы — от плановых моделей до межфилиальных перекрёстных расчётов.
Идея. Матрица n×n хранится в массиве построчно:
элемент (i,j) — это [a (i-1)*n+j]. Дальше работают три средства:
| Средство | Что делает |
|---|---|
[det a,n] | Определитель матрицы n×n. |
lsolve a,b,y,n | Решение системы: a — матрица, b — правая часть, y — массив решения. |
invertm a,c,n | Обращение матрицы a в массив c (a и c могут совпадать). |
Пример — решение системы 2×2 (2x + y = 5, x + 3y = 5):
[a 1, 2, 1, 1, 3]
[b 1, 5, 5]
lsolve a,b,y,2
if [y 1]='fail'
Решения нет
else
x = ^^^^^^[y 1] y = ^^^^^^[y 2]
endif
Пояснения для новичка. Если в матрице или правой части встретились строковые
значения, [y 1] вернёт 'string'; при неуспехе (вырожденная матрица)
— 'fail'. Всегда проверяйте результат, прежде чем печатать числа. Математические
функции того же поколения — [abs], [sqrt], [fsin],
[fcos], [arctan], [rad] (градусы в радианы),
[dgr] (радианы в градусы) — описаны в главе
«Функции: строки, даты, математика».
28. Приложения: ограничения языка и сообщения об ошибках
Эта глава — справочное завершение части II. Здесь собраны количественные ограничения языка и файлов данных, а также сообщения об ошибках компилятора и интерпретатора с пояснениями «что делать».
28.1. Количественные ограничения
База знаний, с которой работает сервер, включает: счета и начальные условия
(acnt.a3p), дерево видов операций (cas.rul), отчётные формы и
первичные документы (*.rpt), журналы операций (*.f3p), ленту фактов
и экстрапараметры (facts.b, extra.b), дисковую базу
(extrd.dat). Ограничения по ним сведены в таблицы.
Емкость основных файлов:
| Файл / объект | Ограничение |
|---|---|
*.f3p — журнал операций за месяц | явного ограничения на число операций нет; годовой предел вытекает из формата уникального кода операции — 17 576 000 записей на двенадцать файлов года (см. главу 2 части I) |
acnt.a3p — план счетов и субсчетов | явно заданных ограничений нет; упор в объём оперативной памяти сервера (новый ФБП:Сервер — 64-разрядное приложение, исторические барьеры памяти сняты; см. главу 2 части I) |
cas.rul — дерево видов операций | до 15 ветвей первого уровня, у каждой — до 15 ветвей второго уровня и т.д.; вложенность до 12 уровней (в расчёт берутся и ветви дерева, и @-обращения в описании проводок); до 15 проводок в листе дерева; размер дерева — до 16000 строк |
extra.b, facts.b — экстрапараметры и лента фактов | ограничений нет: лента и индексы фактов, а также все экстрапараметры должны просто поместиться в ОЗУ сервера |
extrd.dat — дисковая база | зависит только от свободного места на диске |
*.rpt — формы, первичные документы, файлы-коэффициенты | исторически — не более 500 файлов |
Пределы длин строк и имён (вытекают из структур файлов cas.rul,
*.f3p, acnt.a3p):
| Элемент | Предел |
|---|---|
| Комментарий операции | 56 символов, включая добавляемый сервером штамп |
| Глубина вида операции | 12 уровней, каждый уровень — строка до 25 символов |
| Обозначение счёта | 10 символов |
| Наименование счёта | 100 символов; новый сервер хранит до 255 (см. главу 2 части I) |
| Параметров у счёта | до 9; наименование параметра — до 14 символов |
| Текст ветви или листа дерева | 50 символов |
| Текст баллона (подсказки к ветви) | 200 символов |
| Потомков у ветви дерева | 15 |
| Метка в форме | слово до 10 символов |
| Индекс массива | 1..1000000, округляется до ближайшего целого; массивов 26 (по числу латинских букв) |
| Точность чисел | до 15 разрядов без потери точности; сумма операции хранится как 8-байтовый double |
*.f3p поле PosInDay принимает
значения -1, 0, +1 — это позиция операции внутри одного дня. Поле DFN
(индекс первичного документа *.txa) сервером не используется.28.2. Сообщения синтаксического анализатора и компилятора
Ошибки в формах и дереве видов операций обнаруживаются при компиляции. В редакторе форм
клиента CLWP компиляция выполняется клавишей F6: изменённый текст записывается
в файл, серверу уходит запрос W FORM, и ответ с сообщениями об ошибках
открывается отчётной формой. Компилятор дерева обнаруживает большинство формальных ошибок
«на первой секунде» попытки построить баланс.
| Сообщение | Причина и что делать |
|---|---|
| ПУСТАЯ СТРОКА В ОПИСАНИИ ПРОВОДКИ | В листе дерева видов операций и проводок есть пустая строка — уберите её. |
| НЕПРАВИЛЬНО ОПИСАНА ПРОВОДКА | Неправильное описание проводки в листе дерева — проверьте синтаксис строки (дебетуемый, кредитуемый, коэффициент). |
| НЕПРАВИЛЬНЫЙ КОЭФФИЦИЕНТ В ОПИСАНИИ ПРОВОДКИ | Числовое выражение коэффициента задано неверно — проверьте формулу. |
| @-ОБРАЩЕНИЕ К НЕСУЩЕСТВУЮЩЕМУ СЧЕТУ | @-обращение ссылается на счёт, не описанный в списке счетов. Введите новый счёт и его субсчета. |
| @-ОБРАЩЕНИЕ К СЧЕТУ БЕЗ СУБСЧЕТОВ | @-обращение должно ссылаться на счёт, имеющий субсчета: либо субсчета ещё не созданы, либо упомянут не тот счёт. |
| НЕИЗВЕСТНЫЙ (ИЛИ СОСТОЯЩИЙ ИЗ СУБСЧЕТОВ) ДЕБЕТУЕМЫЙ СЧЕТ / КРЕДИТУЕМЫЙ СЧЕТ | Счёт не описан в списке счетов либо состоит из субсчетов, а @-обращение не применяется. |
| НЕТ ОПИСАНИЙ ПРОВОДОК ДЛЯ ЭТОЙ ОПЕРАЦИИ | Для данного вида операции нет листа с описаниями проводок — добавьте лист в дерево. |
| НЕПРАВИЛЬНО УКАЗАН ВИД ОПЕРАЦИИ | Ветвь дерева изменилась после того, как были указаны виды операций; отредактируйте операцию и заново укажите вид (или удалите и введите снова). |
| В ОПИСАНИИ ПРОВОДКИ НЕТ ССЫЛКИ НА ФАЙЛ-КОЭФФИЦИЕНТ | Возникает при редактировании дерева, если текущее описание проводки не содержит коэффициента или содержит числовой коэффициент вместо имени файла. |
28.3. Сообщения времени выполнения
При ошибке во время выполнения формы сервер прекращает её выполнение и передаёт сообщение
об ошибке клиенту. Оператор error в файле-коэффициенте прекращает его
выполнение и выводит остаток строки как сообщение об ошибке.
Часть «ошибок» языка — это не прерывания, а специальные строки-значения, которые функции возвращают вместо результата. Их нужно проверять в форме самостоятельно:
| Значение | Когда возникает |
|---|---|
'NO RU TXT' | [ru …]: внешняя программа не создала файл RU.TXT (сама функция возвращает первую строку этого файла). |
'NO ELEM' | search: частей в образце больше, чем в найденном факте — избыточным переменным присваивается эта строка. |
ОШИБКА TOTAL - сложение строки с числом | total: при накоплении суммы встретилось сложение строки с числом. |
'string' / 'fail' | lsolve, invertm: в матрице встретилось строковое значение / решить систему или обратить матрицу не удалось (результат — в первом элементе выходного массива). |
-1 / '0' | [fe s] возвращает -1, если файл не существует; [crc s] возвращает строку '0' для отсутствующего файла. |
Отдельное сообщение — Вызов типа [..,будущее]. Оно возникает, когда
файл-коэффициент вызывает функции остатков/оборотов с явным интервалом, уходящим в будущее
относительно текущей проводки:
* файл-коэффициент — так делать нельзя
a=[ok 70,mf,ml]
$=a
* результат: сообщение "Вызов типа [OK ,.., будущее]"
Решение — использовать вызовы без явных интервалов: [ok xx],
[ak xx], [mk xx] и их комбинации.
Часть III. Переход на новые программы
Завершающая часть адресована тем, кто переносит действующую настройку с прежних
программ (сервер fnt*, клиент CLW32) на новые ФБП:Сервер V01 и
ФБП:Клиент CLWP:
- глава 29 — полный свод отличий: что не перенесено, что появилось, что переехало на другие клавиши, чек-лист миграции;
- глава 30 — приложения: CGI-доступ, частые ответы-ошибки сервера, глоссарий, состав документации.
29. Что изменилось: переход со старого сервера и клиента
Эта глава — сводная шпаргалка для тех, кто переходит с прежних программ
(сервер fnt* версий 4.4x и клиент CLW32) на новые ФБП:Сервер V01 и
ФБП:Клиент CLWP. Базы знаний и протокол обмена не изменились — миграция сводится
к замене программ и учёту перечисленных ниже отличий.
29.1. Сервер: что не перенесено
| Возможность старого сервера | В новом сервере |
|---|---|
Директива C (компиляция форм из клиента) |
не реализована (ответ E-04); используйте W FORM |
Директива H и дисковый кэш ответов форм
(cache\config.txt) | не реализованы; формы выполняются при каждом запросе |
Директивы B (Break) и % (профилер) |
не реализованы (E-04) |
Директива G (PNG-графика из массивов) |
пустой ответ — графика заглушена (см. п. 9.11) |
Ключевые слова fastrun, noprofile,
logmode, notail, ukraine,
ta1 | игнорируются (см. п. 8.6) |
| Режим DUAL (контексты D и D′, двойной расход памяти) | не перенесён; при сбое пересчёта обслуживание продолжается на прежнем удачном балансе |
Параметры командной строки -C/-U/-F/-X, COLOR/MONO,
OLD/DUAL, автоподбор контекстов | отсутствуют — память и индексы управляются автоматически |
| Дневная гранулярность пересчёта | инвалидируется месяц целиком; зато ввод операции в конец текущего месяца идёт по быстрому пути вообще без пересчёта |
Новогодний Адаптер (версии 3.NY/4.NY, подкаталог
_ny_) | не перенесён (см. п. 3.11) |
Файлы FORMS.ERR/FORMS.EMG, журнал
log по ключу logmode | не создаются; взамен —
постоянный журнал FbpServer-YYYY-MM-DD.log |
29.2. Сервер: что нового
- Служба Windows и Менеджер баз — установка, наблюдение, журналы, автоархивирование без остановки сервера (п. 3.5).
- Лицензирование файлом
FbpServer.licс привязкой к машине; демо-режим 30 минут; число имён пользователей лицензией больше не ограничено (п. 3.3). W FORM— перекомпиляция изменённых форм без перезагрузки базы (п. 3.8).- Heartbeat
_STATUS_.FBP— машиночитаемое состояние сервера для менеджера и внешних сторожей (п. 3.6). - Журнал запросов с временем поступления, длительностью, ошибкой и кодом новой операции; журналируются и транспортные сбои.
- Карантин запросов
*.BAD, защита от двойного запуска_SRVNEW_.LCK, аварийный дамп плана счетовACNT.EMG(п. 3.7). - V01.02: гибернация базы (сон без запросов + пробуждение по запросу),
полный образ базы
_BASEIMG_.FBPдля старта за секунды, автоматическая смена суток (п. 3.9). - V01.02: директива
G— компиляция и выполнение формы из тела запроса без перезагрузки сервера (п. 7.20; PNG-графика по-прежнему не перенесена). - Ответ
V— собственная строка версии (не побайтовая копия прежней); ответIперечисляет только формуALL; в ответеSблоки распределения памяти нулевые.
29.3. Клиент: что появилось в CLWP
- Управляющие строки
N:SHIFTF1:…N:SHIFTF9:и одноразовый автозапускN:AUTO:; цепочки запросов на одной клавише выполняются целиком (глава 23). - Экспорт отчётов в Excel (
Ctrl+E) с сохранением колонок и чисел. - Встроенная панель поиска-выборки в журнале и формах (две строки, И/ИЛИ, учёт
регистра), отбор по значению ячейки (
Ctrl+Enter), копирование ячейки и ссылки на форму. - Темы оформления (7 градаций), масштабирование форм
Ctrl+колесо, закреплённая шапка формы, подсказка формы строкой с■. - Прерываемый долгий запрос к серверу (плашка «Прервать» / «Ждать ещё») — клиент больше не «замирает».
- Рабочий каталог базы: один
CLWP.EXEобслуживает несколько баз через ярлыки; все настройки — в одномCLWP.настройки.xml. - Поля ввода с историей (
F4) и календарём; избранные и недавние команды; поиск командыCtrl+Q; немодальный калькулятор (Ctrl+F3); чат с нейросетью GigaChat. - Регистрация программы (без ключа клиент работает 20 минут).
29.4. Клиент: что переехало на другие клавиши
| Действие | CLW32 | CLWP |
|---|---|---|
| Перенести форму в редактор | F4 | Ctrl+F4
(окно формы не закрывается) |
| Открыть файл в редакторе | F3 | Ctrl+F7
(из любого окна клиента; каждый файл — в своём окне) |
| Шаблоны (прототипы) в редакторе | F4 | меню
«Редактор → Шаблоны»; F4 и F5 теперь ставят символы
· и ■ |
| Калькулятор | F3 | Ctrl+F3 |
| Запись отчёта в файл | F2 | Alt+F8 |
| Печать | F5 | Alt+F5 (сразу),
Ctrl+Alt+F5 (с диалогом) |
| Главное меню | F10 | обычное меню Windows |
Клавиши F3 и F4 в окне отчётной формы освобождены
намеренно — под кнопки форм N:F3: и N:F4:.
29.5. Клиент: что не перенесено
- печать на PRN/LPT и перекодировка OEM→Windows при печати (печать — только средствами Windows, равноширинными шрифтами);
- опция «Период обновления» — заменена автообновлением по
UPTI; - «Параметры окон» — размеры и положения окон запоминаются автоматически;
- балунная подсказка;
- подпись кнопки запроса
N:NAME:— экранной кнопки больше нет, строка игнорируется.
29.6. Короткий чек-лист миграции
- Скопируйте каталог данных боевой базы (без каталога обмена) на новое место.
- Удалите из каталога данных файлы-ключи, не поддержанные новым сервером
(
fastrun,noprofile,logmode,notail,ukraine,ta1) — они просто игнорируются, но чистота не помешает; подкаталогcacheне используется. - Установите ФБП:Сервер и лицензию, зарегистрируйте базу в Менеджере, установите службу (глава 3).
- Проверьте формы, использующие директиву
G(графика), и обращения кC/H/%в автоматике обмена. - Установите клиентам CLWP, создайте ярлыки с рабочими каталогами баз (глава 4).
- Проверьте формы со строками
N:SHIFTFn:, если база должна работать и со старыми клиентами (п. 23.1).
30. Приложения
30.1. Доступ из браузера: NULLCG.CGI (историческая справка)
Скрипт NULLCG.CGI позволяет работать с ФБП:Сервером из браузера:
он копируется в каталог CGI-скриптов веб-сервера (например
C:\WEBSHARE\WWWROOT\CGI-BIN) и общается с сервером тем же файловым
протоколом через каталог обмена. NULLCG.CGI не выводит никакой собственной
информации (кроме сообщений об ошибках) — в браузере отображаются только ваши
формы. Web-формы строятся обычным языком ФБП с выводом HTML-разметки; служебные
поля document, nextform, execute управляют
переходами и отправкой директив.
30.2. Частые ответы-ошибки сервера
Строка ответа, начинающаяся с E-, — отказ; с Q- —
запрос уточнения (сервер ждёт ответ на вопрос формы или операции). Наиболее
частые коды:
| Код | Типичная причина |
|---|---|
E-01 | не указан аргумент директивы |
E-03 | неверная пара имя/пароль; нет права на действие (например, ввод операции в запрещённый месяц); обрыв обслуживания запроса |
E-04 | неправильная команда — в том числе директивы,
не реализованные в новом сервере (C, H,
B, %, X) |
E-06 | неправильно указан вид операции |
E-12/E-13 | обозначение счёта пустое или длиннее 10 символов |
E-26 | форма содержала ошибки и не была загружена
(проверьте компиляцию, W FORM) |
E-27 | ошибка выполнения формы (в тексте — место и причина) |
E-93 | канал обмена монополизирован другим
пользователем (M ON) |
E-94 | сервер в состоянии ожидания (W ON) —
обслуживаются только директивы W |
Полный перечень сообщений интерпретатора языка форм — в приложениях руководства fbp-lang-manual.html.
30.3. Глоссарий
| Термин | Значение |
|---|---|
| База знаний | каталог данных сервера: план счетов, журналы операций, дерево видов операций, формы |
| Вид операции | путь по дереву cas.rul (до 12 уровней);
листья содержат скрытые от клиента проводки |
| Операция | запись в журнале *.f3p: сумма, день,
комментарий со штампом, вид |
| Проводка | предписание изменить дебет/кредит счетов при регистрации операции |
| Штамп | добавляемый сервером хвост комментария:
·пользователь·время·уникальный код |
| Уникальный код | код вида MLLL-000 (буква месяца, три
буквы, три цифры), уникален в году |
| Форма | программа *.rpt на языке ФБП; выполняется
сервером |
| Факт | накопленные сервером данные для быстрых выборок в формах
(search) |
| Баллон | текст подсказки к ветви дерева; часто содержит
·R FORMA — вызов формы |
| Пожелания | невидимые 32 байта опций клиента, дописываемые к каждому запросу (п. 6.3) |
| Каталог обмена | общий каталог для файлов
*.REQ/.IN/.ANS/.OUT и UPTI |
| UPTI | файл признаков изменения данных для автообновления отчётов (п. 6.4) |
| Heartbeat | файл _STATUS_.FBP — машиночитаемое состояние
нового сервера (п. 3.6) |
30.4. Состав документации платформы
- Это руководство (
fbp-net-manual.html) — сетевая версия: архитектура, сервер, клиент, права, протокол, директивы (часть I), полное описание языка программирования ФБП (часть II), переход со старых программ (часть III). - Встроенная справка клиента (
CLWP_help.htmlрядом сCLWP.EXE, клавишаF1) — краткое руководство по интерфейсу клиента. - Подсказки сервера — файлы
HELP\*.HLPв каталоге данных, вызываются директивой?.
Исторические оригиналы: «Финансы без проблем. Руководство пользователя. Сетевая версия» © Хакерс Дизайн, 1995–2012 (hdru.com) — положено в основу части I настоящего издания, а также «Руководство пользователя. Однопользовательские версии» — источник глав о языке (часть II), приведённых здесь к сетевой редакции.