Глава 9. СОЗДАЕМ ОКОННЫЙ ИНТЕРФЕЙС ДОКУМЕНТА «ПРОДАЖА»
Печать счетов-фактур и накладных
Нам потребуется печатать счет-фактуру и накладную. Причем
счет-фактуру желательно получать как в валюте документа,
так и в рублях. Вместо печати в Allegro осуществляется
экспорт в Microsoft Office. Сама печать производится уже из
приложения Microsoft Office. В данном случае мы используем Microsoft
Excel.
Так как мы создали интерфейс документа «Продажа» путем
копирования интерфейса «Поступление на склад», пока что у
нас присутствует старый отчет, вызываемый командой actReport «Отчет
».
Войдем в режим дизайнера, откроем проект sale_project
.ipr и дважды щелкнем на компоненте ActionList1.
Переименуем actReport в actReport1, изменив значение свойств Caption и
Hint с «Отчет» на «Счет-фактура
».
Добавим еще 2 команды, назначая им свойства в Инспекторе
объектов:
Name |
Caption |
Hint |
ImageIndex |
actReport2 |
Счет-фактура, рубли |
Счет-фактура, рубли |
2 |
actReport3 |
Накладная, рубли |
Накладная, рубли |
2 |
Увеличим ширину Width компонента ToolBar1 до 140 и с помощью
контекстного меню этого компонента добавим разделитель и две кнопки.
Назначим добавленным кнопкам в свойстве Action команду actReport2 и actReport3
:
Дважды щелкнем на компоненте PopupMenu1, выберем последний (пустой
) пункт и добавим клавишей Insert три новых пустых пункта
. В свойство Caption первого запишем дефис «-», а свойствам
Action двух следующих назначим команды actReport2 и actReport3:
Дважды щелкнем на компоненте ActionList1 и, последовательно выбирая команды
actReport2 и actReport3, создадим два отдельных обработчика события OnExecute
. Впишем в них такой текст:
procedure TSaleForm.actReport2Execute(Sender: TObject);
begin
XLReport2.Report;
end;
procedure TSaleForm.actReport3Execute(Sender: TObject);
begin
XLReport3.Report;
end;
Для получения реквизитов фирм нам понадобится еще один SQL-
запрос. Добавим на форму компонент IBQuery с палитры InterBase
и придадим ему свойства в Инспекторе объектов:
Свойство |
Значение |
Name |
qryFirm |
Transaction |
traCurrent |
DataSource |
dsrMaster |
SQL |
select * from FIRM where ID = :CONTRAGENT |
Дважды щелкнем на компоненте и добавим все поля в список
«постоянных полей».
В обработчик события OnCreate формы SaleForm запишем:
qryFirm.Open;
Выберем на форме компонент XLReport1 и дважды щелкнем в Инспекторе
на свойстве DataSources. В появившемся редакторе источников данных добавим
новый источник:
Зададим ему свойства:
Свойство |
Значение |
Alias |
FIRM |
DataSet |
qryFirm |
Закроем редактор источников данных. У компонента XLReport1 очистим
свойство XLSTemplate. Теперь скопируем компонент в буфер обмена Windows
с помощью клавиш Ctrl+C. Дважды вставим компонент
из буфера обмена Windows, нажимая комбинацию клавиш Ctrl+
V. На форму добавятся два новых компонента XLReport.
Так как компонент XLReport1 уже был настроен для работы с
источниками данных qryMaster, qryDetail, qryFirm, то для
того чтобы использовать те же настройки во всех отчетах,
мы просто «клонировали» его, а не добавляли
компоненты с палитры:
Сохраним все изменения.
Нам осталось создать файлы шаблонов в Microsoft Excel и вписать
их имена в свойство XSLTemplate каждого из компонентов XLReport.
Вы можете разработать шаблоны документов самостоятельно или воспользоваться теми файлами
, что входят в пример конфигурации TechnoTrade, который доступен
на нашем сайте http://www.gaapinvest.com/
Файл шаблона счета-фактуры должен иметь название facture.
xls и находиться в папке проекта TechnoTrade. Если Вы
сами разрабатываете файл шаблона, то не забудьте, что
тиражируемый регион ячеек должен иметь название range1. Желательно также
определить заголовки колонок как сквозные строки, чтобы при печати
многостраничного документа на каждой странице выводились заголовки столбцов.
Выберем компонент XLReport1 и в свойстве XLSTemplate укажем имя файла
facture.xls. Путь к файлу указывать не надо
, компонент сам будет искать его в директории проекта.
Теперь для того чтобы вызвать шаблон на редактирование, достаточно
дважды щелкнуть на компоненте XLReport1.
В соответствующих ячейках шаблона укажем названия, состоящие из знака
равенства, псевдонима источника данных (как он определен у
нас в свойстве Alias) и имени поля, разделенных
знаком подчеркивания:
Шапка |
Счет-фактура № |
=MASTER_DOC_NO |
от |
=MASTER_DOC_DATE |
Грузополучатель и его адрес |
=FIRM_FULL_NAME |
Покупатель |
=FIRM_FULL_NAME |
Адрес |
=FIRM_JUR_ADDRESS |
Идентификационный номер покупателя (ИНН) |
=FIRM_INN |
Позиции |
№ п/п |
=DETAIL_NUM |
Наименование товара |
=DETAIL_ITEM_NAME |
Кол-во |
=DETAIL_QUANTITY |
Цена за единицу измерения |
=DETAIL_PRICE_L_WO_VAT |
Стоимость товаров (услуг), всего без налога |
=DETAIL_AMOUNT_L_WO_VAT |
Налоговая ставка |
=MASTER_VAT_RATE |
Сумма налога |
=DETAIL_VAT_L |
Стоимость товаров (услуг) всего, с учетом налога |
=DETAIL_AMOUNT_L |
Сохраним все изменения в шаблоне и закроем Excel.
Выберем в окне Запуск/Переменные контекста любой документ типа
«Продажа».
Запустим проект и попробуем вывести счет-фактуру, нажав
на первую кнопку со значком Excel. Взглянем на получившийся
документ. Мы видим, что в нем пока не
выводятся поля «Стоимость товаров (услуг), всего без
налога» и «Сумма налога».
Закроем Excel, отказавшись от сохранения файла.
Добавим недостающие поля в компонент запроса позиций qryDetail. Для
этого дважды щелкнем на нем. В появившемся редакторе полей
добавим (нажимая кнопку с плюсом) 4 поля типа
IBBCD:
Название поля |
Тип поля |
AMOUNT_L_WO_VAT |
IBBCD |
VAT_L |
IBBCD |
AMOUNT_R_WO_VAT |
IBBCD |
VAT_R |
IBBCD |
Выберем все 4 добавленные поля в редакторе полей и назначим
им в Инспекторе объектов свойство FieldKind = fkCalculated. Закроем
редактор полей. В обработчик события OnCalcFields компонента qryDetail добавим
команды (выделено жирным):
procedure TSaleForm.qryDetailCalcFields(DataSet: TDataSet);
begin
with DataSet do
begin
FieldByName('NUM').AsInteger := RecNo;
FieldByName('AMOUNT_L_WO_VAT').AsCurrency :=
FieldByName('PRICE_L_WO_VAT').AsCurrency *
FieldByName('QUANTITY').AsCurrency;
FieldByName('VAT_L').AsCurrency :=
FieldByName('AMOUNT_L').AsCurrency -
FieldByName('AMOUNT_L_WO_VAT').AsCurrency;
FieldByName('AMOUNT_R_WO_VAT').AsCurrency :=
FieldByName('PRICE_R_WO_VAT').AsCurrency *
FieldByName('QUANTITY').AsCurrency;
FieldByName('VAT_R').AsCurrency :=
FieldByName('AMOUNT_R').AsCurrency -
FieldByName('AMOUNT_R_WO_VAT').AsCurrency;
end;
end;
Мы вычисляем сумму без НДС, просто умножая «цену
без НДС» на «количество», а «сумму
НДС» получаем, вычитая «сумму без НДС»
из «суммы с НДС».
Запустим проект и попробуем вывести счет-фактуру еще раз
.
Вызовем предварительный просмотр печати:
В данном случае мы получили печать счета-фактуры в
валюте документа. Для того, чтобы получить такой же
документ в рублях, закроем Excel, создадим копию файла
шаблона под именем facture_r.xls. Запишем
имя этого файла в свойство XLSTemplate компонента XLReport2 и дважды
щелкнем на компоненте, чтобы вызвать шаблон на редактирование.
В шаблоне заменим выражения, относящиеся к ценам и суммам
в валюте документа:
|
Заменить на |
Цена за единицу измерения |
=DETAIL_PRICE_R_WO_VAT |
Стоимость товаров (услуг), всего без налога |
=DETAIL_AMOUNT_R_WO_VAT |
Сумма налога |
=DETAIL_VAT_R |
Стоимость товаров (услуг) всего, с учетом налога |
=DETAIL_AMOUNT_R |
Фактически, нам пришлось лишь заменить букву L на букву
R. Сохраним шаблон и закроем Excel.
Запустим проект и нажмем вторую кнопку со значком Excel.
Итак, вывод счета-фактуры в рублях мы тоже
закончили. Нам осталось реализовать накладные. Закроем Excel,
отказавшись от сохранения файла и вернемся в режим дизайна.
В качестве накладной в этом примере мы выберем достаточно мудреную
накладную, чтобы показать еще ряд нюансов - использование параметров
в компоненте XLReport и формирование суммы прописью.
Заготовим шаблон товарной накладной (форма по ОКУД 330212)
или возьмем его из примера конфигурации. Скопируем файл шаблона
в каталог проектов и назовем его nakl.xls.
Запишем это название в свойство XLSTemplate компонента XLReport3 и дважды
щелкнем на компоненте, чтобы вызвать шаблон на редактирование.
В полях шаблона запишем выражения, как мы это делали
в шаблоне счета-фактуры:
Шапка |
Товарная накладная № |
=MASTER_DOC_NO |
Дата составления |
=MASTER_DOC_DATE |
Грузополучатель |
=FIRM_FULL_NAME_AND_ADDRESS |
Плательщик |
=FIRM_FULL_NAME |
Адрес |
=FIRM_JUR_ADDRESS |
Идентификационный номер покупателя (ИНН) |
=FIRM_INN |
Позиции |
№ п/п |
=DETAIL_NUM |
Наименование товара |
=DETAIL_ITEM_NAME |
Кол-во |
=DETAIL_QUANTITY |
Цена за единицу измерения |
=DETAIL_PRICE_R_WO_VAT |
Сумма без учета НДС |
=DETAIL_AMOUNT_R_WO_VAT |
Ставка НДС |
=MASTER_VAT_RATE |
Сумма НДС |
=DETAIL_VAT_R |
Сумма с учетом НДС |
=DETAIL_AMOUNT_R |
Подвал |
Товарная накладная имеет приложение на
и содержит |
=XLRParams_NUM_IN_WORDS |
Всего отпущено на сумму: |
=XLRParams_AMOUNT_IN_WORDS |
В таблице выделены жирным шрифтом три поля шаблона, для
которых пока у нас нет соответствующих источников в проекте.
Поле FULL_NAME_AND_ADDRESS просто организовать
, добавив в компонент qryFirm вычисляемое поле типа IBString и
задав ему свойства:
Свойство |
Значение |
FiledKind |
FkCalculated |
Size |
250 |
FiledName |
FULL_NAME_AND_ADDRESS |
Для того чтобы это поле получало значения, нужно создать
обработчик события OnCalcFields компонента qryDetail:
procedure TSaleForm.qryFirmCalcFields(DataSet: TDataSet);
begin
with DataSet do
FieldByName('FULL_NAME_AND_ADDRESS').AsString :=
Format('%s, ИНН %s, %s',[FieldByName('FULL_NAME').AsString,
FieldByName('INN').AsString, FieldByName('JUR_ADDRESS').AsString]);
end;
В подвале шаблона у нас имеются два поля, в
которых нужно выводить числа прописью. Это общее количество позиций
и сумма документа. Для того чтобы организовать превращение чисел
в такого рода текст, нам понадобится компонент с палитры
Allegro, умеющий это делать.
Добавим на форму SaleForm два компонента CurrencyInWords с палитры Allegro
.
Придадим им свойства:
Свойство |
1-й компонент |
2-й компонент |
Cent1 |
копейка |
|
Cent2_4 |
копейки |
|
Cent5_20 |
копеек |
|
Cur1 |
рубль |
|
Cur2_4 |
рубля |
|
Cur5_20 |
рублей |
|
Name |
ciwAmount |
ciwNum |
UseCents |
True |
False |
UseFinalPoint |
True |
False |
Компонент CurrencyInWords работает просто: во время выполнения программы его
свойству Value следует присвоить значение, а затем прочитать значение
из свойства Text. Способ преобразования задается в свойствах,
где мы устанавливаем способы склонения центов и валют, а
также род центов и род валюты. Чтобы правильно задать
свойство, нужно задаться вопросом такого рода: 2..
4 чего? – рубля. Следовательно, Cur2_
4 = рубля, 5..20 чего? –
рублей, следовательно Cur5_20 = рублей.
Выберем компонент XLReport3 и Инспекторе объектов дважды щелкнем на его
свойстве Params. Появится редактор параметров, в котором добавим
два параметра с именами: NUM_IN_WORDS
и AMOUNT_IN_WORDS:
Теперь можно обращаться к этим параметрам во время выполнения программы
методом ParamByName. В обработчик события OnExecute команды actReport3 впишем
текст, показанный жирным шрифтом:
procedure TSaleForm.actReport3Execute(Sender: TObject);
begin
with qryDetail do
begin
FetchAll;
ciwAmount.Value := qryMaster.FieldByName('TOTAL_R').AsCurrency;
ciwNum.Value := RecordCount;
end;
XLReport3.ParamByName('AMOUNT_IN_WORDS').Value := ciwAmount.Text;
XLReport3.ParamByName('NUM_IN_WORDS').Value := ciwNum.Text;
XLReport3.Report;
end;
При построении отчета XLReport, найдя в шаблоне поля,
начинающиеся с префикса XLRParams_, выведет значения параметров в соответствующие
ячейки отчета.
Запустим проект и выведем накладную, нажав третью кнопку.
На экране возникнет документ Excel. Вызовем предварительный просмотр печати
в Excel. Накладная, скорее всего, занимает два
листа:
Общее количество позиций в накладной и сумма документа отображаются прописью
.
На этом мы закончили интерфейс документа «Продажа».
В заключение приведем полный листинг проекта.
|