Каталог расширений

Популярные теги

3gp       avi       fb2       jpg       mp3       pdf      

Как загрузить файл в делфи


классика Pascal. Работа с типизированными файлами в Delphi – Delphi в Internet

Удивительно, но факт – запрос “delphi файлы” в Яндексе – это один из самых популярных запросов, касающихся Delphi. Популярнее только “delphi скачать” – видимо ещё не все слышали про такую штуку как Delphi Community Edition. Раз есть в Сети запрос – должен быть и ответ. Посмотрим, что получится в итоге.

Содержание статьи

Классика работы с файлами в Delphi – ключевое слово File

Этот способ, без преувеличения, можно назвать древнейшим способом работы с файлами в Pascal/Delphi. Однако и он до сих пор используется в работе, особенно, если это, например, лабораторная работа по информатике в школе или ВУЗе.

Для определения файловой переменной в Delphi/Pascal используется ключевое слово File. При этом, мы можем определить как типизированный файл, так и не типизированный, например:

type TPerson = record Name: string[20]; Family: string[20]; end;   var UntypedFile: File; //нетипизированный двоичный файл TypedFile: File of TPerson;//типизированный файл

Для типизированного фала мы можем задать тип данных фиксированного размера (ShortString, String[20], Integer, Single и так далее), например, мы можем определить такие типизированные файлы:

 IntFile: File of integer; StringFile: file of single; ShortStringFile: file of ShortString;

Или, как в примере выше использовать для указания типа запись (record), в которой все поля имеют фиксированный размер. Для типизированного файла нельзя указывать типы данных, размер которых не фиксирован, например, вот такие определения файловых переменных недопустимы:

type TIntArr = array of integer;   var StrFile: file of string; //недопустимо - размер string заранее не известен ArrFile: file of TIntArr;//недопустимо - размер динамического массива заранее неизвестен

Более того, даже компилятор Delphi укажет вам на ошибку, сообщив следующее:

[dcc32 Error] E2155 Type ‘string’ needs finalization – not allowed in file type

Определив файловую переменную можно приступать к работе с файлом. Алгоритм работы при этом будет следующим:

  1. Ассоциировать файловую переменную с файлом на диске
  2. Открыть файл
  3. Записать/Прочитать файл
  4. Закрыть файл

При этом, для типизированных и не типизированных файлов работа в части чтения/записи несколько различается в плане используемых методов.

Работа с типизированными файлами в Delphi

Рассмотрим несколько примеров работы с типизированными файлами в Delphi.
Для начала, рассмотрим вариант работы с типизированным файлом, например, представленном выше:

type TPerson = record Name: string[20]; Family: string[20]; end; var TypedFile: File of TPerson;

Пример №1. Запись данных в типизированный файл Delphi

Запишем в наш файл две записи:

program example_1;   {$APPTYPE CONSOLE}   {$R *.res}   uses System.SysUtils;   type TPerson = record Name: string[20]; Family: string[20]; end;   var TypedFile: File of TPerson; Person: TPerson; begin //связываем файловую переменную с файлом на диске AssignFile(TypedFile,'MyFile.txt'); //открываем файл для записи Rewrite(TypedFile); //задаем имя/фамилию человека Person.Name:='Иван'; Person.Family:='Иванов'; //добавляем запись в файл Write(TypedFile, Person); //задаем имя/фамилию второго человека Person.Name:='Петр'; Person.Family:='Петров'; //записываем в файл Write(TypedFile, Person); //закрываем файл CloseFile(TypedFile);   Readln; end.

Рассмотрим методы, используемые в этом примере:

function AssignFile(var F: File; FileName: String): Integer;

Связывает файловую переменную F с внешним файлом FileName. В качестве второго параметра может задаваться как абсолютный путь к файлу, например, ‘C:/MyFile.txt‘, так и относительный, например, в коде выше файл будет создан рядом с exe-файлом.

procedure Rewrite(var F: File; [ RecSize: Integer]);

Создает новый файл и открывает его. Если внешний файл с таким именем уже существует, он удаляется и на его месте создается новый пустой файл. Если F уже открыт, он сначала закрывается, а затем воссоздается. Текущая позиция файла устанавливается в начале пустого файла.
F – это переменная, связанная с внешним файлом с использованием AssignFile. RecSize – это необязательное выражение, которое можно указывать, только если F является нетипизированным файлом (об этом ниже).

procedure Write([var F: File]; P1; [ ..., PN]); overload;

Используется для записи в типизированный файл. F – файловая переменная, P1..PN – это переменная того же типа, что и тип файла F.

procedure CloseFile(var F: File);

Прекращает связь между файловой переменной и файлом внешнего диска. F – это файловая переменная любого типа. Внешний файл, связанный с F, полностью обновляется, а затем закрывается, освобождая дескриптор файла для повторного использования.

В результате выполнения представленного выше кода, рядом с exe-файлом будет создан новый файл MyFile.txt, содержащий две записи, при этом, каждая запись будет иметь фиксированный размер, вне зависимости от фактических имени/фамилии.

Для того, чтобы в delphi не перезаписывать каждый раз файл, а добавлять в конец файла новые записи необходимо открывать типизированные файлы методом Reset. Рассмотрим пример добавления новых записей в типизированные файлы Delphi.

Пример №2. Добавление записей в типизированный файл Delphi

Рассмотрим такой пример Delphi:

program example_2;   {$APPTYPE CONSOLE}   {$R *.res}     uses System.SysUtils;   type TPerson = record Name: string[20]; Family: string[20]; Age: integer; end;   procedure ReadTypedFile; const cStr = '%s %s %d'; var F: File of TPerson; Person: TPerson; begin AssignFile(F, 'MyFile.txt'); Reset(F); while not Eof(F) do begin Read(F, Person); Writeln(Format(cStr, [Person.Name, Person.Family, Person.Age])); end; end;   procedure AppendTypedFile; var F: file of TPerson; Person: TPerson; begin AssignFile(F, 'MyFile.txt'); // открываем файл для записи Reset(F); Seek(F, FileSize(F)); // задаем имя/фамилию человека Writeln('Введите имя: '); Readln(Person.Name); Writeln('Введите фамилию: '); Readln(Person.Family); Writeln('Введите возраст: '); Readln(Person.Age); // добавляем запись в файл Write(F, Person); // закрываем файл CloseFile(F); end;   var TypedFile: File of TPerson; Person: TPerson; DoAppend: integer;   begin if not FileExists('MyFile.txt') then begin AssignFile(TypedFile, 'MyFile.txt'); // открываем файл для записи Rewrite(TypedFile); // закрываем файл CloseFile(TypedFile); end;   // связываем файловую переменную с файлом на диске repeat Writeln('Добавить в файл запись: 1 - Да; 2 - Нет'); Readln(DoAppend); case DoAppend of 1: AppendTypedFile; 2: break; end; until DoAppend = 0; //читаем все записи из типизированного файла ReadTypedFile; Readln; end.

Разберемся с тем, что здесь делается. Во-первых, условие:

if not FileExists('MyFile.txt') then

проверяет, существует ли файл на диске. Метод FileExist имеет следующее описание:

function FileExists(const FileName: string; FollowLink: Boolean = True): Boolean;

FileName – имя файла, существование которого необходимо проверить. Второй параметр – FollowLink учитывается только при использовании символической ссылки. То есть, если нужно проверить только наличие символической ссылки на файл, то параметр FollowLink устанавливается в False, а если нужно проверить наличие и символической ссылки на файл и самого файла, то FollowLink устанавливается в True (значение по умолчанию).

Таким образом, в нашем примере, если файла нет на диске то он создается пустым. Далее выполняется цикл:

repeat Writeln('Добавить в файл запись: 1 - Да; 2 - Нет'); Readln(DoAppend); case DoAppend of 1: AppendTypedFile; 2: break; end; until DoAppend = 0;

В этом цикле, если пользователь вводит 1, выполняется процедура AppendTypedFile, которая добавляет в файл очередную запись:

procedure AppendTypedFile; var F: file of TPerson; Person: TPerson; begin AssignFile(F, 'MyFile.txt'); // открываем файл для записи Reset(F); //смещаемся в конец файла Seek(F, FileSize(F)); // задаем имя/фамилию человека Writeln('Введите имя: '); Readln(Person.Name); Writeln('Введите фамилию: '); Readln(Person.Family); Writeln('Введите возраст: '); Readln(Person.Age); // добавляем запись в файл Write(F, Person); // закрываем файл CloseFile(F); end;

Здесь, в принципе, весь алгоритм расписан в комментариях к процедуре.
Метод Reset не воссоздает файл снова, как Rewrite, а открывает его для чтения/записи (в случае двоичных файлов). Что касается метода Seek, то он имеет следующее описание:

procedure Seek(var F: File; N: Integer);

F – файловая переменная, ассоциированная с файлом на диске, N – номер записи в файле (первый номер – 0). Чтобы переместиться сразу в конец файла, мы сделали такой вызов:

где FileSize – это метод Delphi имеющий следующее описание:

function FileSize(var F: File): Integer;

В случае использования типизированных файлов эта функция возвращает количество записей в файле.

После того, как пользователь вводит что-то кроме 1 срабатывает метод ReadTypedFile – чтение всех записей из файла:

procedure ReadTypedFile; const cStr = '%s %s %d'; var F: File of TPerson; Person: TPerson; begin AssignFile(F, 'MyFile.txt'); Reset(F); while not Eof(F) do begin Read(F, Person); Writeln(Format(cStr, [Person.Name, Person.Family, Person.Age])); end; end;

Здесь мы, опять же, открываем файл методом Reset и в цикле while..do проходим по всем записям файла, пока не дойдем до конца. Здесь мы использовали два новых метода Delphi:

function Eof([var F: File]): Boolean; overload;

Eof возвращает True, если текущая позиция файла находится за последним символом файла или файл пуст. В противном случае Eof возвращает False.
По аналогии с методом Write, метод Read производит чтение очередной записи из файла и имеет следующее описание:

procedure Read(var F: File; V1; [ ..., VN]);

Результат работы нашего примера может быть следующим:

Ещё одним полезным методом для работы с типизированными файлами может быть процедура Truncate:

procedure Truncate(var F: File);

Удаляет все записи после текущей позиции файла. Вызовите Truncate в коде Delphi, чтобы текущая позиция файла стала концом файла (Eof (F) вернет true).
Рассмотрим пример использования этой процедуры.

Пример №3. Удаление последних записей типизированного файла в Delphi

Воспользуемся файлом, созданным в предыдущем примере и удалим из него две последние записи:

program example_3;   {$APPTYPE CONSOLE}   {$R *.res}     uses System.SysUtils;   type TPerson = record Name: string[20]; Family: string[20]; Age: integer; end;   procedure ReadTypedFile; const cStr = '%s %s %d'; var F: File of TPerson; Person: TPerson; begin AssignFile(F, 'MyFile.txt'); Reset(F); while not Eof(F) do begin Read(F, Person); Writeln(Format(cStr, [Person.Name, Person.Family, Person.Age])); end; end;   var TypedFile: File of TPerson; Person: TPerson; Count: integer; DoErase: integer; begin AssignFile(TypedFile,'MyFile.txt'); Reset(TypedFile); Count:=FileSize(TypedFile); if Count<2 then begin Writeln('Количество записей в файле меньше двух. Стереть все записи? 1 - Да; 2 - Нет'); Readln(DoErase); if DoErase=1 then Truncate(TypedFile); end else begin Seek(TypedFile, Count-2); Truncate(TypedFile); end; //читаем все записи из типизированного файла ReadTypedFile; Readln; end.

В этом примере мы делаем следующее:

  1. Открываем файл существующий AssignFile/Reset
  2. Определяем количество записей в файле (Count:=FileSize(TypedFile))
  3. Если количество записей меньше двух, то спрашиваем у пользователя стереть ли все записи и, в случае положительного ответа, вызываем метод Tuncate
  4. Если количество записей в файле больше двух, то смещаемся на нужную нам позицию в файле (Seek(TypedFile, Count-2)) и затираем две последние записи методом Truncate.

Подведем итог

Для работы с типизированными файлами в Delphi в самом общем случае нам необходимо выполнить следующую последовательность операций:

  1. Определить тип записей в файле – это могут быть стандартные типы данных Delphi с фиксированным размером: ShortString, integer, single и так далее или собственные типы данных, например, записи (record), но, в этом случае, главное условие – размер записи должен быть фиксированным.
  2. В коде Delphi/Pascal определить файловую переменную, используя ключевое слово file и, указав тип записей файла, определенный в пункте 1.
  3. Ассоциировать файловую переменную с внешним файлом на диске, используя метод AssignFile.
  4. Открыть файл для чтения/записи, используя методы Rewrite/Reset.
  5. Чтобы сделать в файл очередную запись используем метод Write, для чтения очередной записи из файла – используем метод Read.
  6. Закрыть файл методом CloseFile.

В целом, рассмотренные выше примеры не охватывают всех возможностей работы с типизированными файлами в Delphi, а, скорее, показывают основные операции по работе с типизированными файлами. Поэтому ниже представлен перечень методов которые могут применяться при работе с типизированными файлами в Delphi/Pascal.

Функции и процедуры для работы с типизированными файлами в Delphi/Pascal

Метод Краткое описание
procedure AssignFile(var F: File; FileName: String)
Ассоциирует файловую переменную F с внешним файлом FileName. Переменная FileName может быть как именем файла, так и содержать полный путь к файлу на диске.
procedure CloseFile(var F: File);
Закрывает файл, ассоциированный с переменной F и освобождает переменную для дальнейшего использования.
function Eof(var F: File): Boolean;
Проверяет конец файла и возвращает True, если файловый указатель стоит в конце файла. В случае записи True означает, что очередной компонент будет добавлен в конец файла, при чтении – что файл прочтен полностью.
procedure Erase(var F: File);
Удаляет внешний файл, связанный с файловой переменной F. Перед удалением файла его необходимо закрыть методом CloseFile.
 
function FilePos(var F: File): Integer;
Возвращает текущую позицию в файле. В коде Delphi используйте FilePos для файловой переменной открытого файла, чтобы определить текущую позицию в файле. Если текущая позиция в файле находится в начале, FilePos возвращает 0.
 
function FileSize(var F: File): Integer;

 

Для типизированных файлов возвращает количество записей в файле.
procedure Read(var F: File; V1; [ ..., VN]);
Считывает из типизированного файла одну или несколько записей
procedure Rename(var F: File; Newname: String);
Переименовывает файл, ассоциированный с переменной F
procedure Reset(var F: File; [ RecSize: Integer]);
Открывает файл для чтения. Второй параметр RecSize указывается в случае использования нетипизированных файлов и указывает размер записи в файле в байтах
procedure Rewrite(var F: File; [ RecSize: Integer]);
Воссоздает файл. Если файл существует, то Rewrite его удалит, а затем создаст снова. RecSize используется для нетипизированных файлов
procedure Seek(var F: File; N: Integer);
Перемещает текущую позицию в файле к записи N (первая запись имеет номер 0)
procedure Truncate(var F: File);
Стирает из файла данные, расположенные за текущей позицией
procedure Write([var F: File]; P1; [ ..., PN]);
Записывает в файл F одну или несколько записей
Take Our Poll

0 0 голос

Рейтинг статьи

Работа с ZIP-архивами в Delphi – Delphi в Internet

Пост восстановлен после переезда сайта на новый хостинг. Работа с zip в delphi появилась ещё в Delphi XE2. Однако это событие осталось практически незамеченным на фоне других нововведений, которыми пестрила Delphi XE2: разработка под MacOS и, соответственно, библиотеки Firemonkey, механизм LiveBinding и прочие “фичи”, лежащие на поверхности. А про модуль delphi System.Zip особенно никто подробно и не рассказывал, разве, что здесь была небольшая заметка про zip в delphi. Сегодня я буду рассматривать работу с zip в delphi с позиции использования System.Zip в Delphi 10.3 Rio.

Введение

Для работы с ZIP-архивами в Delphi используется класс TZipFile. Этот класс предоставляет основные возможности для работы с zip, такие как чтение содержимого архива, запись архива, чтение заголовка архивного файла, упаковка и распаковка zip в delphi. И, несмотря на то, что TZipFile не содержит методов и свойств, непосредственно используемых для запароленных архивов, этот класс может предоставлять пользователю информацию о том, что файл зашифрован для того, чтобы использовать другие библиотеки delphi для распаковки зашифрованных zip-архивов.

Работу с модулем System.Zip и, в частности, с классом TZipFile, рассмотрим на примерах.

Чтение содержимого zip архива в Delphi

Для демонстрации возможностей чтения zip в delphi попробуем прочитать архив test.zip, содержащий три файла – текстовый и две схемы XSD для KML:

Для начала, прочитаем имена файлов, содержащихся в zip-архиве. Делается это так:

var Zip: TZipFile; ArchiveFile: String; begin Zip:=TZipFile.Create; try Zip.Open('test.zip',zmRead); for ArchiveFile in Zip.FileNames do ShowMessage(ArchiveFile); Zip.Close; finally Zip.Free; end; end;

Здесь мы создаем объект zip архива, затем открываем архив для чтения, используя метод Open и, используя свойство TZipFile.FileNames, получаем имена файлов в архиве. На что стоит обратить внимание:

  1. Путь к файлу в TZipFile.FileNames определяется относительно zip архива;
  2. В свойстве TZipFile.FileNames содержатся как имена файлов, так и папок архива.

Так, в приведенном выше примере программа выдаст следующим список:

  • kml/2.3.0/
  • kml/2.3.0/atom-author-link.xsd
  • kml/2.3.0/ogckml23.xsd
  • kml/2.3.0/ReadMe.txt

Метод Open имеет две версии:

procedure Open(const ZipFileName: string; OpenMode: TZipMode); overload; procedure Open(ZipFileStream: TStream; OpenMode: TZipMode); overload;

В одной версии мы передаем в качестве zip архива имя файла, а во втором – поток TStream, содержащий zip архив. При этом, второй параметр – OpenMode может принимать следующие значения:

TZipMode = (zmClosed, zmRead, //открываем zip архив для чтения zmReadWrite, //открываем zip архив для чтения и добавления новых файлов zmWrite);//создаем новый архив

Кроме имен файлов в архиве мы также можем получить по нему такую информацию как размер в упакованном и неупакованном виде, метод сжатия, комментарий к файлу в архиве и так далее. Получается эта информация с использованием свойств:

property FileInfos: TArray read GetFileInfos; property FileInfo[Index: Integer]: TZipHeader read GetFileInfo;

При этом тип TZipHeader имеет следующее описание:

 TZipHeader = packed record MadeByVersion: UInt16; // Start of Central Header RequiredVersion: UInt16; // Start of Local Header Flag: UInt16; CompressionMethod: UInt16; ModifiedDateTime: UInt32; CRC32: UInt32; CompressedSize: UInt32; UncompressedSize: UInt32; FileNameLength: UInt16; ExtraFieldLength: UInt16; // End of Local Header FileCommentLength: UInt16; DiskNumberStart: UInt16; InternalAttributes: UInt16; ExternalAttributes: UInt32; LocalHeaderOffset: UInt32; // End of Central Header FileName: TBytes; ExtraField: TBytes; FileComment: TBytes; function GetUTF8Support: Boolean; procedure SetUTF8Support(value: Boolean); property UTF8Support: Boolean read GetUTF8Support write SetUTF8Support; end;

Попробуем получить информацию по файлам и папкам в нашем тестовом архиве. В коде ниже считывается информация о файле из архива: комментарий, метод сжатия, размер файла в сжатом и несжатом состоянии, контрольная сумма и дата последнего изменения файла.

var Header: TZipHeader; Date: TDateTime; begin Memo1.Lines.Clear; Header := Zip.FileInfos[ListBox1.ItemIndex]; Memo1.Lines.Add('FileComment ' + StringOf(Header.FileComment)); Memo1.Lines.Add('Method ' + TZipCompressionToString(TZipCompression(Header.CompressionMethod))); Memo1.Lines.Add('CompressedSize ' + Header.CompressedSize.ToString); Memo1.Lines.Add('UncompressedSize ' + Header.UncompressedSize.ToString); Memo1.Lines.Add('CRC32 ' + Header.CRC32.ToString); WinFileDateToDateTime(Header.ModifiedDateTime, Date); Memo1.Lines.Add('ModifiedDateTime ' + DateTimeToStr(Date)); end;

Здесь мы использовали два новых метода.

function TZipCompressionToString(Compression: TZipCompression): string;

Возвращает “человекопонятный” метод сжатия файла по значению, полученному из заголовка. TZipCompression – это перечислитель, содержащий все доступные методы сжатия файла.
Второй метод (WinFileDateToDateTime) переводит значение даты/времени из формата Windows в обычный TDateTime. Этот метод в System.Zip почему-то не публичный, в отличие от TZipCompressionToString, поэтому пришлось его “вытащить наружу”, метод выглядит следующим образом:

function WinFileDateToDateTime(FileDate: UInt32; out DateTime: TDateTime): Boolean; var LDate: TDateTime; LTime: TDateTime; begin Result := TryEncodeDate( LongRec(FileDate).Hi shr 9 + 1980, LongRec(FileDate).Hi shr 5 and 15, LongRec(FileDate).Hi and 31, LDate);   if Result then begin Result := TryEncodeTime( LongRec(FileDate).Lo shr 11, LongRec(FileDate).Lo shr 5 and 63, LongRec(FileDate).Lo and 31 shl 1, 0, LTime);   if Result then DateTime := LDate + LTime; end; end;

Распаковка файлов из ZIP в Delphi

Следующий момент – распаковка архива. Здесь TZipFile предоставляет возможность распаковки как отдельного файла, так и сразу всех файлов, содержащихся в архиве.

Для того, чтобы распаковать отдельный файл используется одна из версий метода:

procedure Extract(const FileName: string; const Path: string = ''; CreateSubdirs: Boolean = True); overload; procedure Extract(Index: Integer; const Path: string = ''; CreateSubdirs: Boolean = True); overload;

Здесь:

  • FileName – файл, который необходимо распаковать (см. свойство TZipFile.FileNames)
  • Index – индекс файла в TZipFile.FileNames
  • Path – путь по которому необходимо разместить распакованный файл. По умолчанию файл размещается в директории рядом с exe-файлом
  • CreateSubdirs – указывает на то, следует ли воссоздать полный путь к файлу (True) или нет (False)

Для распаковки всего zip архива в delphi используется следующий метод:

procedure ExtractAll(const Path: string = '');

Если же вам необходимо содержимое какого-либо файла для дальнейшей работы в программе, то можно воспользоваться следующими методами:

procedure Read(const FileName: string; out Bytes: TBytes); overload; procedure Read(Index: Integer; out Bytes: TBytes); overload;

Первый параметр в этих процедурах имеет тот же смысл, что и в методах Extract, а второй – массив байтов в который необходимо сохранить содержимое файла. Например, так можно вывести в Memo текст xsd-файла из нашего тестового архива:

var Bytes: TBytes; begin Zip.Read(ListBox1.Items[ListBox1.ItemIndex],//файл из zip архива, выбранный в списке ListBox1 Bytes); Memo1.Lines.Text:=StringOf(Bytes); end;

Создание zip архива в Delphi

Для создания zip архива в delphi необходимо:

  1. Создать экземпляр TZipFile с режимом доступа zmReadWrite
  2. Добавить в архив файлы, используя метод TZipFile.Add
  3. Выполнить метод TZipFile.Close
  4. Уничтожить экземпляр TZipFile

Метод Add имеет следующее описание:

procedure Add(const FileName: string; const ArchiveFileName: string = ''; Compression: TZipCompression = zcDeflate); overload; procedure Add(Data: TBytes; const ArchiveFileName: string; Compression: TZipCompression = zcDeflate); overload; procedure Add(Data: TStream; const ArchiveFileName: string; Compression: TZipCompression = zcDeflate; AExternalAttributes: TFileAttributes = []); overload; procedure Add(Data: TStream; LocalHeader: TZipHeader; CentralHeader: PZipHeader = nil); overload;

Здесь

  • FileName – имя внешнего файла, который необходимо добавить в архив
  • Data – содержимое внешнего файла, который необходимо добавить в архив
  • ArchiveFileName – имя файла в архиве
  • Compression – метод сжатия файла

Например, напишем консольное приложение, которое будет находить все файлы в папке archive рядом с exe-файлом и упаковывать их без всякой структуры в архив с названием test.zip:

program Archivator;   {$APPTYPE CONSOLE}   {$R *.res}   uses System.SysUtils, System.Zip, System.IOUtils;   const cZipName = 'test.zip'; cZipFolder ='archive';   var ZipFile: TZipFile; zName: string; searchPath: string; ArchiveFiles: TArray; AFile: string; begin //задаем имя zip архива zName:=TPath.Combine(ExtractFilePath(ParamStr(0)), cZipName); //задаем путь к папке с файлами для упаковки searchPath:=TPath.Combine(ExtractFilePath(ParamStr(0)), cZipFolder); ZipFile:=TZipFile.Create; try ZipFile.Open(zName,zmWrite); //ищем все файлы в директории ArchiveFiles:=TDirectory.GetFiles(searchPath); //добавляем все найденные файлы в архив for AFile in ArchiveFiles do begin Writeln('Добавляем в архив файл '+AFile); ZipFile.Add(AFile, ExtractFileName(AFile), zcDeflate); end; //закрываем файл ZipFile.Close; finally //уничтожаем TZipFile FreeAndNil(ZipFile); end; readln; end.

Соответственно, если вам необходимо создать сложную структуру zip архива в delphi с папками, подпапками и так далее, то просто изменяете параметр ArchiveFileName, добавляя необходимые пути.

Как работать с запароленными zip архивами в Delphi

Как я писал выше, к сожалению в TZipFile нет как таковых механизмов и методов работы с zip архивами с паролем. Однако, можно проверить наличие шифрования у архива и переадресовать работу с таким архивом другой библиотеке. Для того, чтобы определить, что файл зашифрован, необходимо определить обработчик события OnCreateDecompressStream или определить callback-функцию CreateDecompressStreamCallBack.

Например, определить, что zip архив защищен паролем можно так:

Назначаем обработчик OnCreateDecompressStream

var ZipFile: TZipFile; begin ZipFile:=TZipFile.Create; ZipFile.OnCreateDecompressStream := OnCreateDecompressStream; ZipFile.Open('Password.zip',zmRead); try ZipFile.ExtractAll(); finally ZipFile.Free; end; end;

Сам обработчик выглядит следующим образом:

function TForm13.OnCreateDecompressStream(const InStream: TStream; const ZipFile: TZipFile; const Item: TZipHeader; IsEncrypted: Boolean): TStream; begin try if IsEncrypted then begin ShowMessage('Зашифровано'); end else Result := InStream; except on E: Exception do begin Result := InStream; end; end; end;

В принципе, этот подход был показан давным давно в официальной документации Embarcadero. Однако, при тестировании TZipFile обнаружилось, что, если файл зашифрован одним из методов AES (AES128, AES192, AES256), то вызывается исключение при создании потока TZDecompressionStream и, следовательно, до вызова события OnCreateDecompressStream дело не доходит. Методом AES позволяет шифровать файлы, например, тот же Total Commander:

Однако, если выбрать способ ZIP 2.0, то все работает как надо.

Отображение прогресса создания или распаковки zip архива в Delphi

При добавлении в zip архив большого файла или, наоборот, распаковки большого zip архива в delphi хотелось бы, чтобы наша программа не “висла”. TZipFile предоставляет такую возможность с помощью события OnProgress:

TZipProgressEvent = procedure(Sender: TObject; FileName: string; Header: TZipHeader; Position: Int64) of object;

Здесь

  • FileName – имя файла, который в данный момент обрабатывается
  • Header – информация о файле
  • Position – количество обработанный байт файла

Например, чтобы получить текущий прогресс упаковки файла в zip архив в delphi можно использовать простую формулу:

Position / Header.UnCompressedSize)*100

Ну и, конечно, если вы работаете с TZipFile не в отдельном потоке, то стоит в обработчике также указать:

Application.ProcessMessages

Вот, в принципе и вся основная информация по работе delphi с zip архивами “из коробки”. Остается только добавить, что помимо рассмотренных выше методов и свойств у TZipFile также имеются классовые методы, позволяющие работать с zip архивами без создания экземпляра TZipFile.

5 2 голоса

Рейтинг статьи

Лабораторная работа “Вывод текста из файла” – Delphi в Internet

Текст задания звучит следующим образом: вывести на экран текст из файла text.txt. Это задание базируется на выполнении предыдущего – запись текста в файл. Вывод текста из файла на экран в Pascal/Delphi осуществляется с помощью двух процедур: readln() и writeln(). Рассмотрим подробное решение этой задачи. Лабораторная работа выполняется в Delphi 10.3 Rio.

Анализ задачи

На данном этапе предполагается, что у нас имеется файл text.txt, который содержит некоторое количество строк текста или же файл пуст. Наша задача сводится к следующим шагам:

  1. Получить доступ к файлу
  2. Считывать из файла строки до тех пор, пока не будет достигнут конец файла
  3. Закрыть файл

Решение задачи

Создаем новое консольное приложение в Delphi. Как это сделать – смотри в предыдущей лабораторной работе.

Пишем следующий код:

program ReadTextFile;   {$APPTYPE CONSOLE}   {$R *.res}   uses System.SysUtils;   var F: TextFile; s: string; begin AssignFile(F,'text.txt'); Reset(F); while not Eof(F) do begin readln(F,s); Writeln(s); end; CloseFile(F); readln; end.

Рассмотрим алгоритм решения этой задачи подробно:

1. Определяем переменные в разделе var

– это файловая переменная для работы с текстовым файлом

– это переменная для хранения строки, полученной из текстового файла в delphi

2. Ассоциируем файловую переменную с внешним файлом на диске:

AssignFile(F, 'text.txt');

Более подробно об этой процедуре – см. здесь.

3. После того, как файловая переменная ассоциирована с внешним файлом, открываем текстовый файл, используя метод Reset.

Для открытия текстового файла в Pascal/Delphi могут использоваться три метода – Rewrite, Reset и Append. Однако, так как в тексте задачи указано, что необходимо читать данные из файла, то мы используем метод Reset(), который открывает файл, ассоциированный с переменной F для чтения/записи, не создавая заново и не затирая данные.

4. В цикле с предусловием while..do считываем строки из файла и выводим их на экран:

 while not Eof(F) do begin readln(F,s); Writeln(s); end;

Для условия выхода из цикла мы использовали метод Eof():

Метод Eof() возвращает True (истину), если достигнут конец файл. Таким образом, наше условие выхода из цикла читается как “пока не достигнут конец файла“.

Цикл с постусловием repeat..until в этой задаче лучше не использовать, несмотря на то, что программа не выдаст при этом никаких ошибок. Дело в том, что, если использовать цикл с постусловием, то программа хотя бы один раз попытается считать строку из файла и, если файл окажется пустым, то на экран будет выведена пустая строка – программа сработает “вхолостую”.

5. Закрываем файл и ожидаем пока пользователь не нажмет Enter:

Улучшение программы

Несмотря на то, что программа будет работать, в представленном выше коде есть несколько “тонких” мест. Во-первых, это использование строковой константы (имени файла) непосредственно в коде программы, чего необходимо избегать, так как затрудняется внесение изменений в код программы, если таких констант у вас будет много. Во-вторых, если при запуске программы рядом с exe-файлом не будет обнаружен файл text.txt, то программа вызовет исключение при попытке открыть файл методом reset(). Текст ошибки при этом будет следующим:

—————————
Debugger Exception Notification
—————————
Project ReadTextFile.exe raised exception class EInOutError with message ‘File not found’.
—————————
Break Continue Help
—————————

Улучшим код нашей программы следующим образом:

program ReadTextFile;   {$APPTYPE CONSOLE}   {$R *.res}     uses System.SysUtils;   const cFileName = 'text.txt'; сFileNotFound = 'Файл %s не найден!';   var F: TextFile; s: string;   begin if FileExists(cFileName) then begin AssignFile(F, cFileName); Reset(F); while not Eof(F) do begin readln(F, s); Writeln(s); end; CloseFile(F); end else Write(Format(сFileNotFound,[cFileName])); readln; end.

В этом коде мы вынесли все строковые константы в секцию const, а в самом коде программы добавили условие:

 if FileExists(cFileName) then begin //здесь происходит чтение файла end else Write(Format(сFileNotFound,[cFileName]));

Функция FileExists() проверяет наличие файла на диске и возвращает True, если файл найден.

Функция Format() форматирует строку. В качестве первого аргумента этой функции выступает константа сFileNotFound, содержащая символ форматирования %s, который заменяется, в нашем случае, на имя файла (см. второй аргумент функции).

Таким образом, если рядом с exe-файлом не будет обнаружено необходимого файла, то вместо ошибки будет выведено следующее сообщение:

Подобное улучшение кода делает программу более гибкой к изменению и позволяет избежать лишних проблем в случае, если файл не будет найден.

Файлы для загрузки

Скачать файлы лабораторной работы вы можете со страницы исходников:

0 0 голос

Рейтинг статьи

Как в Delphi записать в файл

const txFileName = 'myFile.txt';

 

//оформим пример в виде процедуры

//на входе сторока, которую надо сохранить в файл

procedure saveIntoTextFile(txt: string);

var

     txtfile: TextFile;

begin

   //для начало нужно собрать файла, куда мы сохраняем текст

   path:= ExtractFilePath(application.ExeName) + '/' + txFileName;

   //ассоциируем название файла с файловой переменной

   AssignFile(txtfile, path);

   //выключаем проверку ошибок ввода-вывода

   //это такой вариант - для ленивых, чтобы и программа не парилась

   //и нам чтобы не реализовывать все проверки по-честному

   {$I-}

   if not FileExists(path) then

      //файла нет - создадим

      Rewrite(txtfile)

   else

      //если есть - откроем и установим указатель записи в конец

      Append(txtfile);

   {$I+}

   //пишем наш текст в открытый файл

   Write(txtfile, txt);

   //освобождаем дескрипторы, закрываем файл

   Closefile(txtfile);

end;

Быстрая обработка данных Excel в Delphi. – Delphi в Internet

Праздники ещё не закончились, работать лень, но надо как-то уже прекращать заниматься кишкоблудством и начинать работать в полную силу. Ну, а чтобы как-то себя расшевелить и начать уже работу в блоге, решил первый пост сделать простым – снова сказать несколько слов про Excel. Дело в том, что с момента выхода поста под названием “Работа с Excel в Delphi. Основы основ.” прошло практически полтора года и этот пост (почему-то вопреки всем ожиданиям) очень прочно закрепился в выдаче поисковиков. Это, конечно хорошо, но этот пост (читай название) дает лишь небольшое представление о том как работать с Excel в Delphi. Никто ведь не изучает сразу квантовую механику с первого класса? Сначала учимся основам вообще – математика, физика и т.д. Так я решил поступить в начале рассказа про Excel – сначала дать общее представление, а потом потихоньку раскрывать тему более подробно и детально. Но поисковики немного спутали карты, подняв пост выше других про Excel. Соответственно, те из посетителей, кто уже имеют представление о работе с Excel, видя представленные в статье примеры, возмущаются по поводу того, что чтение данных в этом случае будет происходить медленно. И я не спорю, да проход по каждой ячейке листа – это жуткие тормоза. А ускорить процесс чтения можно и необходимо. Поэтому можно считать, что эта статья – расширение к основам.

За полтора года мне предлагали кучу вариантов того как ускорить чтение данных с листа Excel – от использования MSXML и других готовых библиотек до самопальных процедур и функций. Что ж, любую задачу можно решить несколькими способами. Рассмотрим несколько вариантов и определимся какой из вариантов окажется наиболее быстрым. Ну, а какой вариант окажется более удобным – это уже каждый решит для себя сам.

Чтение данных из Excel

Вначале рассмотрим вариант чтения данных использованием которого грешат те, кто только начинает свое знакомство с Excel в Delphi – чтение данных из каждой ячейки по отдельности. Тестовая процедура с таким вариантом чтения может выглядеть следующим образом:

procedure TForm16.SlowVariant; var Rows, Cols, i,j: integer; WorkSheet: OLEVariant; d: TDateTime; begin //открываем книгу ExcelApp.Workbooks.Open(edFile.Text); //получаем активный лист WorkSheet:=ExcelApp.ActiveWorkbook.ActiveSheet; //определяем количество строк и столбцов таблицы Rows:=WorkSheet.UsedRange.Rows.Count; Cols:=WorkSheet.UsedRange.Columns.Count;   StringGrid1.RowCount:=Rows; StringGrid1.ColCount:=Cols;   //засекаем время начала чтения d:=Now;   //выводим данные в таблицу for I := 0 to Rows-1 do for j := 0 to Cols-1 do StringGrid1.Cells[J,I]:=WorkSheet.UsedRange.Cells[I+1,J+1].Value;   Label2.Caption:='Время чтения всего листа: '+FormatDateTime('hh:mm:ss:zzz', Now()-d); end;

Счётчик будет в итоге содержать время чтения и вывода в StringGrid данных. Можно было бы сделать счётчик исключительно на чтение данных с листа, но я решил не перегружать исходник лишними переменными. Если будет желание – можете переписать чуть-чуть исходник и получить “чистое” время чтения.

Для теста этого варианта был создан лист Excel, содержащий 143 строки и 142 столбца с данными, т.е. 20306 ячеек с данными. На рисунке ниже представлено значение счётчика после чтения данных:

12 секунд на чтение…а если будет 1000 строк и 1000 столбцов? Так можно и не дождаться окончания операции.

Если внимательно посмотреть на процедуру, представленную выше, то можно видеть, что в цикле мы каждый раз при каждой итерации вначале получаем диапазон, занятый данными, затем в этом диапазоне получаем определенную ячейку и только потом считываем значение в ячейке. На самом деле столько лишних операций для чтения данных с листа не требуется. Тем более, когда данные располагаются непрерывным массивом. Более выгодным в этом случае вариантом чтения будет чтение данных сразу из всего диапазона в массив.

На деле реализация этого варианты работы окажется даже проще, чем представленного выше. Смотрите сами. Вот вариант чтения данных целым диапазоном:

procedure TForm16.RangeRead; var Rows, Cols, i,j: integer; WorkSheet: OLEVariant; FData: OLEVariant; d: TDateTime; begin //открываем книгу ExcelApp.Workbooks.Open(edFile.Text); //получаем активный лист WorkSheet:=ExcelApp.ActiveWorkbook.ActiveSheet; //определяем количество строк и столбцов таблицы Rows:=WorkSheet.UsedRange.Rows.Count; Cols:=WorkSheet.UsedRange.Columns.Count;   //считываем данные всего диапазона FData:=WorkSheet.UsedRange.Value;   StringGrid1.RowCount:=Rows; StringGrid1.ColCount:=Cols;   //засекаем время начала чтения d:=Now;   //выводим данные в таблицу for I := 0 to Rows-1 do for j := 0 to Cols-1 do StringGrid1.Cells[J,I]:=FData[I+1,J+1];   Label2.Caption:='Время чтения всего листа: '+FormatDateTime('hh:mm:ss:zzz', Now()-d); end;

Здесь мы ввели всего одну переменную FData типа Variant. В эту переменную мы прочитали за 1 операцию весь диапазон, занятый данными. После того как диапазон прочитан FData будет содержать матрицу, каждый элемент которой будет типом данных, определенным в Excel.

Смотрим на время выполнения операции:

Как видите, прирост скорости оказался колоссальным, учитывая даже то, что в счётчик попало время обновления StringGrid’а.

Здесь было бы уместно показать и обратный метод работы с Excel, т.е. запись данных на лист Excel с использованием вариантного массива.

Запись данных в Excel

В случае, если нам необходимо записать большой объем данных на лист Excel нам необходимо провести обратную операцию, т.е. вначале создать вариантный массив, затем записать в этот массив данные после чего записать весь массив одной операцией в Excel. Для примера я написал процедуру, которая считывает большой объем данных из StringGrid и записывает эти данные на второй лист открытой книги Excel:

procedure TForm16.WriteData; var i,j: integer; FData: Variant; Sheet,Range: Variant; begin //создаем вариантный массив FData:=VarArrayCreate([1,StringGrid1.RowCount,1,StringGrid1.ColCount],varVariant); //заполняем массив данными из StringGrid for i:=1 to VarArrayHighBound(FData,1) do for j:=1 to VarArrayHighBound(FData,2) do FData[i,j]:=StringGrid1.Cells[J-1,I-1]; {активируем второй лист книги} //открываем книгу ExcelApp.Workbooks.Open(edFile.Text); //активируем Sheet:=ExcelApp.ActiveWorkBook.Sheets[2]; Sheet.Activate; //выделяем диапазон для вставки данных Range:=Sheet.Range[Sheet.Cells[1,1],Sheet.Cells[VarArrayHighBound(FData,1),VarArrayHighBound(FData,2)]]; //вставляем данные Range.Value:=FData; //показываем окно Excel ExcelApp.Visible:=True; end;

Здесь мы вначале создаем двумерный вариантный массив, используя метод VarArrayCreate, после чего заполняем массив данным и передаем этот массив в Excel. Обратите внимание, что при записи в Excel не используются никакие циклы – запись происходит в 2 простых действия:

  • выделяем диапазон, используя в качестве границ диапазона первую и последнюю ячейки
  • присваиваем диапазону значение из массива.

Для полноты картины ниже на рисунке представлено значение счётчика, который отсчитал время от момента создания массива до активации приложения Excel включительно:

Естественно, что с ростом объема данных будет расти и время выполнения операции. Так, например, лист, содержащий 1000 строк и 256 столбцов с данными заполнялся около 7 секунд. Если для Вас такое время неприемлемо, то представленная выше процедура может быть немного ускорена использованием пары методов VarArrayLock() и VarArrayUnLock(), но при этом следует учитывать, что матрица FData будет транспонирована.

Что ещё стоит сказать по поводу чтения/записи данных в Excel? Наверное то, что предложенные выше методы работы в обязательном порядке требуют наличия установленного Excel на том компьютере где запускается Ваша программа. В связи с этим обстоятельством может потребоваться более универсальный способ работы с Excel. Здесь, опять же, может быть несколько вариантов работы, но я покажу, а точнее укажу только на один из них – с использованием библиотека XLSReadWrite.

Про эту библиотеку мне поведал один из читателей блога в комментарии как раз-таки к посту “”Работа с Excel в Delphi. Основы основ“. Чтобы лишний раз Вас не переправлять на комментарий с примером использования этой библиотеки, я с разрешения GS (ник автора кода) просто опубликую здесь уже готовые примеры использования библиотеки XLSReadWrite:

Упрощенный пример для Delphi 7

var IntlXls: TXLSReadWriteII2; I, J: Integer;   begin // создаем объект IntlXls := TXLSReadWriteII2.Create(nil);   // название книги IntlXls.Sheets[0].Name := ‘ Название моего отчета ’; // добавляем необходимое количество строк и колонок IntlXls.Sheets[0].Rows.AddIfNone(0, 10000); IntlXls.Sheets[0].Columns.AddIfNone(0, 100);   // добавляем и заносим ширины ячеек (значение в пикселях) for I := 0 to 99 do IntlXls.Sheets[0].Columns[I].PixelWidth := 150; // заносим высоты строк (значение здесь не в пикселях, поэтому нужно корректировать) for I := 0 to 9999 do IntlXls.Sheets[0].Rows[I].Height := 20 * 14;   // настраиваем for J := 0 to 9999 do for I := 0 to 99 do begin // заносим числовое значение // если нужно например занести строку, то использовать AsString IntlXls.Sheets[0].AsFloat[I, J] := J + I / 100;   // выравнивание по горизонтали (доступно chaLeft, chaCenter, chaRight) IntlXls.Sheets[0].Cell[I, J].HorizAlignment := chaLeft;   // выравнивание по вертикали (доступно cvaTop, cvaCenter, cvaBottom) IntlXls.Sheets[0].Cell[I, J].VertAlignment := cvaTop;   // шрифт IntlXls.Sheets[0].Cell[I, J].FontName := ‘ Arial ’; IntlXls.Sheets[0].Cell[I, J].FontSize := 12; IntlXls.Sheets[0].Cell[I, J].FontStyle := []; IntlXls.Sheets[0].Cell[I, J].FontColor := TColorToClosestXColor(clBlue); IntlXls.Sheets[0].Cell[I, J].Rotation := 0; // жирное начертание with IntlXls.Sheets[0].Cell[I, J] do FontStyle := FontStyle + [xfsBold]; // наклонное начертание with IntlXls.Sheets[0].Cell[I, J] do FontStyle := FontStyle + [xfsItalic]; // цвет фона IntlXls.Sheets[0].Cell[I, J].FillPatternForeColor := TColorToClosestXColor(clYellow);   // бордюр слева (аналогично и остальные бордюры) IntlXls.Sheets[0].Cell[I, J].BorderLeftColor := TColorToClosestXColor(clBlack); IntlXls.Sheets[0].Cell[I, J].BorderLeftStyle := cbsThin;   // объединение ячеек (здесь объединяются две ячейки по горизонтали) if I = 49 then IntlXls.Sheets[0].MergedCells.Add(I, J, I + 1, J); end;   IntlXls.SaveToFile(‘ c: \ demo.xls ’); IntlXls.Free; end;

Полный пример работы с библиотекой:

function ExportToExcelXls(var AFileName: string): Integer; var IntlXls: TXLSReadWriteII2; IntlCol: Integer; IntlRow: Integer; IntlMainCol: Integer; IntlMainRow: Integer; begin // инициализируем статус prgrbrStatus.Max := FLinkReport.RowCount; prgrbrStatus.Position := 0; pnlStatus.Visible := TRUE; pnlStatus.Refresh; // добавлено в конце имени файла расширение ‘.XLS’? if Length(AFileName) < 5 then // добавляем AFileName := AFileName + ‘.xls ’ else if AnsiCompareText(Copy(AFileName, Length(AFileName)— 3, 4), ‘.xls ’) <> 0 then // добавляем AFileName := AFileName + ‘.xls ’; // файл уже существует? if FileExists(AFileName) then // спросим if Application.MessageBox (PChar(‘ Файл « ‘ + AFileName + ‘ » уже существует.Перезаписать ? ’), ‘ Внимание ’, MB_TASKMODAL + MB_ICONQUESTION + MB_YESNO + MB_DEFBUTTON2) <> IDYES then // выходим begin // код ошибки Result := UNIRPT_GENERATE_ABORT;   // выходим Exit; end; // if // создаем объект IntlXls := TXLSReadWriteII2.Create(nil); // все делаем защищаясь try // название книги IntlXls.Sheets[0].Name := FLinkReport.Caption; // добавляем необходимое количество строк и колонок IntlXls.Sheets[0].Rows.AddIfNone(0, FLinkReport.Cells.RowCount + 1); IntlXls.Sheets[0].Columns.AddIfNone(0, FLinkReport.Cells.ColCount + 1); // добавляем и заносим ширины ячеек for IntlCol := 0 to FLinkReport.Cells.ColCount — 1 do IntlXls.Sheets[0].Columns[IntlCol].PixelWidth := FLinkReport.ColWidths[IntlCol]; // заносим высоты строк for IntlRow := 0 to FLinkReport.Cells.RowCount — 1 do IntlXls.Sheets[0].Rows[IntlRow].Height := FLinkReport.RowHeights [IntlRow] * 14; // проходим по всем строкам for IntlRow := 0 to FLinkReport.Cells.RowCount — 1 do begin // проходим по всем колонкам for IntlCol := 0 to FLinkReport.Cells.ColCount — 1 do begin // определяем главную ячейку IntlMainCol := IntlCol + FLinkReport.Cells[IntlCol, IntlRow].Range.Left; IntlMainRow := IntlRow + FLinkReport.Cells[IntlCol, IntlRow].Range.Top; // заносим оформление with FLinkReport.Cells[IntlMainCol, IntlMainRow] do begin // главная ячейка? if (IntlMainCol = IntlCol) and (IntlMainRow = IntlRow) then // да, заносим текст и его оформление begin // значение try // если значение — число то заносим его как число IntlXls.Sheets[0].AsFloat[IntlCol, IntlRow] := StrToFloat(Value); except // иначе заносим его как строку IntlXls.Sheets[0].AsString[IntlCol, IntlRow] := Value; end;   // выравнивание по горизонтали case HorizAlign of haLeft: // выравнивание слева IntlXls.Sheets[0].Cell[IntlCol, IntlRow].HorizAlignment := chaLeft; haCenter: // выравнивание по центру IntlXls.Sheets[0].Cell[IntlCol, IntlRow].HorizAlignment := chaCenter; haRight: // выравнивание справа IntlXls.Sheets[0].Cell[IntlCol, IntlRow].HorizAlignment := chaRight; end; // case // выравнивание по вертикали case VertAlign of vaTop: // выравнивание сверху IntlXls.Sheets[0].Cell[IntlCol, IntlRow].VertAlignment := cvaTop; vaCenter: // выравнивание в центре IntlXls.Sheets[0].Cell[IntlCol, IntlRow].VertAlignment := cvaCenter; vaBottom: // выравнивание снизу IntlXls.Sheets[0].Cell[IntlCol, IntlRow].VertAlignment := cvaBottom; end; // case // шрифт IntlXls.Sheets[0].Cell[IntlCol, IntlRow].FontName := Font.Name; IntlXls.Sheets[0].Cell[IntlCol, IntlRow].FontSize := Font.Size; IntlXls.Sheets[0].Cell[IntlCol, IntlRow].FontCharset := Font.Charset; IntlXls.Sheets[0].Cell[IntlCol, IntlRow].FontStyle := []; IntlXls.Sheets[0].Cell[IntlCol, IntlRow].FontColor := TColorToClosestXColor(Font.Color); IntlXls.Sheets[0].Cell[IntlCol, IntlRow].Rotation := Font.Angle; // есть жирное начертание? if Font.IsBold then // есть with IntlXls.Sheets[0].Cell[IntlCol, IntlRow] do FontStyle := FontStyle + [xfsBold]; // есть наклонное начертание? if Font.IsItalic then // есть with IntlXls.Sheets[0].Cell[IntlCol, IntlRow] do FontStyle := FontStyle + [xfsItalic]; // цвет фона if Color <> clWindow then // цвет задан IntlXls.Sheets[0].Cell[IntlCol, IntlRow].FillPatternForeColor := TColorToClosestXColor(Color); end // if else // просто активизируем ячейку (иначе ниже невозможно добавить бордюры) IntlXls.Sheets[0].AsString[IntlCol, IntlRow] := »;   // бордюр слева есть? with Borders.Left do if LineHeight > 0 then // настраиваем begin // цвет IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderLeftColor := TColorToClosestXColor(Color); // толщина if LineHeight = 1 then // тонка IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderLeftStyle := cbsThin else if LineHeight in [1, 2] then // средняя толщина IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderLeftStyle := cbsMedium else // толстая IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderLeftStyle := cbsHair; end; // if, with // бордюр сверху есть? with Borders.Top do if LineHeight > 0 then // настраиваем begin // цвет IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderTopColor := TColorToClosestXColor(Color); // толщина if LineHeight = 1 then // тонка IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderTopStyle := cbsThin else if LineHeight in [1, 2] then // средняя толщина IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderTopStyle := cbsMedium else // толстая IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderTopStyle := cbsHair; end; // if, with // бордюр справа есть? with Borders.Right do if LineHeight > 0 then // настраиваем begin // цвет IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderRightColor := TColorToClosestXColor(Color); // толщина if LineHeight = 1 then // тонка IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderRightStyle := cbsThin else if LineHeight in [1, 2] then // средняя толщина IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderRightStyle := cbsMedium else // толстая IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderRightStyle := cbsHair; end; // if, with // бордюр снизу есть? with Borders.Bottom do if LineHeight > 0 then // настраиваем begin // цвет IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderBottomColor := TColorToClosestXColor(Color); // толщина if LineHeight = 1 then // тонка IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderBottomStyle := cbsThin else if LineHeight in [1, 2] then // средняя толщина IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderBottomStyle := cbsMedium else // толстая IntlXls.Sheets[0].Cell[IntlCol, IntlRow].BorderBottomStyle := cbsHair; end; // if, with // объединение нужно? if ((Range.Width > 1) or (Range.Height > 1)) and ((IntlMainCol = IntlCol) and (IntlMainRow = IntlRow)) then // объединяем IntlXls.Sheets[0].MergedCells.Add(IntlCol, IntlRow, IntlCol + Range.Width — 1, IntlRow + Range.Height — 1); // пользователь нажал кнопку прерывания экспорта? if btnCancel.Tag = 2 then // да, выходим Break; end; // with end; // for // обновляем статус prgrbrStatus.Position := prgrbrStatus.Position + 1; Application.ProcessMessages; // пользователь нажал кнопку прерывания экспорта? if btnCancel.Tag = 2 then // да, выходим Break; end; // for // пользователь нажал кнопку прерывания экспорта? if btnCancel.Tag <> 2 then // нет begin // на левый верхний угол IntlXls.Sheet[0].TopRow := 0; IntlXls.Sheet[0].LeftCol := 0; IntlXls.Sheet[0].Selection.ActiveRow := 0; IntlXls.Sheet[0].Selection.ActiveCol := 0;   // статус prgrbrStatus.Position := prgrbrStatus.Max; Application.ProcessMessages; // записываем в файл IntlXls.FileName := AFileName; IntlXls.Write; // все успешно Result := UNIRPT_OK;   end // if else // да Result := UNIRPT_GENERATE_ABORT;   finally // освобождаем память IntlXls.Free; end; // try..finally end; // function ExportToExcelXls

Вот такой подробный пример предоставил нам GS в своем комментарии. Спасибо ему за это. Мне же в заключении остается только добавить и подчеркнуть, что самые правильные ответы и примеры к вопросам, касающимся работы с Excel содержаться в Справке для разработчиков в самом Excel и надо только воспользоваться поиском. Например, если вам довольно часто приходится перетаскивать данные из базы данных в Excel и в работе используется ADO, то специально для таких случаев в справке рассказывается про интересный метод объекта Range под названием CopyFromRecordset, а если вам надо разукрасить свою таблицу Excel в разные цвета и установить разные виды границ ячеек, то специально для таких случаев в справке приводится подробные перечень всех перечислителей Excel’я.  В общем много чего есть – надо только этим воспользоваться и все получится. Ну, а если не получится, то милости прошу – задавайте вопросы здесь или на нашем форуме.

Книжная полка

Автор: Юрий Магда

Название:Разработка приложений Microsoft Office 2007 в Delphi

Описание Описаны общие подходы к программированию приложений MS Office. Даны программные методы реализации функций MS Excel, MS Word, MS Access и MS Outlook в среде Delphi.

 

3 1 голос

Рейтинг статьи

Как загрузить файл с помощью HTTP-сообщения? Delphi 2009

Переполнение стека
  1. Около
  2. Товары
  3. Для команд
  1. Переполнение стека Общественные вопросы и ответы
  2. Переполнение стека для команд Где разработчики и технологи делятся частными знаниями с коллегами
.

delphi - Использование idFTP для загрузки файлов

Переполнение стека
  1. Около
  2. Товары
  3. Для команд
  1. Переполнение стека Общественные вопросы и ответы
  2. Переполнение стека для команд Где разработчики и технологи делятся частными знаниями с коллегами
  3. Вакансии Программирование и связанные с ним технические возможности карьерного роста
  4. Талант Нанимайте технических специалистов и создавайте свой бренд работодателя
.

delphi - Используйте PUT для загрузки файла с TIdHTTP

Переполнение стека
  1. Около
  2. Товары
  3. Для команд
  1. Переполнение стека Общественные вопросы и ответы
  2. Переполнение стека для команд Где разработчики и технологи делятся частными знаниями с коллегами
.

Получение скорости загрузки файла с помощью Delphi

Переполнение стека
  1. Около
  2. Товары
  3. Для команд
  1. Переполнение стека Общественные вопросы и ответы
  2. Переполнение стека для команд Где разработчики и технологи делятся частными знаниями с коллегами
.

Delphi - файл загрузки idHTTP с использованием TIdMultipartFormDataStream

Переполнение стека
  1. Около
  2. Товары
  3. Для команд
  1. Переполнение стека Общественные вопросы и ответы
  2. Переполнение стека для команд Где разработчики и технологи делятся частными знаниями с коллегами
  3. Вакансии Программирование и связанные с ним технические возможности карьерного роста
  4. Талант Нанимайте технических специалистов и создавайте свой бренд работодателя
  5. Реклама Обратитесь к разработчикам и технологам со всего мира
  6. О компании

Загрузка…

.

Загрузить файл из Интернета программно с событием Progress с использованием Delphi и Indy

Переполнение стека
  1. Около
  2. Товары
  3. Для команд
  1. Переполнение стека Общественные вопросы и ответы
  2. Переполнение стека для команд Где разработчики и технологи делятся частными знаниями с коллегами
  3. Вакансии Программирование и связанные с ним технические возможности карьерного роста
.

Смотрите также