15 апреля 2011

FastReport. Вывод данных в внизу страницы

   Недавно коллега обратился с вопросом "Как в FastReport сделать так, чтобы бэнд с данными выводился внизу страницы?".
   Первая моя мысль была положить SubReport на PageFooter. Но такое решение естественно не сработало, и я стал пробовать управлять положением бэнда на странице с помощью скрипта. В результате я нашел решение данного вопроса с помощью дополнительного бэнда и одной строчки скрипта. Поясню на примере.
   Например, вверху отчета нам нужно вывести какую-то информацию (добавляем на страницу бэнд MasterData1) и внизу отчета нам нужно вывести какую-то информацию (добавляем на страницу бэнд MasterData2). А между ними положим еще один бэнд (MasterData3), который заполнит пространство между MasterData1 и MasterData2. Его не будем подключать к данным, а просто укажем количество строк RowCount = 1.
   В скрипте, при старте отчета зададим размер MasterData3:

MasterData3.Height := Engine.PageHeight - MasterData1.Height * MasterData1.RowCount – MasterData2.Height * MasterData2.RowCount

т.е., от высоты страницы отнимаем высоту бэндов с данными. Высоту бэндов с данными вычисляем следующим образом: высоту одной строки бэнда умножаем на количество строк, которые будут в нём выводиться. У меня здесь в скрипте количество строк – это RowCount, а в примере отчета для моего коллеги я использовал количество строк в запросе (DataSet.RecordCount).
   Вот такими нехитрыми манипуляциями мне удалось решить поставленную задачу.
Может быть, вы знаете способ проще?

16 февраля 2011

Object Pascal для Java и Android

   На прошедшей в Лас-Вегасе конференции Developer Solutions Conference, компания RemObjects Software впервые представила свой новый проект – "Cooper". Cooper – это новый компилятор языка RemObjects Oxygene для платформ Java и Android (RemObjects Oxygene – это реализация языка Object Pascal для .NET и Mono, третья версия которого была выпущена как Embarcadero Delphi Prism). Cooper подключает стандартные библиотеки Java-классов и создает 100% байт-код для виртуальных машин Java и Dalvik (Dalvik – виртуальная машина Java для Android).
   В ролике показано, как под Mac-OS в командной строке скомпилировали паскалевский код консольной программы и калькулятора, использующего swing-контролы, а затем запустили полученные jar-файлы.

   Планируется интеграция Cooper в Visual Studio и MonoDevelop (аналогично с компилятором для .NET). Обещают выпустить это чудо уже в этом году.

13 февраля 2011

Сохранение в базу данных отчета FastReport в формате PDF

   Недавно пришлось писать DLL, одна из функций которой должна была:
1. сформировать отчет в FastReport;
2. экспортировать отчет в файл PDF-формата и сохранить его в базе данных;
3. возвратить идентификатор сохраненного в базе данных файла.
Предположим, что исходная структура таблицы для хранения файла в базе данных была такая (MS SQLServer 2000):
CREATE TABLE X.FILES (
  ID BIGINT IDENTITY NOT NULL,
  FILE_BODY IMAGE NULL,
  CONSTRAINT PK_FILES PRIMARY KEY (ID)),
где FILE_BODY – это поле, в которое сохраняется файл, а ID – идентификатор файла.
   Для начала я создал процедуру, которая будет вставлять файл в базу данных и возвращать идентификатор вставленного файла.
CREATE PROCEDURE X.InsertFile
 @FILE image,
 @ID bigint OUTPUT
AS
 INSERT INTO X.FILES(FILE_BODY) VALUES(@FILE)
 SET @ID = SCOPE_IDENTITY()
GO
   Потом сел писать код DLL. В Delphi вся работа с файлами реализована с помощью потоков, поэтому я немного удивился, когда оказалось, что метод Export у TfrxReport экспортирует отчет только в файл (честно сказать, я ожидал увидеть, что-то в стиле ExportToStream). Т.е. вместо прямой передачи отчета через поток в базу данных, необходимо было сначала сохранить отчет во временный файл, а потом этот файл загрузить в базу данных. Мне это не понравилось, т.к. файловые операции (сначала записи, потом чтения) должны были хоть немного, но тормозить работу. Но нужно было срочно отдать DLL, поэтому я не стал разбираться с экспортом и сделал через файл:

...
 db: TSDDatabase; // база данных SQLDirect
 spInsertFile: TSDStoredProc; // вызов X.InsertFile
 frxReport: TfrxReport;
 frxPDFExport: TfrxPDFExport;
...

Function GetDoc(const sDotName: String; ...): Integer;
begin
 Result := -1;
 // загружаем шаблон отчета
 If frxReport.LoadFromFile(sDotName)
  then begin
   // устанавливаем параметры отчета
   ...
   If frxReport.PrepareReport
    then try
     // получаем имя временного файла
     frxPDFExport.FileName := GetTempFileName;
     Try
      // экспортируем отчет во временный файл
      frxReport.Export(frxPDFExport);
      // загружаем PDF-файл в параметр процедуры
      // из временного файла
      spInsertFile.Params[1].LoadFromFile(frxPDFExport.FileName, ftBlob);
     Except
      on E: Exception do
       WriteErrorMessage(E.Message);
     End;
     // сохраняем PDF-файл в базу данных
     Try
      db.StartTransaction;
      spInsertFile.ExecProc;
      db.Commit;
      Result := spInsertFile.Params[2].AsInteger;
     Except
      on E: ESDEngineError do
       begin
        db.Rollback;
        WriteErrorMessage(E.Message);
       end;
     End;
    Finally
     // удаляем временный файл
     DeleteFile(frxPDFExport.FileName)
    End
    else WriteErrorMessage('Ошибка подготовки отчета')
  end
  else WriteErrorMessage('Файл шаблона не найден')
end;

   После передачи DLL другому программисту, мысли о лишних файловых операциях при сохранении отчета в базу через временный файл, не давала мне покоя. Вечером, не найдя решения в документации по FastReport, я, прежде чем смотреть исходный код экспорта, решил еще раз пройтись по методам и свойствам экспорта. Глаз сразу же зацепился за свойство Stream. Я создал для этого свойства поток и метод Export у TfrxReport выгрузил отчет не в файл, а в поток.

Function GetDoc(const sDotName: String; ...): Integer;
begin
 Result := -1;
 // загружаем шаблон отчета
 If frxReport.LoadFromFile(sDotName)
  then begin
   // устанавливаем параметры отчета
   ...
   If frxReport.PrepareReport
    then begin
     Try
      Try
       // создаём поток в памяти
       frxPDFExport.Stream := TMemoryStream.Create;
       // экспортируем отчет в поток
       frxReport.Export(frxPDFExport);
       // загружаем PDF-файл в параметр процедуры
       // из потока в памяти
       spInsertFile.Params[1].LoadFromStream(frxPDFExport.Stream, ftBlob);
      Except
       on E: Exception do
        WriteErrorMessage(E.Message);
      End;
     Finally
      frxPDFExport.Stream.Free;
     End;
     // сохраняем PDF-файл в базу данных
     Try
      db.StartTransaction;
      spInsertFile.ExecProc;
      db.Commit;
      Result := spInsertFile.Params[2].AsInteger;
     Except
      on E: ESDEngineError do
       begin
        db.Rollback;
        WriteErrorMessage(E.Message);
       end;
     End;
    end
    else WriteErrorMessage('Ошибка подготовки отчета')
  end
  else WriteErrorMessage('Файл шаблона не найден')
end;

   Часто решение задачи лежит на поверхности и нет нужды копаться в чужом коде. Нужно лишь быть внимательным и никогда не сдавайтесь – "ищите и обрящите".

30 января 2011

Часть антивируса Касперского написана на Delphi

   В конце этой недели в интернет были выложены исходные тексты антивируса Касперского, которые были украдены одним из сотрудников компании в 2008 году (последние изменения датируются декабрём 2007-го года). Как сообщает сайт Softpedia, часть антивируса написано на Delphi :-)

Ссылки по теме:
1. Кому выгодно раскручивать тему утечки кодов из Лаборатории Касперского?
2. Kaspersky Anti-Virus Source Code Leaks online

28 января 2011

Delphi и C++Builder Starter Edition

   По информации SD Times, Embarcadero Technologies собирается продавать новую редакцию Delphi и C++Builder – Starter Edition. Эта редакция будет включать: полноценную IDE с 32-разрядным компилятором, отладчик и библиотеку визуальных компонент (VCL), содержащую сотни компонент для создания пользовательского интерфейса (от стандартных Windows-контролов до контролов в стиле Office Ribbon и touch-интерфейса) и работы с различными Internet протоколами и стандартами. До публикации обновленного "Delphi Feature Matrix" трудно, что то понять о функциональных возможностях новой редакции, но по короткому описанию она очень напоминает Professional Edition.

25 января 2011

Интернет на халяву

   Сегодня заменил свой старый ADSL-модем на новенький с Wi-Fi. Кроме моей точки доступа ноутбук сразу нашел ещё четыре. Одна из них была помечена, как "Unsecured wireless network". Проверив работу своей точки доступа, я отключил её и проверил "соседскую". Через "соседскую" я без проблем вышел в интернет, открыл для тестирования пару сайтов и отключился. Предположим, что на моём месте оказался бы другой любопытный, но менее честный человек. Что тогда? В лучшем случае, он потихоньку приворовывал бы трафик бороздя просторы интернета, а в худшем - забил бы весь чужой канал каким-нибудь торрентом (если там модем без шейпера).
   "Граждане, храните деньги в сберегательной кассе!", - сказал Жорж Милославский, герой всенародно любимого кинофильма "Иван Васильевич меняет профессию", запихивая в карман пухлую пачку денег, похищенную из квартиры доктора Шпака. Так и я таким же поучительным тоном скажу: "Граждане, защитите свою беспроводную сеть! Хотя бы ограничьте подключения к вашей точке доступа по MAC-адресу устройств".

P.S. Вечером на кухне ноутбук находил уже 15 точек доступа, две из которых были открыты для общего пользования...

13 ноября 2010

Delphi Team обидела очередного приверженца Delphi

   Разработчики Delphi все больше ударов наносят по остаткам Delphi-сообщества: постоянные срывы roadmap, кучи багов, минимальное развитие от версии к версии, зашкаливающие цены на обновления... Всем своим поведением они стараются отталкнуть от себя людей. И это им удается!
   Например, в начале ноября 2007-го года Питер Моррис (Peter Morris), весьма известный человек в Delphi-сообществе (автор нескольких open-source библиотек (deAudio, deBold, DIB Controls и FastStrings); автор множества статей по Delphi, Bold и ECO; в феврале 2007-го анонсировал свою книгу, посвященную ECO...), поссорился с CodeGear (Borland) из-за лицензии на Delphi. Менеджеры CodeGear пожадничали, и в результате Питер Моррис закрыл свой сайт (Droopy Eyes Software), отказался от использования Delphi и прекратил поддержку своих open-source проектов.
   Сегодня другая известная личность в Delphi Community - Андреас Хаусладен (Andreas Hausladen) опубликовал на своем блоге заметку XE Update 1 the death of DDevExtensions. Андреас Хаусладен известен своими расширениями для Delphi IDE: DelphiSpeedUp (ускоряет загрузку IDE), DDevExtensions (делает более удобной работу в IDE), IDE Fix Pack (набор патчей для IDE исправляющих баги, до которых у R&D Team нет дела), dcc32Speed (ускоряет работу компилятора (dcc32.exe)) и прочие. Кроме этого он участвует в Project JEDI и разрабатывает собственные библиотеки (VCL Fix Pack, Midas Speed Fix, AsyncCalls и NvAPI). Проблема в том, что R&D Team сильно увлеклась защитой от пиратов, тем самым мешает работе разработчиков расширений для Delphi IDE. Пираты и так найдут, как украсть, а страдают, как всегда, честные люди. Delphi XE Update 1, если установлен DDevExtensions, случайным образом останавливает работу и отправляется на http://www.embarcadero.com/how-to-buy. Думаю, что после прочтения слов Андреаса "Это означает, что DDevExtensions для Delphi XE умер" многочисленные пользователи DDevExtensions по всему миру дружно сказали "фуцк".
   Год от года Delphi-сообщество уменьшается... Только, похоже, что это не волнует ее разработчиков и скоро Delphi, как и Borland, станет достоянием истории.