Шаблон Vedom предназначен для реализации Ведомости документов. Этот extentionl-шаблон содержит код поддержки органов управления окном Ведомости Документов. Сами controls помещаются в окно Ведомости Документов при помощи соответствующих control-шаблонов. Ведомость документов обычно содержит следующие controls:

Документы хранятся в специальном файле (TTN1), который имеет примерно следующую структуру:
TTN1
FILE,DRIVER('BTRIEVE')CREATE,OEM,PRE(TT1)
Number_key KEY(+TT1:Firm,+TT1:TypeOp,+TT1:Number),OPT,NOCASE,PRIMARY
Date_key KEY(+TT1:Firm,+TT1:TypeOp,+TT1:Date),DUP,NOCASE
Comp_key KEY(+TT1:Firm,+TT1:CCode,+TT1:Date),DUP,NOCASE
Note MEMO(255)
RECORD RECORD
Firm USHORT
! Код Фирмы
TypeOp USHORT
! Тип операции (документа)
Number ULONG
! Номер документа
Date LONG
! Дата документа
Store USHORT
! Код Участка учета
CCode USHORT
! Код Контрагента
SCode USHORT
! Код оператора, оформившего
документ
Metka STRING(1)
! Метка "Документ утвержден"
. . .
!
Прочие поля
END
END
Щаблон использует следующие глобальные переменные:
dll:BDate Long,TREAD
! Дата начала периодa
dll:EDate Long,TREAD ! Дата конца
периода
TT1_Queue Queue !
Для временного хранения исходной записи
glo:BVObozn String(4) ! Обозначение
базовой валюты
glo:IniFileName String(80) ! Имя INI-файла
Функция PutDocLog(...) используется для записи информации об изменении документа в Log-файл, смотрите Журналы операций.
#!===================================================================
#EXTENSION (Vedomost, 'Код Ведомости Документов'), PROCEDURE
#!===================================================================
#!
#! ----- Локальные переменные ----
#LOCALDATA
LOC:LastNumber LONG ! Номер последнего
открываемого документа
LOC:Firm USHORT !
Фирма
LOC:TypeOP USHORT ! Тип
Документа
loc:TotSumm REAL !
Сумма в базовой валюте
loc:TotRSumm REAL !
Сумма в рублях
#ENDLOCALDATA
#!
#DISPLAY ('')
#DISPLAY ('1. Сохраняет и восстанавливает формат Browse
и')
#DISPLAY (' номер последнего открываемого документа.')
#DISPLAY ('2. Поддерживает горячие клавиши изменения
метки,')
#DISPLAY (' утверждения, печати и т.п.')
#DISPLAY ('3. Устанавливает дату и номер начала показа
для Browse')
#DISPLAY ('5. Управляет доступом к кнопкам')
#DISPLAY ('6. Записывает в log-файл произведенные
операции')
#DISPLAY ('')
#PROMPT ('Число сортировок:', SPIN (@n1, 1, 40, 1)), %NumTabs, DEFAULT(3)
#DISPLAY ('')
#PROMPT ('Документ с товарами:', CHECK), %TowDocFlag, DEFAULT(%TRUE)
#DISPLAY ('')
#!
#! ---- Инициализация -----
#AT (%ProcedureInitialize)
dll:BDate = date( 1, 1, year(today()) ) ! Дата начала
показываемого периода
dll:EDate = date(12,31, year(today()) ) ! Дата конца
показываемого периода
#ENDAT
#!
#AT (%WindowEventHandling, 'OpenWindow')
?Button_RU{prop:Key} = RUtwKey ! -
Разутверждить
?Button_UTW{prop:Key} = UtwKey ! -
Утверждить
?Button_SummDoc{prop:Key} = SummKey ! - Суммировать
?Vedom{prop:Key} = VedomKey !
- Печатать ведомость
?Print{prop:Key} = PrinterKey ! -
Печатать документ
?Help{prop:Key} = HelpKey
! - Помощь
#ENDAT
#!
#! ---- Подготовка обработки окна -----
#AT (%BeforeAccept)
!-- Инициализировать ключевые поля
tt1:Firm = loc:Firm
tt1:TypeOp = loc:TypeOp
!-- Восстановить формат Browse из INI-файла --
?Browse:1{prop:FORMAT} = getIni( '%Procedure', 'BrowseFormat',
?Browse:1{prop:FORMAT}, glo:IniFileName )
#ENDAT
#!
#! ---- Подготовка горячих клавиш ----
#AT (%PrepareAlerts)
alert( MetkKey ) ! Изменение метки
документа
#ENDAT
#!
#! ---- Обработка горячих клавиш -----
#AT (%WindowEventHandling, 'AlertKey')
if keyCode() = MetkKey ! Изменить метку
документа
do SyncWindow
if tt1:Metka <> ''
tt1:Metka = ''
else
tt1:Metka = '+'
.
put( TTN1 )
ForceRefresh = True
do RefreshWindow
.
#ENDAT
#!
#! ----- После открытия окна -----
#AT (%WindowEventHandling, 'OpenWindow')
! Найти последний открываемый документ
tt1:Number = getIni( '%Procedure', 'OldNumber', loc:LastNumber-1, glo:IniFileName )
UPDATE(?TT1:Number)
if TT1:Number
BRW1::LocateMode = LocateOnValue
DO BRW1::LocateRecord
BRW1::Sort%NumTabs:LocatorValue = TT1:Number
BRW1::Sort%NumTabs:LocatorLength = LEN(CLIP(TT1:Number))
SELECT(?Browse:1)
DO BRW1::PostNewSelection
.
#ENDAT
#!
#! ----- Перед удалением -----
#AT (%BrowseBeforeDelete)
! Выдать предупреждение и запретить удаление
if tt1:Metka<>'' ! Если
документ утвержден
Message('Нельзя удалить утвержденный
документ',' Внимание',icon:Exclamation)
exit
#IF (%TowDocFlag = %TRUE)
else ! Проверить, нет ли утвержденных товаров ?
clear( tt2:Record )
tt2:Firm = tt1:Firm
tt2:TypeOp = tt1:TypeOp
tt2:Number = tt1:Number
set( tt2:Number_key, tt2:Number_key )
loop
next( TTN2 )
if errorcode() or tt2:Firm<>tt1:Firm or
tt2:TypeOp<>tt1:TypeOp or tt2:Number<>tt1:Number
break
.
if tt2:Metka<>''
Message('Нельзя удалить
документ с утвержденными товарами!','
Внимание',icon:Exclamation)
exit
.
. ! end loop TTN2
#ENDIF
.
#ENDAT
#!
#! ----- Перед изменением -----
#AT (%BrowseBeforeChange)
! Сравнить запись с TT1_Queue
free( TT1_Queue )
t1q:Record = tt1:Record
add( TT1_Queue )
#ENDAT
#!
#! ----- После изменения -----
#AT (%BrowseAfterChange)
! Сравнить запись с исходной, хранящейся в
TT1_Queue
if GlobalResponse<>RequestCancelled and tt1:Record<>t1q:Record
if tt1:Firm<>t1q:Firm
PutDocLog( 'Изм. Фирмы', 'Было: ' &
t1q:Firm & ' Стало: ' & tt1:Firm, tt1:Firm, tt1:TypeOp, tt1:Number )
.
if tt1:TypeOp<>t1q:TypeOp
PutDocLog( 'Изм. Типа Документа',
'Было: ' & t1q:TypeOp & ' Стало: ' & tt1:TypeOp, tt1:Firm,
tt1:TypeOp, tt1:Number)
.
if tt1:Number<>t1q:Number
PutDocLog( 'Изм. Номера Документа',
'Было: ' & t1q:Number & ' Стало: ' & tt1:Number, tt1:Firm,
tt1:TypeOp, tt1:Number)
.
if tt1:CCode<>t1q:CCode
PutDocLog( 'Изм. Организации', 'Было: '
& t1q:CCode & ' Стало: ' & tt1:CCode, tt1:Firm, tt1:TypeOp, tt1:Number)
.
if tt1:Store<>t1q:Store
PutDocLog( 'Изм. Участка', 'Было: ' &
t1q:Store & ' Стало: ' & tt1:Store, tt1:Firm, tt1:TypeOp, tt1:Number)
.
if tt1:Date<>t1q:Date
PutDocLog( 'Изм. Даты', 'Было: ' &
format(t1q:Date,@d5.) & ' Стало: ' & format(tt1:Date,@d5.), tt1:Firm,
tt1:TypeOp, tt1:Number)
.
if tt1:Kurs<>t1q:Kurs
PutDocLog( 'Изм. Курса', 'Было: ' &
t1q:Kurs & ' Стало: ' & tt1:Kurs, tt1:Firm, tt1:TypeOp, tt1:Number)
.
if tt1:SCode<>t1q:SCode
PutDocLog( 'Изм. Оператора', 'Было: ' &
t1q:SCode & ' Стало: ' & tt1:SCode, tt1:Firm, tt1:TypeOp, tt1:Number)
.
if tt1:Firm=t1q:Firm and tt1:TypeOp=t1q:TypeOp and
tt1:Number=t1q:Number and tt1:CCode=t1q:CCode and |
tt1:Store=t1q:Store and tt1:Date=t1q:Date and
tt1:Kurs=t1q:Kurs and tt1:SCode=t1q:SCode
PutDocLOG( 'Изменение', 'Суммы: ' &
tt1:ValSumm &' '& tt1:Valut &', '& tt1:SSumm &', '&
clip(format(tt1:Summ,@n-14.2)) &' '& glo:BVObozn, tt1:Firm, tt1:TypeOp,
tt1:Number)
.
.
free( TT1_Queue )
#ENDAT
#!
#! ----- После добавления -----
#AT (%BrowseAfterInsert)
if GlobalResponse<>RequestCancelled
PutDocLOG( 'Создание документа', 'Суммы: ' &
tt1:ValSumm &' '& tt1:Valut &' '& tt1:SSumm &' '&
glo:BVObozn, tt1:Firm, tt1:TypeOp, tt1:Number)
.
#ENDAT
#!
#! ----- После удаления -----
#AT (%BrowseAfterDelete)
if GlobalResponse<>RequestCancelled
PutDocLOG( 'УДАЛЕНИЕ документа', 'Суммы: ' &
tt1:ValSumm &' '& tt1:Valut &' '& tt1:Summ &' '& glo:BVObozn,
tt1:Firm, tt1:TypeOp, tt1:Number)
.
#ENDAT
#!
#! ----- После событий Browse ----
#AT (%ControlPostEventCaseHandling, '?Browse:1')
! -- Запретить / разрешить кнопки --
if tt1:Metka <> ''
disable( ?Delete )
else
enable( ?Delete )
.
if tt1:Metka = '+'
disable( ?Button_Utw )
else
enable( ?Button_Utw )
.
if tt1:Metka = ''
disable( ?Button_RU )
else
enable( ?Button_RU )
.
#ENDAT
#!
#! ---- Перед закрытием окна -----
#AT (%BeforeWindowClosing)
! -- Сохранить формат Browse --
putIni( '%Procedure', 'BrowseFormat', ?Browse:1{prop:FORMAT}, glo:IniFileName )
#ENDAT
#!
#! ----- Возврат из update procedure -----
#AT (%BrowseBoxAfterUpdate)
! -- Сохранить номер последнего открываемого
документа
putIni( '%Procedure', 'OldNumber', tt1:Number, glo:IniFileName )
#IF (%TowDocFlag = %TRUE)
! -- Перевывести список товаров ?List
ForceRefresh = True
display( ?List )
#ENDIF
#ENDAT
Шаблон Button_SummDoc предназначен для
реализации кнопки Суммирования
документов. Предполагается, что эта кнопка
будет расположена в окне Ведомости
Документов.
Суммирование производится в локальных
переменных loc:TotSumm и
loc:TotRSumm, содержимое которых
отображается в соответствующих полях в окне
Ведомости. При суммировании учитываются
Фильтр и диапазон выводимых дат Ведомости.
#!===========================================================
#CONTROL (Button_SummDoc, 'Кнопка Суммировать')
#!===========================================================
CONTROLS
BUTTON,AT(,,16,16),MSG('Суммировать
документы'),TIP('Суммировать'), USE(?Button_SummDoc),
ICON('SUMM.ICO'), KEY('SummKey')
END
#!
#DISPLAY ('')
#DISPLAY ('Кнопка Суммировать')
#DISPLAY ('')
#ATSTART
#DECLARE (%ButtonSummDoc)
#FOR (%Control), WHERE(%ControlInstance = %ActiveTemplateInstance)
#SET (%ButtonSummDoc, %Control)
#ENDFOR
#ENDAT
#!
#AT (%WindowEventHandling, 'OpenWindow')
?Button_SummDoc{prop:Key}=SummKey
#ENDAT
#!
#!------ Кнопка Button_SummDoc ----
#AT (%ControlPostEventHandling, '?Button_SummDoc', 'Accepted')
#! %ProcSummDoc
setCursor( cursor:Wait )
loc:TotSumm = 0
loc:TotRSumm = 0
CCode# = tt1:CCode
clear( tt1:Record )
tt1:Firm = loc:Firm
tt1:TypeOp = loc:TypeOp
set( tt1:Number_key, tt1:Number_key )
loop
next( TTN1 )
if errorcode() or tt1:Firm<>loc:Firm or
tt1:TypeOp<>loc:TypeOp
break
.
if tt1:Metka <> '+'
cycle
.
if dll:FilterFlag = True
if dll:FilterStr<>''
case evaluate( dll:FilterStr )
of '0'
cycle
.
.
if tt1:Date < dll:BDate
cycle
.
if dll:EDate<>0 and tt1:Date>dll:EDate
cycle
.
.
if choice(?CurrentTab)=3 ! Если по
Покупателю
if tt1:CCode <> CCode#
cycle
.
.
if tt1:TowFlag and tt1:PrichodFlag
loc:TotSumm += tt1:Summ
loc:TotRSumm += tt1:RSumm
else
loc:TotSumm += tt1:SSumm
loc:TotRSumm += tt1:RSSumm
.
display( ?loc:TotSumm )
display( ?loc:TotRSumm )
. ! end loop TTN1
display( ?loc:TotSumm )
display( ?loc:TotRSumm )
setCursor()
select( ?Browse:1 )
#ENDAT
Control-шаблон SelectPokup предназначен для
реализации поля ввода и кнопки для выбора
Покупателя из Справочника Контрагентов. Этот
шаблон предназначен для использования в окне
Ведомости Документов для выбора Покупателя
когда BrowseBox отсортирован по Коду Контрагента.
Выбор Контрагента производится при помощи
процедуры Comp_s(),
которая возвращает код выбранного Контрагента.
Функция IsComp()
проверяет наличие данного контрагента в
Справочнике Контрагентов.
#!==============================================================
#CONTROL (SelectPokup, 'Поле и кнопка для выбора
Покупателя')
#!==============================================================
CONTROLS
PROMPT('Покупатель:'),USE(?loc:CCode:Prompt),TRN
ENTRY(@n_5b),AT(46,0,32,10),MSG('Код Покупателя'),TIP('Код
Покупателя'), |
USE(loc:CCode),SKIP,CENTER
BUTTON(''),AT(34,0,11,11),MSG('Выбор Покупателя'),TIP('Выбор
Покупателя'), |
USE(?Comp_), ICON('Look.ico'),SKIP
STRING(@s25),AT(15,0,,10),USE(LOC:CompSName),TRN,FONT(,,COLOR:Navy,FONT:bold)
END
#!
#DISPLAY ('')
#BOXED( ' Признаки ' )
#DISPLAY ('')
#PROMPT ('Признак "Поставщик"', CHECK), %PostFlag,
DEFAULT(%TRUE)
#PROMPT ('Признак "Покупатель"', CHECK), %PokFlag,
DEFAULT(%TRUE)
#DISPLAY ('')
#ENDBOXED
#!
#! ----- Локальные переменные -----
#LOCALDATA
LOC:CCode USHORT ! Код
контрагента
LOC:CompSName STRING(20) ! Название контрагента
LOC:R USHORT !
Возвращаемое значение
#ENDLOCALDATA
#!
#! ----- Инициализация -----
#AT (%ProcedureInitialize)
LOC:CCode = 0
LOC:R = 0
#ENDAT
#!
#! ------- После открытия окна -------
#AT (%AfterWindowOpening)
LOC:CompSName = GetC_SName( LOC:CCode )
#ENDAT
#!
#! ----- ?loc:CCode -----
#AT (%ControlPostEventHandling, '?loc:CCode', 'Accepted')
if ~IsComp( LOC:CCode ) and LOC:CCode<>0
LOC:R = Comp_s( LOC:CCode, %PostFlag, %PokFlag, 1 )
if LOC:R <> 0
LOC:CCode = LOC:R
.
dll:CCode = LOC:CCode
LOC:CompSName = GetC_SName( LOC:CCode )
.
ForceRefresh = True
do RefreshWindow
select( ?Browse:1 )
#ENDAT
#!
#! ----- ?Comp_ -----
#AT (%ControlPostEventHandling, '?Comp_', 'Accepted')
LOC:R = Comp_s( LOC:CCode, %PostFlag, %PokFlag, 1 )
if LOC:R <> 0
LOC:CCode = LOC:R
dll:CCode = LOC:CCode
LOC:CompSName = GetC_SName( LOC:CCode )
ForceRefresh = True
do RefreshWindow
select( ?Browse:1 )
.
#ENDAT
#!
#AT (%ControlPostEventHandling, '?CurrentTab', 'TabChanging')
do SyncWindow
LOC:CCode = tt1:CCode
LOC:CompSName = GetC_SName(tt1:CCode)
dll:CCode = tt1:CCode
#ENDAT
Control-шаблон FilterVedom предназначен для реализации органов управления Динамическим фильтром в Ведомости Документов. Шаблон реализует CheckBox для включения и выключения фильтра, поле для вывода названия фильтра и кнопку для вызова окна выбора фильтра.
Шаблон использует следующие глобальные
переменные (threaded):
dll:FilterFlag BYTE
! Признак "Фильтр
включен"
dll:FilterName STRING(100) ! Название фильтра
dll:FilterStr STRING(200) ! Выражение фильтра
Эти переменные реализованы глобальными из-за того, что они используются также в процедурах печати Ведомости Документов.
Выбор фильтра из Справочника Фильтров производится при помощи функции Filter(). Подробнее о реализации динамических фильтров смотрите в разделе "Динамические фильтры".
#!==============================================================
#CONTROL (FilterVedom, 'Управление фильтром ведомости')
#!==============================================================
CONTROLS
CHECK,MSG('Включение / Выключение
фильтра'),TIP('Вкл/Выкл фильтр'),USE(dll:FilterFlag),TRN,SKIP
PROMPT('Фильтр:'),AT(14,0),USE(?dll:FilterName:Prompt),TRN
ENTRY(@s40),AT(31,0,124,10),FONT(,,0800000H,FONT:bold),MSG('Название
фильтра'), |
TIP('Название фильтра'),USE(dll:FilterName),SKIP,READONLY
BUTTON(''),AT(129,0,11,11),MSG('Выбор фильтра'),TIP('Название
фильтра'),USE(?ButtonFilter), |
ICON('Look.ico'),SKIP
END
#!
#DISPLAY ('')
#DISPLAY ('Условное обозначение фильтра:')
#PROMPT ('Имя фильтра:', @s30), %TableName, REQ
#DISPLAY ('')
#!
#! ----- Локальные переменные -----
#LOCALDATA
LOC:TableName STRING(30) ! Переменная для имени
фильтра
#ENDLOCALDATA
#!
#! ----- Иничиализация -----
#AT (%ProcedureInitialize)
dll:FilterFlag = 0
if LOC:TableName = ''
LOC:TableName = '%TableName'
.
#ENDAT
#!
#! ----- ?dll:FilterFlag ----
#AT (%ControlPostEventHandling, '?dll:FilterFlag', 'Accepted')
ForceRefresh=True
do RefreshWindow
select( ?Browse:1 )
#ENDAT
#!
#! ----- ?ButtonFilter ------
#AT (%ControlPostEventHandling, '?ButtonFilter', 'Accepted')
! --- Вызов окна выбора фильтра ---
dll:FilterStr = Filter_s( loc:TableName )
if dll:FilterStr <> ''
r# = instring( '|', dll:FilterStr, 1, 1 )
if r# > 0
dll:FilterName = sub( dll:FilterStr, r#+1,
len(clip(dll:FilterStr)) - r# )
dll:FilterStr = sub( dll:FilterStr, 1, r#-1 )
.
ForceRefresh = True
do RefreshWindow
select( ?Browse:1 )
.
#ENDAT
#!
#! ---- Validate Record: Filter Checking ---
#AT (%RecordFilter, '1')
if dll:FilterFlag=True
if dll:FilterStr<>''
if evaluate( dll:FilterStr ) = '0'
exit
.
.
if tt1:Date < dll:BDate
exit
.
if dll:EDate<>0 and tt1:Date>dll:EDate
exit
.
.
#ENDAT