Как то, устроившись на работу, я получил творческое задание - написать штук пяток отчетов по выводимым на экран таблицам. Стандарт разработки в фирме был Delphi + XL Report для построения отчетов в Экселе.
Мне предложили сделать шаблон для каждой табличке в эксель (XL Report подразумевает в общем случае наличия шаблона в xls файле, где прописано какие куда поля выводить).
Меня такая перспектива не прельстила. Идите вы нафик, подумал я, я что вам художник что ли, шаблоны рисовать …
Короче, я написал процедуру, которая на входе получает TGrid, координаты откуда начать рисовать таблицу, текст заголовка отчета, а на выходе рисует табличку на основе одного шаблона, из которого берется только оформление таблицы.
Далее случилось непредвиденное мной
TGrid оказался частным случаем, система писавшаяся в разное время разными людьми, содержала так же и EHLib компоненты отображения гридов, и DB гриды и ещё черти что…
Ну блин, подумал я. Пришлось написать базовый класс вывода в эксель набора данных, и несколько его наследников, выводивших в эксель конкретные компоненты дельфи. Написал входную процедурку которая определяет тип переданного компонента и ищет этот тип в списке зарегистрированных обрабатываемых классов.
Далее я задумался над тем, что бы сделать универсальный механизм, чтобы был движок и можно в нём было регистрировать как входящие источники данных, так и выводящие механизмы.
{ TPrintCustomGrid }
procedure TPrintCustomGrid.Print(RepTitle: string; Grid: tobject; col:integer;
row:integer; Shablon: string);
var i: byte;
begin
try
// перебираем обработчики, ищем для нашего класса
for i :=1 to fCount do
if (UpperCase(grid.ClassName)=UpperCase(fInterfaces[i].TypeName)) then
begin
// если нашли, то работаем с ним
fIPrGtid_Data:=fInterfaces[i].Source;
end;
// если не нашли
if fIPrGtid_Data=nil then
begin
fxlReport.Params.Clear;
raise Exception.Create('Данный тип таблиц ('+Grid.ClassName+') не поддерживается, напишите свой ' +
'класс для реализации интерфейса IPrGrid_Data для этого класса');
end;
if Shablon='' then fxlReport.XLSTemplate:='Print_CustomGrid.xls'
else fxlReport.XLSTemplate:=Shablon;
fRepTitle:=RepTitle;
fRow:=row;
fCol:=col;
with fxlReport.Params.Add do
begin
// заголовок - =XLRParams_Title
Name:='Title';
AsString:=fRepTitle
end;
В качестве входящих - процедура умеющая выбирать данные из определенного класса.
В качестве выходящих - процедура умеющая выводить передаваемые ей данные в конкретный выходной формат - эксель, текст, html, XL Report, FastReport
Что то думал насчет не добавить ли ещё и тип данных - таблица, ээээ…. ещё что-нибудь
Но мои фантазии были прерваны, меня кинули на другую задачу. Так я и не довел дело до ума, но процедука печатающия произвольный DBGrid,StringGrid осталась. Ей иногда даже пользуются. Иногда, потому что наблюдается некая инертность, большинство не любят использовать чужие разработки - лень разбираться, делаю как привык и тд.
А вспомнил я это к тому, что Navision у меня встала задача построения отчетов на основе ADO запросов к sql серверу (родная среда делает всё достаточно медленно, как тут один выразился - через жопу курсор…, поэтому для ускорения медленных отчетов, пишется хранимая процедура на самом SQL сервере).
Дык вспомнив свои наработки на Delphi, быстренько наваял простую процедуру, которая получая на входе SQL запрос, выводит в эксель результат, который вернет запрос с указанным заголовком. Остаётся только написать запрос вида
Select "Item No_" as 'Номер товара', Quantity as 'Количество' from ...
чем не ленивый отчет? Кстати, коллеги по Navision пользуются этой процедурой гораздо охотнее, чем в Delphi, наверно сказывается ограниченость данной системы (Navision)
Это кросспост из блога
"Блог жителей Чертенка.ру"
Вы можете посмотреть коментарии и оставить свои комертарии
тут
(регистрация не нужна)